1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/osx/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" 
  28 #if wxOSX_USE_COCOA_OR_CARBON 
  29 #include <CoreServices/CoreServices.h> 
  31 #include <Foundation/Foundation.h> 
  34 #include "wx/osx/uma.h" 
  36 // the possible states of the thread: 
  37 // ("=>" shows all possible transitions from this state) 
  40     STATE_NEW
, // didn't start execution yet (=> RUNNING) 
  41     STATE_RUNNING
, // thread is running (=> PAUSED, CANCELED) 
  42     STATE_PAUSED
, // thread is temporarily suspended (=> RUNNING) 
  43     STATE_CANCELED
, // thread should terminate a.s.a.p. (=> EXITED) 
  44     STATE_EXITED 
// thread is terminating 
  47 // ---------------------------------------------------------------------------- 
  49 // ---------------------------------------------------------------------------- 
  51 // the task ID of the main thread 
  52 wxThreadIdType 
wxThread::ms_idMainThread 
= kInvalidID
; 
  54 // this is the Per-Task Storage for the pointer to the appropriate wxThread 
  55 TaskStorageIndex gs_tlsForWXThread 
= 0; 
  57 // if it's false, some secondary thread is holding the GUI lock 
  58 static bool gs_bGuiOwnedByMainThread 
= true; 
  60 // critical section which controls access to all GUI functions: any secondary 
  61 // thread (i.e. except the main one) must enter this crit section before doing 
  63 static wxCriticalSection 
*gs_critsectGui 
= NULL
; 
  65 // critical section which protects gs_nWaitingForGui variable 
  66 static wxCriticalSection 
*gs_critsectWaitingForGui 
= NULL
; 
  68 // number of threads waiting for GUI in wxMutexGuiEnter() 
  69 static size_t gs_nWaitingForGui 
= 0; 
  71 // overall number of threads, needed for determining 
  72 // the sleep value of the main event loop 
  73 size_t g_numberOfThreads 
= 0; 
  77 MPCriticalRegionID gs_guiCritical 
= kInvalidID
; 
  80 // ============================================================================ 
  81 // MacOS implementation of thread classes 
  82 // ============================================================================ 
  87     The implementation is very close to the phtreads implementation, the reason for 
  88     using MPServices is the fact that these are also available under OS 9. Thus allowing 
  89     for one common API for all current builds. 
  91     As soon as wxThreads are on a 64 bit address space, the TLS must be extended 
  92     to use two indices one for each 32 bit part as the MP implementation is limited 
  95     I have three implementations for mutexes : 
  96     version A based on a binary semaphore, problem - not reentrant, version B based 
  97     on a critical region, allows for reentrancy, performance implications not 
  98     yet tested, and third a plain pthreads implementation 
 100     The same for condition internal, one implementation by Aj Lavin and the other one 
 101     copied from the thrimpl.cpp which I assume has been more broadly tested, I've just 
 102     replaced the interlock increment with the appropriate PPC calls 
 105 // ---------------------------------------------------------------------------- 
 107 // ---------------------------------------------------------------------------- 
 109 wxCriticalSection::wxCriticalSection( wxCriticalSectionType 
WXUNUSED(critSecType
) ) 
 111     MPCreateCriticalRegion( (MPCriticalRegionID
*) &m_critRegion 
); 
 114 wxCriticalSection::~wxCriticalSection() 
 116     MPDeleteCriticalRegion( (MPCriticalRegionID
) m_critRegion 
); 
 119 void wxCriticalSection::Enter() 
 121     MPEnterCriticalRegion( (MPCriticalRegionID
) m_critRegion
, kDurationForever 
); 
 124 bool wxCriticalSection::TryEnter() 
 126     return MPEnterCriticalRegion( (MPCriticalRegionID
) m_critRegion
, kDurationImmediate 
) == noErr
; 
 129 void wxCriticalSection::Leave() 
 131     MPExitCriticalRegion( (MPCriticalRegionID
) m_critRegion 
); 
 134 // ---------------------------------------------------------------------------- 
 135 // wxMutex implementation 
 136 // ---------------------------------------------------------------------------- 
 138 #define wxUSE_MAC_SEMAPHORE_MUTEX 0 
 139 #define wxUSE_MAC_CRITICAL_REGION_MUTEX 1 
 140 #define wxUSE_MAC_PTHREADS_MUTEX 0 
 142 #if wxUSE_MAC_CRITICAL_REGION_MUTEX 
 144 class wxMutexInternal
 
 147     wxMutexInternal( wxMutexType mutexType 
); 
 148     virtual ~wxMutexInternal(); 
 150     bool IsOk() const { return m_isOk
; } 
 152     wxMutexError 
