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 // ---------------------------------------------------------------------------- 
  50 // ---------------------------------------------------------------------------- 
  52 // the possible states of the thread ("=>" shows all possible transitions from 
  56         STATE_NEW
,              // didn't start execution yet (=> RUNNING) 
  57         STATE_RUNNING
,  // thread is running (=> PAUSED, CANCELED) 
  58         STATE_PAUSED
,   // thread is temporarily suspended (=> RUNNING) 
  59         STATE_CANCELED
, // thread should terminate a.s.a.p. (=> EXITED) 
  60         STATE_EXITED    
// thread is terminating 
  63 // ---------------------------------------------------------------------------- 
  64 // this module globals 
  65 // ---------------------------------------------------------------------------- 
  68 // the task ID of the main thread 
  69 static wxThreadIdType gs_idMainThread 
= kInvalidID
; 
  71 // this is the Per-Task Storage for the pointer to the appropriate wxThread 
  72 TaskStorageIndex gs_tlsForWXThread 
= 0 ; 
  74 // if it's false, some secondary thread is holding the GUI lock 
  75 static bool gs_bGuiOwnedByMainThread 
= true; 
  77 // critical section which controls access to all GUI functions: any secondary 
  78 // thread (i.e. except the main one) must enter this crit section before doing 
  80 static wxCriticalSection 
*gs_critsectGui 
= NULL
; 
  82 // critical section which protects gs_nWaitingForGui variable 
  83 static wxCriticalSection 
*gs_critsectWaitingForGui 
= NULL
; 
  85 // number of threads waiting for GUI in wxMutexGuiEnter() 
  86 static size_t gs_nWaitingForGui 
= 0; 
  88 // overall number of threads, needed for determining the sleep value of the main  
  90 size_t g_numberOfThreads 
= 0; 
  96 MPCriticalRegionID gs_guiCritical 
= kInvalidID
; 
 100 // ============================================================================ 
 101 // MacOS implementation of thread classes 
 102 // ============================================================================ 
 107     The implementation is very close to the phtreads implementation, the reason for 
 108     using MPServices is the fact that these are also available under OS 9. Thus allowing 
 109     for one common API for all current builds. 
 111     As soon as wxThreads are on a 64 bit address space, the TLS must be extended 
 112     to use two indices one for each 32 bit part as the MP implementation is limited 
 115     I have two implementations for mutexes : 
 116     version A based on a binary semaphore, problem - not reentrant, version B based  
 117     on a critical region, allows for reentrancy, performance implications not 
 120     The same for condition internal, one implementation by Aj Lavin and the other one 
 121     copied from the thrimpl.cpp which I assume has been more broadly tested, I've just 
 122     replaced the interlock increment with the appropriate PPC calls  
 125 // ---------------------------------------------------------------------------- 
 126 // wxMutex implementation 
 127 // ---------------------------------------------------------------------------- 
 129 static bool wxMacMPThreadsInitVerify() 
 131         static bool hasThreadManager 
= false ; 
 132         if ( !hasThreadManager 
) 
 133             hasThreadManager 
= MPLibraryIsLoaded(); 
 135         if ( !hasThreadManager 
) 
 137                 wxMessageBox( wxT("Error") , wxT("MP Thread Support is not available on this System" ), wxOK 
) ; 
 145 class wxMutexInternal
 
 148         wxMutexInternal(wxMutexType mutexType
) ; 
 150         bool IsOk() const { return m_isOk
; } 
 152         wxMutexError 
Lock() ; 
 153         wxMutexError 
TryLock() ; 
 154         wxMutexError 
Unlock(); 
 156     MPSemaphoreID m_semaphore
; 
 160 wxMutexInternal::wxMutexInternal(wxMutexType mutexType 
) 
 162     wxMacMPThreadsInitVerify() ; 
 165     m_semaphore 
= kInvalidID 
; 
 167     OSStatus err 
= noErr 
; 
 170         case wxMUTEX_DEFAULT 
: 
 172                 verify_noerr( MPCreateBinarySemaphore( & m_semaphore
) ); 
 173                 m_isOk 
= ( m_semaphore 
!= kInvalidID 
) ; 
 176         case wxMUTEX_RECURSIVE 
: 
 177             wxFAIL_MSG(wxT("Recursive Mutex not supported yet") ) ; 
 180             wxFAIL_MSG(wxT("Unknown mutex type") ) ; 
 185 wxMutexInternal::~wxMutexInternal() 
 187     if ( m_semaphore 
!= kInvalidID 
) 
 188             MPDeleteSemaphore( m_semaphore
); 
 191 wxMutexError 
wxMutexInternal::Lock() 
 193     wxCHECK_MSG( m_isOk 
, wxMUTEX_MISC_ERROR 
, wxT("Invalid Mutex") ) ; 
 194         OSStatus err 
= MPWaitOnSemaphore( m_semaphore
, kDurationForever
); 
 197                 wxLogSysError(wxT("Could not lock mutex")); 
 198                 return wxMUTEX_MISC_ERROR
; 
 201         return wxMUTEX_NO_ERROR
; 
 204 wxMutexError 
