1 ///////////////////////////////////////////////////////////////////////////// 
   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 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) 
  14 #pragma implementation "thread.h" 
  17 // ---------------------------------------------------------------------------- 
  19 // ---------------------------------------------------------------------------- 
  21 // For compilers that support precompilation, includes "wx.h". 
  22 #include "wx/wxprec.h" 
  24 #if defined(__BORLANDC__) 
  34 #include "wx/module.h" 
  35 #include "wx/thread.h" 
  38 #if TARGET_API_MAC_OSX 
  39 #include <CoreServices/CoreServices.h> 
  41 #include <DriverServices.h> 
  42 #include <Multiprocessing.h> 
  45 #include "wx/mac/uma.h" 
  48 #include "wx/mac/macnotfy.h" 
  50 // ---------------------------------------------------------------------------- 
  52 // ---------------------------------------------------------------------------- 
  54 // the possible states of the thread ("=>" shows all possible transitions from 
  58         STATE_NEW
,              // didn't start execution yet (=> RUNNING) 
  59         STATE_RUNNING
,  // thread is running (=> PAUSED, CANCELED) 
  60         STATE_PAUSED
,   // thread is temporarily suspended (=> RUNNING) 
  61         STATE_CANCELED
, // thread should terminate a.s.a.p. (=> EXITED) 
  62         STATE_EXITED    
// thread is terminating 
  65 // ---------------------------------------------------------------------------- 
  66 // this module globals 
  67 // ---------------------------------------------------------------------------- 
  70 // the task ID of the main thread 
  71 static wxThreadIdType gs_idMainThread 
= kInvalidID
; 
  73 // this is the Per-Task Storage for the pointer to the appropriate wxThread 
  74 TaskStorageIndex gs_tlsForWXThread 
= 0 ; 
  76 // if it's false, some secondary thread is holding the GUI lock 
  77 static bool gs_bGuiOwnedByMainThread 
= true; 
  79 // critical section which controls access to all GUI functions: any secondary 
  80 // thread (i.e. except the main one) must enter this crit section before doing 
  82 static wxCriticalSection 
*gs_critsectGui 
= NULL
; 
  84 // critical section which protects gs_nWaitingForGui variable 
  85 static wxCriticalSection 
*gs_critsectWaitingForGui 
= NULL
; 
  87 // number of threads waiting for GUI in wxMutexGuiEnter() 
  88 static size_t gs_nWaitingForGui 
= 0; 
  90 // overall number of threads, needed for determining the sleep value of the main  
  92 size_t g_numberOfThreads 
= 0; 
  98 MPCriticalRegionID gs_guiCritical 
= kInvalidID
; 
 102 // ============================================================================ 
 103 // MacOS implementation of thread classes 
 104 // ============================================================================ 
 109     The implementation is very close to the phtreads implementation, the reason for 
 110     using MPServices is the fact that these are also available under OS 9. Thus allowing 
 111     for one common API for all current builds. 
 113     As soon as wxThreads are on a 64 bit address space, the TLS must be extended 
 114     to use two indices one for each 32 bit part as the MP implementation is limited 
 117     I have three implementations for mutexes : 
 118     version A based on a binary semaphore, problem - not reentrant, version B based  
 119     on a critical region, allows for reentrancy, performance implications not 
 120     yet tested, and third a plain pthreads implementation 
 122     The same for condition internal, one implementation by Aj Lavin and the other one 
 123     copied from the thrimpl.cpp which I assume has been more broadly tested, I've just 
 124     replaced the interlock increment with the appropriate PPC calls  
 127 // ---------------------------------------------------------------------------- 
 129 // ---------------------------------------------------------------------------- 
 131 wxCriticalSection::wxCriticalSection() 
 133     MPCreateCriticalRegion( (MPCriticalRegionID
*) &m_critRegion 
) ; 
 136 wxCriticalSection::~wxCriticalSection() 
 138     MPDeleteCriticalRegion( (MPCriticalRegionID
) m_critRegion 
) ; 
 141 void wxCriticalSection::Enter() 
 143     MPEnterCriticalRegion( (MPCriticalRegionID
) m_critRegion 
, kDurationForever 
) ; 
 146 void wxCriticalSection::Leave() 
 148     MPExitCriticalRegion((MPCriticalRegionID
) m_critRegion 
) ; 
 151 // ---------------------------------------------------------------------------- 
 152 // wxMutex implementation 
 153 // ---------------------------------------------------------------------------- 
 155 #if TARGET_API_MAC_OSX 
 156 #define wxUSE_MAC_SEMAPHORE_MUTEX 0 
 157 #define wxUSE_MAC_CRITICAL_REGION_MUTEX 1 
 158 #define wxUSE_MAC_PTHREADS_MUTEX 0 
 160 #define wxUSE_MAC_SEMAPHORE_MUTEX 0 
 161 #define wxUSE_MAC_CRITICAL_REGION_MUTEX 1 
 162 #define wxUSE_MAC_PTHREADS_MUTEX 0 
 165 #if wxUSE_MAC_PTHREADS_MUTEX  
 169 class wxMutexInternal
 
 172     wxMutexInternal(wxMutexType mutexType
); 
 176     wxMutexError 
TryLock(); 
 177     wxMutexError 
Unlock(); 
 179     bool IsOk() const { return m_isOk
; } 
 182     pthread_mutex_t m_mutex
; 
 185     // wxConditionInternal uses our m_mutex 
 186     friend class wxConditionInternal
; 
 189 #ifdef HAVE_PTHREAD_MUTEXATTR_T 
 190 // on some systems pthread_mutexattr_settype() is not in the headers (but it is 
 191 // in the library, otherwise we wouldn't compile this code at all) 
 192 extern "C" int pthread_mutexattr_settype(pthread_mutexattr_t 
*, int); 
 195 wxMutexInternal::wxMutexInternal(wxMutexType mutexType
) 
 200         case wxMUTEX_RECURSIVE
