]> git.saurik.com Git - wxWidgets.git/blobdiff - src/mac/carbon/thread.cpp
Replaced SOCKLEN_T by WX_SOCKLEN_T to resolve conflict with AIX system headers.
[wxWidgets.git] / src / mac / carbon / thread.cpp
index fed5af4d817872ad219722ba3449d47c2f3ca521..bbfafd4b38cc8f0dca4637d941f081988ec2fdd1 100644 (file)
@@ -10,7 +10,7 @@
 // Licence:    wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
 
 // Licence:    wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
 
-#ifdef __GNUG__
+#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
 #pragma implementation "thread.h"
 #endif
 
 #pragma implementation "thread.h"
 #endif
 
 #include "wx/thread.h"
 
 #ifdef __WXMAC__
 #include "wx/thread.h"
 
 #ifdef __WXMAC__
-#if TARGET_API_MAC_OSX
+#ifdef __DARWIN__
 #include <CoreServices/CoreServices.h>
 #else
 #include <DriverServices.h>
 #include <Multiprocessing.h>
 #include <CoreServices/CoreServices.h>
 #else
 #include <DriverServices.h>
 #include <Multiprocessing.h>
-#include <math.h>
+#include "wx/math.h"
 #endif
 #include "wx/mac/uma.h"
 #endif
 #endif
 #include "wx/mac/uma.h"
 #endif
@@ -114,16 +114,40 @@ MPCriticalRegionID gs_guiCritical = kInvalidID;
     to use two indices one for each 32 bit part as the MP implementation is limited
     to longs.
     
     to use two indices one for each 32 bit part as the MP implementation is limited
     to longs.
     
-    I have two implementations for mutexes :
+    I have three implementations for mutexes :
     version A based on a binary semaphore, problem - not reentrant, version B based 
     on a critical region, allows for reentrancy, performance implications not
     version A based on a binary semaphore, problem - not reentrant, version B based 
     on a critical region, allows for reentrancy, performance implications not
-    yet tested
+    yet tested, and third a plain pthreads implementation
 
     The same for condition internal, one implementation by Aj Lavin and the other one
     copied from the thrimpl.cpp which I assume has been more broadly tested, I've just
     replaced the interlock increment with the appropriate PPC calls 
 */
 
 
     The same for condition internal, one implementation by Aj Lavin and the other one
     copied from the thrimpl.cpp which I assume has been more broadly tested, I've just
     replaced the interlock increment with the appropriate PPC calls 
 */
 
+// ----------------------------------------------------------------------------
+// wxCriticalSection
+// ----------------------------------------------------------------------------
+
+wxCriticalSection::wxCriticalSection()
+{
+    MPCreateCriticalRegion( (MPCriticalRegionID*) &m_critRegion ) ;
+}
+
+wxCriticalSection::~wxCriticalSection()
+{
+    MPDeleteCriticalRegion( (MPCriticalRegionID) m_critRegion ) ;
+}
+
+void wxCriticalSection::Enter()
+{
+    MPEnterCriticalRegion( (MPCriticalRegionID) m_critRegion , kDurationForever ) ;
+}    
+
+void wxCriticalSection::Leave()
+{
+    MPExitCriticalRegion((MPCriticalRegionID) m_critRegion ) ;
+}
+
 // ----------------------------------------------------------------------------
 // wxMutex implementation
 // ----------------------------------------------------------------------------
 // ----------------------------------------------------------------------------
 // wxMutex implementation
 // ----------------------------------------------------------------------------
@@ -962,7 +986,7 @@ private:
        MPQueueID           m_notifyQueueId;    // its notification queue
 
     wxThreadState m_state;              // see wxThreadState enum
        MPQueueID           m_notifyQueueId;    // its notification queue
 
     wxThreadState m_state;              // see wxThreadState enum
-    int           m_prio;               // in wxWindows units: from 0 to 100
+    int           m_prio;               // in wxWidgets units: from 0 to 100
 
     // this flag is set when the thread should terminate
     bool m_cancelled;
 
     // this flag is set when the thread should terminate
     bool m_cancelled;