wxMutexInternal::TryLock() 
 206     wxCHECK_MSG( m_isOk 
, wxMUTEX_MISC_ERROR 
, wxT("Invalid Mutex") ) ; 
 207         OSStatus err 
= MPWaitOnSemaphore( m_semaphore
, kDurationImmediate
); 
 210                 if ( err 
== kMPTimeoutErr
) 
 214                 wxLogSysError(wxT("Could not try lock mutex")); 
 215                 return wxMUTEX_MISC_ERROR
;     
 218         return wxMUTEX_NO_ERROR
; 
 221 wxMutexError 
wxMutexInternal::Unlock() 
 223     wxCHECK_MSG( m_isOk 
, wxMUTEX_MISC_ERROR 
, wxT("Invalid Mutex") ) ; 
 224         OSStatus err 
= MPSignalSemaphore( m_semaphore
); 
 227                 wxLogSysError(_("Could not unlock mutex")); 
 228                 return wxMUTEX_MISC_ERROR
;         
 231         return wxMUTEX_NO_ERROR
; 
 236 class wxMutexInternal
 
 239         wxMutexInternal(wxMutexType mutexType
) ; 
 241         bool IsOk() const { return m_isOk
; } 
 243         wxMutexError 
Lock() ; 
 244         wxMutexError 
TryLock() ; 
 245         wxMutexError 
Unlock(); 
 247     MPCriticalRegionID m_critRegion 
; 
 251 wxMutexInternal::wxMutexInternal(wxMutexType mutexType 
) 
 253     wxMacMPThreadsInitVerify() ; 
 255     m_critRegion 
= kInvalidID 
; 
 257     verify_noerr( MPCreateCriticalRegion( & m_critRegion
) ); 
 258     m_isOk 
= ( m_critRegion 
!= kInvalidID 
) ; 
 261         wxFAIL_MSG(wxT("Error when creating mutex") ) ; 
 264 wxMutexInternal::~wxMutexInternal() 
 266     if ( m_critRegion 
!= kInvalidID 
) 
 267             MPDeleteCriticalRegion( m_critRegion
); 
 270 wxMutexError 
wxMutexInternal::Lock() 
 272     wxCHECK_MSG( m_isOk 
, wxMUTEX_MISC_ERROR 
, wxT("Invalid Mutex") ) ; 
 273         OSStatus err 
= MPEnterCriticalRegion( m_critRegion
, kDurationForever
); 
 276                 wxLogSysError(wxT("Could not lock mutex")); 
 277                 return wxMUTEX_MISC_ERROR
; 
 280         return wxMUTEX_NO_ERROR
; 
 283 wxMutexError 
wxMutexInternal::TryLock() 
 285     wxCHECK_MSG( m_isOk 
, wxMUTEX_MISC_ERROR 
, wxT("Invalid Mutex") ) ; 
 286         OSStatus err 
= MPEnterCriticalRegion( m_critRegion
, kDurationImmediate
); 
 289                 if ( err 
== kMPTimeoutErr
) 
 293                 wxLogSysError(wxT("Could not try lock mutex")); 
 294                 return wxMUTEX_MISC_ERROR
;     
 297         return wxMUTEX_NO_ERROR
; 
 300 wxMutexError 
wxMutexInternal::Unlock() 
 302     wxCHECK_MSG( m_isOk 
, wxMUTEX_MISC_ERROR 
, wxT("Invalid Mutex") ) ; 
 303         OSStatus err 
= MPExitCriticalRegion( m_critRegion
); 
 306                 wxLogSysError(_("Could not unlock mutex")); 
 307                 return wxMUTEX_MISC_ERROR
;         
 310         return wxMUTEX_NO_ERROR
; 
 315 // -------------------------------------------------------------------------- 
 317 // -------------------------------------------------------------------------- 
 319 class wxSemaphoreInternal
 
 322         wxSemaphoreInternal(int initialcount
, int maxcount
); 
 323         ~wxSemaphoreInternal(); 
 325         bool IsOk() const { return m_isOk
; } 
 327         wxSemaError 
WaitTimeout(unsigned long milliseconds
); 
 329         wxSemaError 
Wait() { return WaitTimeout( kDurationForever
); } 
 331         wxSemaError 
TryWait()  
 333             wxSemaError err 
= WaitTimeout(kDurationImmediate
);  
 334             if ( err 
== wxSEMA_TIMEOUT 
) 
 341     MPSemaphoreID m_semaphore
; 
 345 wxSemaphoreInternal::wxSemaphoreInternal(int initialcount
, int maxcount
) 
 347     wxMacMPThreadsInitVerify() ; 
 349     m_semaphore 
= kInvalidID 
; 
 352                 // make it practically infinite 
 355         verify_noerr( MPCreateSemaphore( maxcount
, initialcount
, & m_semaphore
) ); 
 356     m_isOk 
= ( m_semaphore 
!= kInvalidID 
) ; 
 359         wxFAIL_MSG(wxT("Error when creating semaphore") ) ; 
 362 wxSemaphoreInternal::~wxSemaphoreInternal() 
 364     if( m_semaphore 
!= kInvalidID 
) 
 365             MPDeleteSemaphore( m_semaphore
); 
 368 wxSemaError 
