1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/mac/carbon/thread.cpp 
   3 // Purpose:     wxThread Implementation 
   4 // Author:      Original from Wolfram Gloger/Guilhem Lavaux/Vadim Zeitlin 
   5 // Modified by: Aj Lavin, Stefan Csomor 
   8 // Copyright:   (c) Wolfram Gloger (1996, 1997); Guilhem Lavaux (1998), 
   9 //                  Vadim Zeitlin (1999), Stefan Csomor (2000) 
  10 // Licence:     wxWindows licence 
  11 ///////////////////////////////////////////////////////////////////////////// 
  13 #include "wx/wxprec.h" 
  15 #if defined(__BORLANDC__) 
  21     #include "wx/module.h" 
  26 #include "wx/thread.h" 
  30     #include <CoreServices/CoreServices.h> 
  32     #include <DriverServices.h> 
  33     #include <Multiprocessing.h> 
  36 #include "wx/mac/uma.h" 
  39 #include "wx/mac/macnotfy.h" 
  42 // the possible states of the thread: 
  43 // ("=>" shows all possible transitions from this state) 
  46     STATE_NEW
, // didn't start execution yet (=> RUNNING) 
  47     STATE_RUNNING
, // thread is running (=> PAUSED, CANCELED) 
  48     STATE_PAUSED
, // thread is temporarily suspended (=> RUNNING) 
  49     STATE_CANCELED
, // thread should terminate a.s.a.p. (=> EXITED) 
  50     STATE_EXITED 
// thread is terminating 
  53 // ---------------------------------------------------------------------------- 
  55 // ---------------------------------------------------------------------------- 
  57 // the task ID of the main thread 
  58 static wxThreadIdType gs_idMainThread 
= kInvalidID
; 
  60 // this is the Per-Task Storage for the pointer to the appropriate wxThread 
  61 TaskStorageIndex gs_tlsForWXThread 
= 0; 
  63 // if it's false, some secondary thread is holding the GUI lock 
  64 static bool gs_bGuiOwnedByMainThread 
= true; 
  66 // critical section which controls access to all GUI functions: any secondary 
  67 // thread (i.e. except the main one) must enter this crit section before doing 
  69 static wxCriticalSection 
*gs_critsectGui 
= NULL
; 
  71 // critical section which protects gs_nWaitingForGui variable 
  72 static wxCriticalSection 
*gs_critsectWaitingForGui 
= NULL
; 
  74 // number of threads waiting for GUI in wxMutexGuiEnter() 
  75 static size_t gs_nWaitingForGui 
= 0; 
  77 // overall number of threads, needed for determining 
  78 // the sleep value of the main event loop 
  79 size_t g_numberOfThreads 
= 0; 
  83 MPCriticalRegionID gs_guiCritical 
= kInvalidID
; 
  86 // ============================================================================ 
  87 // MacOS implementation of thread classes 
  88 // ============================================================================ 
  93     The implementation is very close to the phtreads implementation, the reason for 
  94     using MPServices is the fact that these are also available under OS 9. Thus allowing 
  95     for one common API for all current builds. 
  97     As soon as wxThreads are on a 64 bit address space, the TLS must be extended 
  98     to use two indices one for each 32 bit part as the MP implementation is limited 
 101     I have three implementations for mutexes : 
 102     version A based on a binary semaphore, problem - not reentrant, version B based 
 103     on a critical region, allows for reentrancy, performance implications not 
 104     yet tested, and third a plain pthreads implementation 
 106     The same for condition internal, one implementation by Aj Lavin and the other one 
 107     copied from the thrimpl.cpp which I assume has been more broadly tested, I've just 
 108     replaced the interlock increment with the appropriate PPC calls 
 111 // ---------------------------------------------------------------------------- 
 113 // ---------------------------------------------------------------------------- 
 115 wxCriticalSection::wxCriticalSection() 
 117     MPCreateCriticalRegion( (MPCriticalRegionID
*) &m_critRegion 
); 
 120 wxCriticalSection::~wxCriticalSection() 
 122     MPDeleteCriticalRegion( (MPCriticalRegionID
) m_critRegion 
); 
 125 void wxCriticalSection::Enter() 
 127     MPEnterCriticalRegion( (MPCriticalRegionID
) m_critRegion
, kDurationForever 
); 
 130 void wxCriticalSection::Leave() 
 132     MPExitCriticalRegion( (MPCriticalRegionID
) m_critRegion 
); 
 135 // ---------------------------------------------------------------------------- 
 136 // wxMutex implementation 
 137 // ---------------------------------------------------------------------------- 
 139 #if TARGET_API_MAC_OSX 
 140 #define wxUSE_MAC_SEMAPHORE_MUTEX 0 
 141 #define wxUSE_MAC_CRITICAL_REGION_MUTEX 1 
 142 #define wxUSE_MAC_PTHREADS_MUTEX 0 
 144 #define wxUSE_MAC_SEMAPHORE_MUTEX 0 
 145 #define wxUSE_MAC_CRITICAL_REGION_MUTEX 1 
 146 #define wxUSE_MAC_PTHREADS_MUTEX 0 
 149 #if wxUSE_MAC_PTHREADS_MUTEX 
 154 class wxMutexInternal
 
 157     wxMutexInternal( wxMutexType mutexType 
); 
 161     wxMutexError 
TryLock(); 
 162     wxMutexError 
Unlock(); 
 168     pthread_mutex_t m_mutex
; 
 171     // wxConditionInternal uses our m_mutex 
 172     friend class wxConditionInternal
; 
 175 #ifdef HAVE_PTHREAD_MUTEXATTR_T 
 176 // on some systems pthread_mutexattr_settype() is not in the headers (but it is 
 177 // in the library, otherwise we wouldn't compile this code at all) 
 178 extern "C" int pthread_mutexattr_settype( pthread_mutexattr_t 
*, int ); 
 181 wxMutexInternal::wxMutexInternal( wxMutexType mutexType 
) 
 186         case wxMUTEX_RECURSIVE