Lock() { return Lock(kDurationForever
); } 
 153     wxMutexError 
Lock(unsigned long ms
); 
 154     wxMutexError 
TryLock(); 
 155     wxMutexError 
Unlock(); 
 158     MPCriticalRegionID m_critRegion
; 
 162 wxMutexInternal::wxMutexInternal( wxMutexType 
WXUNUSED(mutexType
) ) 
 165     m_critRegion 
= kInvalidID
; 
 167     verify_noerr( MPCreateCriticalRegion( &m_critRegion 
) ); 
 168     m_isOk 
= ( m_critRegion 
!= kInvalidID 
); 
 171         wxFAIL_MSG( wxT("Error when creating mutex") ); 
 175 wxMutexInternal::~wxMutexInternal() 
 177     if ( m_critRegion 
!= kInvalidID 
) 
 178         MPDeleteCriticalRegion( m_critRegion 
); 
 183 wxMutexError 
wxMutexInternal::Lock(unsigned long ms
) 
 185     wxCHECK_MSG( m_isOk 
, wxMUTEX_MISC_ERROR 
, wxT("Invalid Mutex") ); 
 187     OSStatus err 
= MPEnterCriticalRegion( m_critRegion
, ms 
); 
 194             wxASSERT_MSG( ms 
!= kDurationForever
, wxT("unexpected timeout") ); 
 195             return wxMUTEX_TIMEOUT
; 
 198             wxLogSysError(wxT("Could not lock mutex")); 
 199             return wxMUTEX_MISC_ERROR
; 
 202     return wxMUTEX_NO_ERROR
; 
 205 wxMutexError 
wxMutexInternal::TryLock() 
 207     wxCHECK_MSG( m_isOk 
, wxMUTEX_MISC_ERROR 
, wxT("Invalid Mutex") ) ; 
 209     OSStatus err 
= MPEnterCriticalRegion( m_critRegion
, kDurationImmediate
); 
 212         if ( err 
== kMPTimeoutErr
) 
 215         wxLogSysError( wxT("Could not try lock mutex") ); 
 216         return wxMUTEX_MISC_ERROR
; 
 219     return wxMUTEX_NO_ERROR
; 
 222 wxMutexError 
wxMutexInternal::Unlock() 
 224     wxCHECK_MSG( m_isOk 
, wxMUTEX_MISC_ERROR 
, wxT("Invalid Mutex") ) ; 
 226     OSStatus err 
= MPExitCriticalRegion( m_critRegion 
); 
 231         wxLogSysError( wxT("Could not unlock mutex") ); 
 233         return wxMUTEX_MISC_ERROR
; 
 236     return wxMUTEX_NO_ERROR
; 
 241 // -------------------------------------------------------------------------- 
 243 // -------------------------------------------------------------------------- 
 245 class wxSemaphoreInternal
 
 248     wxSemaphoreInternal( int initialcount
, int maxcount 
); 
 249     virtual ~wxSemaphoreInternal(); 
 255     wxSemaError 
WaitTimeout( unsigned long milliseconds 
); 
 258     { return WaitTimeout( kDurationForever
); } 
 260     wxSemaError 
TryWait() 
 262         wxSemaError err 
= WaitTimeout( kDurationImmediate 
); 
 263         if (err 
== wxSEMA_TIMEOUT
) 
 270     MPSemaphoreID m_semaphore
; 
 274 wxSemaphoreInternal::wxSemaphoreInternal( int initialcount
, int maxcount
) 
 277     m_semaphore 
= kInvalidID
; 
 279         // make it practically infinite 
 282     verify_noerr( MPCreateSemaphore( maxcount
, initialcount
, &m_semaphore 
) ); 
 283     m_isOk 
= ( m_semaphore 
!= kInvalidID 
); 
 287         wxFAIL_MSG( wxT("Error when creating semaphore") ); 
 291 wxSemaphoreInternal::~wxSemaphoreInternal() 
 293     if (m_semaphore 
!= kInvalidID
) 
 294         MPDeleteSemaphore( m_semaphore 
); 
 299 wxSemaError 
wxSemaphoreInternal::WaitTimeout( unsigned long milliseconds 
) 
 301     OSStatus err 
= MPWaitOnSemaphore( m_semaphore
, milliseconds 
); 
 304         if (err 
== kMPTimeoutErr
) 
 305             return wxSEMA_TIMEOUT
; 
 307         return wxSEMA_MISC_ERROR