wxSemaphoreInternal::WaitTimeout(unsigned long milliseconds
) 
 370         OSStatus err 
= MPWaitOnSemaphore( m_semaphore
, milliseconds
); 
 373                 if ( err 
== kMPTimeoutErr
) 
 375                         return wxSEMA_TIMEOUT
; 
 377                 return wxSEMA_MISC_ERROR
; 
 379         return wxSEMA_NO_ERROR
; 
 382 wxSemaError 
wxSemaphoreInternal::Post() 
 384         OSStatus err 
= MPSignalSemaphore( m_semaphore
); 
 387                 return wxSEMA_MISC_ERROR
; 
 389         return wxSEMA_NO_ERROR
; 
 392 // ---------------------------------------------------------------------------- 
 393 // wxCondition implementation 
 394 // ---------------------------------------------------------------------------- 
 398 class wxConditionInternal
 
 402         wxConditionInternal(wxMutex
& mutex
)  
 412         ~wxConditionInternal() 
 416         bool IsOk() const { return m_mutex
.IsOk() ; } 
 420                 return WaitTimeout( kDurationForever
); 
 423         wxCondError 
WaitTimeout(unsigned long msectimeout
); 
 427                 return DoSignal( false); 
 430         wxCondError 
Broadcast() 
 432                 return DoSignal( true); 
 437                 wxCondError 
DoSignal( bool signalAll
); 
 440         wxSemaphoreInternal     m_semaphore
;  // Signals the waiting threads. 
 441         wxSemaphoreInternal       m_gate
; 
 442         wxCriticalSection m_varSection
; 
 443         size_t    m_waiters
;    // Number of threads waiting for a signal. 
 444         size_t          m_signals
;      // Number of signals to send. 
 445         size_t    m_canceled
;   // Number of canceled waiters in m_waiters. 
 449 wxCondError 
wxConditionInternal::WaitTimeout(unsigned long msectimeout
) 
 452         if ( ++ m_waiters 
== INT_MAX
) 
 454                 m_varSection
.Enter(); 
 455                 m_waiters 
-= m_canceled
; 
 456                 m_signals 
-= m_canceled
; 
 458                 m_varSection
.Leave(); 
 464         wxSemaError err 
= m_semaphore
.WaitTimeout( msectimeout
); 
 465         wxASSERT( err 
== wxSEMA_NO_ERROR 
|| err 
== wxSEMA_TIMEOUT
); 
 467         m_varSection
.Enter(); 
 468         if ( err 
!= wxSEMA_NO_ERROR
) 
 470                 if ( m_signals 
> m_canceled
) 
 472                         // A signal is being sent after we timed out. 
 474                         if ( m_waiters 
== m_signals
) 
 476                                 // There are no excess waiters to catch the signal, so 
 477                                 // we must throw it away. 
 479                                 wxSemaError err2 
= m_semaphore
.Wait(); 
 480                                 if ( err2 
!= wxSEMA_NO_ERROR
) 
 482                                         wxLogSysError(_("Error while waiting on semaphore")); 
 484                                 wxASSERT( err2 
== wxSEMA_NO_ERROR
); 
 486                                 if ( -- m_signals 
== m_canceled
) 
 488                                         // This was the last signal. open the gate. 
 489                                         wxASSERT( m_waiters 
== m_canceled
); 
 495                                 // There are excess waiters to catch the signal, leave 
 502                         // No signals is being sent. 
 503                         // The gate may be open or closed, so we can't touch m_waiters. 
 510                 // We caught a signal. 
 511                 wxASSERT( m_signals 
> m_canceled
); 
 513                 if ( -- m_signals 
== m_canceled
) 
 515                         // This was the last signal. open the gate. 
 516                         wxASSERT( m_waiters 
== m_canceled
); 
 520         m_varSection
.Leave(); 
 526                 return err 
== wxSEMA_TIMEOUT 
? wxCOND_TIMEOUT 
: wxCOND_MISC_ERROR
; 
 529         return wxCOND_NO_ERROR
; 
 533 wxCondError 
wxConditionInternal::DoSignal( bool signalAll
) 
 536         m_varSection
.Enter(); 
 538         wxASSERT( m_signals 
== m_canceled
); 
 540         if ( m_waiters 
== m_canceled
) 
 542                 m_varSection
.Leave(); 
 544                 return wxCOND_NO_ERROR
; 
 549                 m_waiters 
-= m_canceled
; 
 554         m_signals 
= signalAll 
? m_waiters 
: 1; 
 555         size_t n 
= m_signals
; 
 557         m_varSection
.Leave(); 
 559         // Let the waiters inherit the gate lock. 
 563                 wxSemaError err 
= m_semaphore
.Post(); 
 564                 wxASSERT( err 
== wxSEMA_NO_ERROR
); 
 567         return wxCOND_NO_ERROR
; 
 571 class wxConditionInternal
 
 574     wxConditionInternal(wxMutex
& mutex
); 
 576     bool IsOk() const { return m_mutex
.IsOk() && m_semaphore
.IsOk(); } 
 579     wxCondError 
WaitTimeout(unsigned long milliseconds
); 
 581     wxCondError 
