1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:      src/mac/carbon/mpthread.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 // ---------------------------------------------------------------------------- 
  15 // ---------------------------------------------------------------------------- 
  17 // For compilers that support precompilation, includes "wx.h". 
  18 #include "wx/wxprec.h" 
  20 #if defined(__BORLANDC__) 
  28     #include "wx/module.h" 
  31 #include "wx/thread.h" 
  34 #if TARGET_API_MAC_OSX 
  35 #include <CoreServices/CoreServices.h> 
  37 #include <DriverServices.h> 
  38 #include <Multiprocessing.h> 
  40 #include "wx/mac/uma.h" 
  43 // ---------------------------------------------------------------------------- 
  45 // ---------------------------------------------------------------------------- 
  47 // the possible states of the thread ("=>" shows all possible transitions from 
  51     STATE_NEW
,      // didn't start execution yet (=> RUNNING) 
  52     STATE_RUNNING
,  // thread is running (=> PAUSED, CANCELED) 
  53     STATE_PAUSED
,   // thread is temporarily suspended (=> RUNNING) 
  54     STATE_CANCELED
, // thread should terminate a.s.a.p. (=> EXITED) 
  55     STATE_EXITED    
// thread is terminating 
  58 // ---------------------------------------------------------------------------- 
  59 // this module globals 
  60 // ---------------------------------------------------------------------------- 
  63 // the task ID of the main thread 
  64 static wxThreadIdType gs_idMainThread 
= kInvalidID
; 
  66 // this is the Per-Task Storage for the pointer to the appropriate wxThread 
  67 TaskStorageIndex gs_tlsForWXThread 
= 0 ; 
  69 // if it's false, some secondary thread is holding the GUI lock 
  70 static bool gs_bGuiOwnedByMainThread 
= true; 
  72 // critical section which controls access to all GUI functions: any secondary 
  73 // thread (i.e. except the main one) must enter this crit section before doing 
  75 static wxCriticalSection 
*gs_critsectGui 
= NULL
; 
  77 // critical section which protects gs_nWaitingForGui variable 
  78 static wxCriticalSection 
*gs_critsectWaitingForGui 
= NULL
; 
  80 // number of threads waiting for GUI in wxMutexGuiEnter() 
  81 static size_t gs_nWaitingForGui 
= 0; 
  83 // overall number of threads, needed for determining the sleep value of the main 
  85 size_t g_numberOfThreads 
= 0; 
  91 MPCriticalRegionID gs_guiCritical 
= kInvalidID
; 
  95 // ============================================================================ 
  96 // MacOS implementation of thread classes 
  97 // ============================================================================ 
 102     The implementation is very close to the phtreads implementation, the reason for 
 103     using MPServices is the fact that these are also available under OS 9. Thus allowing 
 104     for one common API for all current builds. 
 106     As soon as wxThreads are on a 64 bit address space, the TLS must be extended 
 107     to use two indices one for each 32 bit part as the MP implementation is limited 
 110     I have two implementations for mutexes : 
 111     version A based on a binary semaphore, problem - not reentrant, version B based 
 112     on a critical region, allows for reentrancy, performance implications not 
 115     The same for condition internal, one implementation by Aj Lavin and the other one 
 116     copied from the thrimpl.cpp which I assume has been more broadly tested, I've just 
 117     replaced the interlock increment with the appropriate PPC calls 
 120 // ---------------------------------------------------------------------------- 
 121 // wxMutex implementation 
 122 // ---------------------------------------------------------------------------- 
 124 static bool wxMacMPThreadsInitVerify() 
 126     static bool hasThreadManager 
= false ; 
 127     if ( !hasThreadManager 
) 
 128         hasThreadManager 
= MPLibraryIsLoaded(); 
 130     if ( !hasThreadManager 
) 
 132         wxMessageBox( wxT("Error") , wxT("MP Thread Support is not available on this System" ), wxOK 
) ; 
 140 class wxMutexInternal
 
 143     wxMutexInternal(wxMutexType mutexType
) ; 
 145     bool IsOk() const { return m_isOk
; } 
 147     wxMutexError 
Lock() ; 
 148     wxMutexError 
TryLock() ; 
 149     wxMutexError 
Unlock(); 
 151     MPSemaphoreID m_semaphore
; 
 155 wxMutexInternal::wxMutexInternal(wxMutexType mutexType 
) 
 157     wxMacMPThreadsInitVerify() ; 
 160     m_semaphore 
= kInvalidID 
; 
 162     OSStatus err 
= noErr 
; 
 165         case wxMUTEX_DEFAULT 
: 
 167                 verify_noerr( MPCreateBinarySemaphore( & m_semaphore
) ); 
 168                 m_isOk 
= ( m_semaphore 
!= kInvalidID 
) ; 
 171         case wxMUTEX_RECURSIVE 
: 
 172             wxFAIL_MSG(wxT("Recursive Mutex not supported yet") ) ; 
 175             wxFAIL_MSG(wxT("Unknown mutex type") ) ; 
 180 wxMutexInternal::~wxMutexInternal() 
 182     if ( m_semaphore 
!= kInvalidID 
) 
 183         MPDeleteSemaphore( m_semaphore
); 
 186 wxMutexError 