; 
 310     return wxSEMA_NO_ERROR
; 
 313 wxSemaError 
wxSemaphoreInternal::Post() 
 315     OSStatus err 
= MPSignalSemaphore( m_semaphore 
); 
 318         return wxSEMA_MISC_ERROR
; 
 320     return wxSEMA_NO_ERROR
; 
 323 // ---------------------------------------------------------------------------- 
 324 // wxCondition implementation 
 325 // ---------------------------------------------------------------------------- 
 327 class wxConditionInternal
 
 330     wxConditionInternal( wxMutex
& mutex 
); 
 333     { return m_mutex
.IsOk() && m_semaphore
.IsOk(); } 
 336     wxCondError 
WaitTimeout( unsigned long milliseconds 
); 
 338     wxCondError 
Signal(); 
 339     wxCondError 
Broadcast(); 
 342     // the number of threads currently waiting for this condition 
 345     // the critical section protecting m_numWaiters 
 346     wxCriticalSection m_csWaiters
; 
 349     wxSemaphore m_semaphore
; 
 351     wxDECLARE_NO_COPY_CLASS(wxConditionInternal
); 
 354 wxConditionInternal::wxConditionInternal( wxMutex
& mutex 
) 
 357     // another thread can't access it until we return from ctor, so no need to 
 358     // protect access to m_numWaiters here 
 362 wxCondError 
wxConditionInternal::Wait() 
 364     // increment the number of waiters 
 365     IncrementAtomic( &m_numWaiters 
); 
 369     // a potential race condition can occur here 
 371     // after a thread increments nwaiters, and unlocks the mutex and before the 
 372     // semaphore.Wait() is called, if another thread can cause a signal to be 
 375     // this race condition is handled by using a semaphore and incrementing the 
 376     // semaphore only if 'nwaiters' is greater that zero since the semaphore, 
 377     // can 'remember' signals the race condition will not occur 
 379     // wait ( if necessary ) and decrement semaphore 
 380     wxSemaError err 
= m_semaphore
.Wait(); 
 383     return err 
== wxSEMA_NO_ERROR 
? wxCOND_NO_ERROR 
: wxCOND_MISC_ERROR
; 
 386 wxCondError 
wxConditionInternal::WaitTimeout( unsigned long milliseconds 
) 
 388     IncrementAtomic( &m_numWaiters 
); 
 392     // a race condition can occur at this point in the code 
 394     // please see the comments in Wait(), for details 
 396     wxSemaError err 
= m_semaphore
.WaitTimeout(milliseconds
); 
 398     if ( err 
== wxSEMA_TIMEOUT 
) 
 400         // another potential race condition exists here it is caused when a 
 401         // 'waiting' thread timesout, and returns from WaitForSingleObject, but 
 402         // has not yet decremented 'nwaiters'. 
 404         // at this point if another thread calls signal() then the semaphore 
 405         // will be incremented, but the waiting thread will miss it. 
 407         // to handle this particular case, the waiting thread calls 
 408         // WaitForSingleObject again with a timeout of 0, after locking 
 409         // 'nwaiters_mutex'. this call does not block because of the zero 
 410         // timeout, but will allow the waiting thread to catch the missed 
 412         wxCriticalSectionLocker 
lock(m_csWaiters
); 
 414         err 
= m_semaphore
.WaitTimeout(0); 
 416         if ( err 
!= wxSEMA_NO_ERROR 
) 
 424     return err 
== wxSEMA_NO_ERROR 
? wxCOND_NO_ERROR 
: wxCOND_MISC_ERROR
; 
 427 wxCondError 
wxConditionInternal::Signal() 
 429     wxCriticalSectionLocker 
lock(m_csWaiters
); 
 431     if ( m_numWaiters 
> 0 ) 
 433         // increment the semaphore by 1 
 434         if ( m_semaphore
.Post() != wxSEMA_NO_ERROR 
) 
 435             return wxCOND_MISC_ERROR
; 
 440     return wxCOND_NO_ERROR
; 
 443 wxCondError 
wxConditionInternal::Broadcast() 
 445     wxCriticalSectionLocker 
lock(m_csWaiters
); 
 447     while ( m_numWaiters 
> 0 ) 
 449         if ( m_semaphore
.Post() != wxSEMA_NO_ERROR 
) 
 450             return wxCOND_MISC_ERROR
; 
 455     return wxCOND_NO_ERROR