Signal(); 
 582     wxCondError 
Broadcast(); 
 585     // the number of threads currently waiting for this condition 
 588     // the critical section protecting m_numWaiters 
 589     wxCriticalSection m_csWaiters
; 
 592     wxSemaphore m_semaphore
; 
 594     DECLARE_NO_COPY_CLASS(wxConditionInternal
) 
 597 wxConditionInternal::wxConditionInternal(wxMutex
& mutex
) 
 600     // another thread can't access it until we return from ctor, so no need to 
 601     // protect access to m_numWaiters here 
 605 wxCondError 
wxConditionInternal::Wait() 
 607     // increment the number of waiters 
 608     IncrementAtomic(&m_numWaiters
); 
 612     // a potential race condition can occur here 
 614     // after a thread increments nwaiters, and unlocks the mutex and before the 
 615     // semaphore.Wait() is called, if another thread can cause a signal to be 
 618     // this race condition is handled by using a semaphore and incrementing the 
 619     // semaphore only if 'nwaiters' is greater that zero since the semaphore, 
 620     // can 'remember' signals the race condition will not occur 
 622     // wait ( if necessary ) and decrement semaphore 
 623     wxSemaError err 
= m_semaphore
.Wait(); 
 626     return err 
== wxSEMA_NO_ERROR 
? wxCOND_NO_ERROR 
: wxCOND_MISC_ERROR
; 
 629 wxCondError 
wxConditionInternal::WaitTimeout(unsigned long milliseconds
) 
 631     IncrementAtomic(&m_numWaiters
); 
 635     // a race condition can occur at this point in the code 
 637     // please see the comments in Wait(), for details 
 639     wxSemaError err 
= m_semaphore
.WaitTimeout(milliseconds
); 
 641     if ( err 
== wxSEMA_BUSY 
) 
 643         // another potential race condition exists here it is caused when a 
 644         // 'waiting' thread timesout, and returns from WaitForSingleObject, but 
 645         // has not yet decremented 'nwaiters'. 
 647         // at this point if another thread calls signal() then the semaphore 
 648         // will be incremented, but the waiting thread will miss it. 
 650         // to handle this particular case, the waiting thread calls 
 651         // WaitForSingleObject again with a timeout of 0, after locking 
 652         // 'nwaiters_mutex'. this call does not block because of the zero 
 653         // timeout, but will allow the waiting thread to catch the missed 
 655         wxCriticalSectionLocker 
lock(m_csWaiters
); 
 657         err 
= m_semaphore
.WaitTimeout(0); 
 659         if ( err 
!= wxSEMA_NO_ERROR 
) 
 667     return err 
== wxSEMA_NO_ERROR 
? wxCOND_NO_ERROR 
: wxCOND_MISC_ERROR
; 
 670 wxCondError 
wxConditionInternal::Signal() 
 672     wxCriticalSectionLocker 
lock(m_csWaiters
); 
 674     if ( m_numWaiters 
> 0 ) 
 676         // increment the semaphore by 1 
 677         if ( m_semaphore
.Post() != wxSEMA_NO_ERROR 
) 
 678             return wxCOND_MISC_ERROR
; 
 683     return wxCOND_NO_ERROR
; 
 686 wxCondError 
wxConditionInternal::Broadcast() 
 688     wxCriticalSectionLocker 
lock(m_csWaiters
); 
 690     while ( m_numWaiters 
> 0 ) 
 692         if ( m_semaphore
.Post() != wxSEMA_NO_ERROR 
) 
 693             return wxCOND_MISC_ERROR
; 
 698     return wxCOND_NO_ERROR
; 
 702 // ---------------------------------------------------------------------------- 
 703 // wxCriticalSection implementation 
 704 // ---------------------------------------------------------------------------- 
 706 // XXX currently implemented as mutex in headers. Change to critical section. 
 708 // ---------------------------------------------------------------------------- 
 709 // wxThread implementation 
 710 // ---------------------------------------------------------------------------- 
 712 // wxThreadInternal class 
 713 // ---------------------- 
 715 class wxThreadInternal
 
 722                 m_prio 
= WXTHREAD_DEFAULT_PRIORITY
; 
 723                 m_notifyQueueId 
= kInvalidID
; 
 725         m_cancelled 
= FALSE 
; 
 727         // set to TRUE only when the thread starts waiting on m_semSuspend 
 730         // defaults for joinable threads 
 731         m_shouldBeJoined 
= TRUE
; 
 732         m_isDetached 
= FALSE
; 
 736                 if ( m_notifyQueueId
) 
 738                         MPDeleteQueue( m_notifyQueueId
); 
 739                         m_notifyQueueId 
= kInvalidID 
; 
 744         static OSStatus    
MacThreadStart(void* arg
); 
 746     // create a new (suspended) thread (for the given thread object) 
 747     bool Create(wxThread 
*thread
, unsigned int stackSize
); 
 752     // unblock the thread allowing it to run 
 753     void SignalRun() { m_semRun
.Post(); } 
 754     // ask the thread to terminate 
 756     // go to sleep until Resume() is called 
 763     int GetPriority() const { return m_prio
; } 
 764     void SetPriority(int prio
) ; 
 766     wxThreadState 