: 
 187             // support recursive locks like Win32, i.e. a thread can lock a 
 188             // mutex which it had itself already locked 
 190             // unfortunately initialization of recursive mutexes is non 
 191             // portable, so try several methods 
 192 #ifdef HAVE_PTHREAD_MUTEXATTR_T 
 194                 pthread_mutexattr_t attr
; 
 195                 pthread_mutexattr_init( &attr 
); 
 196                 pthread_mutexattr_settype( &attr
, PTHREAD_MUTEX_RECURSIVE 
); 
 198                 err 
= pthread_mutex_init( &m_mutex
, &attr 
); 
 200 #elif defined(HAVE_PTHREAD_RECURSIVE_MUTEX_INITIALIZER) 
 201             // we can use this only as initializer so we have to assign it 
 202             // first to a temp var - assigning directly to m_mutex wouldn't 
 205                 pthread_mutex_t mutex 
= PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
; 
 208 #else // no recursive mutexes 
 210 #endif // HAVE_PTHREAD_MUTEXATTR_T/... 
 214             wxFAIL_MSG( wxT("unknown mutex type") ); 
 217         case wxMUTEX_DEFAULT
: 
 218             err 
= pthread_mutex_init( &m_mutex
, NULL 
); 
 225         wxLogApiError( wxT("pthread_mutex_init()"), err 
); 
 229 wxMutexInternal::~wxMutexInternal() 
 233         int err 
= pthread_mutex_destroy( &m_mutex 
); 
 236             wxLogApiError( wxT("pthread_mutex_destroy()"), err 
); 
 241 wxMutexError 
wxMutexInternal::Lock() 
 243     int err 
= pthread_mutex_lock( &m_mutex 
); 
 247             // only error checking mutexes return this value and so it's an 
 248             // unexpected situation -- hence use assert, not wxLogDebug 
 249             wxFAIL_MSG( wxT("mutex deadlock prevented") ); 
 250             return wxMUTEX_DEAD_LOCK
; 
 253             wxLogDebug( wxT("pthread_mutex_lock(): mutex not initialized.") ); 
 257             return wxMUTEX_NO_ERROR
; 
 260             wxLogApiError( wxT("pthread_mutex_lock()"), err 
); 
 263     return wxMUTEX_MISC_ERROR
; 
 266 wxMutexError 
wxMutexInternal::TryLock() 
 268     int err 
= pthread_mutex_trylock( &m_mutex 
); 
 272             // not an error: mutex is already locked, but we're prepared for this case 
 276             wxLogDebug( wxT("pthread_mutex_trylock(): mutex not initialized.") ); 
 280             return wxMUTEX_NO_ERROR
; 
 283             wxLogApiError( wxT("pthread_mutex_trylock()"), err 
); 
 286     return wxMUTEX_MISC_ERROR
; 
 289 wxMutexError 
wxMutexInternal::Unlock() 
 291     int err 
= pthread_mutex_unlock( &m_mutex 
); 
 295             // we don't own the mutex 
 296             return wxMUTEX_UNLOCKED
; 
 299             wxLogDebug( wxT("pthread_mutex_unlock(): mutex not initialized.") ); 
 303             return wxMUTEX_NO_ERROR
; 
 306             wxLogApiError( wxT("pthread_mutex_unlock()"), err 
); 
 309     return wxMUTEX_MISC_ERROR
; 
 314 #if wxUSE_MAC_SEMAPHORE_MUTEX 
 316 class wxMutexInternal
 
 319     wxMutexInternal( wxMutexType mutexType 
); 
 320     virtual ~wxMutexInternal(); 
 326     wxMutexError 
TryLock(); 
 327     wxMutexError 
Unlock(); 
 330     MPSemaphoreID m_semaphore
; 
 334 wxMutexInternal::wxMutexInternal(wxMutexType mutexType 
) 
 337     m_semaphore 
= kInvalidID
; 
 338     OSStatus err 
= noErr
; 
 342         case wxMUTEX_DEFAULT 
: 
 343             verify_noerr( MPCreateBinarySemaphore( &m_semaphore 
) ); 
 344             m_isOk 
= ( m_semaphore 
!= kInvalidID 
); 
 347         case wxMUTEX_RECURSIVE 
: 
 348             wxFAIL_MSG( wxT("Recursive Mutex not supported yet") ); 
 352             wxFAIL_MSG( wxT("Unknown mutex type") ); 
 357 wxMutexInternal::~wxMutexInternal() 
 359     if ( m_semaphore 
!= kInvalidID 
) 
 360         MPDeleteSemaphore( m_semaphore 
); 
 365 wxMutexError 
wxMutexInternal::Lock() 
 367     wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") ); 
 368     OSStatus err 
= MPWaitOnSemaphore( m_semaphore
, kDurationForever 
); 
 371         wxLogSysError( wxT("Could not lock mutex") ); 
 373         return wxMUTEX_MISC_ERROR
; 
 376     return wxMUTEX_NO_ERROR
; 
 379 wxMutexError 
wxMutexInternal::TryLock() 
 381     wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") ); 
 382     OSStatus err 
= MPWaitOnSemaphore( m_semaphore
, kDurationImmediate 
); 
 385         if (err 
== kMPTimeoutErr
) 
 388         wxLogSysError( wxT("Could not try lock mutex") ); 
 390         return wxMUTEX_MISC_ERROR
; 
 393     return wxMUTEX_NO_ERROR
; 
 396 wxMutexError 
wxMutexInternal::Unlock() 
 398     wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") ); 
 399     OSStatus err 
= MPSignalSemaphore( m_semaphore 
); 
 404         wxLogSysError( wxT("Could not unlock mutex") ); 
 405         return wxMUTEX_MISC_ERROR
; 
 408     return wxMUTEX_NO_ERROR