; 
 458 // ---------------------------------------------------------------------------- 
 459 // wxCriticalSection implementation 
 460 // ---------------------------------------------------------------------------- 
 462 // XXX currently implemented as mutex in headers. Change to critical section. 
 464 // ---------------------------------------------------------------------------- 
 465 // wxThread implementation 
 466 // ---------------------------------------------------------------------------- 
 468 // wxThreadInternal class 
 469 // ---------------------- 
 471 class wxThreadInternal
 
 478         m_prio 
= WXTHREAD_DEFAULT_PRIORITY
; 
 479         m_notifyQueueId 
= kInvalidID
; 
 481         m_cancelled 
= false ; 
 483         // set to true only when the thread starts waiting on m_semSuspend 
 486         // defaults for joinable threads 
 487         m_shouldBeJoined 
= true; 
 488         m_isDetached 
= false; 
 491     virtual ~wxThreadInternal() 
 493         if ( m_notifyQueueId
) 
 495             MPDeleteQueue( m_notifyQueueId 
); 
 496             m_notifyQueueId 
= kInvalidID 
; 
 501     static OSStatus 
MacThreadStart(void* arg
); 
 503     // create a new (suspended) thread (for the given thread object) 
 504     bool Create(wxThread 
*thread
, unsigned int stackSize
); 
 511     // unblock the thread allowing it to run 
 512     void SignalRun() { m_semRun
.Post(); } 
 514     // ask the thread to terminate 
 517     // go to sleep until Resume() is called 
 525     int GetPriority() const 
 527     void SetPriority(int prio
); 
 530     wxThreadState 
GetState() const 
 532     void SetState(wxThreadState state
) 
 535     // Get the ID of this thread's underlying MP Services task. 
 536     MPTaskID  
GetId() const 
 540     { m_cancelled 
= true; } 
 542     bool WasCancelled() const 
 543     { return m_cancelled
; } 
 546     void SetExitCode(wxThread::ExitCode exitcode
) 
 547     { m_exitcode 
= exitcode
; } 
 548     wxThread::ExitCode 
GetExitCode() const 
 549     { return m_exitcode
; } 
 552     void SetReallyPaused(bool paused
) 
 553     { m_isPaused 
= paused
; } 
 554     bool IsReallyPaused() const 
 555     { return m_isPaused
; } 
 557     // tell the thread that it is a detached one 
 560         wxCriticalSectionLocker 
lock(m_csJoinFlag
); 
 562         m_shouldBeJoined 
= false; 
 567     // the thread we're associated with 
 570     MPTaskID        m_tid
;                // thread id 
 571     MPQueueID        m_notifyQueueId
;    // its notification queue 
 573     wxThreadState m_state
;              // see wxThreadState enum 
 574     int           m_prio
;               // in wxWidgets units: from 0 to 100 
 576     // this flag is set when the thread should terminate 
 579     // this flag is set when the thread is blocking on m_semSuspend 
 582     // the thread exit code - only used for joinable (!detached) threads and 
 583     // is only valid after the thread termination 
 584     wxThread::ExitCode m_exitcode
; 
 586     // many threads may call Wait(), but only one of them should call 
 587     // pthread_join(), so we have to keep track of this 
 588     wxCriticalSection m_csJoinFlag
; 
 589     bool m_shouldBeJoined
; 
 592     // this semaphore is posted by Run() and the threads Entry() is not 
 593     // called before it is done 
 594     wxSemaphore m_semRun
; 
 596     // this one is signaled when the thread should resume after having been 
 598     wxSemaphore m_semSuspend
; 
 601 OSStatus 
wxThreadInternal::MacThreadStart(void *parameter
) 
 603     wxThread
* thread 
= (wxThread
*) parameter 
; 
 604     wxThreadInternal 
*pthread 
= thread
->m_internal
; 
 606     // add to TLS so that This() will work 
 607     verify_noerr( MPSetTaskStorageValue( gs_tlsForWXThread 
, (TaskStorageValue
) thread 
) ) ; 
 609     // have to declare this before pthread_cleanup_push() which defines a 
 613     // wait for the semaphore to be posted from Run() 
 614     pthread
->m_semRun
.Wait(); 
 616     // test whether we should run the run at all - may be it was deleted 
 617     // before it started to Run()? 
 619         wxCriticalSectionLocker 
lock(thread
->m_critsect
); 
 621         dontRunAtAll 
= pthread
->GetState() == STATE_NEW 
&& 
 622                        pthread
->WasCancelled(); 
 627         pthread
->m_exitcode 
= thread
->Entry(); 
 630             wxCriticalSectionLocker 
lock(thread
->m_critsect
); 
 631             pthread