GetState() const { return m_state
; } 
 767     void SetState(wxThreadState state
) { m_state 
= state
; } 
 769         // Get the ID of this thread's underlying MP Services task. 
 770         MPTaskID  
GetId() const { return m_tid
; } 
 772     void SetCancelFlag() { m_cancelled 
= TRUE
; } 
 773     bool WasCancelled() const { return m_cancelled
; } 
 775     void SetExitCode(wxThread::ExitCode exitcode
) { m_exitcode 
= exitcode
; } 
 776     wxThread::ExitCode 
GetExitCode() const { return m_exitcode
; } 
 779     void SetReallyPaused(bool paused
) { m_isPaused 
= paused
; } 
 780     bool IsReallyPaused() const { return m_isPaused
; } 
 782     // tell the thread that it is a detached one 
 785         wxCriticalSectionLocker 
lock(m_csJoinFlag
); 
 787         m_shouldBeJoined 
= FALSE
; 
 792     // the thread we're associated with 
 795         MPTaskID        m_tid
;              // thread id 
 796         MPQueueID           m_notifyQueueId
;    // its notification queue 
 798     wxThreadState m_state
;              // see wxThreadState enum 
 799     int           m_prio
;               // in wxWidgets units: from 0 to 100 
 801     // this flag is set when the thread should terminate 
 804     // this flag is set when the thread is blocking on m_semSuspend 
 807     // the thread exit code - only used for joinable (!detached) threads and 
 808     // is only valid after the thread termination 
 809     wxThread::ExitCode m_exitcode
; 
 811     // many threads may call Wait(), but only one of them should call 
 812     // pthread_join(), so we have to keep track of this 
 813     wxCriticalSection m_csJoinFlag
; 
 814     bool m_shouldBeJoined
; 
 817     // this semaphore is posted by Run() and the threads Entry() is not 
 818     // called before it is done 
 819     wxSemaphore m_semRun
; 
 821     // this one is signaled when the thread should resume after having been 
 823     wxSemaphore m_semSuspend
; 
 826 OSStatus 
wxThreadInternal::MacThreadStart(void *parameter
) 
 828         wxThread
* thread 
= (wxThread
*) parameter 
; 
 829     wxThreadInternal 
*pthread 
= thread
->m_internal
; 
 831     // add to TLS so that This() will work 
 832         verify_noerr( MPSetTaskStorageValue( gs_tlsForWXThread 
, (long) thread 
) ) ; 
 834     // have to declare this before pthread_cleanup_push() which defines a 
 838     // wait for the semaphore to be posted from Run() 
 839     pthread
->m_semRun
.Wait(); 
 841     // test whether we should run the run at all - may be it was deleted 
 842     // before it started to Run()? 
 844         wxCriticalSectionLocker 
lock(thread
->m_critsect
); 
 846         dontRunAtAll 
= pthread
->GetState() == STATE_NEW 
&& 
 847                        pthread
->WasCancelled(); 
 852         pthread
->m_exitcode 
= thread
->Entry(); 
 855             wxCriticalSectionLocker 
lock(thread
->m_critsect
); 
 856             pthread
->SetState(STATE_EXITED
); 
 862         if ( pthread
->m_isDetached 
) 
 869         // on mac for the running code the correct thread termination is to 
 872         // terminate the thread 
 873         thread
->Exit(pthread
->m_exitcode
); 
 875         return (OSStatus
) NULL 
; // pthread->m_exitcode; 
 879 bool wxThreadInternal::Create(wxThread 
*thread
, unsigned int stackSize
) 
 881     wxMacMPThreadsInitVerify() ; 
 882     wxASSERT_MSG( m_state 
== STATE_NEW 
&& !m_tid
, 
 883                     _T("Create()ing thread twice?") ); 
 885         OSStatus err 
= noErr 
; 
 888         if ( m_notifyQueueId 
== kInvalidID 
) 
 890                 OSStatus err 
= MPCreateQueue( & m_notifyQueueId
); 
 893                         wxLogSysError(_("Cant create the thread event queue")); 
 900         err 
