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(); 
 421     bool IsOk() const { return m_isOk
; } 
 423     wxMutexError 
Lock() { return Lock(kDurationForever
); } 
 424     wxMutexError 
Lock(unsigned long ms
); 
 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(unsigned long ms
) 
 456     wxCHECK_MSG( m_isOk 
, wxMUTEX_MISC_ERROR 
, wxT("Invalid Mutex") ); 
 458     OSStatus err 
= MPEnterCriticalRegion( m_critRegion
, ms 
); 
 465             wxASSERT_MSG( ms 
!= kDurationForever
, wxT("unexpected timeout") ); 
 466             return wxMUTEX_TIMEOUT
; 
 469             wxLogSysError(wxT("Could not lock mutex")); 
 470             return wxMUTEX_MISC_ERROR
; 
 473     return wxMUTEX_NO_ERROR
; 
 476 wxMutexError 
wxMutexInternal::TryLock() 
 478     wxCHECK_MSG( m_isOk 
, wxMUTEX_MISC_ERROR 
, wxT("Invalid Mutex") ) ; 
 480     OSStatus err 
= MPEnterCriticalRegion( m_critRegion
, kDurationImmediate
); 
 483         if ( err 
== kMPTimeoutErr
) 
 486         wxLogSysError( wxT("Could not try lock mutex") ); 
 487         return wxMUTEX_MISC_ERROR
; 
 490     return wxMUTEX_NO_ERROR
; 
 493 wxMutexError 
wxMutexInternal::Unlock() 
 495     wxCHECK_MSG( m_isOk 
, wxMUTEX_MISC_ERROR 
, wxT("Invalid Mutex") ) ; 
 497     OSStatus err 
= MPExitCriticalRegion( m_critRegion 
); 
 502         wxLogSysError( wxT("Could not unlock mutex") ); 
 504         return wxMUTEX_MISC_ERROR
; 
 507     return wxMUTEX_NO_ERROR
; 
 512 // -------------------------------------------------------------------------- 
 514 // -------------------------------------------------------------------------- 
 516 class wxSemaphoreInternal
 
 519     wxSemaphoreInternal( int initialcount
, int maxcount 
); 
 520     virtual ~wxSemaphoreInternal(); 
 526     wxSemaError 
WaitTimeout( unsigned long milliseconds 
); 
 529     { return WaitTimeout( kDurationForever
); } 
 531     wxSemaError 
TryWait() 
 533         wxSemaError err 
= WaitTimeout( kDurationImmediate 
); 
 534         if (err 
== wxSEMA_TIMEOUT
) 
 541     MPSemaphoreID m_semaphore
; 
 545 wxSemaphoreInternal::wxSemaphoreInternal( int initialcount
, int maxcount
) 
 548     m_semaphore 
= kInvalidID
; 
 550         // make it practically infinite 
 553     verify_noerr( MPCreateSemaphore( maxcount
, initialcount
, &m_semaphore 
) ); 
 554     m_isOk 
= ( m_semaphore 
!= kInvalidID 
); 
 558         wxFAIL_MSG( wxT("Error when creating semaphore") ); 
 562 wxSemaphoreInternal::~wxSemaphoreInternal() 
 564     if (m_semaphore 
!= kInvalidID
) 
 565         MPDeleteSemaphore( m_semaphore 
); 
 570 wxSemaError 
wxSemaphoreInternal::WaitTimeout( unsigned long milliseconds 
) 
 572     OSStatus err 
= MPWaitOnSemaphore( m_semaphore
, milliseconds 
); 
 575         if (err 
== kMPTimeoutErr
) 
 576             return wxSEMA_TIMEOUT
; 
 578         return wxSEMA_MISC_ERROR
; 
 581     return wxSEMA_NO_ERROR
; 
 584 wxSemaError 
wxSemaphoreInternal::Post() 
 586     OSStatus err 
= MPSignalSemaphore( m_semaphore 
); 
 589         return wxSEMA_MISC_ERROR
; 
 591     return wxSEMA_NO_ERROR
; 
 594 // ---------------------------------------------------------------------------- 
 595 // wxCondition implementation 
 596 // ---------------------------------------------------------------------------- 
 600 class wxConditionInternal
 
 603     wxConditionInternal( wxMutex
& mutex 
) 
 614     virtual ~wxConditionInternal() {} 
 617     { return m_mutex
.IsOk(); } 
 620     { return WaitTimeout( kDurationForever 
); } 
 622     wxCondError 