: 
 201             // support recursive locks like Win32, i.e. a thread can lock a 
 202             // mutex which it had itself already locked 
 204             // unfortunately initialization of recursive mutexes is non 
 205             // portable, so try several methods 
 206 #ifdef HAVE_PTHREAD_MUTEXATTR_T 
 208                 pthread_mutexattr_t attr
; 
 209                 pthread_mutexattr_init(&attr
); 
 210                 pthread_mutexattr_settype(&attr
, PTHREAD_MUTEX_RECURSIVE
); 
 212                 err 
= pthread_mutex_init(&m_mutex
, &attr
); 
 214 #elif defined(HAVE_PTHREAD_RECURSIVE_MUTEX_INITIALIZER) 
 215             // we can use this only as initializer so we have to assign it 
 216             // first to a temp var - assigning directly to m_mutex wouldn't 
 219                 pthread_mutex_t mutex 
= PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
; 
 222 #else // no recursive mutexes 
 224 #endif // HAVE_PTHREAD_MUTEXATTR_T/... 
 228             wxFAIL_MSG( _T("unknown mutex type") ); 
 231         case wxMUTEX_DEFAULT
: 
 232             err 
= pthread_mutex_init(&m_mutex
, NULL
); 
 239         wxLogApiError( wxT("pthread_mutex_init()"), err
); 
 243 wxMutexInternal::~wxMutexInternal() 
 247         int err 
= pthread_mutex_destroy(&m_mutex
); 
 250             wxLogApiError( wxT("pthread_mutex_destroy()"), err
); 
 255 wxMutexError 
wxMutexInternal::Lock() 
 257     int err 
= pthread_mutex_lock(&m_mutex
); 
 261             // only error checking mutexes return this value and so it's an 
 262             // unexpected situation -- hence use assert, not wxLogDebug 
 263             wxFAIL_MSG( _T("mutex deadlock prevented") ); 
 264             return wxMUTEX_DEAD_LOCK
; 
 267             wxLogDebug(_T("pthread_mutex_lock(): mutex not initialized.")); 
 271             return wxMUTEX_NO_ERROR
; 
 274             wxLogApiError(_T("pthread_mutex_lock()"), err
); 
 277     return wxMUTEX_MISC_ERROR
; 
 280 wxMutexError 
wxMutexInternal::TryLock() 
 282     int err 
= pthread_mutex_trylock(&m_mutex
); 
 286             // not an error: mutex is already locked, but we're prepared for 
 291             wxLogDebug(_T("pthread_mutex_trylock(): mutex not initialized.")); 
 295             return wxMUTEX_NO_ERROR
; 
 298             wxLogApiError(_T("pthread_mutex_trylock()"), err
); 
 301     return wxMUTEX_MISC_ERROR
; 
 304 wxMutexError 
wxMutexInternal::Unlock() 
 306     int err 
= pthread_mutex_unlock(&m_mutex
); 
 310             // we don't own the mutex 
 311             return wxMUTEX_UNLOCKED
; 
 314             wxLogDebug(_T("pthread_mutex_unlock(): mutex not initialized.")); 
 318             return wxMUTEX_NO_ERROR
; 
 321             wxLogApiError(_T("pthread_mutex_unlock()"), err
); 
 324     return wxMUTEX_MISC_ERROR
; 
 330 #if wxUSE_MAC_SEMAPHORE_MUTEX  
 332 class wxMutexInternal
 
 335         wxMutexInternal(wxMutexType mutexType
) ; 
 337         bool IsOk() const { return m_isOk
; } 
 339         wxMutexError 
Lock() ; 
 340         wxMutexError 
TryLock() ; 
 341         wxMutexError 
Unlock(); 
 343     MPSemaphoreID m_semaphore
; 
 347 wxMutexInternal::wxMutexInternal(wxMutexType mutexType 
) 
 350     m_semaphore 
= kInvalidID 
; 
 352     OSStatus err 
= noErr 
; 
 355         case wxMUTEX_DEFAULT 
: 
 357                 verify_noerr( MPCreateBinarySemaphore( & m_semaphore
) ); 
 358                 m_isOk 
= ( m_semaphore 
!= kInvalidID 
) ; 
 361         case wxMUTEX_RECURSIVE 
: 
 362             wxFAIL_MSG(wxT("Recursive Mutex not supported yet") ) ; 
 365             wxFAIL_MSG(wxT("Unknown mutex type") ) ; 
 370 wxMutexInternal::~wxMutexInternal() 
 372     if ( m_semaphore 
!= kInvalidID 
) 
 373             MPDeleteSemaphore( m_semaphore
); 
 377 wxMutexError 
wxMutexInternal::Lock() 
 379     wxCHECK_MSG( m_isOk 
, wxMUTEX_MISC_ERROR 
, wxT("Invalid Mutex") ) ; 
 380         OSStatus err 
= MPWaitOnSemaphore( m_semaphore
, kDurationForever
); 
 383                 wxLogSysError(wxT("Could not lock mutex")); 
 384                 return wxMUTEX_MISC_ERROR
; 
 387         return wxMUTEX_NO_ERROR
; 
 390 wxMutexError 
wxMutexInternal::TryLock() 
 392     wxCHECK_MSG( m_isOk 
, wxMUTEX_MISC_ERROR 
, wxT("Invalid Mutex") ) ; 
 393         OSStatus err 
= MPWaitOnSemaphore( m_semaphore
, kDurationImmediate
); 
 396                 if ( err 
== kMPTimeoutErr
) 
 400                 wxLogSysError(wxT("Could not try lock mutex")); 
 401                 return wxMUTEX_MISC_ERROR
;     
 404         return wxMUTEX_NO_ERROR
; 
 407 wxMutexError 
wxMutexInternal::Unlock() 
 409     wxCHECK_MSG( m_isOk 
, wxMUTEX_MISC_ERROR 
, wxT("Invalid Mutex") ) ; 
 410         OSStatus err 