= MPCreateTask( MacThreadStart
, 
 911                 wxLogSysError(_("Can't create thread"));                 
 915         if ( m_prio 
!= WXTHREAD_DEFAULT_PRIORITY 
) 
 923 void wxThreadInternal::SetPriority( int priority
) 
 929                 // Mac priorities range from 1 to 10,000, with a default of 100. 
 930                 // wxWidgets priorities range from 0 to 100 with a default of 50. 
 931                 // We can map wxWidgets to Mac priorities easily by assuming 
 932                 // the former uses a logarithmic scale. 
 933                 const unsigned int macPriority 
= ( int)( exp( priority 
/ 25.0 * log( 10.0)) + 0.5); 
 935                 MPSetTaskWeight( m_tid
, macPriority
); 
 939 wxThreadError 
wxThreadInternal::Run() 
 941     wxCHECK_MSG( GetState() == STATE_NEW
, wxTHREAD_RUNNING
, 
 942                  wxT("thread may only be started once after Create()") ); 
 944     SetState(STATE_RUNNING
); 
 946     // wake up threads waiting for our start 
 949     return wxTHREAD_NO_ERROR
; 
 952 void wxThreadInternal::Wait() 
 954    wxCHECK_RET( !m_isDetached
, _T("can't wait for a detached thread") ); 
 956     // if the thread we're waiting for is waiting for the GUI mutex, we will 
 957     // deadlock so make sure we release it temporarily 
 958     if ( wxThread::IsMain() ) 
 962         wxCriticalSectionLocker 
lock(m_csJoinFlag
); 
 964         if ( m_shouldBeJoined 
) 
 970             OSStatus err 
= MPWaitOnQueue ( m_notifyQueueId
,  
 977                 wxLogSysError( _( "Cannot wait for thread termination.")); 
 981             // actually param1 would be the address of m_exitcode 
 982             // but we don't need this here 
 985             m_shouldBeJoined 
= FALSE
; 
 989     // reacquire GUI mutex 
 990     if ( wxThread::IsMain() ) 
 994 void wxThreadInternal::Pause() 
 996     // the state is set from the thread which pauses us first, this function 
 997     // is called later so the state should have been already set 
 998     wxCHECK_RET( m_state 
== STATE_PAUSED
, 
 999                  wxT("thread must first be paused with wxThread::Pause().") ); 
1001     // wait until the semaphore is Post()ed from Resume() 
1002     m_semSuspend
.Wait(); 
1005 void wxThreadInternal::Resume() 
1007     wxCHECK_RET( m_state 
== STATE_PAUSED
, 
1008                  wxT("can't resume thread which is not suspended.") ); 
1010     // the thread might be not actually paused yet - if there were no call to 
1011     // TestDestroy() since the last call to Pause() for example 
1012     if ( IsReallyPaused() ) 
1015         m_semSuspend
.Post(); 
1018         SetReallyPaused(FALSE
); 
1021     SetState(STATE_RUNNING
); 
1027 wxThread 
*wxThread::This() 
1029     wxThread
* thr 
= (wxThread
*) MPGetTaskStorageValue( gs_tlsForWXThread 
) ; 
1033 bool wxThread::IsMain() 
1035         return GetCurrentId() == gs_idMainThread
; 
1042 void wxThread::Yield() 
1044 #if TARGET_API_MAC_OSX 
1045         CFRunLoopRunInMode( kCFRunLoopDefaultMode 
, 0 , true ) ; 
1051 void wxThread::Sleep(unsigned long milliseconds
) 
1053         AbsoluteTime wakeup 
= AddDurationToAbsolute( milliseconds
, UpTime()); 
1054         MPDelayUntil( & wakeup
); 
1058 int wxThread::GetCPUCount() 
1060         return MPProcessors(); 
1063 unsigned long wxThread::GetCurrentId() 
1065         return (unsigned long)MPCurrentTaskID(); 
1069 bool wxThread::SetConcurrency(size_t level
) 
1071     // Cannot be set in MacOS. 
1076 wxThread::wxThread(wxThreadKind kind
) 
1078         g_numberOfThreads
++; 
1079         m_internal 
= new wxThreadInternal(); 
1081         m_isDetached 
= (kind 
== wxTHREAD_DETACHED
); 
1084 wxThread::~wxThread() 
1086     wxASSERT_MSG( g_numberOfThreads
>0 , wxT("More threads deleted than created.") ) ; 
1087     g_numberOfThreads
--; 
1092     // check that the thread either exited or couldn't be created 
1093     if ( m_internal
->GetState() != STATE_EXITED 
&& 
1094          m_internal
->GetState() != STATE_NEW 
) 
1096         wxLogDebug(_T("The thread %ld is being destroyed although it is still running! The application may crash."), GetId()); 
1100 #endif // __WXDEBUG__ 
1102     wxDELETE( m_internal 
) ; 
1106 wxThreadError 
wxThread::Create(unsigned int stackSize
) 
1108         wxCriticalSectionLocker 
lock(m_critsect
); 
1112         m_internal
->Detach() ; 
1114         if ( m_internal
->Create(this, stackSize
) == false ) 
1116         m_internal
->SetState(STATE_EXITED
); 
1117         return wxTHREAD_NO_RESOURCE
; 
1120         return wxTHREAD_NO_ERROR
; 
1123 wxThreadError 
wxThread::Run() 
1125     wxCriticalSectionLocker 
lock(m_critsect
); 
1127     wxCHECK_MSG( m_internal
->GetId(), wxTHREAD_MISC_ERROR
, 
1128                  wxT("must call wxThread::Create() first") ); 
1130     return m_internal
->Run(); 
1133 // ----------------------------------------------------------------------------- 
1135 // ----------------------------------------------------------------------------- 
1137 wxThreadError 
wxThread::Pause() 
1139     wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
, 
1140                  _T("a thread can't pause itself") ); 
1142     wxCriticalSectionLocker 
lock(m_critsect
); 
1144     if ( m_internal
->GetState() != STATE_RUNNING 
) 
1146         wxLogDebug(wxT("Can't pause thread which is not running.")); 
1148         return wxTHREAD_NOT_RUNNING
; 
1151     // just set a flag, the thread will be really paused only during the next 
1152     // call to TestDestroy() 
1153     m_internal
->SetState(STATE_PAUSED
); 
1155     return wxTHREAD_NO_ERROR
; 
1158 wxThreadError 
wxThread::Resume() 
1160     wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
, 
1161                  _T("a thread can't resume itself") ); 
1163     wxCriticalSectionLocker 
lock(m_critsect
); 
1165     wxThreadState state 
= m_internal
->GetState(); 
1170             m_internal
->Resume(); 
1171             return wxTHREAD_NO_ERROR
; 
1173             return wxTHREAD_NO_ERROR
; 
1176             wxLogDebug(_T("Attempt to resume a thread which is not paused.")); 
1178             return wxTHREAD_MISC_ERROR
; 
1182 // ----------------------------------------------------------------------------- 
1184 // ----------------------------------------------------------------------------- 
1186 wxThread::ExitCode 
wxThread::Wait() 
1188     wxCHECK_MSG( This() != this, (ExitCode
)-1, 
1189                  _T("a thread can't wait for itself") ); 
1191     wxCHECK_MSG( !m_isDetached
, (ExitCode
)-1, 
1192                  _T("can't wait for detached thread") ); 
1196     return m_internal
->GetExitCode(); 
1199 wxThreadError 
wxThread::Delete(ExitCode 
*rc
) 
1201     wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
, 
1202                  _T("a thread can't delete itself") ); 
1204     bool isDetached 
= m_isDetached
; 
1207     wxThreadState state 
= m_internal
->GetState(); 
1209     // ask the thread to stop 
1210     m_internal
->SetCancelFlag(); 
1217             // we need to wake up the thread so that PthreadStart() will 
1218             // terminate - right now it's blocking on run semaphore in 
1220             m_internal
->SignalRun(); 
1229             // resume the thread first 
1230             m_internal
->Resume(); 
1237                 // wait until the thread stops 
1242                     // return the exit code of the thread 
1243                     *rc 
= m_internal
->GetExitCode(); 
1246             //else: can't wait for detached threads 
1249     return wxTHREAD_NO_ERROR
; 
1252 wxThreadError 
wxThread::Kill() 
1254     wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
, 
1255                  _T("a thread can't kill itself") ); 
1257     switch ( m_internal
->GetState() ) 
1261             return wxTHREAD_NOT_RUNNING
; 
1264             // resume the thread first 
1270             OSStatus err 
= MPTerminateTask( m_internal
->GetId() , -1 ) ; 
1273                 wxLogError(_("Failed to terminate a thread.")); 
1275                 return wxTHREAD_MISC_ERROR
; 
1284                 // this should be retrieved by Wait actually 
1285                 m_internal
->SetExitCode((void*)-1); 
1288             return wxTHREAD_NO_ERROR
; 
1292 void wxThread::Exit(ExitCode status
) 
1294     wxASSERT_MSG( This() == this, 
1295                   _T("wxThread::Exit() can only be called in the context of the same thread") ); 
1297     // don't enter m_critsect before calling OnExit() because the user code 
1298     // might deadlock if, for example, it signals a condition in OnExit() (a 
1299     // common case) while the main thread calls any of functions entering 
1300     // m_critsect on us (almost all of them do) 
1303     MPTerminateTask( m_internal
->GetId() , (long) status
) ; 
1311         // update the status of the joinable thread 
1312         wxCriticalSectionLocker 
lock(m_critsect
); 
1313         m_internal
->SetState(STATE_EXITED
); 
1317 // also test whether we were paused 
1318 bool wxThread::TestDestroy() 
1320     wxASSERT_MSG( This() == this, 
1321                   _T("wxThread::TestDestroy() can only be called in the context of the same thread") ); 
1325     if ( m_internal
->GetState() == STATE_PAUSED 
) 
1327         m_internal
->SetReallyPaused(TRUE
); 
1329         // leave the crit section or the other threads will stop too if they 
1330         // try to call any of (seemingly harmless) IsXXX() functions while we 
1334         m_internal
->Pause(); 
1338         // thread wasn't requested to pause, nothing to do 
1342     return m_internal
->WasCancelled(); 
1345 // ----------------------------------------------------------------------------- 
1347 // ----------------------------------------------------------------------------- 
1349 void wxThread::SetPriority(unsigned int prio
) 
1351     wxCHECK_RET( ((int)WXTHREAD_MIN_PRIORITY 
<= (int)prio
) && 
1352                  ((int)prio 
<= (int)WXTHREAD_MAX_PRIORITY
), 
1353                  wxT("invalid thread priority") ); 
1355     wxCriticalSectionLocker 
lock(m_critsect
); 
1357     switch ( m_internal
->GetState() ) 
1362             // thread not yet started, priority will be set when it is 
1363             m_internal
->SetPriority(prio
); 
1368             wxFAIL_MSG(wxT("impossible to set thread priority in this state")); 
1372 unsigned int wxThread::GetPriority() const 
1374     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); // const_cast 
1376     return m_internal
->GetPriority(); 
1379 unsigned long wxThread::GetId() const 
1381     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); // const_cast 
1383     return (unsigned long)m_internal
->GetId(); 
1386 // ----------------------------------------------------------------------------- 
1388 // ----------------------------------------------------------------------------- 
1390 bool wxThread::IsRunning() const 
1392     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); 
1394     return m_internal
->GetState() == STATE_RUNNING
; 
1397 bool wxThread::IsAlive() const 
1399     wxCriticalSectionLocker 
lock((wxCriticalSection
&)m_critsect
); 
1401     switch ( m_internal
->GetState() ) 
1412 bool wxThread::IsPaused() const 
1414     wxCriticalSectionLocker 
lock((wxCriticalSection
&)m_critsect
); 
1416     return (m_internal
->GetState() == STATE_PAUSED
); 
1419 // ---------------------------------------------------------------------------- 
1420 // Automatic initialization for thread module 
1421 // ---------------------------------------------------------------------------- 
1423 class wxThreadModule 
: public wxModule
 