wxMutexInternal::Lock() 
 188     wxCHECK_MSG( m_isOk 
, wxMUTEX_MISC_ERROR 
, wxT("Invalid Mutex") ) ; 
 189     OSStatus err 
= MPWaitOnSemaphore( m_semaphore
, kDurationForever
); 
 192         wxLogSysError(wxT("Could not lock mutex")); 
 193         return wxMUTEX_MISC_ERROR
; 
 196     return wxMUTEX_NO_ERROR
; 
 199 wxMutexError 
wxMutexInternal::TryLock() 
 201     wxCHECK_MSG( m_isOk 
, wxMUTEX_MISC_ERROR 
, wxT("Invalid Mutex") ) ; 
 202     OSStatus err 
= MPWaitOnSemaphore( m_semaphore
, kDurationImmediate
); 
 205         if ( err 
== kMPTimeoutErr
) 
 209         wxLogSysError(wxT("Could not try lock mutex")); 
 210         return wxMUTEX_MISC_ERROR
; 
 213     return wxMUTEX_NO_ERROR
; 
 216 wxMutexError 
wxMutexInternal::Unlock() 
 218     wxCHECK_MSG( m_isOk 
, wxMUTEX_MISC_ERROR 
, wxT("Invalid Mutex") ) ; 
 219     OSStatus err 
= MPSignalSemaphore( m_semaphore
); 
 222         wxLogSysError(_("Could not unlock mutex")); 
 223         return wxMUTEX_MISC_ERROR
; 
 226     return wxMUTEX_NO_ERROR
; 
 231 class wxMutexInternal
 
 234     wxMutexInternal(wxMutexType mutexType
) ; 
 236     bool IsOk() const { return m_isOk
; } 
 238     wxMutexError 
Lock() ; 
 239     wxMutexError 
TryLock() ; 
 240     wxMutexError 
Unlock(); 
 242     MPCriticalRegionID m_critRegion 
; 
 246 wxMutexInternal::wxMutexInternal(wxMutexType mutexType 
) 
 248     wxMacMPThreadsInitVerify() ; 
 250     m_critRegion 
= kInvalidID 
; 
 252     verify_noerr( MPCreateCriticalRegion( & m_critRegion
) ); 
 253     m_isOk 
= ( m_critRegion 
!= kInvalidID 
) ; 
 256         wxFAIL_MSG(wxT("Error when creating mutex") ) ; 
 259 wxMutexInternal::~wxMutexInternal() 
 261     if ( m_critRegion 
!= kInvalidID 
) 
 262         MPDeleteCriticalRegion( m_critRegion
); 
 265 wxMutexError 
wxMutexInternal::Lock() 
 267     wxCHECK_MSG( m_isOk 
, wxMUTEX_MISC_ERROR 
, wxT("Invalid Mutex") ) ; 
 268     OSStatus err 
= MPEnterCriticalRegion( m_critRegion
, kDurationForever
); 
 271         wxLogSysError(wxT("Could not lock mutex")); 
 272         return wxMUTEX_MISC_ERROR
; 
 275     return wxMUTEX_NO_ERROR
; 
 278 wxMutexError 
wxMutexInternal::TryLock() 
 280     wxCHECK_MSG( m_isOk 
, wxMUTEX_MISC_ERROR 
, wxT("Invalid Mutex") ) ; 
 281     OSStatus err 
= MPEnterCriticalRegion( m_critRegion
, kDurationImmediate
); 
 284         if ( err 
== kMPTimeoutErr
) 
 288         wxLogSysError(wxT("Could not try lock mutex")); 
 289         return wxMUTEX_MISC_ERROR
; 
 292     return wxMUTEX_NO_ERROR
; 
 295 wxMutexError 
wxMutexInternal::Unlock() 
 297     wxCHECK_MSG( m_isOk 
, wxMUTEX_MISC_ERROR 
, wxT("Invalid Mutex") ) ; 
 298     OSStatus err 
= MPExitCriticalRegion( m_critRegion
); 
 301         wxLogSysError(_("Could not unlock mutex")); 
 302         return wxMUTEX_MISC_ERROR
; 
 305     return wxMUTEX_NO_ERROR
; 
 310 // -------------------------------------------------------------------------- 
 312 // -------------------------------------------------------------------------- 
 314 class wxSemaphoreInternal
 
 317     wxSemaphoreInternal(int initialcount
, int maxcount
); 
 318     ~wxSemaphoreInternal(); 
 320     bool IsOk() const { return m_isOk
; } 
 322     wxSemaError 
WaitTimeout(unsigned long milliseconds
); 
 324     wxSemaError 
Wait() { return WaitTimeout( kDurationForever
); } 
 326     wxSemaError 
TryWait() 
 328         wxSemaError err 
= WaitTimeout(kDurationImmediate
); 
 329         if ( err 
== wxSEMA_TIMEOUT 
) 
 336     MPSemaphoreID m_semaphore
; 
 340 wxSemaphoreInternal::wxSemaphoreInternal(int initialcount
, int maxcount
) 
 342     wxMacMPThreadsInitVerify() ; 
 344     m_semaphore 
= kInvalidID 
; 
 347         // make it practically infinite 
 350     verify_noerr( MPCreateSemaphore( maxcount
, initialcount
, & m_semaphore
) ); 
 351     m_isOk 