= MPSignalSemaphore( m_semaphore
); 
 414                 wxLogSysError(_("Could not unlock mutex")); 
 415                 return wxMUTEX_MISC_ERROR
;         
 417         return wxMUTEX_NO_ERROR
; 
 422 #if wxUSE_MAC_CRITICAL_REGION_MUTEX 
 424 class wxMutexInternal
 
 427         wxMutexInternal(wxMutexType mutexType
) ; 
 429         bool IsOk() const { return m_isOk
; } 
 431         wxMutexError 
Lock() ; 
 432         wxMutexError 
TryLock() ; 
 433         wxMutexError 
Unlock(); 
 435     MPCriticalRegionID m_critRegion 
; 
 439 wxMutexInternal::wxMutexInternal(wxMutexType mutexType 
) 
 442     m_critRegion 
= kInvalidID 
; 
 444     verify_noerr( MPCreateCriticalRegion( & m_critRegion
) ); 
 445     m_isOk 
= ( m_critRegion 
!= kInvalidID 
) ; 
 448         wxFAIL_MSG(wxT("Error when creating mutex") ) ; 
 451 wxMutexInternal::~wxMutexInternal() 
 453     if ( m_critRegion 
!= kInvalidID 
) 
 454             MPDeleteCriticalRegion( m_critRegion
); 
 458 wxMutexError 
wxMutexInternal::Lock() 
 460     wxCHECK_MSG( m_isOk 
, wxMUTEX_MISC_ERROR 
, wxT("Invalid Mutex") ) ; 
 461         OSStatus err 
= MPEnterCriticalRegion( m_critRegion
, kDurationForever
); 
 464                 wxLogSysError(wxT("Could not lock mutex")); 
 465                 return wxMUTEX_MISC_ERROR
; 
 468         return wxMUTEX_NO_ERROR
; 
 471 wxMutexError 
wxMutexInternal::TryLock() 
 473     wxCHECK_MSG( m_isOk 
, wxMUTEX_MISC_ERROR 
, wxT("Invalid Mutex") ) ; 
 474         OSStatus err 
= MPEnterCriticalRegion( m_critRegion
, kDurationImmediate
); 
 477                 if ( err 
== kMPTimeoutErr
) 
 481                 wxLogSysError(wxT("Could not try lock mutex")); 
 482                 return wxMUTEX_MISC_ERROR
;     
 485         return wxMUTEX_NO_ERROR
; 
 488 wxMutexError 
wxMutexInternal::Unlock() 
 490     wxCHECK_MSG( m_isOk 
, wxMUTEX_MISC_ERROR 
, wxT("Invalid Mutex") ) ; 
 491         OSStatus err 