1426         virtual bool OnInit(); 
1427         virtual void OnExit(); 
1430                 DECLARE_DYNAMIC_CLASS(wxThreadModule
) 
1433 IMPLEMENT_DYNAMIC_CLASS(wxThreadModule
, wxModule
) 
1435 bool wxThreadModule::OnInit() 
1437         if ( !wxMacMPThreadsInitVerify() ) 
1442         verify_noerr( MPAllocateTaskStorageIndex( &gs_tlsForWXThread 
) ) ; 
1443         // main thread's This() is NULL 
1444         verify_noerr( MPSetTaskStorageValue( gs_tlsForWXThread 
, NULL 
) ) ; 
1446         gs_idMainThread 
= wxThread::GetCurrentId() ; 
1448     gs_critsectWaitingForGui 
= new wxCriticalSection(); 
1450     gs_critsectGui 
= new wxCriticalSection(); 
1451     gs_critsectGui
->Enter(); 
1456 void wxThreadModule::OnExit() 
1458     if ( gs_critsectGui 
) 
1460         gs_critsectGui
->Leave(); 
1461         delete gs_critsectGui
; 
1462         gs_critsectGui 
= NULL
; 
1465     delete gs_critsectWaitingForGui
; 
1466     gs_critsectWaitingForGui 
= NULL
; 
1469 // ---------------------------------------------------------------------------- 
1470 // GUI Serialization copied from MSW implementation 
1471 // ---------------------------------------------------------------------------- 
1473 void WXDLLIMPEXP_BASE 
wxMutexGuiEnter() 
1475     // this would dead lock everything... 
1476     wxASSERT_MSG( !wxThread::IsMain(), 
1477                   wxT("main thread doesn't want to block in wxMutexGuiEnter()!") ); 
1479     // the order in which we enter the critical sections here is crucial!! 
1481     // set the flag telling to the main thread that we want to do some GUI 
1483         wxCriticalSectionLocker 
enter(*gs_critsectWaitingForGui
); 
1485         gs_nWaitingForGui
++; 
1488     wxWakeUpMainThread(); 
1490     // now we may block here because the main thread will soon let us in 
1491     // (during the next iteration of OnIdle()) 
1492     gs_critsectGui
->Enter(); 
1495 void WXDLLIMPEXP_BASE 
wxMutexGuiLeave() 
1497     wxCriticalSectionLocker 
enter(*gs_critsectWaitingForGui
); 
1499     if ( wxThread::IsMain() ) 
1501         gs_bGuiOwnedByMainThread 
= false; 
1505         // decrement the number of threads waiting for GUI access now 
1506         wxASSERT_MSG( gs_nWaitingForGui 
> 0, 
1507                       wxT("calling wxMutexGuiLeave() without entering it first?") ); 
1509         gs_nWaitingForGui
--; 
1511         wxWakeUpMainThread(); 
1514     gs_critsectGui
->Leave(); 
1517 void WXDLLIMPEXP_BASE 
wxMutexGuiLeaveOrEnter() 
1519     wxASSERT_MSG( wxThread::IsMain(), 
1520                   wxT("only main thread may call wxMutexGuiLeaveOrEnter()!") ); 
1522     wxCriticalSectionLocker 
enter(*gs_critsectWaitingForGui
); 
1524     if ( gs_nWaitingForGui 
== 0 ) 
1526         // no threads are waiting for GUI - so we may acquire the lock without 
1527         // any danger (but only if we don't already have it) 
1528         if ( !wxGuiOwnedByMainThread() ) 
1530             gs_critsectGui
->Enter(); 
1532             gs_bGuiOwnedByMainThread 
= true; 
1534         //else: already have it, nothing to do 
1538         // some threads are waiting, release the GUI lock if we have it 
1539         if ( wxGuiOwnedByMainThread() ) 
1543         //else: some other worker thread is doing GUI 
1547 bool WXDLLIMPEXP_BASE 
wxGuiOwnedByMainThread() 
1549     return gs_bGuiOwnedByMainThread
; 
1552 // wake up the main thread 
1553 void WXDLLEXPORT 
wxWakeUpMainThread() 
1558 // ---------------------------------------------------------------------------- 
1559 // include common implementation code 
1560 // ---------------------------------------------------------------------------- 
1562 #include "wx/thrimpl.cpp" 
1564 #endif // wxUSE_THREADS