WaitTimeout( unsigned long msectimeout 
); 
 625     { return DoSignal( false); } 
 627     wxCondError 
Broadcast() 
 628     { return DoSignal( true ); } 
 631     wxCondError 
DoSignal( bool signalAll 
); 
 634     wxSemaphoreInternal m_semaphore
;  // Signals the waiting threads. 
 635     wxSemaphoreInternal m_gate
; 
 636     wxCriticalSection m_varSection
; 
 637     size_t m_waiters
; // Number of threads waiting for a signal. 
 638     size_t m_signals
; // Number of signals to send. 
 639     size_t m_canceled
; // Number of canceled waiters in m_waiters. 
 642 wxCondError 
wxConditionInternal::WaitTimeout( unsigned long msectimeout 
) 
 646     if ( ++ m_waiters 
== INT_MAX 
) 
 648         m_varSection
.Enter(); 
 650         m_waiters 
-= m_canceled
; 
 651         m_signals 
-= m_canceled
; 
 654         m_varSection
.Leave(); 
 660     wxSemaError err 
= m_semaphore
.WaitTimeout( msectimeout
); 
 661     wxASSERT( err 
== wxSEMA_NO_ERROR 
|| err 
== wxSEMA_TIMEOUT
); 
 663     m_varSection
.Enter(); 
 665     if ( err 
!= wxSEMA_NO_ERROR 
) 
 667         if ( m_signals 
> m_canceled 
) 
 669             // A signal is being sent after we timed out. 
 670             if ( m_waiters 
== m_signals 
) 
 672                 // There are no excess waiters to catch the signal, so 
 673                 // we must throw it away. 
 674                 wxSemaError err2 
= m_semaphore
.Wait(); 
 675                 if ( err2 
!= wxSEMA_NO_ERROR 
) 
 677                     wxLogSysError( wx("Error while waiting on semaphore") ); 
 680                 wxASSERT( err2 
== wxSEMA_NO_ERROR
); 
 683                 if ( --m_signals 
== m_canceled 
) 
 685                     // This was the last signal. open the gate. 
 686                     wxASSERT( m_waiters 
== m_canceled 
); 
 692                 // There are excess waiters to catch the signal, leave it be. 
 698             // No signals is being sent: 
 699             // the gate may be open or closed, so we can't touch m_waiters. 
 706         // We caught a signal. 
 707         wxASSERT( m_signals 
> m_canceled 
); 
 711         if ( --m_signals 
== m_canceled
) 
 713             // This was the last signal. open the gate. 
 714             wxASSERT( m_waiters 
== m_canceled 
); 
 720     m_varSection
.Leave(); 
 724         return err 
== wxSEMA_TIMEOUT 
? wxCOND_TIMEOUT 
: wxCOND_MISC_ERROR
; 
 726     return wxCOND_NO_ERROR
; 
 730 wxCondError 
wxConditionInternal::DoSignal( bool signalAll
) 
 733     m_varSection
.Enter(); 
 735     wxASSERT( m_signals 
== m_canceled 
); 
 737     if ( m_waiters 
== m_canceled
) 
 739         m_varSection
.Leave(); 
 741         return wxCOND_NO_ERROR
; 
 746         m_waiters 
-= m_canceled
; 
 751     m_signals 
= signalAll 
? m_waiters 
: 1; 
 752     size_t n 
= m_signals
; 
 754     m_varSection
.Leave(); 
 756     // Let the waiters inherit the gate lock. 
 760         wxSemaError err 
= m_semaphore
.Post(); 
 761         wxASSERT( err 
== wxSEMA_NO_ERROR 
); 
 765     return wxCOND_NO_ERROR
; 
 769 class wxConditionInternal
 
 772     wxConditionInternal( wxMutex
& mutex 
); 
 775     { return m_mutex
.IsOk() && m_semaphore
.IsOk(); } 
 778     wxCondError 
WaitTimeout( unsigned long milliseconds 
); 
 780     wxCondError 
Signal(); 
 781     wxCondError 
Broadcast(); 
 784     // the number of threads currently waiting for this condition 
 787     // the critical section protecting m_numWaiters 
 788     wxCriticalSection m_csWaiters
; 
 791     wxSemaphore m_semaphore