->SetState( STATE_EXITED 
); 
 637         if ( pthread
->m_isDetached 
) 
 644         // on Mac for the running code, 
 645         // the correct thread termination is to return 
 647         // terminate the thread 
 648         thread
->Exit( pthread
->m_exitcode 
); 
 650         return (OSStatus
) NULL
; // pthread->m_exitcode; 
 654 bool wxThreadInternal::Create( wxThread 
*thread
, unsigned int stackSize 
) 
 656     wxASSERT_MSG( m_state 
== STATE_NEW 
&& !m_tid
, 
 657                     wxT("Create()ing thread twice?") ); 
 659     OSStatus err 
= noErr
; 
 662     if ( m_notifyQueueId 
== kInvalidID 
) 
 664         OSStatus err 
= MPCreateQueue( &m_notifyQueueId 
); 
 667             wxLogSysError( wxT("Cant create the thread event queue") ); 
 676         MacThreadStart
, (void*)m_thread
, stackSize
, 
 677         m_notifyQueueId
, &m_exitcode
, 0, 0, &m_tid 
); 
 681         wxLogSysError( wxT("Can't create thread") ); 
 686     if ( m_prio 
!= WXTHREAD_DEFAULT_PRIORITY 
) 
 687         SetPriority( m_prio 
); 
 692 void wxThreadInternal::SetPriority( int priority 
) 
 698         // Mac priorities range from 1 to 10,000, with a default of 100. 
 699         // wxWidgets priorities range from 0 to 100 with a default of 50. 
 700         // We can map wxWidgets to Mac priorities easily by assuming 
 701         // the former uses a logarithmic scale. 
 702         const unsigned int macPriority 
= (int)( exp( priority 
/ 25.0 * log( 10.0)) + 0.5); 
 704         MPSetTaskWeight( m_tid
, macPriority 
); 
 708 wxThreadError 
wxThreadInternal::Run() 
 710     wxCHECK_MSG( GetState() == STATE_NEW
, wxTHREAD_RUNNING
, 
 711                  wxT("thread may only be started once after Create()") ); 
 713     SetState( STATE_RUNNING 
); 
 715     // wake up threads waiting for our start 
 718     return wxTHREAD_NO_ERROR
; 
 721 void wxThreadInternal::Wait() 
 723    wxCHECK_RET( !m_isDetached
, wxT("can't wait for a detached thread") ); 
 725     // if the thread we're waiting for is waiting for the GUI mutex, we will 
 726     // deadlock so make sure we release it temporarily 
 727     if ( wxThread::IsMain() ) 
 729         // give the thread we're waiting for chance to do the GUI call 
 730         // it might be in, we don't do this conditionally as the to be waited on 
 731         // thread might have to acquire the mutex later but before terminating 
 732         if ( wxGuiOwnedByMainThread() ) 
 737         wxCriticalSectionLocker 
lock(m_csJoinFlag
); 
 739         if ( m_shouldBeJoined 
) 
 741             void *param1
, *param2
, *rc
; 
 743             OSStatus err 