= ( m_semaphore 
!= kInvalidID 
) ; 
 354         wxFAIL_MSG(wxT("Error when creating semaphore") ) ; 
 357 wxSemaphoreInternal::~wxSemaphoreInternal() 
 359     if( m_semaphore 
!= kInvalidID 
) 
 360         MPDeleteSemaphore( m_semaphore
); 
 363 wxSemaError 
wxSemaphoreInternal::WaitTimeout(unsigned long milliseconds
) 
 365     OSStatus err 
= MPWaitOnSemaphore( m_semaphore
, milliseconds
); 
 368         if ( err 
== kMPTimeoutErr
) 
 370             return wxSEMA_TIMEOUT
; 
 372         return wxSEMA_MISC_ERROR
; 
 374     return wxSEMA_NO_ERROR
; 
 377 wxSemaError 
wxSemaphoreInternal::Post() 
 379     OSStatus err 
= MPSignalSemaphore( m_semaphore
); 
 382         return wxSEMA_MISC_ERROR
; 
 384     return wxSEMA_NO_ERROR
; 
 387 // ---------------------------------------------------------------------------- 
 388 // wxCondition implementation 
 389 // ---------------------------------------------------------------------------- 
 393 class wxConditionInternal
 
 397     wxConditionInternal(wxMutex
& mutex
) 
 407     ~wxConditionInternal() 
 411     bool IsOk() const { return m_mutex
.IsOk() ; } 
 415         return WaitTimeout( kDurationForever
); 
 418     wxCondError 
WaitTimeout(unsigned long msectimeout
); 
 422         return DoSignal( false); 
 425     wxCondError 
Broadcast() 
 427         return DoSignal( true); 
 432     wxCondError 
DoSignal( bool signalAll
); 
 435     wxSemaphoreInternal     m_semaphore
;  // Signals the waiting threads. 
 436     wxSemaphoreInternal     m_gate
; 
 437     wxCriticalSection       m_varSection
; 
 438     size_t                  m_waiters
;    // Number of threads waiting for a signal. 
 439     size_t                  m_signals
;    // Number of signals to send. 
 440     size_t                  m_canceled
;   // Number of canceled waiters in m_waiters. 
 444 wxCondError 
wxConditionInternal::WaitTimeout(unsigned long msectimeout
) 
 447         if ( ++ m_waiters 
== INT_MAX
) 
 449                 m_varSection
.Enter(); 
 450                 m_waiters 
-= m_canceled
; 
 451                 m_signals 
-= m_canceled
; 
 453                 m_varSection
.Leave(); 
 459         wxSemaError err 
= m_semaphore
.WaitTimeout( msectimeout
); 
 460         wxASSERT( err 
== wxSEMA_NO_ERROR 
|| err 
== wxSEMA_TIMEOUT
); 
 462         m_varSection
.Enter(); 
 463         if ( err 
!= wxSEMA_NO_ERROR
) 
 465                 if ( m_signals 
> m_canceled
) 
 467                         // A signal is being sent after we timed out. 
 469                         if ( m_waiters 
== m_signals
) 
 471                                 // There are no excess waiters to catch the signal, so 
 472                                 // we must throw it away. 
 474                                 wxSemaError err2 
= m_semaphore
.Wait(); 
 475                                 if ( err2 
!= wxSEMA_NO_ERROR
) 
 477                                         wxLogSysError(_("Error while waiting on semaphore")); 
 479                                 wxASSERT( err2 
== wxSEMA_NO_ERROR
); 
 481                                 if ( -- m_signals 
== m_canceled
) 
 483                                         // This was the last signal. open the gate. 
 484                                         wxASSERT( m_waiters 
== m_canceled
); 
 490                                 // There are excess waiters to catch the signal, leave 
 497                         // No signals is being sent. 
 498                         // The gate may be open or closed, so we can't touch m_waiters. 
 505                 // We caught a signal. 
 506                 wxASSERT( m_signals 
> m_canceled
); 
 508                 if ( -- m_signals 
== m_canceled
) 
 510                         // This was the last signal. open the gate. 
 511                         wxASSERT( m_waiters 
== m_canceled
); 
 515         m_varSection
.Leave(); 
 521                 return err 
== wxSEMA_TIMEOUT 
? wxCOND_TIMEOUT 
: wxCOND_MISC_ERROR
; 
 524     return wxCOND_NO_ERROR
; 
 528 wxCondError 
wxConditionInternal::DoSignal( bool signalAll
) 
 531         m_varSection
.Enter(); 
 533         wxASSERT( m_signals 
== m_canceled
); 
 535         if ( m_waiters 
== m_canceled
) 
 537                 m_varSection
.Leave(); 
 539                 return wxCOND_NO_ERROR
; 
 544                 m_waiters 
-= m_canceled
; 
 549         m_signals 
= signalAll 
? m_waiters 
: 1; 
 550         size_t n 
= m_signals
; 
 552         m_varSection
.Leave(); 
 554         // Let the waiters inherit the gate lock. 
 558                 wxSemaError err 
= m_semaphore
.Post(); 
 559                 wxASSERT( err 
== wxSEMA_NO_ERROR
); 
 562         return wxCOND_NO_ERROR