= MPExitCriticalRegion( m_critRegion
); 
 495                 wxLogSysError(_("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         ~wxSemaphoreInternal(); 
 514         bool IsOk() const { return m_isOk
; } 
 516         wxSemaError 
WaitTimeout(unsigned long milliseconds
); 
 518         wxSemaError 
Wait() { return WaitTimeout( kDurationForever
); } 
 520         wxSemaError 
TryWait()  
 522             wxSemaError err 
= WaitTimeout(kDurationImmediate
);  
 523             if ( err 
== wxSEMA_TIMEOUT 
) 
 530     MPSemaphoreID m_semaphore
; 
 534 wxSemaphoreInternal::wxSemaphoreInternal(int initialcount
, int maxcount
) 
 537     m_semaphore 
= kInvalidID 
; 
 540                 // make it practically infinite 
 543         verify_noerr( MPCreateSemaphore( maxcount
, initialcount
, & m_semaphore
) ); 
 544     m_isOk 
= ( m_semaphore 
!= kInvalidID 
) ; 
 547         wxFAIL_MSG(wxT("Error when creating semaphore") ) ; 
 550 wxSemaphoreInternal::~wxSemaphoreInternal() 
 552     if( m_semaphore 
!= kInvalidID 
) 
 553             MPDeleteSemaphore( m_semaphore
); 
 557 wxSemaError 
wxSemaphoreInternal::WaitTimeout(unsigned long milliseconds
) 
 559         OSStatus err 
= MPWaitOnSemaphore( m_semaphore
, milliseconds
); 
 562                 if ( err 
== kMPTimeoutErr
) 
 564                         return wxSEMA_TIMEOUT
; 
 566                 return wxSEMA_MISC_ERROR
; 
 568         return wxSEMA_NO_ERROR
; 
 571 wxSemaError 
wxSemaphoreInternal::Post() 
 573         OSStatus err 
= MPSignalSemaphore( m_semaphore
); 
 577                 return wxSEMA_MISC_ERROR
; 
 579         return wxSEMA_NO_ERROR
; 
 582 // ---------------------------------------------------------------------------- 
 583 // wxCondition implementation 
 584 // ---------------------------------------------------------------------------- 
 588 class wxConditionInternal
 
 592         wxConditionInternal(wxMutex
& mutex
)  
 602         ~wxConditionInternal() 
 606         bool IsOk() const { return m_mutex
.IsOk() ; } 
 610                 return WaitTimeout( kDurationForever
); 
 613         wxCondError 
WaitTimeout(unsigned long msectimeout
); 
 617                 return DoSignal( false); 
 620         wxCondError 
Broadcast() 
 622                 return DoSignal( true); 
 627                 wxCondError 
DoSignal( bool signalAll
); 
 630         wxSemaphoreInternal     m_semaphore
;  // Signals the waiting threads. 
 631         wxSemaphoreInternal       m_gate
; 
 632         wxCriticalSection m_varSection
; 
 633         size_t    m_waiters
;    // Number of threads waiting for a signal. 
 634         size_t          m_signals
;      // Number of signals to send. 
 635         size_t    m_canceled
;   // Number of canceled waiters in m_waiters. 
 639 wxCondError 
wxConditionInternal::WaitTimeout(unsigned long msectimeout
) 
 642         if ( ++ m_waiters 
== INT_MAX
) 
 644                 m_varSection
.Enter(); 
 645                 m_waiters 
-= m_canceled
; 
 646                 m_signals 
-= m_canceled
; 
 648                 m_varSection
.Leave(); 
 654         wxSemaError err 
= m_semaphore
.WaitTimeout( msectimeout
); 
 655         wxASSERT( err 
== wxSEMA_NO_ERROR 
|| err 
== wxSEMA_TIMEOUT
); 
 657         m_varSection
.Enter(); 
 658         if ( err 
!= wxSEMA_NO_ERROR
) 
 660                 if ( m_signals 
> m_canceled
) 
 662                         // A signal is being sent after we timed out. 
 664                         if ( m_waiters 
== m_signals
) 
 666                                 // There are no excess waiters to catch the signal, so 
 667                                 // we must throw it away. 
 669                                 wxSemaError err2 
= m_semaphore
.Wait(); 
 670                                 if ( err2 
!= wxSEMA_NO_ERROR
) 
 672                                         wxLogSysError(_("Error while waiting on semaphore")); 
 674                                 wxASSERT( err2 
== wxSEMA_NO_ERROR
); 
 676                                 if ( -- m_signals 
== m_canceled
) 
 678                                         // This was the last signal. open the gate. 
 679                                         wxASSERT( m_waiters 
== m_canceled
); 
 685                                 // There are excess waiters to catch the signal, leave 
 692                         // No signals is being sent. 
 693                         // The gate may be open or closed, so we can't touch m_waiters. 
 700                 // We caught a signal. 
 701                 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
); 
 710         m_varSection
.Leave(); 
 716                 return err 
== wxSEMA_TIMEOUT 
? wxCOND_TIMEOUT 
: wxCOND_MISC_ERROR
; 
 719         return wxCOND_NO_ERROR
; 
 723 wxCondError 
wxConditionInternal::DoSignal( bool signalAll
) 
 726         m_varSection
.Enter(); 
 728         wxASSERT( m_signals 
== m_canceled
); 
 730         if ( m_waiters 
== m_canceled
) 
 732                 m_varSection
.Leave(); 
 734                 return wxCOND_NO_ERROR
; 
 739                 m_waiters 
-= m_canceled
; 
 744         m_signals 
= signalAll 
? m_waiters 
: 1; 
 745         size_t n 
= m_signals
; 
 747         m_varSection
.Leave(); 
 749         // Let the waiters inherit the gate lock. 
 753                 wxSemaError err 
= m_semaphore
.Post(); 
 754                 wxASSERT( err 
== wxSEMA_NO_ERROR
); 
 757         return wxCOND_NO_ERROR
; 
 761 class wxConditionInternal
 
 764     wxConditionInternal(wxMutex
& mutex
); 
 766     bool IsOk() const { return m_mutex
.IsOk() && m_semaphore
.IsOk(); } 
 769     wxCondError 
WaitTimeout(unsigned long milliseconds
); 
 771     wxCondError 
Signal(); 
 772     wxCondError 
Broadcast(); 
 775     // the number of threads currently waiting for this condition 
 778     // the critical section protecting m_numWaiters 
 779     wxCriticalSection m_csWaiters
; 
 782     wxSemaphore m_semaphore
; 
 784     DECLARE_NO_COPY_CLASS(wxConditionInternal
) 
 787 wxConditionInternal::wxConditionInternal(wxMutex
& mutex
) 
 790     // another thread can't access it until we return from ctor, so no need to 
 791     // protect access to m_numWaiters here 
 795 wxCondError 
wxConditionInternal::Wait() 
 797     // increment the number of waiters 
 798     IncrementAtomic(&m_numWaiters
); 
 802     // a potential race condition can occur here 
 804     // after a thread increments nwaiters, and unlocks the mutex and before the 
 805     // semaphore.Wait() is called, if another thread can cause a signal to be 
 808     // this race condition is handled by using a semaphore and incrementing the 
 809     // semaphore only if 'nwaiters' is greater that zero since the semaphore, 
 810     // can 'remember' signals the race condition will not occur 
 812     // wait ( if necessary ) and decrement semaphore 
 813     wxSemaError err 
= m_semaphore
.Wait(); 
 816     return err 
== wxSEMA_NO_ERROR 
? wxCOND_NO_ERROR 
: wxCOND_MISC_ERROR
; 
 819 wxCondError 
wxConditionInternal::WaitTimeout(unsigned long milliseconds
) 
 821     IncrementAtomic(&m_numWaiters
); 
 825     // a race condition can occur at this point in the code 
 827     // please see the comments in Wait(), for details 
 829     wxSemaError err 
= m_semaphore
.WaitTimeout(milliseconds
); 
 831     if ( err 
== wxSEMA_BUSY 
) 
 833         // another potential race condition exists here it is caused when a 
 834         // 'waiting' thread timesout, and returns from WaitForSingleObject, but 
 835         // has not yet decremented 'nwaiters'. 
 837         // at this point if another thread calls signal() then the semaphore 
 838         // will be incremented, but the waiting thread will miss it. 
 840         // to handle this particular case, the waiting thread calls 
 841         // WaitForSingleObject again with a timeout of 0, after locking 
 842         // 'nwaiters_mutex'. this call does not block because of the zero 
 843         // timeout, but will allow the waiting thread to catch the missed 
 845         wxCriticalSectionLocker 
lock(m_csWaiters
); 
 847         err 
= m_semaphore
.WaitTimeout(0); 
 849         if ( err 
!= wxSEMA_NO_ERROR 
) 
 857     return err 
== wxSEMA_NO_ERROR 
? wxCOND_NO_ERROR 
: wxCOND_MISC_ERROR
; 
 860 wxCondError 
wxConditionInternal::Signal() 
 862     wxCriticalSectionLocker 
lock(m_csWaiters
); 
 864     if ( m_numWaiters 
> 0 ) 
 866         // increment the semaphore by 1 
 867         if ( m_semaphore
.Post() != wxSEMA_NO_ERROR 
) 
 868             return wxCOND_MISC_ERROR
; 
 873     return wxCOND_NO_ERROR
; 
 876 wxCondError 
wxConditionInternal::Broadcast() 
 878     wxCriticalSectionLocker 
lock(m_csWaiters
); 
 880     while ( m_numWaiters 
> 0 ) 
 882         if ( m_semaphore
.Post() != wxSEMA_NO_ERROR 
) 
 883             return wxCOND_MISC_ERROR
; 
 888     return wxCOND_NO_ERROR
; 
 892 // ---------------------------------------------------------------------------- 
 893 // wxCriticalSection implementation 
 894 // ---------------------------------------------------------------------------- 
 896 // XXX currently implemented as mutex in headers. Change to critical section. 
 898 // ---------------------------------------------------------------------------- 
 899 // wxThread implementation 
 900 // ---------------------------------------------------------------------------- 
 902 // wxThreadInternal class 
 903 // ---------------------- 
 905 class wxThreadInternal
 
 912                 m_prio 
= WXTHREAD_DEFAULT_PRIORITY
; 
 913                 m_notifyQueueId 
= kInvalidID
; 
 915         m_cancelled 
= FALSE 
; 
 917         // set to TRUE only when the thread starts waiting on m_semSuspend 
 920         // defaults for joinable threads 
 921         m_shouldBeJoined 
= TRUE
; 
 922         m_isDetached 
= FALSE
; 
 926                 if ( m_notifyQueueId
) 
 928                         MPDeleteQueue( m_notifyQueueId
); 
 929                         m_notifyQueueId 
= kInvalidID 
; 
 934         static OSStatus    
MacThreadStart(void* arg
); 
 936     // create a new (suspended) thread (for the given thread object) 
 937     bool Create(wxThread 
*thread
, unsigned int stackSize
); 
 942     // unblock the thread allowing it to run 
 943     void SignalRun() { m_semRun
.Post(); } 
 944     // ask the thread to terminate 
 946     // go to sleep until Resume() is called 
 953     int GetPriority() const { return m_prio
; } 
 954     void SetPriority(int prio
) ; 
 956     wxThreadState 
GetState() const { return m_state
; } 
 957     void SetState(wxThreadState state
) { m_state 
= state
; } 
 959         // Get the ID of this thread's underlying MP Services task. 
 960         MPTaskID  
GetId() const { return m_tid
; } 
 962     void SetCancelFlag() { m_cancelled 
= TRUE
; } 
 963     bool WasCancelled() const { return m_cancelled
; } 
 965     void SetExitCode(wxThread::ExitCode exitcode
) { m_exitcode 
= exitcode
; } 
 966     wxThread::ExitCode 
GetExitCode() const { return m_exitcode
; } 
 969     void SetReallyPaused(bool paused
) { m_isPaused 
= paused
; } 
 970     bool IsReallyPaused() const { return m_isPaused
; } 
 972     // tell the thread that it is a detached one 
 975         wxCriticalSectionLocker 
lock(m_csJoinFlag
); 
 977         m_shouldBeJoined 
= FALSE
; 
 982     // the thread we're associated with 
 985         MPTaskID        m_tid
;              // thread id 
 986         MPQueueID           m_notifyQueueId
;    // its notification queue 
 988     wxThreadState m_state
;              // see wxThreadState enum 
 989     int           m_prio
;               // in wxWidgets units: from 0 to 100 
 991     // this flag is set when the thread should terminate 
 994     // this flag is set when the thread is blocking on m_semSuspend 
 997     // the thread exit code - only used for joinable (!detached) threads and 
 998     // is only valid after the thread termination 
 999     wxThread::ExitCode m_exitcode
; 
1001     // many threads may call Wait(), but only one of them should call 
1002     // pthread_join(), so we have to keep track of this 
1003     wxCriticalSection m_csJoinFlag
; 
1004     bool m_shouldBeJoined
; 
1007     // this semaphore is posted by Run() and the threads Entry() is not 
1008     // called before it is done 
1009     wxSemaphore m_semRun
; 
1011     // this one is signaled when the thread should resume after having been 
1013     wxSemaphore m_semSuspend
; 
1016 OSStatus 
wxThreadInternal::MacThreadStart(void *parameter
) 
1018         wxThread
* thread 
= (wxThread
*) parameter 
; 
1019     wxThreadInternal 
*pthread 
= thread
->m_internal
; 
1021     // add to TLS so that This() will work 
1022         verify_noerr( MPSetTaskStorageValue( gs_tlsForWXThread 
, (long) thread 
) ) ; 
1024     // have to declare this before pthread_cleanup_push() which defines a 
1028     // wait for the semaphore to be posted from Run() 
1029     pthread
->m_semRun
.Wait(); 
1031     // test whether we should run the run at all - may be it was deleted 
1032     // before it started to Run()? 
1034         wxCriticalSectionLocker 
lock(thread
->m_critsect
); 
1036         dontRunAtAll 
= pthread
->GetState() == STATE_NEW 
&& 
1037                        pthread
->WasCancelled(); 
1040     if ( !dontRunAtAll 
) 
1042         pthread
->m_exitcode 
= thread
->Entry(); 
1045             wxCriticalSectionLocker 
lock(thread
->m_critsect
); 
1046             pthread
->SetState(STATE_EXITED
); 
1052         if ( pthread
->m_isDetached 
) 
1059         // on mac for the running code the correct thread termination is to 
1062         // terminate the thread 
1063         thread
->Exit(pthread
->m_exitcode
); 
1065         return (OSStatus
) NULL 
; // pthread->m_exitcode; 
1069 bool wxThreadInternal::Create(wxThread 
*thread
, unsigned int stackSize
) 
1071     wxASSERT_MSG( m_state 
== STATE_NEW 
&& !m_tid
, 
1072                     _T("Create()ing thread twice?") ); 
1074         OSStatus err 
= noErr 
; 
1077         if ( m_notifyQueueId 
== kInvalidID 
) 
1079                 OSStatus err 
= MPCreateQueue( & m_notifyQueueId
); 
1082                         wxLogSysError(_("Cant create the thread event queue")); 
1087         m_state 
= STATE_NEW
; 
1089         err 
= MPCreateTask( MacThreadStart
, 
1100                 wxLogSysError(_("Can't create thread"));                 
1104         if ( m_prio 
!= WXTHREAD_DEFAULT_PRIORITY 
) 
1106                 SetPriority(m_prio
); 
1112 void wxThreadInternal::SetPriority( int priority
) 
1118                 // Mac priorities range from 1 to 10,000, with a default of 100. 
1119                 // wxWidgets priorities range from 0 to 100 with a default of 50. 
1120                 // We can map wxWidgets to Mac priorities easily by assuming 
1121                 // the former uses a logarithmic scale. 
1122                 const unsigned int macPriority 
= ( int)( exp( priority 
/ 25.0 * log( 10.0)) + 0.5); 
1124                 MPSetTaskWeight( m_tid
, macPriority
); 
1128 wxThreadError 
wxThreadInternal::Run() 
1130     wxCHECK_MSG( GetState() == STATE_NEW
, wxTHREAD_RUNNING
, 
1131                  wxT("thread may only be started once after Create()") ); 
1133     SetState(STATE_RUNNING
); 
1135     // wake up threads waiting for our start 
1138     return wxTHREAD_NO_ERROR
; 
1141 void wxThreadInternal::Wait() 
1143    wxCHECK_RET( !m_isDetached
, _T("can't wait for a detached thread") ); 
1145     // if the thread we're waiting for is waiting for the GUI mutex, we will 
1146     // deadlock so make sure we release it temporarily 
1147     if ( wxThread::IsMain() ) 
1149         // give the thread we're waiting for chance to do the GUI call 
1150         // it might be in, we don't do this conditionally as the to be waited on  
1151         // thread might have to acquire the mutex later but before terminating 
1152         if ( wxGuiOwnedByMainThread() ) 
1159         wxCriticalSectionLocker 
lock(m_csJoinFlag
); 
1161         if ( m_shouldBeJoined 
) 
1167             OSStatus err 
= MPWaitOnQueue ( m_notifyQueueId
,  
1174                 wxLogSysError( _( "Cannot wait for thread termination.")); 
1178             // actually param1 would be the address of m_exitcode 
1179             // but we don't need this here 
1182             m_shouldBeJoined 
= FALSE
; 
1187 void wxThreadInternal::Pause() 
1189     // the state is set from the thread which pauses us first, this function 
1190     // is called later so the state should have been already set 
1191     wxCHECK_RET( m_state 
== STATE_PAUSED
, 
1192                  wxT("thread must first be paused with wxThread::Pause().") ); 
1194     // wait until the semaphore is Post()ed from Resume() 
1195     m_semSuspend
.Wait(); 
1198 void wxThreadInternal::Resume() 
1200     wxCHECK_RET( m_state 
== STATE_PAUSED
, 
1201                  wxT("can't resume thread which is not suspended.") ); 
1203     // the thread might be not actually paused yet - if there were no call to 
1204     // TestDestroy() since the last call to Pause() for example 
1205     if ( IsReallyPaused() ) 
1208         m_semSuspend
.Post(); 
1211         SetReallyPaused(FALSE
); 
1214     SetState(STATE_RUNNING
); 
1220 wxThread 
*wxThread::This() 
1222     wxThread
* thr 
= (wxThread
*) MPGetTaskStorageValue( gs_tlsForWXThread 
) ; 
1226 bool wxThread::IsMain() 
1228         return GetCurrentId() == gs_idMainThread 
|| gs_idMainThread 
== kInvalidID 
; 
1235 void wxThread::Yield() 
1237 #if TARGET_API_MAC_OSX 
1238         CFRunLoopRunInMode( kCFRunLoopDefaultMode 
, 0 , true ) ; 
1244 void wxThread::Sleep(unsigned long milliseconds
) 
1246         AbsoluteTime wakeup 
= AddDurationToAbsolute( milliseconds
, UpTime()); 
1247         MPDelayUntil( & wakeup
); 
1251 int wxThread::GetCPUCount() 
1253         return MPProcessors(); 
1256 unsigned long wxThread::GetCurrentId() 
1258         return (unsigned long)MPCurrentTaskID(); 
1262 bool wxThread::SetConcurrency(size_t level
) 
1264     // Cannot be set in MacOS. 
1269 wxThread::wxThread(wxThreadKind kind
) 
1271         g_numberOfThreads
++; 
1272         m_internal 
= new wxThreadInternal(); 
1274         m_isDetached 
= (kind 
== wxTHREAD_DETACHED
); 
1277 wxThread::~wxThread() 
1279     wxASSERT_MSG( g_numberOfThreads
>0 , wxT("More threads deleted than created.") ) ; 
1280     g_numberOfThreads
--; 
1285     // check that the thread either exited or couldn't be created 
1286     if ( m_internal
->GetState() != STATE_EXITED 
&& 
1287          m_internal
->GetState() != STATE_NEW 
) 
1289         wxLogDebug(_T("The thread %ld is being destroyed although it is still running! The application may crash."), GetId()); 
1293 #endif // __WXDEBUG__ 
1295     wxDELETE( m_internal 
) ; 
1299 wxThreadError 
wxThread::Create(unsigned int stackSize
) 
1301         wxCriticalSectionLocker 
lock(m_critsect
); 
1305         m_internal
->Detach() ; 
1307         if ( m_internal
->Create(this, stackSize
) == false ) 
1309         m_internal
->SetState(STATE_EXITED
); 
1310         return wxTHREAD_NO_RESOURCE
; 
1313         return wxTHREAD_NO_ERROR
; 
1316 wxThreadError 
wxThread::Run() 
1318     wxCriticalSectionLocker 
lock(m_critsect
); 
1320     wxCHECK_MSG( m_internal
->GetId(), wxTHREAD_MISC_ERROR
, 
1321                  wxT("must call wxThread::Create() first") ); 
1323     return m_internal
->Run(); 
1326 // ----------------------------------------------------------------------------- 
1328 // ----------------------------------------------------------------------------- 
1330 wxThreadError 
wxThread::Pause() 
1332     wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
, 
1333                  _T("a thread can't pause itself") ); 
1335     wxCriticalSectionLocker 
lock(m_critsect
); 
1337     if ( m_internal
->GetState() != STATE_RUNNING 
) 
1339         wxLogDebug(wxT("Can't pause thread which is not running.")); 
1341         return wxTHREAD_NOT_RUNNING
; 
1344     // just set a flag, the thread will be really paused only during the next 
1345     // call to TestDestroy() 
1346     m_internal
->SetState(STATE_PAUSED
); 
1348     return wxTHREAD_NO_ERROR
; 
1351 wxThreadError 
wxThread::Resume() 
1353     wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
, 
1354                  _T("a thread can't resume itself") ); 
1356     wxCriticalSectionLocker 
lock(m_critsect
); 
1358     wxThreadState state 
= m_internal
->GetState(); 
1363             m_internal
->Resume(); 
1364             return wxTHREAD_NO_ERROR
; 
1366             return wxTHREAD_NO_ERROR
; 
1369             wxLogDebug(_T("Attempt to resume a thread which is not paused.")); 
1371             return wxTHREAD_MISC_ERROR
; 
1375 // ----------------------------------------------------------------------------- 
1377 // ----------------------------------------------------------------------------- 
1379 wxThread::ExitCode 
wxThread::Wait() 
1381     wxCHECK_MSG( This() != this, (ExitCode
)-1, 
1382                  _T("a thread can't wait for itself") ); 
1384     wxCHECK_MSG( !m_isDetached
, (ExitCode
)-1, 
1385                  _T("can't wait for detached thread") ); 
1389     return m_internal
->GetExitCode(); 
1392 wxThreadError 
wxThread::Delete(ExitCode 
*rc
) 
1394     wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
, 
1395                  _T("a thread can't delete itself") ); 
1397     bool isDetached 
= m_isDetached
; 
1400     wxThreadState state 
= m_internal
->GetState(); 
1402     // ask the thread to stop 
1403     m_internal
->SetCancelFlag(); 
1410             // we need to wake up the thread so that PthreadStart() will 
1411             // terminate - right now it's blocking on run semaphore in 
1413             m_internal
->SignalRun(); 
1422             // resume the thread first 
1423             m_internal
->Resume(); 
1430                 // wait until the thread stops 
1435                     // return the exit code of the thread 
1436                     *rc 
= m_internal
->GetExitCode(); 
1441     return wxTHREAD_NO_ERROR
; 
1444 wxThreadError 
wxThread::Kill() 
1446     wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
, 
1447                  _T("a thread can't kill itself") ); 
1449     switch ( m_internal
->GetState() ) 
1453             return wxTHREAD_NOT_RUNNING
; 
1456             // resume the thread first 
1462             OSStatus err 
= MPTerminateTask( m_internal
->GetId() , -1 ) ; 
1465                 wxLogError(_("Failed to terminate a thread.")); 
1467                 return wxTHREAD_MISC_ERROR
; 
1476                 // this should be retrieved by Wait actually 
1477                 m_internal
->SetExitCode((void*)-1); 
1480             return wxTHREAD_NO_ERROR
; 
1484 void wxThread::Exit(ExitCode status
) 
1486     wxASSERT_MSG( This() == this, 
1487                   _T("wxThread::Exit() can only be called in the context of the same thread") ); 
1489     // don't enter m_critsect before calling OnExit() because the user code 
1490     // might deadlock if, for example, it signals a condition in OnExit() (a 
1491     // common case) while the main thread calls any of functions entering 
1492     // m_critsect on us (almost all of them do) 
1495     MPTaskID threadid 
= m_internal
->GetId() ; 
1503         // update the status of the joinable thread 
1504         wxCriticalSectionLocker 
lock(m_critsect
); 
1505         m_internal
->SetState(STATE_EXITED
); 
1507     MPTerminateTask( threadid 
, (long) status
) ;     
1510 // also test whether we were paused 
1511 bool wxThread::TestDestroy() 
1513     wxASSERT_MSG( This() == this, 
1514                   _T("wxThread::TestDestroy() can only be called in the context of the same thread") ); 
1518     if ( m_internal
->GetState() == STATE_PAUSED 
) 
1520         m_internal
->SetReallyPaused(TRUE
); 
1522         // leave the crit section or the other threads will stop too if they 
1523         // try to call any of (seemingly harmless) IsXXX() functions while we 
1527         m_internal
->Pause(); 
1531         // thread wasn't requested to pause, nothing to do 
1535     return m_internal
->WasCancelled(); 
1538 // ----------------------------------------------------------------------------- 
1540 // ----------------------------------------------------------------------------- 
1542 void wxThread::SetPriority(unsigned int prio
) 
1544     wxCHECK_RET( ((int)WXTHREAD_MIN_PRIORITY 
<= (int)prio
) && 
1545                  ((int)prio 
<= (int)WXTHREAD_MAX_PRIORITY
), 
1546                  wxT("invalid thread priority") ); 
1548     wxCriticalSectionLocker 
lock(m_critsect
); 
1550     switch ( m_internal
->GetState() ) 
1555             // thread not yet started, priority will be set when it is 
1556             m_internal
->SetPriority(prio
); 
1561             wxFAIL_MSG(wxT("impossible to set thread priority in this state")); 
1565 unsigned int wxThread::GetPriority() const 
1567     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); // const_cast 
1569     return m_internal
->GetPriority(); 
1572 unsigned long wxThread::GetId() const 
1574     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); // const_cast 
1576     return (unsigned long)m_internal
->GetId(); 
1579 // ----------------------------------------------------------------------------- 
1581 // ----------------------------------------------------------------------------- 
1583 bool wxThread::IsRunning() const 
1585     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); 
1587     return m_internal
->GetState() == STATE_RUNNING
; 
1590 bool wxThread::IsAlive() const 
1592     wxCriticalSectionLocker 
lock((wxCriticalSection
&)m_critsect
); 
1594     switch ( m_internal
->GetState() ) 
1605 bool wxThread::IsPaused() const 
1607     wxCriticalSectionLocker 
lock((wxCriticalSection
&)m_critsect
); 
1609     return (m_internal
->GetState() == STATE_PAUSED
); 
1612 // ---------------------------------------------------------------------------- 
1613 // Automatic initialization for thread module 
1614 // ---------------------------------------------------------------------------- 
1616 class wxThreadModule 
: public wxModule
 