= MPWaitOnQueue( 
 751                 wxLogSysError( wxT( "Cannot wait for thread termination.")); 
 755             // actually param1 would be the address of m_exitcode 
 756             // but we don't need this here 
 759             m_shouldBeJoined 
= false; 
 764 void wxThreadInternal::Pause() 
 766     // the state is set from the thread which pauses us first, this function 
 767     // is called later so the state should have been already set 
 768     wxCHECK_RET( m_state 
== STATE_PAUSED
, 
 769                  wxT("thread must first be paused with wxThread::Pause().") ); 
 771     // wait until the semaphore is Post()ed from Resume() 
 775 void wxThreadInternal::Resume() 
 777     wxCHECK_RET( m_state 
== STATE_PAUSED
, 
 778                  wxT("can't resume thread which is not suspended.") ); 
 780     // the thread might be not actually paused yet - if there were no call to 
 781     // TestDestroy() since the last call to Pause() for example 
 782     if ( IsReallyPaused() ) 
 788         SetReallyPaused( false ); 
 791     SetState( STATE_RUNNING 
); 
 797 wxThread 
*wxThread::This() 
 799     wxThread
* thr 
= (wxThread
*) MPGetTaskStorageValue( gs_tlsForWXThread 
) ; 
 808 void wxThread::Yield() 
 810     CFRunLoopRunInMode( kCFRunLoopDefaultMode 
, 0 , true ) ; 
 815 void wxThread::Sleep( unsigned long milliseconds 
) 
 817     AbsoluteTime wakeup 
= AddDurationToAbsolute( milliseconds
, UpTime() ); 
 818     MPDelayUntil( &wakeup 
); 
 821 int wxThread::GetCPUCount() 
 823     return MPProcessors(); 
 826 unsigned long wxThread::GetCurrentId() 
 828     return (unsigned long)MPCurrentTaskID(); 
 831 bool wxThread::SetConcurrency( size_t WXUNUSED(level
) ) 
 833     // Cannot be set in MacOS. 
 837 wxThread::wxThread( wxThreadKind kind 
) 
 840     m_internal 
= new wxThreadInternal(); 
 842     m_isDetached 
= (kind 
== wxTHREAD_DETACHED
); 
 845 wxThread::~wxThread() 
 847     wxASSERT_MSG( g_numberOfThreads
>0 , wxT("More threads deleted than created.") ) ; 
 853     // check that the thread either exited or couldn't be created 
 854     if ( m_internal
->GetState() != STATE_EXITED 
&& 
 855          m_internal
->GetState() != STATE_NEW 
) 
 858             wxT("The thread %ld is being destroyed although it is still running! The application may crash."), 
 864     wxDELETE( m_internal 
) ; 
 867 wxThreadError 
wxThread::Create( unsigned int stackSize 
) 
 869     wxCriticalSectionLocker 
lock(m_critsect
); 
 872         m_internal
->Detach() ; 
 874     if ( !m_internal
->Create(this, stackSize
) ) 
 876         m_internal
->SetState( STATE_EXITED 
); 
 878         return wxTHREAD_NO_RESOURCE
; 
 881     return wxTHREAD_NO_ERROR
; 
 884 wxThreadError 
wxThread::Run() 
 886     wxCriticalSectionLocker 
lock(m_critsect
); 
 888     wxCHECK_MSG( m_internal
->GetId(), wxTHREAD_MISC_ERROR
, 
 889                  wxT("must call wxThread::Create() first") ); 
 891     return m_internal
->Run(); 
 894 // ----------------------------------------------------------------------------- 
 896 // ----------------------------------------------------------------------------- 
 898 wxThreadError 
wxThread::Pause() 
 900     wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
, 
 901                  wxT("a thread can't pause itself") ); 
 903     wxCriticalSectionLocker 
lock(m_critsect
); 
 905     if ( m_internal
->GetState() != STATE_RUNNING 
) 
 907         wxLogDebug( wxT("Can't pause thread which is not running.") ); 
 909         return wxTHREAD_NOT_RUNNING
; 
 912     // just set a flag, the thread will be really paused only during the next 
 913     // call to TestDestroy() 
 914     m_internal
->SetState( STATE_PAUSED 
); 
 916     return wxTHREAD_NO_ERROR
; 
 919 wxThreadError 
wxThread::Resume() 
 921     wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
, 
 922                  wxT("a thread can't resume itself") ); 
 924     wxCriticalSectionLocker 
lock(m_critsect
); 
 926     wxThreadState state 
= m_internal
->GetState(); 
 931             m_internal
->Resume(); 
 932             return wxTHREAD_NO_ERROR
; 
 935             return wxTHREAD_NO_ERROR
; 
 938             wxLogDebug( wxT("Attempt to resume a thread which is not paused.") ); 
 940             return wxTHREAD_MISC_ERROR
; 
 944 // ----------------------------------------------------------------------------- 
 946 // ----------------------------------------------------------------------------- 
 948 wxThread::ExitCode 
wxThread::Wait(wxThreadWait 
WXUNUSED(waitMode
)) 
 950     wxCHECK_MSG( This() != this, (ExitCode
)-1, 
 951                  wxT("a thread can't wait for itself") ); 
 953     wxCHECK_MSG( !m_isDetached
, (ExitCode
)-1, 
 954                  wxT("can't wait for detached thread") ); 
 958     return m_internal
->GetExitCode(); 
 961 wxThreadError 
wxThread::Delete(ExitCode 
*rc
, wxThreadWait 
WXUNUSED(waitMode
)) 
 963     wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
, 
 964                  wxT("a thread can't delete itself") ); 
 966     bool isDetached 
= m_isDetached
; 
 969     wxThreadState state 
= m_internal
->GetState(); 
 971     // ask the thread to stop 
 972     m_internal
->SetCancelFlag(); 
 979             // we need to wake up the thread so that PthreadStart() will 
 980             // terminate - right now it's blocking on run semaphore in 
 982             m_internal
->SignalRun(); 
 991             // resume the thread first 
 992             m_internal