; 
 566 class wxConditionInternal
 
 569     wxConditionInternal(wxMutex
& mutex
); 
 571     bool IsOk() const { return m_mutex
.IsOk() && m_semaphore
.IsOk(); } 
 574     wxCondError 
WaitTimeout(unsigned long milliseconds
); 
 576     wxCondError 
Signal(); 
 577     wxCondError 
Broadcast(); 
 580     // the number of threads currently waiting for this condition 
 583     // the critical section protecting m_numWaiters 
 584     wxCriticalSection m_csWaiters
; 
 587     wxSemaphore m_semaphore
; 
 589     DECLARE_NO_COPY_CLASS(wxConditionInternal
) 
 592 wxConditionInternal::wxConditionInternal(wxMutex
& mutex
) 
 595     // another thread can't access it until we return from ctor, so no need to 
 596     // protect access to m_numWaiters here 
 600 wxCondError 
wxConditionInternal::Wait() 
 602     // increment the number of waiters 
 603     IncrementAtomic(&m_numWaiters
); 
 607     // a potential race condition can occur here 
 609     // after a thread increments nwaiters, and unlocks the mutex and before the 
 610     // semaphore.Wait() is called, if another thread can cause a signal to be 
 613     // this race condition is handled by using a semaphore and incrementing the 
 614     // semaphore only if 'nwaiters' is greater that zero since the semaphore, 
 615     // can 'remember' signals the race condition will not occur 
 617     // wait ( if necessary ) and decrement semaphore 
 618     wxSemaError err 
= m_semaphore
.Wait(); 
 621     return err 
== wxSEMA_NO_ERROR 
? wxCOND_NO_ERROR 
: wxCOND_MISC_ERROR
; 
 624 wxCondError 
wxConditionInternal::WaitTimeout(unsigned long milliseconds
) 
 626     IncrementAtomic(&m_numWaiters
); 
 630     // a race condition can occur at this point in the code 
 632     // please see the comments in Wait(), for details 
 634     wxSemaError err 
= m_semaphore
.WaitTimeout(milliseconds
); 
 636     if ( err 
== wxSEMA_BUSY 
) 
 638         // another potential race condition exists here it is caused when a 
 639         // 'waiting' thread timesout, and returns from WaitForSingleObject, but 
 640         // has not yet decremented 'nwaiters'. 
 642         // at this point if another thread calls signal() then the semaphore 
 643         // will be incremented, but the waiting thread will miss it. 
 645         // to handle this particular case, the waiting thread calls 
 646         // WaitForSingleObject again with a timeout of 0, after locking 
 647         // 'nwaiters_mutex'. this call does not block because of the zero 
 648         // timeout, but will allow the waiting thread to catch the missed 
 650         wxCriticalSectionLocker 
lock(m_csWaiters
); 
 652         err 
= m_semaphore
.WaitTimeout(0); 
 654         if ( err 
!= wxSEMA_NO_ERROR 
) 
 662     return err 
== wxSEMA_NO_ERROR 
? wxCOND_NO_ERROR 
: wxCOND_MISC_ERROR
; 
 665 wxCondError 
wxConditionInternal::Signal() 
 667     wxCriticalSectionLocker 
lock(m_csWaiters
); 
 669     if ( m_numWaiters 
> 0 ) 
 671         // increment the semaphore by 1 
 672         if ( m_semaphore
.Post() != wxSEMA_NO_ERROR 
) 
 673             return wxCOND_MISC_ERROR
; 
 678     return wxCOND_NO_ERROR
; 
 681 wxCondError 
wxConditionInternal::Broadcast() 
 683     wxCriticalSectionLocker 
lock(m_csWaiters
); 
 685     while ( m_numWaiters 
> 0 ) 
 687         if ( m_semaphore
.Post() != wxSEMA_NO_ERROR 
) 
 688             return wxCOND_MISC_ERROR
; 
 693     return wxCOND_NO_ERROR
; 
 697 // ---------------------------------------------------------------------------- 
 698 // wxCriticalSection implementation 
 699 // ---------------------------------------------------------------------------- 
 701 // XXX currently implemented as mutex in headers. Change to critical section. 
 703 // ---------------------------------------------------------------------------- 
 704 // wxThread implementation 
 705 // ---------------------------------------------------------------------------- 
 707 // wxThreadInternal class 
 708 // ---------------------- 
 710 class wxThreadInternal
 
 717                 m_prio 
= WXTHREAD_DEFAULT_PRIORITY
; 
 718                 m_notifyQueueId 
= kInvalidID
; 
 720         m_cancelled 
= false ; 
 722         // set to true only when the thread starts waiting on m_semSuspend 
 725         // defaults for joinable threads 
 726         m_shouldBeJoined 
= true; 
 727         m_isDetached 
= false; 
 731                 if ( m_notifyQueueId
) 
 733                         MPDeleteQueue( m_notifyQueueId
); 
 734                         m_notifyQueueId 
= kInvalidID 
; 
 739         static OSStatus    