; 
 413 #if wxUSE_MAC_CRITICAL_REGION_MUTEX 
 415 class wxMutexInternal
 
 418     wxMutexInternal( wxMutexType mutexType 
); 
 419     virtual ~wxMutexInternal(); 
 424     wxMutexError 
Lock() ; 
 425     wxMutexError 
TryLock(); 
 426     wxMutexError 
Unlock(); 
 429     MPCriticalRegionID m_critRegion
; 
 433 wxMutexInternal::wxMutexInternal( wxMutexType mutexType 
) 
 436     m_critRegion 
= kInvalidID
; 
 438     verify_noerr( MPCreateCriticalRegion( &m_critRegion 
) ); 
 439     m_isOk 
= ( m_critRegion 
!= kInvalidID 
); 
 442         wxFAIL_MSG( wxT("Error when creating mutex") ); 
 446 wxMutexInternal::~wxMutexInternal() 
 448     if ( m_critRegion 
!= kInvalidID 
) 
 449         MPDeleteCriticalRegion( m_critRegion 
); 
 454 wxMutexError 
wxMutexInternal::Lock() 
 456     wxCHECK_MSG( m_isOk 
, wxMUTEX_MISC_ERROR 
, wxT("Invalid Mutex") ); 
 458     OSStatus err 
= MPEnterCriticalRegion( m_critRegion
, kDurationForever
); 
 461         wxLogSysError(wxT("Could not lock mutex")); 
 462         return wxMUTEX_MISC_ERROR
; 
 465     return wxMUTEX_NO_ERROR
; 
 468 wxMutexError 
wxMutexInternal::TryLock() 
 470     wxCHECK_MSG( m_isOk 
, wxMUTEX_MISC_ERROR 
, wxT("Invalid Mutex") ) ; 
 472     OSStatus err 
= MPEnterCriticalRegion( m_critRegion
, kDurationImmediate
); 
 475         if ( err 
== kMPTimeoutErr
) 
 478         wxLogSysError( wxT("Could not try lock mutex") ); 
 479         return wxMUTEX_MISC_ERROR
; 
 482     return wxMUTEX_NO_ERROR
; 
 485 wxMutexError 
wxMutexInternal::Unlock() 
 487     wxCHECK_MSG( m_isOk 
, wxMUTEX_MISC_ERROR 
, wxT("Invalid Mutex") ) ; 
 489     OSStatus err 
= MPExitCriticalRegion( m_critRegion 
); 
 494         wxLogSysError( wxT("Could not unlock mutex") ); 
 496         return wxMUTEX_MISC_ERROR
; 
 499     return wxMUTEX_NO_ERROR
; 
 504 // -------------------------------------------------------------------------- 
 506 // -------------------------------------------------------------------------- 
 508 class wxSemaphoreInternal
 
 511     wxSemaphoreInternal( int initialcount
, int maxcount 
); 
 512     virtual ~wxSemaphoreInternal(); 
 518     wxSemaError 
WaitTimeout( unsigned long milliseconds 
); 
 521     { return WaitTimeout( kDurationForever
); } 
 523     wxSemaError 
TryWait() 
 525         wxSemaError err 
= WaitTimeout( kDurationImmediate 
); 
 526         if (err 
== wxSEMA_TIMEOUT
) 
 533     MPSemaphoreID m_semaphore
; 
 537 wxSemaphoreInternal::wxSemaphoreInternal( int initialcount
, int maxcount
) 
 540     m_semaphore 
= kInvalidID
; 
 542         // make it practically infinite 
 545     verify_noerr( MPCreateSemaphore( maxcount
, initialcount
, &m_semaphore 
) ); 
 546     m_isOk 
= ( m_semaphore 
!= kInvalidID 
); 
 550         wxFAIL_MSG( wxT("Error when creating semaphore") ); 
 554 wxSemaphoreInternal::~wxSemaphoreInternal() 
 556     if (m_semaphore 
!= kInvalidID
) 
 557         MPDeleteSemaphore( m_semaphore 
); 
 562 wxSemaError 
wxSemaphoreInternal::WaitTimeout( unsigned long milliseconds 
) 
 564     OSStatus err 
= MPWaitOnSemaphore( m_semaphore
, milliseconds 
); 
 567         if (err 
== kMPTimeoutErr
) 
 568             return wxSEMA_TIMEOUT
; 
 570         return wxSEMA_MISC_ERROR
; 
 573     return wxSEMA_NO_ERROR
; 
 576 wxSemaError 
wxSemaphoreInternal::Post() 
 578     OSStatus err 
= MPSignalSemaphore( m_semaphore 
); 
 581         return wxSEMA_MISC_ERROR
; 
 583     return wxSEMA_NO_ERROR
; 
 586 // ---------------------------------------------------------------------------- 
 587 // wxCondition implementation 
 588 // ---------------------------------------------------------------------------- 
 592 class wxConditionInternal
 
 595     wxConditionInternal( wxMutex
& mutex 
) 
 606     virtual ~wxConditionInternal() {} 
 609     { return m_mutex
.IsOk(); } 
 612     { return WaitTimeout( kDurationForever 
); } 
 614     wxCondError 
WaitTimeout( unsigned long msectimeout 
); 
 617     { return DoSignal( false); } 
 619     wxCondError 
Broadcast() 
 620     { return DoSignal( true ); } 
 623     wxCondError 
DoSignal( bool signalAll 
); 
 626     wxSemaphoreInternal m_semaphore
;  // Signals the waiting threads. 
 627     wxSemaphoreInternal m_gate
; 
 628     wxCriticalSection m_varSection
; 
 629     size_t m_waiters
; // Number of threads waiting for a signal. 
 630     size_t m_signals
; // Number of signals to send. 
 631     size_t m_canceled
; // Number of canceled waiters in m_waiters. 
 634 wxCondError 
wxConditionInternal::WaitTimeout( unsigned long msectimeout 
) 
 638     if ( ++ m_waiters 
== INT_MAX 
) 
 640         m_varSection
.Enter(); 
 642         m_waiters 