->Resume(); 
 999                 // wait until the thread stops 
1004                     // return the exit code of the thread 
1005                     *rc 
= m_internal
->GetExitCode(); 
1010     return wxTHREAD_NO_ERROR
; 
1013 wxThreadError 
wxThread::Kill() 
1015     wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
, 
1016                  wxT("a thread can't kill itself") ); 
1018     switch ( m_internal
->GetState() ) 
1022             return wxTHREAD_NOT_RUNNING
; 
1025             // resume the thread first 
1031             OSStatus err 
= MPTerminateTask( m_internal
->GetId() , -1 ) ; 
1034                 wxLogError( wxT("Failed to terminate a thread.") ); 
1036                 return wxTHREAD_MISC_ERROR
; 
1045                 // this should be retrieved by Wait actually 
1046                 m_internal
->SetExitCode( (void*)-1 ); 
1049             return wxTHREAD_NO_ERROR
; 
1053 void wxThread::Exit( ExitCode status 
) 
1055     wxASSERT_MSG( This() == this, 
1056                   wxT("wxThread::Exit() can only be called in the context of the same thread") ); 
1058     // don't enter m_critsect before calling OnExit() because the user code 
1059     // might deadlock if, for example, it signals a condition in OnExit() (a 
1060     // common case) while the main thread calls any of functions entering 
1061     // m_critsect on us (almost all of them do) 
1064     MPTaskID threadid 
= m_internal
->GetId(); 
1072         // update the status of the joinable thread 
1073         wxCriticalSectionLocker 
lock( m_critsect 
); 
1074         m_internal
->SetState( STATE_EXITED 
); 
1077     MPTerminateTask( threadid
, (long)status 
); 
1080 // also test whether we were paused 
1081 bool wxThread::TestDestroy() 
1083     wxASSERT_MSG( This() == this, 
1084                   wxT("wxThread::TestDestroy() can only be called in the context of the same thread") ); 
1088     if ( m_internal
->GetState() == STATE_PAUSED 
) 
1090         m_internal
->SetReallyPaused( true ); 
1092         // leave the crit section or the other threads will stop too if they attempt 
1093         // to call any of (seemingly harmless) IsXXX() functions while we sleep 
1096         m_internal
->Pause(); 
1100         // thread wasn't requested to pause, nothing to do 
1104     return m_internal
->WasCancelled(); 
1107 // ----------------------------------------------------------------------------- 
1109 // ----------------------------------------------------------------------------- 
1111 void wxThread::SetPriority(unsigned int prio
) 
1113     wxCHECK_RET( ((int)WXTHREAD_MIN_PRIORITY 
<= (int)prio
) && 
1114                  ((int)prio 
<= (int)WXTHREAD_MAX_PRIORITY
), 
1115                  wxT("invalid thread priority") ); 
1117     wxCriticalSectionLocker 
lock(m_critsect
); 
1119     switch ( m_internal
->GetState() ) 
1124             // thread not yet started, priority will be set when it is 
1125             m_internal
->SetPriority( prio 
); 
1130             wxFAIL_MSG( wxT("impossible to set thread priority in this state") ); 
1134 unsigned int wxThread::GetPriority() const 
1136     wxCriticalSectionLocker 
lock(const_cast<wxCriticalSection 
&>(m_critsect
)); 
1138     return m_internal
->GetPriority(); 
1141 unsigned long wxThread::GetId() const 
1143     wxCriticalSectionLocker 
lock(const_cast<wxCriticalSection 
&>(m_critsect
)); 
1145     return (unsigned long)m_internal
->GetId(); 
1148 // ----------------------------------------------------------------------------- 
1150 // ----------------------------------------------------------------------------- 
1152 bool wxThread::IsRunning() const 
1154     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); 
1156     return m_internal
->GetState() == STATE_RUNNING
; 
1159 bool wxThread::IsAlive() const 
1161     wxCriticalSectionLocker 
lock((wxCriticalSection
&)m_critsect
); 
1163     switch ( m_internal
->GetState() ) 
1174 bool wxThread::IsPaused() const 
1176     wxCriticalSectionLocker 
lock((wxCriticalSection
&)m_critsect
); 
1178     return (m_internal
->GetState() == STATE_PAUSED
); 
1181 // ---------------------------------------------------------------------------- 
1182 // Automatic initialization for thread module 
1183 // ---------------------------------------------------------------------------- 
1185 class wxThreadModule 
: public wxModule
 