MacThreadStart(void* arg
); 
 741     // create a new (suspended) thread (for the given thread object) 
 742     bool Create(wxThread 
*thread
, unsigned int stackSize
); 
 747     // unblock the thread allowing it to run 
 748     void SignalRun() { m_semRun
.Post(); } 
 749     // ask the thread to terminate 
 751     // go to sleep until Resume() is called 
 758     int GetPriority() const { return m_prio
; } 
 759     void SetPriority(int prio
) ; 
 761     wxThreadState 
GetState() const { return m_state
; } 
 762     void SetState(wxThreadState state
) { m_state 
= state
; } 
 764         // Get the ID of this thread's underlying MP Services task. 
 765         MPTaskID  
GetId() const { return m_tid
; } 
 767     void SetCancelFlag() { m_cancelled 
= true; } 
 768     bool WasCancelled() const { return m_cancelled
; } 
 770     void SetExitCode(wxThread::ExitCode exitcode
) { m_exitcode 
= exitcode
; } 
 771     wxThread::ExitCode 
GetExitCode() const { return m_exitcode
; } 
 774     void SetReallyPaused(bool paused
) { m_isPaused 
= paused
; } 
 775     bool IsReallyPaused() const { return m_isPaused
; } 
 777     // tell the thread that it is a detached one 
 780         wxCriticalSectionLocker 
lock(m_csJoinFlag
); 
 782         m_shouldBeJoined 
= false; 
 787     // the thread we're associated with 
 790         MPTaskID        m_tid
;              // thread id 
 791         MPQueueID           m_notifyQueueId
;    // its notification queue 
 793     wxThreadState m_state
;              // see wxThreadState enum 
 794     int           m_prio
;               // in wxWidgets units: from 0 to 100 
 796     // this flag is set when the thread should terminate 
 799     // this flag is set when the thread is blocking on m_semSuspend 
 802     // the thread exit code - only used for joinable (!detached) threads and 
 803     // is only valid after the thread termination 
 804     wxThread::ExitCode m_exitcode
; 
 806     // many threads may call Wait(), but only one of them should call 
 807     // pthread_join(), so we have to keep track of this 
 808     wxCriticalSection m_csJoinFlag
; 
 809     bool m_shouldBeJoined
; 
 812     // this semaphore is posted by Run() and the threads Entry() is not 
 813     // called before it is done 
 814     wxSemaphore m_semRun
; 
 816     // this one is signaled when the thread should resume after having been 
 818     wxSemaphore m_semSuspend
; 
 821 OSStatus 
wxThreadInternal::MacThreadStart(void *parameter
) 
 823         wxThread
* thread 
= (wxThread
*) parameter 
; 
 824     wxThreadInternal 
*pthread 
= thread
->m_internal
; 
 826     // add to TLS so that This() will work 
 827         verify_noerr( MPSetTaskStorageValue( gs_tlsForWXThread 
, (long) thread 
) ) ; 
 829     // have to declare this before pthread_cleanup_push() which defines a 
 833     // wait for the semaphore to be posted from Run() 
 834     pthread
->m_semRun
.Wait(); 
 836     // test whether we should run the run at all - may be it was deleted 
 837     // before it started to Run()? 
 839         wxCriticalSectionLocker 
lock(thread
->m_critsect
); 
 841         dontRunAtAll 
= pthread
->GetState() == STATE_NEW 
&& 
 842                        pthread
->WasCancelled(); 
 847         pthread
->m_exitcode 
= thread
->Entry(); 
 850             wxCriticalSectionLocker 
lock(thread
->m_critsect
); 
 851             pthread
->SetState(STATE_EXITED
); 
 857         if ( pthread
->m_isDetached 
) 
 864         // on mac for the running code the correct thread termination is to 
 867         // terminate the thread 
 868         thread
->Exit(pthread
->m_exitcode
); 
 870         return (OSStatus
) NULL 
; // pthread->m_exitcode; 
 874 bool wxThreadInternal::Create(wxThread 
*thread
, unsigned int stackSize
) 
 876     wxMacMPThreadsInitVerify() ; 
 877     wxASSERT_MSG( m_state 
== STATE_NEW 
&& !m_tid
, 
 878                     _T("Create()ing thread twice?") ); 
 880         OSStatus err 
= noErr 
; 
 883         if ( m_notifyQueueId 
== kInvalidID 
) 
 885                 OSStatus err 
= MPCreateQueue( & m_notifyQueueId
); 
 888                         wxLogSysError(_("Cant create the thread event queue")); 
 895         err 