; 
 793     DECLARE_NO_COPY_CLASS(wxConditionInternal
) 
 796 wxConditionInternal::wxConditionInternal( wxMutex
& mutex 
) 
 799     // another thread can't access it until we return from ctor, so no need to 
 800     // protect access to m_numWaiters here 
 804 wxCondError 
wxConditionInternal::Wait() 
 806     // increment the number of waiters 
 807     IncrementAtomic( &m_numWaiters 
); 
 811     // a potential race condition can occur here 
 813     // after a thread increments nwaiters, and unlocks the mutex and before the 
 814     // semaphore.Wait() is called, if another thread can cause a signal to be 
 817     // this race condition is handled by using a semaphore and incrementing the 
 818     // semaphore only if 'nwaiters' is greater that zero since the semaphore, 
 819     // can 'remember' signals the race condition will not occur 
 821     // wait ( if necessary ) and decrement semaphore 
 822     wxSemaError err 
= m_semaphore
.Wait(); 
 825     return err 
== wxSEMA_NO_ERROR 
? wxCOND_NO_ERROR 
: wxCOND_MISC_ERROR
; 
 828 wxCondError 
wxConditionInternal::WaitTimeout( unsigned long milliseconds 
) 
 830     IncrementAtomic( &m_numWaiters 
); 
 834     // a race condition can occur at this point in the code 
 836     // please see the comments in Wait(), for details 
 838     wxSemaError err 
= m_semaphore
.WaitTimeout(milliseconds
); 
 840     if ( err 
== wxSEMA_TIMEOUT 
) 
 842         // another potential race condition exists here it is caused when a 
 843         // 'waiting' thread timesout, and returns from WaitForSingleObject, but 
 844         // has not yet decremented 'nwaiters'. 
 846         // at this point if another thread calls signal() then the semaphore 
 847         // will be incremented, but the waiting thread will miss it. 
 849         // to handle this particular case, the waiting thread calls 
 850         // WaitForSingleObject again with a timeout of 0, after locking 
 851         // 'nwaiters_mutex'. this call does not block because of the zero 
 852         // timeout, but will allow the waiting thread to catch the missed 
 854         wxCriticalSectionLocker 
lock(m_csWaiters
); 
 856         err 
= m_semaphore
.WaitTimeout(0); 
 858         if ( err 
!= wxSEMA_NO_ERROR 
) 
 866     return err 
== wxSEMA_NO_ERROR 
? wxCOND_NO_ERROR 
: wxCOND_MISC_ERROR
; 
 869 wxCondError 
wxConditionInternal::Signal() 
 871     wxCriticalSectionLocker 
lock(m_csWaiters
); 
 873     if ( m_numWaiters 
> 0 ) 
 875         // increment the semaphore by 1 
 876         if ( m_semaphore
.Post() != wxSEMA_NO_ERROR 
) 
 877             return wxCOND_MISC_ERROR
; 
 882     return wxCOND_NO_ERROR
; 
 885 wxCondError 
wxConditionInternal::Broadcast() 
 887     wxCriticalSectionLocker 
lock(m_csWaiters
); 
 889     while ( m_numWaiters 
> 0 ) 
 891         if ( m_semaphore
.Post() != wxSEMA_NO_ERROR 
) 
 892             return wxCOND_MISC_ERROR
; 
 897     return wxCOND_NO_ERROR
; 
 901 // ---------------------------------------------------------------------------- 
 902 // wxCriticalSection implementation 
 903 // ---------------------------------------------------------------------------- 
 905 // XXX currently implemented as mutex in headers. Change to critical section. 
 907 // ---------------------------------------------------------------------------- 
 908 // wxThread implementation 
 909 // ---------------------------------------------------------------------------- 
 911 // wxThreadInternal class 
 912 // ---------------------- 
 914 class wxThreadInternal
 
 921         m_prio 
= WXTHREAD_DEFAULT_PRIORITY
; 
 922         m_notifyQueueId 
= kInvalidID
; 
 924         m_cancelled 
= false ; 
 926         // set to true only when the thread starts waiting on m_semSuspend 
 929         // defaults for joinable threads 
 930         m_shouldBeJoined 
= true; 
 931         m_isDetached 
= false; 
 934     virtual ~wxThreadInternal() 
 936         if ( m_notifyQueueId
) 
 938             MPDeleteQueue( m_notifyQueueId 
); 
 939             m_notifyQueueId 
= kInvalidID 
; 
 944     static OSStatus 