1188     virtual bool OnInit(); 
1189     virtual void OnExit(); 
1192     DECLARE_DYNAMIC_CLASS(wxThreadModule
) 
1195 IMPLEMENT_DYNAMIC_CLASS(wxThreadModule
, wxModule
) 
1197 bool wxThreadModule::OnInit() 
1199     bool hasThreadManager 
= 
1201         true ; // TODO VERIFY IN NEXT BUILD 
1203         MPLibraryIsLoaded(); 
1206     if ( !hasThreadManager 
) 
1208         wxLogError( wxT("MP thread support is not available on this system" ) ) ; 
1213     // main thread's This() is NULL 
1214     verify_noerr( MPAllocateTaskStorageIndex( &gs_tlsForWXThread 
) ) ; 
1215     verify_noerr( MPSetTaskStorageValue( gs_tlsForWXThread
, 0 ) ) ; 
1217     wxThread::ms_idMainThread 
= wxThread::GetCurrentId(); 
1218     gs_critsectWaitingForGui 
= new wxCriticalSection(); 
1220     gs_critsectGui 
= new wxCriticalSection(); 
1221     gs_critsectGui
->Enter(); 
1226 void wxThreadModule::OnExit() 
1228     if ( gs_critsectGui 
) 
1230         if ( !wxGuiOwnedByMainThread() ) 
1232             gs_critsectGui
->Enter(); 
1233             gs_bGuiOwnedByMainThread 
= true; 
1236         gs_critsectGui
->Leave(); 
1237         wxDELETE(gs_critsectGui
); 
1240     wxDELETE(gs_critsectWaitingForGui
); 
1243 // ---------------------------------------------------------------------------- 
1244 // GUI Serialization copied from MSW implementation 
1245 // ---------------------------------------------------------------------------- 
1247 void wxMutexGuiEnterImpl() 
1249     // this would dead lock everything... 
1250     wxASSERT_MSG( !wxThread::IsMain(), 
1251                   wxT("main thread doesn't want to block in wxMutexGuiEnter()!") ); 
1253     // the order in which we enter the critical sections here is crucial!! 
1255     // set the flag telling to the main thread that we want to do some GUI 
1257         wxCriticalSectionLocker 
enter(*gs_critsectWaitingForGui
); 
1259         gs_nWaitingForGui
++; 
1262     wxWakeUpMainThread(); 
1264     // now we may block here because the main thread will soon let us in 
1265     // (during the next iteration of OnIdle()) 
1266     gs_critsectGui
->Enter(); 
1269 void wxMutexGuiLeaveImpl() 
1271     wxCriticalSectionLocker 
enter(*gs_critsectWaitingForGui
); 
1273     if ( wxThread::IsMain() ) 
1275         gs_bGuiOwnedByMainThread 
= false; 
1279         // decrement the number of threads waiting for GUI access now 
1280         wxASSERT_MSG( gs_nWaitingForGui 
> 0, 
1281                       wxT("calling wxMutexGuiLeave() without entering it first?") ); 
1283         gs_nWaitingForGui
--; 
1285         wxWakeUpMainThread(); 
1288     gs_critsectGui
->Leave(); 
1291 void WXDLLIMPEXP_BASE 
wxMutexGuiLeaveOrEnter() 
1293     wxASSERT_MSG( wxThread::IsMain(), 
1294                   wxT("only main thread may call wxMutexGuiLeaveOrEnter()!") ); 
1296     if ( !gs_critsectWaitingForGui 
) 
1299     wxCriticalSectionLocker 
enter(*gs_critsectWaitingForGui
); 
1301     if ( gs_nWaitingForGui 
== 0 ) 
1303         // no threads are waiting for GUI - so we may acquire the lock without 
1304         // any danger (but only if we don't already have it) 
1305         if ( !wxGuiOwnedByMainThread() ) 
1307             gs_critsectGui
->Enter(); 
1309             gs_bGuiOwnedByMainThread 
= true; 
1311         //else: already have it, nothing to do 
1315         // some threads are waiting, release the GUI lock if we have it 
1316         if ( wxGuiOwnedByMainThread() ) 
1318         //else: some other worker thread is doing GUI 
1322 bool WXDLLIMPEXP_BASE 
wxGuiOwnedByMainThread() 
1324     return gs_bGuiOwnedByMainThread
; 
1327 // wake up the main thread 
1328 void WXDLLEXPORT 
wxWakeUpMainThread() 
1333 // ---------------------------------------------------------------------------- 
1334 // include common implementation code 
1335 // ---------------------------------------------------------------------------- 
1337 #include "wx/thrimpl.cpp" 
1339 #endif // wxUSE_THREADS