= MPCreateTask( MacThreadStart
, 
 906                 wxLogSysError(_("Can't create thread")); 
 910         if ( m_prio 
!= WXTHREAD_DEFAULT_PRIORITY 
) 
 918 void wxThreadInternal::SetPriority( int priority
) 
 924                 // Mac priorities range from 1 to 10,000, with a default of 100. 
 925                 // wxWidgets priorities range from 0 to 100 with a default of 50. 
 926                 // We can map wxWidgets to Mac priorities easily by assuming 
 927                 // the former uses a logarithmic scale. 
 928                 const unsigned int macPriority 
= ( int)( exp( priority 
/ 25.0 * log( 10.0)) + 0.5); 
 930                 MPSetTaskWeight( m_tid
, macPriority
); 
 934 wxThreadError 
wxThreadInternal::Run() 
 936     wxCHECK_MSG( GetState() == STATE_NEW
, wxTHREAD_RUNNING
, 
 937                  wxT("thread may only be started once after Create()") ); 
 939     SetState(STATE_RUNNING
); 
 941     // wake up threads waiting for our start 
 944     return wxTHREAD_NO_ERROR
; 
 947 void wxThreadInternal::Wait() 
 949    wxCHECK_RET( !m_isDetached
, _T("can't wait for a detached thread") ); 
 951     // if the thread we're waiting for is waiting for the GUI mutex, we will 
 952     // deadlock so make sure we release it temporarily 
 953     if ( wxThread::IsMain() ) 
 957         wxCriticalSectionLocker 
lock(m_csJoinFlag
); 
 959         if ( m_shouldBeJoined 
) 
 965             OSStatus err 
= MPWaitOnQueue ( m_notifyQueueId
, 
 972                 wxLogSysError( _( "Cannot wait for thread termination.")); 
 976             // actually param1 would be the address of m_exitcode 
 977             // but we don't need this here 
 980             m_shouldBeJoined 
= false; 
 984     // reacquire GUI mutex 
 985     if ( wxThread::IsMain() ) 
 989 void wxThreadInternal::Pause() 
 991     // the state is set from the thread which pauses us first, this function 
 992     // is called later so the state should have been already set 
 993     wxCHECK_RET( m_state 
== STATE_PAUSED
, 
 994                  wxT("thread must first be paused with wxThread::Pause().") ); 
 996     // wait until the semaphore is Post()ed from Resume() 
1000 void wxThreadInternal::Resume() 
1002     wxCHECK_RET( m_state 
== STATE_PAUSED
, 
1003                  wxT("can't resume thread which is not suspended.") ); 
1005     // the thread might be not actually paused yet - if there were no call to 
1006     // TestDestroy() since the last call to Pause() for example 
1007     if ( IsReallyPaused() ) 
1010         m_semSuspend
.Post(); 
1013         SetReallyPaused(FALSE
); 
1016     SetState(STATE_RUNNING
); 
1022 wxThread 
*wxThread::This() 
1024     wxThread
* thr 
= (wxThread
*) MPGetTaskStorageValue( gs_tlsForWXThread 
) ; 
1028 bool wxThread::IsMain() 
1030         return GetCurrentId() == gs_idMainThread
; 
1037 void wxThread::Yield() 
1039 #if TARGET_API_MAC_OSX 
1040         CFRunLoopRunInMode( kCFRunLoopDefaultMode 
, 0 , true ) ; 
1046 void wxThread::Sleep(unsigned long milliseconds
) 
1048         AbsoluteTime wakeup 
= AddDurationToAbsolute( milliseconds
, UpTime()); 
1049         MPDelayUntil( & wakeup
); 
1053 int wxThread::GetCPUCount() 
1055         return MPProcessors(); 
1058 unsigned long wxThread::GetCurrentId() 
1060         return (unsigned long)MPCurrentTaskID(); 
1064 bool wxThread::SetConcurrency(size_t level
) 
1066     // Cannot be set in MacOS. 
1071 wxThread::wxThread(wxThreadKind kind
) 
1073         g_numberOfThreads
++; 
1074         m_internal 
= new wxThreadInternal(); 
1076         m_isDetached 
= (kind 
== wxTHREAD_DETACHED
); 
1079 wxThread::~wxThread() 
1081     wxASSERT_MSG( g_numberOfThreads
>0 , wxT("More threads deleted than created.") ) ; 
1082     g_numberOfThreads
--; 
1087     // check that the thread either exited or couldn't be created 
1088     if ( m_internal
->GetState() != STATE_EXITED 
&& 
1089          m_internal
->GetState() != STATE_NEW 
) 
1091         wxLogDebug(_T("The thread %ld is being destroyed although it is still running! The application may crash."), GetId()); 
1095 #endif // __WXDEBUG__ 
1097     wxDELETE( m_internal 
) ; 
1101 wxThreadError 
wxThread::Create(unsigned int stackSize
) 
1103         wxCriticalSectionLocker 
lock(m_critsect
); 
1107         m_internal
->Detach() ; 
1109         if ( m_internal
->Create(this, stackSize
) == false ) 
1111         m_internal
->SetState(STATE_EXITED
); 
1112         return wxTHREAD_NO_RESOURCE
; 
1115         return wxTHREAD_NO_ERROR
; 
1118 wxThreadError 
wxThread::Run() 
1120     wxCriticalSectionLocker 
lock(m_critsect
); 
1122     wxCHECK_MSG( m_internal
->GetId(), wxTHREAD_MISC_ERROR
, 
1123                  wxT("must call wxThread::Create() first") ); 
1125     return m_internal
->Run(); 
1128 // ----------------------------------------------------------------------------- 
1130 // ----------------------------------------------------------------------------- 
1132 wxThreadError 
wxThread::Pause() 
1134     wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
, 
1135                  _T("a thread can't pause itself") ); 
1137     wxCriticalSectionLocker 
lock(m_critsect
); 
1139     if ( m_internal
->GetState() != STATE_RUNNING 
) 
1141         wxLogDebug(wxT("Can't pause thread which is not running.")); 
1143         return wxTHREAD_NOT_RUNNING
; 
1146     // just set a flag, the thread will be really paused only during the next 
1147     // call to TestDestroy() 
1148     m_internal
->SetState(STATE_PAUSED
); 
1150     return wxTHREAD_NO_ERROR
; 
1153 wxThreadError 
wxThread::Resume() 
1155     wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
, 
1156                  _T("a thread can't resume itself") ); 
1158     wxCriticalSectionLocker 
lock(m_critsect
); 
1160     wxThreadState state 
= m_internal
->GetState(); 
1165             m_internal
->Resume(); 
1166             return wxTHREAD_NO_ERROR
; 
1168             return wxTHREAD_NO_ERROR
; 
1171             wxLogDebug(_T("Attempt to resume a thread which is not paused.")); 
1173             return wxTHREAD_MISC_ERROR
; 
1177 // ----------------------------------------------------------------------------- 
1179 // ----------------------------------------------------------------------------- 
1181 wxThread::ExitCode 
wxThread::Wait() 
1183     wxCHECK_MSG( This() != this, (ExitCode
)-1, 
1184                  _T("a thread can't wait for itself") ); 
1186     wxCHECK_MSG( !m_isDetached
, (ExitCode
)-1, 
1187                  _T("can't wait for detached thread") ); 
1191     return m_internal
->GetExitCode(); 
1194 wxThreadError 
wxThread::Delete(ExitCode 
*rc
) 
1196     wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
, 
1197                  _T("a thread can't delete itself") ); 
1199     bool isDetached 
= m_isDetached
; 
1202     wxThreadState state 
= m_internal
->GetState(); 
1204     // ask the thread to stop 
1205     m_internal
->SetCancelFlag(); 
1212             // we need to wake up the thread so that PthreadStart() will 
1213             // terminate - right now it's blocking on run semaphore in 
1215             m_internal
->SignalRun(); 
1224             // resume the thread first 
1225             m_internal
->Resume(); 
1232                 // wait until the thread stops 
1237                     // return the exit code of the thread 
1238                     *rc 
= m_internal
->GetExitCode(); 
1241             //else: can't wait for detached threads 
1244     return wxTHREAD_NO_ERROR
; 
1247 wxThreadError 
wxThread::Kill() 
1249     wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
, 
1250                  _T("a thread can't kill itself") ); 
1252     switch ( m_internal
->GetState() ) 
1256             return wxTHREAD_NOT_RUNNING
; 
1259             // resume the thread first 
1265             OSStatus err 
= MPTerminateTask( m_internal
->GetId() , -1 ) ; 
1268                 wxLogError(_("Failed to terminate a thread.")); 
1270                 return wxTHREAD_MISC_ERROR
; 
1279                 // this should be retrieved by Wait actually 
1280                 m_internal
->SetExitCode((void*)-1); 
1283             return wxTHREAD_NO_ERROR
; 
1287 void wxThread::Exit(ExitCode status
) 
1289     wxASSERT_MSG( This() == this, 
1290                   _T("wxThread::Exit() can only be called in the context of the same thread") ); 
1292     // don't enter m_critsect before calling OnExit() because the user code 
1293     // might deadlock if, for example, it signals a condition in OnExit() (a 
1294     // common case) while the main thread calls any of functions entering 
1295     // m_critsect on us (almost all of them do) 
1298     MPTerminateTask( m_internal
->GetId() , (long) status
) ; 
1306         // update the status of the joinable thread 
1307         wxCriticalSectionLocker 
lock(m_critsect
); 
1308         m_internal
->SetState(STATE_EXITED
); 
1312 // also test whether we were paused 
1313 bool wxThread::TestDestroy() 
1315     wxASSERT_MSG( This() == this, 
1316                   _T("wxThread::TestDestroy() can only be called in the context of the same thread") ); 
1320     if ( m_internal
->GetState() == STATE_PAUSED 
) 
1322         m_internal
->SetReallyPaused(TRUE
); 
1324         // leave the crit section or the other threads will stop too if they 
1325         // try to call any of (seemingly harmless) IsXXX() functions while we 
1329         m_internal
->Pause(); 
1333         // thread wasn't requested to pause, nothing to do 
1337     return m_internal
->WasCancelled(); 
1340 // ----------------------------------------------------------------------------- 
1342 // ----------------------------------------------------------------------------- 
1344 void wxThread::SetPriority(unsigned int prio
) 
1346     wxCHECK_RET( ((int)WXTHREAD_MIN_PRIORITY 
<= (int)prio
) && 
1347                  ((int)prio 
<= (int)WXTHREAD_MAX_PRIORITY
), 
1348                  wxT("invalid thread priority") ); 
1350     wxCriticalSectionLocker 
lock(m_critsect
); 
1352     switch ( m_internal
->GetState() ) 
1357             // thread not yet started, priority will be set when it is 
1358             m_internal
->SetPriority(prio
); 
1363             wxFAIL_MSG(wxT("impossible to set thread priority in this state")); 
1367 unsigned int wxThread::GetPriority() const 
1369     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); // const_cast 
1371     return m_internal
->GetPriority(); 
1374 unsigned long wxThread::GetId() const 
1376     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); // const_cast 
1378     return (unsigned long)m_internal
->GetId(); 
1381 // ----------------------------------------------------------------------------- 
1383 // ----------------------------------------------------------------------------- 
1385 bool wxThread::IsRunning() const 
1387     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); 
1389     return m_internal
->GetState() == STATE_RUNNING
; 
1392 bool wxThread::IsAlive() const 
1394     wxCriticalSectionLocker 
lock((wxCriticalSection
&)m_critsect
); 
1396     switch ( m_internal
->GetState() ) 
1407 bool wxThread::IsPaused() const 
1409     wxCriticalSectionLocker 
lock((wxCriticalSection
&)m_critsect
); 
1411     return (m_internal
->GetState() == STATE_PAUSED
); 
1414 // ---------------------------------------------------------------------------- 
1415 // Automatic initialization for thread module 
1416 // ---------------------------------------------------------------------------- 
1418 class wxThreadModule 
: public wxModule
 