MacThreadStart(void* arg
); 
 946     // create a new (suspended) thread (for the given thread object) 
 947     bool Create(wxThread 
*thread
, unsigned int stackSize
); 
 954     // unblock the thread allowing it to run 
 955     void SignalRun() { m_semRun
.Post(); } 
 957     // ask the thread to terminate 
 960     // go to sleep until Resume() is called 
 968     int GetPriority() const 
 970     void SetPriority(int prio
); 
 973     wxThreadState 
GetState() const 
 975     void SetState(wxThreadState state
) 
 978     // Get the ID of this thread's underlying MP Services task. 
 979     MPTaskID  
GetId() const 
 983     { m_cancelled 
= true; } 
 985     bool WasCancelled() const 
 986     { return m_cancelled
; } 
 989     void SetExitCode(wxThread::ExitCode exitcode
) 
 990     { m_exitcode 
= exitcode
; } 
 991     wxThread::ExitCode 
GetExitCode() const 
 992     { return m_exitcode
; } 
 995     void SetReallyPaused(bool paused
) 
 996     { m_isPaused 
= paused
; } 
 997     bool IsReallyPaused() const 
 998     { return m_isPaused
; } 
1000     // tell the thread that it is a detached one 
1003         wxCriticalSectionLocker 
lock(m_csJoinFlag
); 
1005         m_shouldBeJoined 
= false; 
1006         m_isDetached 
= true; 
1010     // the thread we're associated with 
1011     wxThread 
*      m_thread
; 
1013     MPTaskID        m_tid
;                // thread id 
1014     MPQueueID        m_notifyQueueId
;    // its notification queue 
1016     wxThreadState m_state
;              // see wxThreadState enum 
1017     int           m_prio
;               // in wxWidgets units: from 0 to 100 
1019     // this flag is set when the thread should terminate 
1022     // this flag is set when the thread is blocking on m_semSuspend 
1025     // the thread exit code - only used for joinable (!detached) threads and 
1026     // is only valid after the thread termination 
1027     wxThread::ExitCode m_exitcode
; 
1029     // many threads may call Wait(), but only one of them should call 
1030     // pthread_join(), so we have to keep track of this 
1031     wxCriticalSection m_csJoinFlag
; 
1032     bool m_shouldBeJoined
; 
1035     // this semaphore is posted by Run() and the threads Entry() is not 
1036     // called before it is done 
1037     wxSemaphore m_semRun
; 
1039     // this one is signaled when the thread should resume after having been 
1041     wxSemaphore m_semSuspend
; 
1044 OSStatus 
wxThreadInternal::MacThreadStart(void *parameter
) 
1046     wxThread
* thread 
= (wxThread
*) parameter 
; 
1047     wxThreadInternal 
*pthread 
= thread
->m_internal
; 
1049     // add to TLS so that This() will work 
1050     verify_noerr( MPSetTaskStorageValue( gs_tlsForWXThread 
, (TaskStorageValue
) thread 
) ) ; 
1052     // have to declare this before pthread_cleanup_push() which defines a 
1056     // wait for the semaphore to be posted from Run() 
1057     pthread
->m_semRun
.Wait(); 
1059     // test whether we should run the run at all - may be it was deleted 
1060     // before it started to Run()? 
1062         wxCriticalSectionLocker 
lock(thread
->m_critsect
); 
1064         dontRunAtAll 
= pthread
->GetState() == STATE_NEW 
&& 
1065                        pthread
->WasCancelled(); 
1068     if ( !dontRunAtAll 
) 
1070         pthread
->m_exitcode 
= thread
->Entry(); 
1073             wxCriticalSectionLocker 
lock(thread
->m_critsect
); 
1074             pthread
->SetState( STATE_EXITED 
); 
1080         if ( pthread
->m_isDetached 
) 
1087         // on Mac for the running code, 
1088         // the correct thread termination is to return 
1090         // terminate the thread 
1091         thread
->Exit( pthread
->m_exitcode 
); 
1093         return (OSStatus
) NULL
; // pthread->m_exitcode; 
1097 bool wxThreadInternal::Create( wxThread 
*thread
, unsigned int stackSize 
) 
1099     wxASSERT_MSG( m_state 
== STATE_NEW 
&& !m_tid
, 
1100                     wxT("Create()ing thread twice?") ); 
1102     OSStatus err 
= noErr
; 
1105     if ( m_notifyQueueId 
== kInvalidID 
) 
1107         OSStatus err 
= MPCreateQueue( &m_notifyQueueId 
); 
1110             wxLogSysError( wxT("Cant create the thread event queue") ); 
1116     m_state 
= STATE_NEW
; 
1119         MacThreadStart
, (void*)m_thread
, stackSize
, 
1120         m_notifyQueueId
, &m_exitcode
, 0, 0, &m_tid 
); 
1124         wxLogSysError( wxT("Can't create thread") ); 
1129     if ( m_prio 
!= WXTHREAD_DEFAULT_PRIORITY 
) 
1130         SetPriority( m_prio 
); 
1135 void wxThreadInternal::SetPriority( int priority 
) 
1141         // Mac priorities range from 1 to 10,000, with a default of 100. 
1142         // wxWidgets priorities range from 0 to 100 with a default of 50. 
1143         // We can map wxWidgets to Mac priorities easily by assuming 
1144         // the former uses a logarithmic scale. 
1145         const unsigned int macPriority 
= (int)( exp( priority 
/ 25.0 * log( 10.0)) + 0.5); 
1147         MPSetTaskWeight( m_tid
, macPriority 
); 
1151 wxThreadError 
wxThreadInternal::Run() 
1153     wxCHECK_MSG( GetState() == STATE_NEW
, wxTHREAD_RUNNING
, 
1154                  wxT("thread may only be started once after Create()") ); 
1156     SetState( STATE_RUNNING 
); 
1158     // wake up threads waiting for our start 
1161     return wxTHREAD_NO_ERROR
; 
1164 void wxThreadInternal::Wait() 
1166    wxCHECK_RET( !m_isDetached
, wxT("can't wait for a detached thread") ); 
1168     // if the thread we're waiting for is waiting for the GUI mutex, we will 
1169     // deadlock so make sure we release it temporarily 
1170     if ( wxThread::IsMain() ) 
1172         // give the thread we're waiting for chance to do the GUI call 
1173         // it might be in, we don't do this conditionally as the to be waited on 
1174         // thread might have to acquire the mutex later but before terminating 
1175         if ( wxGuiOwnedByMainThread() ) 
1180         wxCriticalSectionLocker 
lock(m_csJoinFlag
); 
1182         if ( m_shouldBeJoined 
) 
1184             void *param1
, *param2
, *rc
; 
1186             OSStatus err 
= MPWaitOnQueue( 
1194                 wxLogSysError( wxT( "Cannot wait for thread termination.")); 
1198             // actually param1 would be the address of m_exitcode 
1199             // but we don't need this here 
1202             m_shouldBeJoined 
= false; 
1207 void wxThreadInternal::Pause() 
1209     // the state is set from the thread which pauses us first, this function 
1210     // is called later so the state should have been already set 
1211     wxCHECK_RET( m_state 
== STATE_PAUSED
, 
1212                  wxT("thread must first be paused with wxThread::Pause().") ); 
1214     // wait until the semaphore is Post()ed from Resume() 
1215     m_semSuspend
.Wait(); 
1218 void wxThreadInternal::Resume() 
1220     wxCHECK_RET( m_state 
== STATE_PAUSED
, 
1221                  wxT("can't resume thread which is not suspended.") ); 
1223     // the thread might be not actually paused yet - if there were no call to 
1224     // TestDestroy() since the last call to Pause() for example 
1225     if ( IsReallyPaused() ) 
1228         m_semSuspend
.Post(); 
1231         SetReallyPaused( false ); 
1234     SetState( STATE_RUNNING 
); 
1240 wxThread 
*wxThread::This() 
1242     wxThread
* thr 
= (wxThread
*) MPGetTaskStorageValue( gs_tlsForWXThread 
) ; 
1247 bool wxThread::IsMain() 
1249     return GetCurrentId() == gs_idMainThread 
|| gs_idMainThread 
== kInvalidID 
; 
1256 void wxThread::Yield() 
1258 #if TARGET_API_MAC_OSX 
1259     CFRunLoopRunInMode( kCFRunLoopDefaultMode 
, 0 , true ) ; 
1265 void wxThread::Sleep( unsigned long milliseconds 
) 
1267     AbsoluteTime wakeup 
= AddDurationToAbsolute( milliseconds
, UpTime() ); 
1268     MPDelayUntil( &wakeup 
); 
1271 int wxThread::GetCPUCount() 
1273     return MPProcessors(); 
1276 unsigned long wxThread::GetCurrentId() 
1278     return (unsigned long)MPCurrentTaskID(); 
1281 bool wxThread::SetConcurrency( size_t level 
) 
1283     // Cannot be set in MacOS. 
1287 wxThread::wxThread( wxThreadKind kind 
) 
1289     g_numberOfThreads
++; 
1290     m_internal 
= new wxThreadInternal(); 
1292     m_isDetached 
= (kind 
== wxTHREAD_DETACHED
); 
1295 wxThread::~wxThread() 
1297     wxASSERT_MSG( g_numberOfThreads
>0 , wxT("More threads deleted than created.") ) ; 
1299     g_numberOfThreads
--; 
1304     // check that the thread either exited or couldn't be created 
1305     if ( m_internal
->GetState() != STATE_EXITED 
&& 
1306          m_internal
->GetState() != STATE_NEW 
) 
1309             wxT("The thread %ld is being destroyed although it is still running! The application may crash."), 
1316     wxDELETE( m_internal 
) ; 
1319 wxThreadError 
wxThread::Create( unsigned int stackSize 
) 
1321     wxCriticalSectionLocker 
lock(m_critsect
); 
1324         m_internal
->Detach() ; 
1326     if ( !m_internal
->Create(this, stackSize
) ) 
1328         m_internal
->SetState( STATE_EXITED 
); 
1330         return wxTHREAD_NO_RESOURCE
; 
1333     return wxTHREAD_NO_ERROR
; 
1336 wxThreadError 
wxThread::Run() 
1338     wxCriticalSectionLocker 
lock(m_critsect
); 
1340     wxCHECK_MSG( m_internal
->GetId(), wxTHREAD_MISC_ERROR
, 
1341                  wxT("must call wxThread::Create() first") ); 
1343     return m_internal
->Run(); 
1346 // ----------------------------------------------------------------------------- 
1348 // ----------------------------------------------------------------------------- 
1350 wxThreadError 
wxThread::Pause() 
1352     wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
, 
1353                  _T("a thread can't pause itself") ); 
1355     wxCriticalSectionLocker 
lock(m_critsect
); 
1357     if ( m_internal
->GetState() != STATE_RUNNING 
) 
1359         wxLogDebug( wxT("Can't pause thread which is not running.") ); 
1361         return wxTHREAD_NOT_RUNNING
; 
1364     // just set a flag, the thread will be really paused only during the next 
1365     // call to TestDestroy() 
1366     m_internal
->SetState( STATE_PAUSED 
); 
1368     return wxTHREAD_NO_ERROR
; 
1371 wxThreadError 
wxThread::Resume() 
1373     wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
, 
1374                  wxT("a thread can't resume itself") ); 
1376     wxCriticalSectionLocker 
lock(m_critsect
); 
1378     wxThreadState state 
= m_internal
->GetState(); 
1383             m_internal
->Resume(); 
1384             return wxTHREAD_NO_ERROR
; 
1387             return wxTHREAD_NO_ERROR
; 
1390             wxLogDebug( wxT("Attempt to resume a thread which is not paused.") ); 
1392             return wxTHREAD_MISC_ERROR
; 
1396 // ----------------------------------------------------------------------------- 
1398 // ----------------------------------------------------------------------------- 
1400 wxThread::ExitCode 
wxThread::Wait() 
1402     wxCHECK_MSG( This() != this, (ExitCode
)-1, 
1403                  wxT("a thread can't wait for itself") ); 
1405     wxCHECK_MSG( !m_isDetached
, (ExitCode
)-1, 
1406                  wxT("can't wait for detached thread") ); 
1410     return m_internal
->GetExitCode(); 
1413 wxThreadError 
wxThread::Delete(ExitCode 
*rc
) 
1415     wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
, 
1416                  wxT("a thread can't delete itself") ); 
1418     bool isDetached 
= m_isDetached
; 
1421     wxThreadState state 
= m_internal
->GetState(); 
1423     // ask the thread to stop 
1424     m_internal
->SetCancelFlag(); 
1431             // we need to wake up the thread so that PthreadStart() will 
1432             // terminate - right now it's blocking on run semaphore in 
1434             m_internal
->SignalRun(); 
1443             // resume the thread first 
1444             m_internal
->Resume(); 
1451                 // wait until the thread stops 
1456                     // return the exit code of the thread 
1457                     *rc 
= m_internal
->GetExitCode(); 
1462     return wxTHREAD_NO_ERROR
; 
1465 wxThreadError 
wxThread::Kill() 
1467     wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
, 
1468                  wxT("a thread can't kill itself") ); 
1470     switch ( m_internal
->GetState() ) 
1474             return wxTHREAD_NOT_RUNNING
; 
1477             // resume the thread first 
1483             OSStatus err 
= MPTerminateTask( m_internal
->GetId() , -1 ) ; 
1486                 wxLogError( wxT("Failed to terminate a thread.") ); 
1488                 return wxTHREAD_MISC_ERROR
; 
1497                 // this should be retrieved by Wait actually 
1498                 m_internal
->SetExitCode( (void*)-1 ); 
1501             return wxTHREAD_NO_ERROR
; 
1505 void wxThread::Exit( ExitCode status 
) 
1507     wxASSERT_MSG( This() == this, 
1508                   wxT("wxThread::Exit() can only be called in the context of the same thread") ); 
1510     // don't enter m_critsect before calling OnExit() because the user code 
1511     // might deadlock if, for example, it signals a condition in OnExit() (a 
1512     // common case) while the main thread calls any of functions entering 
1513     // m_critsect on us (almost all of them do) 
1516     MPTaskID threadid 
= m_internal
->GetId(); 
1524         // update the status of the joinable thread 
1525         wxCriticalSectionLocker 
lock( m_critsect 
); 
1526         m_internal
->SetState( STATE_EXITED 
); 
1529     MPTerminateTask( threadid
, (long)status 
); 
1532 // also test whether we were paused 
1533 bool wxThread::TestDestroy() 
1535     wxASSERT_MSG( This() == this, 
1536                   wxT("wxThread::TestDestroy() can only be called in the context of the same thread") ); 
1540     if ( m_internal
->GetState() == STATE_PAUSED 
) 
1542         m_internal
->SetReallyPaused( true ); 
1544         // leave the crit section or the other threads will stop too if they attempt 
1545         // to call any of (seemingly harmless) IsXXX() functions while we sleep 
1548         m_internal
->Pause(); 
1552         // thread wasn't requested to pause, nothing to do 
1556     return m_internal
->WasCancelled(); 
1559 // ----------------------------------------------------------------------------- 
1561 // ----------------------------------------------------------------------------- 
1563 void wxThread::SetPriority(unsigned int prio
) 
1565     wxCHECK_RET( ((int)WXTHREAD_MIN_PRIORITY 
<= (int)prio
) && 
1566                  ((int)prio 
<= (int)WXTHREAD_MAX_PRIORITY
), 
1567                  wxT("invalid thread priority") ); 
1569     wxCriticalSectionLocker 
lock(m_critsect
); 
1571     switch ( m_internal
->GetState() ) 
1576             // thread not yet started, priority will be set when it is 
1577             m_internal
->SetPriority( prio 
); 
1582             wxFAIL_MSG( wxT("impossible to set thread priority in this state") ); 
1586 unsigned int wxThread::GetPriority() const 
1588     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); // const_cast 
1590     return m_internal
->GetPriority(); 
1593 unsigned long wxThread::GetId() const 
1595     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); // const_cast 
1597     return (unsigned long)m_internal
->GetId(); 
1600 // ----------------------------------------------------------------------------- 
1602 // ----------------------------------------------------------------------------- 
1604 bool wxThread::IsRunning() const 
1606     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); 
1608     return m_internal
->GetState() == STATE_RUNNING
; 
1611 bool wxThread::IsAlive() const 
1613     wxCriticalSectionLocker 
lock((wxCriticalSection
&)m_critsect
); 
1615     switch ( m_internal
->GetState() ) 
1626 bool wxThread::IsPaused() const 
1628     wxCriticalSectionLocker 
lock((wxCriticalSection
&)m_critsect
); 
1630     return (m_internal
->GetState() == STATE_PAUSED
); 
1633 // ---------------------------------------------------------------------------- 
1634 // Automatic initialization for thread module 
1635 // ---------------------------------------------------------------------------- 
1637 class wxThreadModule 
: public wxModule
 