@@ -1092,8 +1116,8 @@ void wxThreadInternal::SetPriority( int priority)
        if ( m_tid)
     {
                // Mac priorities range from 1 to 10,000, with a default of 100.
        if ( m_tid)
     {
                // Mac priorities range from 1 to 10,000, with a default of 100.
-               // wxWindows priorities range from 0 to 100 with a default of 50.
-               // We can map wxWindows to Mac priorities easily by assuming
+               // wxWidgets priorities range from 0 to 100 with a default of 50.
+               // We can map wxWidgets to Mac priorities easily by assuming
                // the former uses a logarithmic scale.
                const unsigned int macPriority = ( int)( exp( priority / 25.0 * log( 10.0)) + 0.5);
                
                // the former uses a logarithmic scale.
                const unsigned int macPriority = ( int)( exp( priority / 25.0 * log( 10.0)) + 0.5);
                
@@ -1121,7 +1145,15 @@ void wxThreadInternal::Wait()
     // if the thread we're waiting for is waiting for the GUI mutex, we will
     // deadlock so make sure we release it temporarily
     if ( wxThread::IsMain() )
     // if the thread we're waiting for is waiting for the GUI mutex, we will
     // deadlock so make sure we release it temporarily
     if ( wxThread::IsMain() )
-        wxMutexGuiLeave();
+    {
+        // give the thread we're waiting for chance to do the GUI call
+        // it might be in, we don't do this conditionally as the to be waited on 
+        // thread might have to acquire the mutex later but before terminating
+        if ( wxGuiOwnedByMainThread() )
+        {
+            wxMutexGuiLeave();
+        }
+    }
 
     {
         wxCriticalSectionLocker lock(m_csJoinFlag);
 
     {
         wxCriticalSectionLocker lock(m_csJoinFlag);
@@ -1139,7 +1171,7 @@ void wxThreadInternal::Wait()
                                 kDurationForever);
             if ( err)
             {
                                 kDurationForever);
             if ( err)
             {
-                wxLogSysError( _( "Cannot wait on thread to exit."));
+                wxLogSysError( _( "Cannot wait for thread termination."));
                 rc = (void*) -1;
             }
 
                 rc = (void*) -1;
             }
 
@@ -1150,10 +1182,6 @@ void wxThreadInternal::Wait()
             m_shouldBeJoined = FALSE;
         }
     }
             m_shouldBeJoined = FALSE;
         }
     }
-
-    // reacquire GUI mutex
-    if ( wxThread::IsMain() )
-        wxMutexGuiEnter();
 }
 
 void wxThreadInternal::Pause()
 }
 
 void wxThreadInternal::Pause()
@@ -1197,7 +1225,7 @@ wxThread *wxThread::This()
 
 bool wxThread::IsMain()
 {
 
 bool wxThread::IsMain()
 {
-       return GetCurrentId() == gs_idMainThread || gs_idMainThread == kNoThreadID;
+       return GetCurrentId() == gs_idMainThread || gs_idMainThread == kInvalidID ;
 }
 
 #ifdef Yield
 }
 
 #ifdef Yield
@@ -1408,7 +1436,6 @@ wxThreadError wxThread::Delete(ExitCode *rc)
                     *rc = m_internal->GetExitCode();
                 }
             }
                     *rc = m_internal->GetExitCode();
                 }
             }
-            //else: can't wait for detached threads
     }
 
     return wxTHREAD_NO_ERROR;
     }
 
     return wxTHREAD_NO_ERROR;
@@ -1611,7 +1638,7 @@ bool wxThreadModule::OnInit()
        
        verify_noerr( MPAllocateTaskStorageIndex( &gs_tlsForWXThread ) ) ;
        // main thread's This() is NULL
        
        verify_noerr( MPAllocateTaskStorageIndex( &gs_tlsForWXThread ) ) ;
        // main thread's This() is NULL
-       verify_noerr( MPSetTaskStorageValue( gs_tlsForWXThread , NULL ) ) ;
+       verify_noerr( MPSetTaskStorageValue( gs_tlsForWXThread , 0 ) ) ;
 
        gs_idMainThread = wxThread::GetCurrentId() ;
        
 
        gs_idMainThread = wxThread::GetCurrentId() ;
        
@@ -1627,6 +1654,11 @@ void wxThreadModule::OnExit()
 {
     if ( gs_critsectGui )
     {
 {
     if ( gs_critsectGui )
     {
+        if ( !wxGuiOwnedByMainThread() )
+        {
+            gs_critsectGui->Enter();
+            gs_bGuiOwnedByMainThread = true;
+        }
         gs_critsectGui->Leave();
         delete gs_critsectGui;
         gs_critsectGui = NULL;
         gs_critsectGui->Leave();
         delete gs_critsectGui;
         gs_critsectGui = NULL;
@@ -1689,6 +1721,9 @@ void WXDLLIMPEXP_BASE wxMutexGuiLeaveOrEnter()
     wxASSERT_MSG( wxThread::IsMain(),
                   wxT("only main thread may call wxMutexGuiLeaveOrEnter()!") );
 
     wxASSERT_MSG( wxThread::IsMain(),
                   wxT("only main thread may call wxMutexGuiLeaveOrEnter()!") );
 
+    if( !gs_critsectWaitingForGui )
+        return;
+        
     wxCriticalSectionLocker enter(*gs_critsectWaitingForGui);
 
     if ( gs_nWaitingForGui == 0 )
     wxCriticalSectionLocker enter(*gs_critsectWaitingForGui);
 
     if ( gs_nWaitingForGui == 0 )