-= m_canceled
; 
 643         m_signals 
-= m_canceled
; 
 646         m_varSection
.Leave(); 
 652     wxSemaError err 
= m_semaphore
.WaitTimeout( msectimeout
); 
 653     wxASSERT( err 
== wxSEMA_NO_ERROR 
|| err 
== wxSEMA_TIMEOUT
); 
 655     m_varSection
.Enter(); 
 657     if ( err 
!= wxSEMA_NO_ERROR 
) 
 659         if ( m_signals 
> m_canceled 
) 
 661             // A signal is being sent after we timed out. 
 662             if ( m_waiters 
== m_signals 
) 
 664                 // There are no excess waiters to catch the signal, so 
 665                 // we must throw it away. 
 666                 wxSemaError err2 
= m_semaphore
.Wait(); 
 667                 if ( err2 
!= wxSEMA_NO_ERROR 
) 
 669                     wxLogSysError( wx("Error while waiting on semaphore") ); 
 672                 wxASSERT( err2 
== wxSEMA_NO_ERROR
); 
 675                 if ( --m_signals 
== m_canceled 
) 
 677                     // This was the last signal. open the gate. 
 678                     wxASSERT( m_waiters 
== m_canceled 
); 
 684                 // There are excess waiters to catch the signal, leave it be. 
 690             // No signals is being sent: 
 691             // the gate may be open or closed, so we can't touch m_waiters. 
 698         // We caught a signal. 
 699         wxASSERT( m_signals 
> m_canceled 
); 
 703         if ( --m_signals 
== m_canceled
) 
 705             // This was the last signal. open the gate. 
 706             wxASSERT( m_waiters 
== m_canceled 
); 
 712     m_varSection
.Leave(); 
 716         return err 
== wxSEMA_TIMEOUT 
? wxCOND_TIMEOUT 
: wxCOND_MISC_ERROR
; 
 718     return wxCOND_NO_ERROR
; 
 722 wxCondError 
wxConditionInternal::DoSignal( bool signalAll
) 
 725     m_varSection
.Enter(); 
 727     wxASSERT( m_signals 
== m_canceled 
); 
 729     if ( m_waiters 
== m_canceled
) 
 731         m_varSection
.Leave(); 
 733         return wxCOND_NO_ERROR
; 
 738         m_waiters 
-= m_canceled
; 
 743     m_signals 
= signalAll 
? m_waiters 
: 1; 
 744     size_t n 
= m_signals
; 
 746     m_varSection
.Leave(); 
 748     // Let the waiters inherit the gate lock. 
 752         wxSemaError err 
= m_semaphore
.Post(); 
 753         wxASSERT( err 
== wxSEMA_NO_ERROR 
); 
 757     return wxCOND_NO_ERROR
; 
 761 class wxConditionInternal
 
 764     wxConditionInternal( wxMutex
& mutex 
); 
 767     { return m_mutex
.IsOk() && m_semaphore
.IsOk(); } 
 770     wxCondError 
WaitTimeout( unsigned long milliseconds 
); 
 772     wxCondError 
Signal(); 
 773     wxCondError 
Broadcast(); 
 776     // the number of threads currently waiting for this condition 
 779     // the critical section protecting m_numWaiters 
 780     wxCriticalSection m_csWaiters
; 
 783     wxSemaphore m_semaphore
; 
 785     DECLARE_NO_COPY_CLASS(wxConditionInternal
) 
 788 wxConditionInternal::wxConditionInternal( wxMutex
& mutex 
) 
 791     // another thread can't access it until we return from ctor, so no need to 
 792     // protect access to m_numWaiters here 
 796 wxCondError 
wxConditionInternal::Wait() 
 798     // increment the number of waiters 
 799     IncrementAtomic( &m_numWaiters 
); 
 803     // a potential race condition can occur here 
 805     // after a thread increments nwaiters, and unlocks the mutex and before the 
 806     // semaphore.Wait() is called, if another thread can cause a signal to be 
 809     // this race condition is handled by using a semaphore and incrementing the 
 810     // semaphore only if 'nwaiters' is greater that zero since the semaphore, 
 811     // can 'remember' signals the race condition will not occur 
 813     // wait ( if necessary ) and decrement semaphore 
 814     wxSemaError err 
= m_semaphore
.Wait(); 
 817     return err 
== wxSEMA_NO_ERROR 
? wxCOND_NO_ERROR 
: wxCOND_MISC_ERROR
; 
 820 wxCondError 
wxConditionInternal::WaitTimeout( unsigned long milliseconds 
) 
 822     IncrementAtomic( &m_numWaiters 
); 
 826     // a race condition can occur at this point in the code 
 828     // please see the comments in Wait(), for details 
 830     wxSemaError err 
= m_semaphore
.WaitTimeout(milliseconds
); 
 832     if ( err 
== wxSEMA_BUSY 
) 
 834         // another potential race condition exists here it is caused when a 
 835         // 'waiting' thread timesout, and returns from WaitForSingleObject, but 
 836         // has not yet decremented 'nwaiters'. 
 838         // at this point if another thread calls signal() then the semaphore 
 839         // will be incremented, but the waiting thread will miss it. 
 841         // to handle this particular case, the waiting thread calls 
 842         // WaitForSingleObject again with a timeout of 0, after locking 
 843         // 'nwaiters_mutex'. this call does not block because of the zero 
 844         // timeout, but will allow the waiting thread to catch the missed 
 846         wxCriticalSectionLocker 
lock(m_csWaiters
); 
 848         err 
= m_semaphore
.WaitTimeout(0); 
 850         if ( err 
!= wxSEMA_NO_ERROR 
) 
 858     return err 
== wxSEMA_NO_ERROR 
? wxCOND_NO_ERROR 
: wxCOND_MISC_ERROR
; 
 861 wxCondError 
wxConditionInternal::Signal() 
 863     wxCriticalSectionLocker 