1619         virtual bool OnInit(); 
1620         virtual void OnExit(); 
1623                 DECLARE_DYNAMIC_CLASS(wxThreadModule
) 
1626 IMPLEMENT_DYNAMIC_CLASS(wxThreadModule
, wxModule
) 
1628 bool wxThreadModule::OnInit() 
1630         bool hasThreadManager 
= false ; 
1631         hasThreadManager 
= MPLibraryIsLoaded(); 
1633         if ( !hasThreadManager 
) 
1635                 wxLogError( _("MP Thread Support is not available on this System" ) ) ; 
1639         verify_noerr( MPAllocateTaskStorageIndex( &gs_tlsForWXThread 
) ) ; 
1640         // main thread's This() is NULL 
1641         verify_noerr( MPSetTaskStorageValue( gs_tlsForWXThread 
, 0 ) ) ; 
1643         gs_idMainThread 
= wxThread::GetCurrentId() ; 
1645     gs_critsectWaitingForGui 
= new wxCriticalSection(); 
1647     gs_critsectGui 
= new wxCriticalSection(); 
1648     gs_critsectGui
->Enter(); 
1653 void wxThreadModule::OnExit() 
1655     if ( gs_critsectGui 
) 
1657         if ( !wxGuiOwnedByMainThread() ) 
1659             gs_critsectGui
->Enter(); 
1660             gs_bGuiOwnedByMainThread 
= true; 
1662         gs_critsectGui
->Leave(); 
1663         delete gs_critsectGui
; 
1664         gs_critsectGui 
= NULL
; 
1667     delete gs_critsectWaitingForGui
; 
1668     gs_critsectWaitingForGui 
= NULL
; 
1671 // ---------------------------------------------------------------------------- 
1672 // GUI Serialization copied from MSW implementation 
1673 // ---------------------------------------------------------------------------- 
1675 void WXDLLIMPEXP_BASE 
wxMutexGuiEnter() 
1677     // this would dead lock everything... 
1678     wxASSERT_MSG( !wxThread::IsMain(), 
1679                   wxT("main thread doesn't want to block in wxMutexGuiEnter()!") ); 
1681     // the order in which we enter the critical sections here is crucial!! 
1683     // set the flag telling to the main thread that we want to do some GUI 
1685         wxCriticalSectionLocker 
enter(*gs_critsectWaitingForGui
); 
1687         gs_nWaitingForGui
++; 
1690     wxWakeUpMainThread(); 
1692     // now we may block here because the main thread will soon let us in 
1693     // (during the next iteration of OnIdle()) 
1694     gs_critsectGui
->Enter(); 
1697 void WXDLLIMPEXP_BASE 
wxMutexGuiLeave() 
1699     wxCriticalSectionLocker 
enter(*gs_critsectWaitingForGui
); 
1701     if ( wxThread::IsMain() ) 
1703         gs_bGuiOwnedByMainThread 
= false; 
1707         // decrement the number of threads waiting for GUI access now 
1708         wxASSERT_MSG( gs_nWaitingForGui 
> 0, 
1709                       wxT("calling wxMutexGuiLeave() without entering it first?") ); 
1711         gs_nWaitingForGui
--; 
1713         wxWakeUpMainThread(); 
1716     gs_critsectGui
->Leave(); 
1719 void WXDLLIMPEXP_BASE 
wxMutexGuiLeaveOrEnter() 
1721     wxASSERT_MSG( wxThread::IsMain(), 
1722                   wxT("only main thread may call wxMutexGuiLeaveOrEnter()!") ); 
1724     wxCriticalSectionLocker 
enter(*gs_critsectWaitingForGui
); 
1726     if ( gs_nWaitingForGui 
== 0 ) 
1728         // no threads are waiting for GUI - so we may acquire the lock without 
1729         // any danger (but only if we don't already have it) 
1730         if ( !wxGuiOwnedByMainThread() ) 
1732             gs_critsectGui
->Enter(); 
1734             gs_bGuiOwnedByMainThread 
= true; 
1736         //else: already have it, nothing to do 
1740         // some threads are waiting, release the GUI lock if we have it 
1741         if ( wxGuiOwnedByMainThread() ) 
1745         //else: some other worker thread is doing GUI 
1749 bool WXDLLIMPEXP_BASE 
wxGuiOwnedByMainThread() 
1751     return gs_bGuiOwnedByMainThread
; 
1754 // wake up the main thread 
1755 void WXDLLEXPORT 
wxWakeUpMainThread() 
1760 // ---------------------------------------------------------------------------- 
1761 // include common implementation code 
1762 // ---------------------------------------------------------------------------- 
1764 #include "wx/thrimpl.cpp" 
1766 #endif // wxUSE_THREADS