1421         virtual bool OnInit(); 
1422         virtual void OnExit(); 
1425                 DECLARE_DYNAMIC_CLASS(wxThreadModule
) 
1428 IMPLEMENT_DYNAMIC_CLASS(wxThreadModule
, wxModule
) 
1430 bool wxThreadModule::OnInit() 
1432         if ( !wxMacMPThreadsInitVerify() ) 
1437         verify_noerr( MPAllocateTaskStorageIndex( &gs_tlsForWXThread 
) ) ; 
1438         // main thread's This() is NULL 
1439         verify_noerr( MPSetTaskStorageValue( gs_tlsForWXThread 
, NULL 
) ) ; 
1441         gs_idMainThread 
= wxThread::GetCurrentId() ; 
1443     gs_critsectWaitingForGui 
= new wxCriticalSection(); 
1445     gs_critsectGui 
= new wxCriticalSection(); 
1446     gs_critsectGui
->Enter(); 
1451 void wxThreadModule::OnExit() 
1453     if ( gs_critsectGui 
) 
1455         gs_critsectGui
->Leave(); 
1456         delete gs_critsectGui
; 
1457         gs_critsectGui 
= NULL
; 
1460     delete gs_critsectWaitingForGui
; 
1461     gs_critsectWaitingForGui 
= NULL
; 
1464 // ---------------------------------------------------------------------------- 
1465 // GUI Serialization copied from MSW implementation 
1466 // ---------------------------------------------------------------------------- 
1468 void WXDLLIMPEXP_BASE 
wxMutexGuiEnter() 
1470     // this would dead lock everything... 
1471     wxASSERT_MSG( !wxThread::IsMain(), 
1472                   wxT("main thread doesn't want to block in wxMutexGuiEnter()!") ); 
1474     // the order in which we enter the critical sections here is crucial!! 
1476     // set the flag telling to the main thread that we want to do some GUI 
1478         wxCriticalSectionLocker 
enter(*gs_critsectWaitingForGui
); 
1480         gs_nWaitingForGui
++; 
1483     wxWakeUpMainThread(); 
1485     // now we may block here because the main thread will soon let us in 
1486     // (during the next iteration of OnIdle()) 
1487     gs_critsectGui
->Enter(); 
1490 void WXDLLIMPEXP_BASE 
wxMutexGuiLeave() 
1492     wxCriticalSectionLocker 
enter(*gs_critsectWaitingForGui
); 
1494     if ( wxThread::IsMain() ) 
1496         gs_bGuiOwnedByMainThread 
= false; 
1500         // decrement the number of threads waiting for GUI access now 
1501         wxASSERT_MSG( gs_nWaitingForGui 
> 0, 
1502                       wxT("calling wxMutexGuiLeave() without entering it first?") ); 
1504         gs_nWaitingForGui
--; 
1506         wxWakeUpMainThread(); 
1509     gs_critsectGui
->Leave(); 
1512 void WXDLLIMPEXP_BASE 
wxMutexGuiLeaveOrEnter() 
1514     wxASSERT_MSG( wxThread::IsMain(), 
1515                   wxT("only main thread may call wxMutexGuiLeaveOrEnter()!") ); 
1517     wxCriticalSectionLocker 
enter(*gs_critsectWaitingForGui
); 
1519     if ( gs_nWaitingForGui 
== 0 ) 
1521         // no threads are waiting for GUI - so we may acquire the lock without 
1522         // any danger (but only if we don't already have it) 
1523         if ( !wxGuiOwnedByMainThread() ) 
1525             gs_critsectGui
->Enter(); 
1527             gs_bGuiOwnedByMainThread 
= true; 
1529         //else: already have it, nothing to do 
1533         // some threads are waiting, release the GUI lock if we have it 
1534         if ( wxGuiOwnedByMainThread() ) 
1538         //else: some other worker thread is doing GUI 
1542 bool WXDLLIMPEXP_BASE 
wxGuiOwnedByMainThread() 
1544     return gs_bGuiOwnedByMainThread
; 
1547 // wake up the main thread 
1548 void WXDLLEXPORT 
wxWakeUpMainThread() 
1553 // ---------------------------------------------------------------------------- 
1554 // include common implementation code 
1555 // ---------------------------------------------------------------------------- 
1557 #include "wx/thrimpl.cpp" 
1559 #endif // wxUSE_THREADS