lock(m_csWaiters
); 
 865     if ( m_numWaiters 
> 0 ) 
 867         // increment the semaphore by 1 
 868         if ( m_semaphore
.Post() != wxSEMA_NO_ERROR 
) 
 869             return wxCOND_MISC_ERROR
; 
 874     return wxCOND_NO_ERROR
; 
 877 wxCondError 
wxConditionInternal::Broadcast() 
 879     wxCriticalSectionLocker 
lock(m_csWaiters
); 
 881     while ( m_numWaiters 
> 0 ) 
 883         if ( m_semaphore
.Post() != wxSEMA_NO_ERROR 
) 
 884             return wxCOND_MISC_ERROR
; 
 889     return wxCOND_NO_ERROR
; 
 893 // ---------------------------------------------------------------------------- 
 894 // wxCriticalSection implementation 
 895 // ---------------------------------------------------------------------------- 
 897 // XXX currently implemented as mutex in headers. Change to critical section. 
 899 // ---------------------------------------------------------------------------- 
 900 // wxThread implementation 
 901 // ---------------------------------------------------------------------------- 
 903 // wxThreadInternal class 
 904 // ---------------------- 
 906 class wxThreadInternal
 
 913         m_prio 
= WXTHREAD_DEFAULT_PRIORITY
; 
 914         m_notifyQueueId 
= kInvalidID
; 
 916         m_cancelled 
= false ; 
 918         // set to true only when the thread starts waiting on m_semSuspend 
 921         // defaults for joinable threads 
 922         m_shouldBeJoined 
= true; 
 923         m_isDetached 
= false; 
 926     virtual ~wxThreadInternal() 
 928         if ( m_notifyQueueId
) 
 930             MPDeleteQueue( m_notifyQueueId 
); 
 931             m_notifyQueueId 
= kInvalidID 
; 
 936     static OSStatus 
MacThreadStart(void* arg
); 
 938     // create a new (suspended) thread (for the given thread object) 
 939     bool Create(wxThread 
*thread
, unsigned int stackSize
); 
 946     // unblock the thread allowing it to run 
 947     void SignalRun() { m_semRun
.Post(); } 
 949     // ask the thread to terminate 
 952     // go to sleep until Resume() is called 
 960     int GetPriority() const 
 962     void SetPriority(int prio
); 
 965     wxThreadState 
GetState() const 
 967     void SetState(wxThreadState state
) 
 970     // Get the ID of this thread's underlying MP Services task. 
 971     MPTaskID  
GetId() const 
 975     { m_cancelled 
= true; } 
 977     bool WasCancelled() const 
 978     { return m_cancelled
; } 
 981     void SetExitCode(wxThread::ExitCode exitcode
) 
 982     { m_exitcode 
= exitcode
; } 
 983     wxThread::ExitCode 
GetExitCode() const 
 984     { return m_exitcode
; } 
 987     void SetReallyPaused(bool paused
) 
 988     { m_isPaused 
= paused
; } 
 989     bool IsReallyPaused() const 
 990     { return m_isPaused
; } 
 992     // tell the thread that it is a detached one 
 995         wxCriticalSectionLocker 
lock(m_csJoinFlag
); 
 997         m_shouldBeJoined 