1640     virtual bool OnInit(); 
1641     virtual void OnExit(); 
1644     DECLARE_DYNAMIC_CLASS(wxThreadModule
) 
1647 IMPLEMENT_DYNAMIC_CLASS(wxThreadModule
, wxModule
) 
1649 bool wxThreadModule::OnInit() 
1651     bool hasThreadManager 
=  
1653         true ; // TODO VERIFY IN NEXT BUILD 
1655         MPLibraryIsLoaded(); 
1658     if ( !hasThreadManager 
) 
1660         wxLogError( wxT("MP thread support is not available on this system" ) ) ; 
1665     // main thread's This() is NULL 
1666     verify_noerr( MPAllocateTaskStorageIndex( &gs_tlsForWXThread 
) ) ; 
1667     verify_noerr( MPSetTaskStorageValue( gs_tlsForWXThread
, 0 ) ) ; 
1669     gs_idMainThread 
= wxThread::GetCurrentId(); 
1670     gs_critsectWaitingForGui 
= new wxCriticalSection(); 
1672     gs_critsectGui 
= new wxCriticalSection(); 
1673     gs_critsectGui
->Enter(); 
1678 void wxThreadModule::OnExit() 
1680     if ( gs_critsectGui 
) 
1682         if ( !wxGuiOwnedByMainThread() ) 
1684             gs_critsectGui
->Enter(); 
1685             gs_bGuiOwnedByMainThread 
= true; 
1688         gs_critsectGui
->Leave(); 
1689         delete gs_critsectGui
; 
1690         gs_critsectGui 
= NULL
; 
1693     delete gs_critsectWaitingForGui
; 
1694     gs_critsectWaitingForGui 
= NULL
; 
1697 // ---------------------------------------------------------------------------- 
1698 // GUI Serialization copied from MSW implementation 
1699 // ---------------------------------------------------------------------------- 
1701 void WXDLLIMPEXP_BASE 
wxMutexGuiEnter() 
1703     // this would dead lock everything... 
1704     wxASSERT_MSG( !wxThread::IsMain(), 
1705                   wxT("main thread doesn't want to block in wxMutexGuiEnter()!") ); 
1707     // the order in which we enter the critical sections here is crucial!! 
1709     // set the flag telling to the main thread that we want to do some GUI 
1711         wxCriticalSectionLocker 
enter(*gs_critsectWaitingForGui
); 
1713         gs_nWaitingForGui
++; 
1716     wxWakeUpMainThread(); 
1718     // now we may block here because the main thread will soon let us in 
1719     // (during the next iteration of OnIdle()) 
1720     gs_critsectGui
->Enter(); 
1723 void WXDLLIMPEXP_BASE 
wxMutexGuiLeave() 
1725     wxCriticalSectionLocker 
enter(*gs_critsectWaitingForGui
); 
1727     if ( wxThread::IsMain() ) 
1729         gs_bGuiOwnedByMainThread 
= false; 
1733         // decrement the number of threads waiting for GUI access now 
1734         wxASSERT_MSG( gs_nWaitingForGui 
> 0, 
1735                       wxT("calling wxMutexGuiLeave() without entering it first?") ); 
1737         gs_nWaitingForGui
--; 
1739         wxWakeUpMainThread(); 
1742     gs_critsectGui
->Leave(); 
1745 void WXDLLIMPEXP_BASE 
wxMutexGuiLeaveOrEnter() 
1747     wxASSERT_MSG( wxThread::IsMain(), 
1748                   wxT("only main thread may call wxMutexGuiLeaveOrEnter()!") ); 
1750     if ( !gs_critsectWaitingForGui 
) 
1753     wxCriticalSectionLocker 
enter(*gs_critsectWaitingForGui
); 
1755     if ( gs_nWaitingForGui 
== 0 ) 
1757         // no threads are waiting for GUI - so we may acquire the lock without 
1758         // any danger (but only if we don't already have it) 
1759         if ( !wxGuiOwnedByMainThread() ) 
1761             gs_critsectGui
->Enter(); 
1763             gs_bGuiOwnedByMainThread 
= true; 
1765         //else: already have it, nothing to do 
1769         // some threads are waiting, release the GUI lock if we have it 
1770         if ( wxGuiOwnedByMainThread() ) 
1772         //else: some other worker thread is doing GUI 
1776 bool WXDLLIMPEXP_BASE 
wxGuiOwnedByMainThread() 
1778     return gs_bGuiOwnedByMainThread
; 
1781 // wake up the main thread 
1782 void WXDLLEXPORT 
wxWakeUpMainThread() 
1787 // ---------------------------------------------------------------------------- 
1788 // include common implementation code 
1789 // ---------------------------------------------------------------------------- 
1791 #include "wx/thrimpl.cpp" 
1793 #endif // wxUSE_THREADS