= false; 
1002     // the thread we're associated with 
1003     wxThread 
*      m_thread
; 
1005     MPTaskID        m_tid
;                // thread id 
1006     MPQueueID        m_notifyQueueId
;    // its notification queue 
1008     wxThreadState m_state
;              // see wxThreadState enum 
1009     int           m_prio
;               // in wxWidgets units: from 0 to 100 
1011     // this flag is set when the thread should terminate 
1014     // this flag is set when the thread is blocking on m_semSuspend 
1017     // the thread exit code - only used for joinable (!detached) threads and 
1018     // is only valid after the thread termination 
1019     wxThread::ExitCode m_exitcode
; 
1021     // many threads may call Wait(), but only one of them should call 
1022     // pthread_join(), so we have to keep track of this 
1023     wxCriticalSection m_csJoinFlag
; 
1024     bool m_shouldBeJoined
; 
1027     // this semaphore is posted by Run() and the threads Entry() is not 
1028     // called before it is done 
1029     wxSemaphore m_semRun
; 
1031     // this one is signaled when the thread should resume after having been 
1033     wxSemaphore m_semSuspend
; 
1036 OSStatus 
wxThreadInternal::MacThreadStart(void *parameter
) 
1038     wxThread
* thread 
= (wxThread
*) parameter 
; 
1039     wxThreadInternal 
*pthread 
= thread
->m_internal
; 
1041     // add to TLS so that This() will work 
1042     verify_noerr( MPSetTaskStorageValue( gs_tlsForWXThread 
, (TaskStorageValue
) thread 
) ) ; 
1044     // have to declare this before pthread_cleanup_push() which defines a 
1048     // wait for the semaphore to be posted from Run() 
1049     pthread
->m_semRun
.Wait(); 
1051     // test whether we should run the run at all - may be it was deleted 
1052     // before it started to Run()? 
1054         wxCriticalSectionLocker 
lock(thread
->m_critsect
); 
1056         dontRunAtAll 
= pthread
->GetState() == STATE_NEW 
&& 
1057                        pthread
->WasCancelled(); 
1060     if ( !dontRunAtAll 
) 
1062         pthread
->m_exitcode 
= thread
->Entry(); 
1065             wxCriticalSectionLocker 
lock(thread
->m_critsect
); 
1066             pthread
->SetState( STATE_EXITED 
); 
1072         if ( pthread
->m_isDetached 
) 
1079         // on Mac for the running code, 
1080         // the correct thread termination is to return 
1082         // terminate the thread 
1083         thread
->Exit( pthread
->m_exitcode 
); 
1085         return (OSStatus
) NULL
; // pthread->m_exitcode; 
1089 bool wxThreadInternal::Create( wxThread 
*thread
, unsigned int stackSize 
) 
1091     wxASSERT_MSG( m_state 
== STATE_NEW 
&& !m_tid
, 
1092                     wxT("Create()ing thread twice?") ); 
1094     OSStatus err 
= noErr
; 
1097     if ( m_notifyQueueId 
== kInvalidID 
) 
1099         OSStatus err 
= MPCreateQueue( &m_notifyQueueId 
); 
1102             wxLogSysError( wxT("Cant create the thread event queue") ); 
1108     m_state 
= STATE_NEW
; 
1111         MacThreadStart
, (void*)m_thread
, stackSize
, 
1112         m_notifyQueueId
, &m_exitcode
, 0, 0, &m_tid 
); 
1116         wxLogSysError( wxT("Can't create thread") ); 
1121     if ( m_prio 
!= WXTHREAD_DEFAULT_PRIORITY 
) 
1122         SetPriority( m_prio 
); 
1127 void wxThreadInternal::SetPriority( int priority 
) 
1133         // Mac priorities range from 1 to 10,000, with a default of 100. 
1134         // wxWidgets priorities range from 0 to 100 with a default of 50. 
1135         // We can map wxWidgets to Mac priorities easily by assuming 
1136         // the former uses a logarithmic scale. 
1137         const unsigned int macPriority 
= (int)( exp( priority 
/ 25.0 * log( 10.0)) + 0.5); 
1139         MPSetTaskWeight( m_tid
, macPriority 
); 
1143 wxThreadError 
wxThreadInternal::Run() 
1145     wxCHECK_MSG( GetState() == STATE_NEW
, wxTHREAD_RUNNING
, 
1146                  wxT("thread may only be started once after Create()") ); 
1148     SetState( STATE_RUNNING 
); 
1150     // wake up threads waiting for our start 
1153     return wxTHREAD_NO_ERROR
; 
1156 void wxThreadInternal::Wait() 
1158    wxCHECK_RET( !m_isDetached
, wxT("can't wait for a detached thread") ); 
1160     // if the thread we're waiting for is waiting for the GUI mutex, we will 
1161     // deadlock so make sure we release it temporarily 
1162     if ( wxThread::IsMain() ) 
1164         // give the thread we're waiting for chance to do the GUI call 
1165         // it might be in, we don't do this conditionally as the to be waited on 
1166         // thread might have to acquire the mutex later but before terminating 
1167         if ( wxGuiOwnedByMainThread() ) 
1172         wxCriticalSectionLocker 
lock(m_csJoinFlag
); 
1174         if ( m_shouldBeJoined 
) 
1176             void *param1
, *param2
, *rc
; 
1178             OSStatus err 
= MPWaitOnQueue( 
1186                 wxLogSysError( wxT( "Cannot wait for thread termination.")); 
1190             // actually param1 would be the address of m_exitcode 
1191             // but we don't need this here 
1194             m_shouldBeJoined 
= false; 
1199 void wxThreadInternal::Pause() 
1201     // the state is set from the thread which pauses us first, this function 
1202     // is called later so the state should have been already set 
1203     wxCHECK_RET( m_state 
== STATE_PAUSED
, 
1204                  wxT("thread must first be paused with wxThread::Pause().") ); 
1206     // wait until the semaphore is Post()ed from Resume() 
1207     m_semSuspend
.Wait(); 
1210 void wxThreadInternal::Resume() 
1212     wxCHECK_RET( m_state 
== STATE_PAUSED
, 
1213                  wxT("can't resume thread which is not suspended.") ); 
1215     // the thread might be not actually paused yet - if there were no call to 
1216     // TestDestroy() since the last call to Pause() for example 
1217     if ( IsReallyPaused() ) 
1220         m_semSuspend
.Post(); 
1223         SetReallyPaused( false ); 
1226     SetState( STATE_RUNNING 
); 
1232 wxThread 
*wxThread::This() 
1234     wxThread
* thr 
= (wxThread
*) MPGetTaskStorageValue( gs_tlsForWXThread 
) ; 
1239 bool wxThread::IsMain() 
1241     return GetCurrentId() == gs_idMainThread 
|| gs_idMainThread 
== kInvalidID 
; 
1248 void wxThread::Yield() 
1250 #if TARGET_API_MAC_OSX 
1251     CFRunLoopRunInMode( kCFRunLoopDefaultMode 
, 0 , true ) ; 
1257 void wxThread::Sleep( unsigned long milliseconds 
) 
1259     AbsoluteTime wakeup 
= AddDurationToAbsolute( milliseconds
, UpTime() ); 
1260     MPDelayUntil( &wakeup 
); 
1263 int wxThread::GetCPUCount() 
1265     return MPProcessors(); 
1268 unsigned long wxThread::GetCurrentId() 
1270     return (unsigned long)MPCurrentTaskID(); 
1273 bool wxThread::SetConcurrency( size_t level 
) 
1275     // Cannot be set in MacOS. 
1279 wxThread::wxThread( wxThreadKind kind 
) 
1281     g_numberOfThreads
++; 
1282     m_internal 
= new wxThreadInternal(); 
1284     m_isDetached 
= (kind 
== wxTHREAD_DETACHED
); 
1287 wxThread::~wxThread() 
1289     wxASSERT_MSG( g_numberOfThreads
>0 , wxT("More threads deleted than created.") ) ; 
1291     g_numberOfThreads
--; 
1296     // check that the thread either exited or couldn't be created 
1297     if ( m_internal
->GetState() != STATE_EXITED 
&& 
1298          m_internal
->GetState() != STATE_NEW 
) 
1301             wxT("The thread %ld is being destroyed although it is still running! The application may crash."), 
1308     wxDELETE( m_internal 
) ; 
1311 wxThreadError 
wxThread::Create( unsigned int stackSize 
) 
1313     wxCriticalSectionLocker 
lock(m_critsect
); 
1316         m_internal
->Detach() ; 
1318     if ( !m_internal
->Create(this, stackSize
) ) 
1320         m_internal
->SetState( STATE_EXITED 
); 
1322         return wxTHREAD_NO_RESOURCE
; 
1325     return wxTHREAD_NO_ERROR
; 
1328 wxThreadError 
wxThread::Run() 
1330     wxCriticalSectionLocker 
lock(m_critsect
); 
1332     wxCHECK_MSG( m_internal
->GetId(), wxTHREAD_MISC_ERROR
, 
1333                  wxT("must call wxThread::Create() first") ); 
1335     return m_internal
->Run(); 
1338 // ----------------------------------------------------------------------------- 
1340 // ----------------------------------------------------------------------------- 
1342 wxThreadError 
wxThread::Pause() 
1344     wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
, 
1345                  _T("a thread can't pause itself") ); 
1347     wxCriticalSectionLocker 
lock(m_critsect
); 
1349     if ( m_internal
->GetState() != STATE_RUNNING 
) 
1351         wxLogDebug( wxT("Can't pause thread which is not running.") ); 
1353         return wxTHREAD_NOT_RUNNING
; 
1356     // just set a flag, the thread will be really paused only during the next 
1357     // call to TestDestroy() 
1358     m_internal
->SetState( STATE_PAUSED 
); 
1360     return wxTHREAD_NO_ERROR
; 
1363 wxThreadError 
wxThread::Resume() 
1365     wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
, 
1366                  wxT("a thread can't resume itself") ); 
1368     wxCriticalSectionLocker 
lock(m_critsect
); 
1370     wxThreadState state 
= m_internal
->GetState(); 
1375             m_internal
->Resume(); 
1376             return wxTHREAD_NO_ERROR
; 
1379             return wxTHREAD_NO_ERROR
; 
1382             wxLogDebug( wxT("Attempt to resume a thread which is not paused.") ); 
1384             return wxTHREAD_MISC_ERROR
; 
1388 // ----------------------------------------------------------------------------- 
1390 // ----------------------------------------------------------------------------- 
1392 wxThread::ExitCode 
wxThread::Wait() 
1394     wxCHECK_MSG( This() != this, (ExitCode
)-1, 
1395                  wxT("a thread can't wait for itself") ); 
1397     wxCHECK_MSG( !m_isDetached
, (ExitCode
)-1, 
1398                  wxT("can't wait for detached thread") ); 
1402     return m_internal
->GetExitCode(); 
1405 wxThreadError 
wxThread::Delete(ExitCode 
*rc
) 
1407     wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
, 
1408                  wxT("a thread can't delete itself") ); 
1410     bool isDetached 
= m_isDetached
; 
1413     wxThreadState state 
= m_internal
->GetState(); 
1415     // ask the thread to stop 
1416     m_internal
->SetCancelFlag(); 
1423             // we need to wake up the thread so that PthreadStart() will 
1424             // terminate - right now it's blocking on run semaphore in 
1426             m_internal
->SignalRun(); 
1435             // resume the thread first 
1436             m_internal
->Resume(); 
1443                 // wait until the thread stops 
1448                     // return the exit code of the thread 
1449                     *rc 
= m_internal
->GetExitCode(); 
1454     return wxTHREAD_NO_ERROR
; 
1457 wxThreadError 
wxThread::Kill() 
1459     wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
, 
1460                  wxT("a thread can't kill itself") ); 
1462     switch ( m_internal
->GetState() ) 
1466             return wxTHREAD_NOT_RUNNING
; 
1469             // resume the thread first 
1475             OSStatus err 
= MPTerminateTask( m_internal
->GetId() , -1 ) ; 
1478                 wxLogError( wxT("Failed to terminate a thread.") ); 
1480                 return wxTHREAD_MISC_ERROR
; 
1489                 // this should be retrieved by Wait actually 
1490                 m_internal
->SetExitCode( (void*)-1 ); 
1493             return wxTHREAD_NO_ERROR
; 
1497 void wxThread::Exit( ExitCode status 
) 
1499     wxASSERT_MSG( This() == this, 
1500                   wxT("wxThread::Exit() can only be called in the context of the same thread") ); 
1502     // don't enter m_critsect before calling OnExit() because the user code 
1503     // might deadlock if, for example, it signals a condition in OnExit() (a 
1504     // common case) while the main thread calls any of functions entering 
1505     // m_critsect on us (almost all of them do) 
1508     MPTaskID threadid 
= m_internal
->GetId(); 
1516         // update the status of the joinable thread 
1517         wxCriticalSectionLocker 
lock( m_critsect 
); 
1518         m_internal
->SetState( STATE_EXITED 
); 
1521     MPTerminateTask( threadid
, (long)status 
); 
1524 // also test whether we were paused 
1525 bool wxThread::TestDestroy() 
1527     wxASSERT_MSG( This() == this, 
1528                   wxT("wxThread::TestDestroy() can only be called in the context of the same thread") ); 
1532     if ( m_internal
->GetState() == STATE_PAUSED 
) 
1534         m_internal
->SetReallyPaused( true ); 
1536         // leave the crit section or the other threads will stop too if they attempt 
1537         // to call any of (seemingly harmless) IsXXX() functions while we sleep 
1540         m_internal
->Pause(); 
1544         // thread wasn't requested to pause, nothing to do 
1548     return m_internal
->WasCancelled(); 
1551 // ----------------------------------------------------------------------------- 
1553 // ----------------------------------------------------------------------------- 
1555 void wxThread::SetPriority(unsigned int prio
) 
1557     wxCHECK_RET( ((int)WXTHREAD_MIN_PRIORITY 
<= (int)prio
) && 
1558                  ((int)prio 
<= (int)WXTHREAD_MAX_PRIORITY
), 
1559                  wxT("invalid thread priority") ); 
1561     wxCriticalSectionLocker 
lock(m_critsect
); 
1563     switch ( m_internal
->GetState() ) 
1568             // thread not yet started, priority will be set when it is 
1569             m_internal
->SetPriority( prio 
); 
1574             wxFAIL_MSG( wxT("impossible to set thread priority in this state") ); 
1578 unsigned int wxThread::GetPriority() const 
1580     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); // const_cast 
1582     return m_internal
->GetPriority(); 
1585 unsigned long wxThread::GetId() const 
1587     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); // const_cast 
1589     return (unsigned long)m_internal
->GetId(); 
1592 // ----------------------------------------------------------------------------- 
1594 // ----------------------------------------------------------------------------- 
1596 bool wxThread::IsRunning() const 
1598     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); 
1600     return m_internal
->GetState() == STATE_RUNNING
; 
1603 bool wxThread::IsAlive() const 
1605     wxCriticalSectionLocker 
lock((wxCriticalSection
&)m_critsect
); 
1607     switch ( m_internal
->GetState() ) 
1618 bool wxThread::IsPaused() const 
1620     wxCriticalSectionLocker 
lock((wxCriticalSection
&)m_critsect
); 
1622     return (m_internal
->GetState() == STATE_PAUSED
); 
1625 // ---------------------------------------------------------------------------- 
1626 // Automatic initialization for thread module 
1627 // ---------------------------------------------------------------------------- 
1629 class wxThreadModule 
: public wxModule
 
1632     virtual bool OnInit(); 
1633     virtual void OnExit(); 
1636     DECLARE_DYNAMIC_CLASS(wxThreadModule
) 
1639 IMPLEMENT_DYNAMIC_CLASS(wxThreadModule
, wxModule
) 
1641 bool wxThreadModule::OnInit() 
1643     bool hasThreadManager 
=  
1645         true ; // TODO VERIFY IN NEXT BUILD 
1647         MPLibraryIsLoaded(); 
1650     if ( !hasThreadManager 
) 
1652         wxLogError( wxT("MP thread support is not available on this system" ) ) ; 
1657     // main thread's This() is NULL 
1658     verify_noerr( MPAllocateTaskStorageIndex( &gs_tlsForWXThread 
) ) ; 
1659     verify_noerr( MPSetTaskStorageValue( gs_tlsForWXThread
, 0 ) ) ; 
1661     gs_idMainThread 
= wxThread::GetCurrentId(); 
1662     gs_critsectWaitingForGui 
= new wxCriticalSection(); 
1664     gs_critsectGui 
= new wxCriticalSection(); 
1665     gs_critsectGui
->Enter(); 
1670 void wxThreadModule::OnExit() 
1672     if ( gs_critsectGui 
) 
1674         if ( !wxGuiOwnedByMainThread() ) 
1676             gs_critsectGui
->Enter(); 
1677             gs_bGuiOwnedByMainThread 
= true; 
1680         gs_critsectGui
->Leave(); 
1681         delete gs_critsectGui
; 
1682         gs_critsectGui 
= NULL
; 
1685     delete gs_critsectWaitingForGui
; 
1686     gs_critsectWaitingForGui 
= NULL
; 
1689 // ---------------------------------------------------------------------------- 
1690 // GUI Serialization copied from MSW implementation 
1691 // ---------------------------------------------------------------------------- 
1693 void WXDLLIMPEXP_BASE 
wxMutexGuiEnter() 
1695     // this would dead lock everything... 
1696     wxASSERT_MSG( !wxThread::IsMain(), 
1697                   wxT("main thread doesn't want to block in wxMutexGuiEnter()!") ); 
1699     // the order in which we enter the critical sections here is crucial!! 
1701     // set the flag telling to the main thread that we want to do some GUI 
1703         wxCriticalSectionLocker 
enter(*gs_critsectWaitingForGui
); 
1705         gs_nWaitingForGui
++; 
1708     wxWakeUpMainThread(); 
1710     // now we may block here because the main thread will soon let us in 
1711     // (during the next iteration of OnIdle()) 
1712     gs_critsectGui
->Enter(); 
1715 void WXDLLIMPEXP_BASE 
wxMutexGuiLeave() 
1717     wxCriticalSectionLocker 
enter(*gs_critsectWaitingForGui
); 
1719     if ( wxThread::IsMain() ) 
1721         gs_bGuiOwnedByMainThread 
= false; 
1725         // decrement the number of threads waiting for GUI access now 
1726         wxASSERT_MSG( gs_nWaitingForGui 
> 0, 
1727                       wxT("calling wxMutexGuiLeave() without entering it first?") ); 
1729         gs_nWaitingForGui
--; 
1731         wxWakeUpMainThread(); 
1734     gs_critsectGui
->Leave(); 
1737 void WXDLLIMPEXP_BASE 
wxMutexGuiLeaveOrEnter() 
1739     wxASSERT_MSG( wxThread::IsMain(), 
1740                   wxT("only main thread may call wxMutexGuiLeaveOrEnter()!") ); 
1742     if ( !gs_critsectWaitingForGui 
) 
1745     wxCriticalSectionLocker 
enter(*gs_critsectWaitingForGui
); 
1747     if ( gs_nWaitingForGui 
== 0 ) 
1749         // no threads are waiting for GUI - so we may acquire the lock without 
1750         // any danger (but only if we don't already have it) 
1751         if ( !wxGuiOwnedByMainThread() ) 
1753             gs_critsectGui
->Enter(); 
1755             gs_bGuiOwnedByMainThread 
= true; 
1757         //else: already have it, nothing to do 
1761         // some threads are waiting, release the GUI lock if we have it 
1762         if ( wxGuiOwnedByMainThread() ) 
1764         //else: some other worker thread is doing GUI 
1768 bool WXDLLIMPEXP_BASE 
wxGuiOwnedByMainThread() 
1770     return gs_bGuiOwnedByMainThread
; 
1773 // wake up the main thread 
1774 void WXDLLEXPORT 
wxWakeUpMainThread() 
1779 // ---------------------------------------------------------------------------- 
1780 // include common implementation code 
1781 // ---------------------------------------------------------------------------- 
1783 #include "wx/thrimpl.cpp" 
1785 #endif // wxUSE_THREADS