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 /////////////////////////////////////////////////////////////////////////////
14 #pragma implementation "thread.h"
17 // ----------------------------------------------------------------------------
19 // ----------------------------------------------------------------------------
21 // For compilers that support precompilation, includes "wx.h".
22 #include "wx/wxprec.h"
24 #if defined(__BORLANDC__)
34 #include "wx/module.h"
35 #include "wx/thread.h"
38 #if TARGET_API_MAC_OSX
39 #include <CoreServices/CoreServices.h>
41 #include <DriverServices.h>
42 #include <Multiprocessing.h>
45 #include "wx/mac/uma.h"
48 #include "wx/mac/macnotfy.h"
50 // ----------------------------------------------------------------------------
52 // ----------------------------------------------------------------------------
54 // the possible states of the thread ("=>" shows all possible transitions from
58 STATE_NEW
, // didn't start execution yet (=> RUNNING)
59 STATE_RUNNING
, // thread is running (=> PAUSED, CANCELED)
60 STATE_PAUSED
, // thread is temporarily suspended (=> RUNNING)
61 STATE_CANCELED
, // thread should terminate a.s.a.p. (=> EXITED)
62 STATE_EXITED
// thread is terminating
65 // ----------------------------------------------------------------------------
66 // this module globals
67 // ----------------------------------------------------------------------------
70 // the task ID of the main thread
71 static wxThreadIdType gs_idMainThread
= kInvalidID
;
73 // this is the Per-Task Storage for the pointer to the appropriate wxThread
74 TaskStorageIndex gs_tlsForWXThread
= 0 ;
76 // if it's false, some secondary thread is holding the GUI lock
77 static bool gs_bGuiOwnedByMainThread
= true;
79 // critical section which controls access to all GUI functions: any secondary
80 // thread (i.e. except the main one) must enter this crit section before doing
82 static wxCriticalSection
*gs_critsectGui
= NULL
;
84 // critical section which protects gs_nWaitingForGui variable
85 static wxCriticalSection
*gs_critsectWaitingForGui
= NULL
;
87 // number of threads waiting for GUI in wxMutexGuiEnter()
88 static size_t gs_nWaitingForGui
= 0;
90 // overall number of threads, needed for determining the sleep value of the main
92 size_t g_numberOfThreads
= 0;
98 MPCriticalRegionID gs_guiCritical
= kInvalidID
;
102 // ============================================================================
103 // MacOS implementation of thread classes
104 // ============================================================================
109 The implementation is very close to the phtreads implementation, the reason for
110 using MPServices is the fact that these are also available under OS 9. Thus allowing
111 for one common API for all current builds.
113 As soon as wxThreads are on a 64 bit address space, the TLS must be extended
114 to use two indices one for each 32 bit part as the MP implementation is limited
117 I have two implementations for mutexes :
118 version A based on a binary semaphore, problem - not reentrant, version B based
119 on a critical region, allows for reentrancy, performance implications not
122 The same for condition internal, one implementation by Aj Lavin and the other one
123 copied from the thrimpl.cpp which I assume has been more broadly tested, I've just
124 replaced the interlock increment with the appropriate PPC calls
127 // ----------------------------------------------------------------------------
128 // wxMutex implementation
129 // ----------------------------------------------------------------------------
131 #if TARGET_API_MAC_OSX
132 #define wxUSE_MAC_SEMAPHORE_MUTEX 0
133 #define wxUSE_MAC_CRITICAL_REGION_MUTEX 0
134 #define wxUSE_MAC_PTHREADS_MUTEX 1
136 #define wxUSE_MAC_SEMAPHORE_MUTEX 0
137 #define wxUSE_MAC_CRITICAL_REGION_MUTEX 1
138 #define wxUSE_MAC_PTHREADS_MUTEX 0
141 #if wxUSE_MAC_PTHREADS_MUTEX
145 class wxMutexInternal
148 wxMutexInternal(wxMutexType mutexType
);
152 wxMutexError
TryLock();
153 wxMutexError
Unlock();
155 bool IsOk() const { return m_isOk
; }
158 pthread_mutex_t m_mutex
;
161 // wxConditionInternal uses our m_mutex
162 friend class wxConditionInternal
;
165 #ifdef HAVE_PTHREAD_MUTEXATTR_T
166 // on some systems pthread_mutexattr_settype() is not in the headers (but it is
167 // in the library, otherwise we wouldn't compile this code at all)
168 extern "C" int pthread_mutexattr_settype(pthread_mutexattr_t
*, int);
171 wxMutexInternal::wxMutexInternal(wxMutexType mutexType
)
176 case wxMUTEX_RECURSIVE
:
177 // support recursive locks like Win32, i.e. a thread can lock a
178 // mutex which it had itself already locked
180 // unfortunately initialization of recursive mutexes is non
181 // portable, so try several methods
182 #ifdef HAVE_PTHREAD_MUTEXATTR_T
184 pthread_mutexattr_t attr
;
185 pthread_mutexattr_init(&attr
);
186 pthread_mutexattr_settype(&attr
, PTHREAD_MUTEX_RECURSIVE
);
188 err
= pthread_mutex_init(&m_mutex
, &attr
);
190 #elif defined(HAVE_PTHREAD_RECURSIVE_MUTEX_INITIALIZER)
191 // we can use this only as initializer so we have to assign it
192 // first to a temp var - assigning directly to m_mutex wouldn't
195 pthread_mutex_t mutex
= PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
;
198 #else // no recursive mutexes
200 #endif // HAVE_PTHREAD_MUTEXATTR_T/...
204 wxFAIL_MSG( _T("unknown mutex type") );
207 case wxMUTEX_DEFAULT
:
208 err
= pthread_mutex_init(&m_mutex
, NULL
);
215 wxLogApiError( wxT("pthread_mutex_init()"), err
);
219 wxMutexInternal::~wxMutexInternal()
223 int err
= pthread_mutex_destroy(&m_mutex
);
226 wxLogApiError( wxT("pthread_mutex_destroy()"), err
);
231 wxMutexError
wxMutexInternal::Lock()
233 int err
= pthread_mutex_lock(&m_mutex
);
237 // only error checking mutexes return this value and so it's an
238 // unexpected situation -- hence use assert, not wxLogDebug
239 wxFAIL_MSG( _T("mutex deadlock prevented") );
240 return wxMUTEX_DEAD_LOCK
;
243 wxLogDebug(_T("pthread_mutex_lock(): mutex not initialized."));
247 return wxMUTEX_NO_ERROR
;
250 wxLogApiError(_T("pthread_mutex_lock()"), err
);
253 return wxMUTEX_MISC_ERROR
;
256 wxMutexError
wxMutexInternal::TryLock()
258 int err
= pthread_mutex_trylock(&m_mutex
);
262 // not an error: mutex is already locked, but we're prepared for
267 wxLogDebug(_T("pthread_mutex_trylock(): mutex not initialized."));
271 return wxMUTEX_NO_ERROR
;
274 wxLogApiError(_T("pthread_mutex_trylock()"), err
);
277 return wxMUTEX_MISC_ERROR
;
280 wxMutexError
wxMutexInternal::Unlock()
282 int err
= pthread_mutex_unlock(&m_mutex
);
286 // we don't own the mutex
287 return wxMUTEX_UNLOCKED
;
290 wxLogDebug(_T("pthread_mutex_unlock(): mutex not initialized."));
294 return wxMUTEX_NO_ERROR
;
297 wxLogApiError(_T("pthread_mutex_unlock()"), err
);
300 return wxMUTEX_MISC_ERROR
;
306 #if wxUSE_MAC_SEMAPHORE_MUTEX
308 class wxMutexInternal
311 wxMutexInternal(wxMutexType mutexType
) ;
313 bool IsOk() const { return m_isOk
; }
315 wxMutexError
Lock() ;
316 wxMutexError
TryLock() ;
317 wxMutexError
Unlock();
319 MPSemaphoreID m_semaphore
;
323 wxMutexInternal::wxMutexInternal(wxMutexType mutexType
)
326 m_semaphore
= kInvalidID
;
328 OSStatus err
= noErr
;
331 case wxMUTEX_DEFAULT
:
333 verify_noerr( MPCreateBinarySemaphore( & m_semaphore
) );
334 m_isOk
= ( m_semaphore
!= kInvalidID
) ;
337 case wxMUTEX_RECURSIVE
:
338 wxFAIL_MSG(wxT("Recursive Mutex not supported yet") ) ;
341 wxFAIL_MSG(wxT("Unknown mutex type") ) ;
346 wxMutexInternal::~wxMutexInternal()
348 if ( m_semaphore
!= kInvalidID
)
349 MPDeleteSemaphore( m_semaphore
);
352 wxMutexError
wxMutexInternal::Lock()
354 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") ) ;
355 OSStatus err
= MPWaitOnSemaphore( m_semaphore
, kDurationForever
);
358 wxLogSysError(wxT("Could not lock mutex"));
359 return wxMUTEX_MISC_ERROR
;
362 return wxMUTEX_NO_ERROR
;
365 wxMutexError
wxMutexInternal::TryLock()
367 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") ) ;
368 OSStatus err
= MPWaitOnSemaphore( m_semaphore
, kDurationImmediate
);
371 if ( err
== kMPTimeoutErr
)
375 wxLogSysError(wxT("Could not try lock mutex"));
376 return wxMUTEX_MISC_ERROR
;
379 return wxMUTEX_NO_ERROR
;
382 wxMutexError
wxMutexInternal::Unlock()
384 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") ) ;
385 OSStatus err
= MPSignalSemaphore( m_semaphore
);
388 wxLogSysError(_("Could not unlock mutex"));
389 return wxMUTEX_MISC_ERROR
;
392 return wxMUTEX_NO_ERROR
;
397 #if wxUSE_MAC_CRITICAL_REGION_MUTEX
399 class wxMutexInternal
402 wxMutexInternal(wxMutexType mutexType
) ;
404 bool IsOk() const { return m_isOk
; }
406 wxMutexError
Lock() ;
407 wxMutexError
TryLock() ;
408 wxMutexError
Unlock();
410 MPCriticalRegionID m_critRegion
;
414 wxMutexInternal::wxMutexInternal(wxMutexType mutexType
)
417 m_critRegion
= kInvalidID
;
419 verify_noerr( MPCreateCriticalRegion( & m_critRegion
) );
420 m_isOk
= ( m_critRegion
!= kInvalidID
) ;
423 wxFAIL_MSG(wxT("Error when creating mutex") ) ;
426 wxMutexInternal::~wxMutexInternal()
428 if ( m_critRegion
!= kInvalidID
)
429 MPDeleteCriticalRegion( m_critRegion
);
432 wxMutexError
wxMutexInternal::Lock()
434 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") ) ;
435 OSStatus err
= MPEnterCriticalRegion( m_critRegion
, kDurationForever
);
438 wxLogSysError(wxT("Could not lock mutex"));
439 return wxMUTEX_MISC_ERROR
;
442 return wxMUTEX_NO_ERROR
;
445 wxMutexError
wxMutexInternal::TryLock()
447 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") ) ;
448 OSStatus err
= MPEnterCriticalRegion( m_critRegion
, kDurationImmediate
);
451 if ( err
== kMPTimeoutErr
)
455 wxLogSysError(wxT("Could not try lock mutex"));
456 return wxMUTEX_MISC_ERROR
;
459 return wxMUTEX_NO_ERROR
;
462 wxMutexError
wxMutexInternal::Unlock()
464 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") ) ;
465 OSStatus err
= MPExitCriticalRegion( m_critRegion
);
468 wxLogSysError(_("Could not unlock mutex"));
469 return wxMUTEX_MISC_ERROR
;
472 return wxMUTEX_NO_ERROR
;
477 // --------------------------------------------------------------------------
479 // --------------------------------------------------------------------------
481 class wxSemaphoreInternal
484 wxSemaphoreInternal(int initialcount
, int maxcount
);
485 ~wxSemaphoreInternal();
487 bool IsOk() const { return m_isOk
; }
489 wxSemaError
WaitTimeout(unsigned long milliseconds
);
491 wxSemaError
Wait() { return WaitTimeout( kDurationForever
); }
493 wxSemaError
TryWait()
495 wxSemaError err
= WaitTimeout(kDurationImmediate
);
496 if ( err
== wxSEMA_TIMEOUT
)
503 MPSemaphoreID m_semaphore
;
507 wxSemaphoreInternal::wxSemaphoreInternal(int initialcount
, int maxcount
)
510 m_semaphore
= kInvalidID
;
513 // make it practically infinite
516 verify_noerr( MPCreateSemaphore( maxcount
, initialcount
, & m_semaphore
) );
517 m_isOk
= ( m_semaphore
!= kInvalidID
) ;
520 wxFAIL_MSG(wxT("Error when creating semaphore") ) ;
523 wxSemaphoreInternal::~wxSemaphoreInternal()
525 if( m_semaphore
!= kInvalidID
)
526 MPDeleteSemaphore( m_semaphore
);
529 wxSemaError
wxSemaphoreInternal::WaitTimeout(unsigned long milliseconds
)
531 OSStatus err
= MPWaitOnSemaphore( m_semaphore
, milliseconds
);
534 if ( err
== kMPTimeoutErr
)
536 return wxSEMA_TIMEOUT
;
538 return wxSEMA_MISC_ERROR
;
540 return wxSEMA_NO_ERROR
;
543 wxSemaError
wxSemaphoreInternal::Post()
545 OSStatus err
= MPSignalSemaphore( m_semaphore
);
548 return wxSEMA_MISC_ERROR
;
550 return wxSEMA_NO_ERROR
;
553 // ----------------------------------------------------------------------------
554 // wxCondition implementation
555 // ----------------------------------------------------------------------------
559 class wxConditionInternal
563 wxConditionInternal(wxMutex
& mutex
)
573 ~wxConditionInternal()
577 bool IsOk() const { return m_mutex
.IsOk() ; }
581 return WaitTimeout( kDurationForever
);
584 wxCondError
WaitTimeout(unsigned long msectimeout
);
588 return DoSignal( false);
591 wxCondError
Broadcast()
593 return DoSignal( true);
598 wxCondError
DoSignal( bool signalAll
);
601 wxSemaphoreInternal m_semaphore
; // Signals the waiting threads.
602 wxSemaphoreInternal m_gate
;
603 wxCriticalSection m_varSection
;
604 size_t m_waiters
; // Number of threads waiting for a signal.
605 size_t m_signals
; // Number of signals to send.
606 size_t m_canceled
; // Number of canceled waiters in m_waiters.
610 wxCondError
wxConditionInternal::WaitTimeout(unsigned long msectimeout
)
613 if ( ++ m_waiters
== INT_MAX
)
615 m_varSection
.Enter();
616 m_waiters
-= m_canceled
;
617 m_signals
-= m_canceled
;
619 m_varSection
.Leave();
625 wxSemaError err
= m_semaphore
.WaitTimeout( msectimeout
);
626 wxASSERT( err
== wxSEMA_NO_ERROR
|| err
== wxSEMA_TIMEOUT
);
628 m_varSection
.Enter();
629 if ( err
!= wxSEMA_NO_ERROR
)
631 if ( m_signals
> m_canceled
)
633 // A signal is being sent after we timed out.
635 if ( m_waiters
== m_signals
)
637 // There are no excess waiters to catch the signal, so
638 // we must throw it away.
640 wxSemaError err2
= m_semaphore
.Wait();
641 if ( err2
!= wxSEMA_NO_ERROR
)
643 wxLogSysError(_("Error while waiting on semaphore"));
645 wxASSERT( err2
== wxSEMA_NO_ERROR
);
647 if ( -- m_signals
== m_canceled
)
649 // This was the last signal. open the gate.
650 wxASSERT( m_waiters
== m_canceled
);
656 // There are excess waiters to catch the signal, leave
663 // No signals is being sent.
664 // The gate may be open or closed, so we can't touch m_waiters.
671 // We caught a signal.
672 wxASSERT( m_signals
> m_canceled
);
674 if ( -- m_signals
== m_canceled
)
676 // This was the last signal. open the gate.
677 wxASSERT( m_waiters
== m_canceled
);
681 m_varSection
.Leave();
687 return err
== wxSEMA_TIMEOUT
? wxCOND_TIMEOUT
: wxCOND_MISC_ERROR
;
690 return wxCOND_NO_ERROR
;
694 wxCondError
wxConditionInternal::DoSignal( bool signalAll
)
697 m_varSection
.Enter();
699 wxASSERT( m_signals
== m_canceled
);
701 if ( m_waiters
== m_canceled
)
703 m_varSection
.Leave();
705 return wxCOND_NO_ERROR
;
710 m_waiters
-= m_canceled
;
715 m_signals
= signalAll
? m_waiters
: 1;
716 size_t n
= m_signals
;
718 m_varSection
.Leave();
720 // Let the waiters inherit the gate lock.
724 wxSemaError err
= m_semaphore
.Post();
725 wxASSERT( err
== wxSEMA_NO_ERROR
);
728 return wxCOND_NO_ERROR
;
732 class wxConditionInternal
735 wxConditionInternal(wxMutex
& mutex
);
737 bool IsOk() const { return m_mutex
.IsOk() && m_semaphore
.IsOk(); }
740 wxCondError
WaitTimeout(unsigned long milliseconds
);
742 wxCondError
Signal();
743 wxCondError
Broadcast();
746 // the number of threads currently waiting for this condition
749 // the critical section protecting m_numWaiters
750 wxCriticalSection m_csWaiters
;
753 wxSemaphore m_semaphore
;
755 DECLARE_NO_COPY_CLASS(wxConditionInternal
)
758 wxConditionInternal::wxConditionInternal(wxMutex
& mutex
)
761 // another thread can't access it until we return from ctor, so no need to
762 // protect access to m_numWaiters here
766 wxCondError
wxConditionInternal::Wait()
768 // increment the number of waiters
769 IncrementAtomic(&m_numWaiters
);
773 // a potential race condition can occur here
775 // after a thread increments nwaiters, and unlocks the mutex and before the
776 // semaphore.Wait() is called, if another thread can cause a signal to be
779 // this race condition is handled by using a semaphore and incrementing the
780 // semaphore only if 'nwaiters' is greater that zero since the semaphore,
781 // can 'remember' signals the race condition will not occur
783 // wait ( if necessary ) and decrement semaphore
784 wxSemaError err
= m_semaphore
.Wait();
787 return err
== wxSEMA_NO_ERROR
? wxCOND_NO_ERROR
: wxCOND_MISC_ERROR
;
790 wxCondError
wxConditionInternal::WaitTimeout(unsigned long milliseconds
)
792 IncrementAtomic(&m_numWaiters
);
796 // a race condition can occur at this point in the code
798 // please see the comments in Wait(), for details
800 wxSemaError err
= m_semaphore
.WaitTimeout(milliseconds
);
802 if ( err
== wxSEMA_BUSY
)
804 // another potential race condition exists here it is caused when a
805 // 'waiting' thread timesout, and returns from WaitForSingleObject, but
806 // has not yet decremented 'nwaiters'.
808 // at this point if another thread calls signal() then the semaphore
809 // will be incremented, but the waiting thread will miss it.
811 // to handle this particular case, the waiting thread calls
812 // WaitForSingleObject again with a timeout of 0, after locking
813 // 'nwaiters_mutex'. this call does not block because of the zero
814 // timeout, but will allow the waiting thread to catch the missed
816 wxCriticalSectionLocker
lock(m_csWaiters
);
818 err
= m_semaphore
.WaitTimeout(0);
820 if ( err
!= wxSEMA_NO_ERROR
)
828 return err
== wxSEMA_NO_ERROR
? wxCOND_NO_ERROR
: wxCOND_MISC_ERROR
;
831 wxCondError
wxConditionInternal::Signal()
833 wxCriticalSectionLocker
lock(m_csWaiters
);
835 if ( m_numWaiters
> 0 )
837 // increment the semaphore by 1
838 if ( m_semaphore
.Post() != wxSEMA_NO_ERROR
)
839 return wxCOND_MISC_ERROR
;
844 return wxCOND_NO_ERROR
;
847 wxCondError
wxConditionInternal::Broadcast()
849 wxCriticalSectionLocker
lock(m_csWaiters
);
851 while ( m_numWaiters
> 0 )
853 if ( m_semaphore
.Post() != wxSEMA_NO_ERROR
)
854 return wxCOND_MISC_ERROR
;
859 return wxCOND_NO_ERROR
;
863 // ----------------------------------------------------------------------------
864 // wxCriticalSection implementation
865 // ----------------------------------------------------------------------------
867 // XXX currently implemented as mutex in headers. Change to critical section.
869 // ----------------------------------------------------------------------------
870 // wxThread implementation
871 // ----------------------------------------------------------------------------
873 // wxThreadInternal class
874 // ----------------------
876 class wxThreadInternal
883 m_prio
= WXTHREAD_DEFAULT_PRIORITY
;
884 m_notifyQueueId
= kInvalidID
;
886 m_cancelled
= FALSE
;
888 // set to TRUE only when the thread starts waiting on m_semSuspend
891 // defaults for joinable threads
892 m_shouldBeJoined
= TRUE
;
893 m_isDetached
= FALSE
;
897 if ( m_notifyQueueId
)
899 MPDeleteQueue( m_notifyQueueId
);
900 m_notifyQueueId
= kInvalidID
;
905 static OSStatus
MacThreadStart(void* arg
);
907 // create a new (suspended) thread (for the given thread object)
908 bool Create(wxThread
*thread
, unsigned int stackSize
);
913 // unblock the thread allowing it to run
914 void SignalRun() { m_semRun
.Post(); }
915 // ask the thread to terminate
917 // go to sleep until Resume() is called
924 int GetPriority() const { return m_prio
; }
925 void SetPriority(int prio
) ;
927 wxThreadState
GetState() const { return m_state
; }
928 void SetState(wxThreadState state
) { m_state
= state
; }
930 // Get the ID of this thread's underlying MP Services task.
931 MPTaskID
GetId() const { return m_tid
; }
933 void SetCancelFlag() { m_cancelled
= TRUE
; }
934 bool WasCancelled() const { return m_cancelled
; }
936 void SetExitCode(wxThread::ExitCode exitcode
) { m_exitcode
= exitcode
; }
937 wxThread::ExitCode
GetExitCode() const { return m_exitcode
; }
940 void SetReallyPaused(bool paused
) { m_isPaused
= paused
; }
941 bool IsReallyPaused() const { return m_isPaused
; }
943 // tell the thread that it is a detached one
946 wxCriticalSectionLocker
lock(m_csJoinFlag
);
948 m_shouldBeJoined
= FALSE
;
953 // the thread we're associated with
956 MPTaskID m_tid
; // thread id
957 MPQueueID m_notifyQueueId
; // its notification queue
959 wxThreadState m_state
; // see wxThreadState enum
960 int m_prio
; // in wxWindows units: from 0 to 100
962 // this flag is set when the thread should terminate
965 // this flag is set when the thread is blocking on m_semSuspend
968 // the thread exit code - only used for joinable (!detached) threads and
969 // is only valid after the thread termination
970 wxThread::ExitCode m_exitcode
;
972 // many threads may call Wait(), but only one of them should call
973 // pthread_join(), so we have to keep track of this
974 wxCriticalSection m_csJoinFlag
;
975 bool m_shouldBeJoined
;
978 // this semaphore is posted by Run() and the threads Entry() is not
979 // called before it is done
980 wxSemaphore m_semRun
;
982 // this one is signaled when the thread should resume after having been
984 wxSemaphore m_semSuspend
;
987 OSStatus
wxThreadInternal::MacThreadStart(void *parameter
)
989 wxThread
* thread
= (wxThread
*) parameter
;
990 wxThreadInternal
*pthread
= thread
->m_internal
;
992 // add to TLS so that This() will work
993 verify_noerr( MPSetTaskStorageValue( gs_tlsForWXThread
, (long) thread
) ) ;
995 // have to declare this before pthread_cleanup_push() which defines a
999 // wait for the semaphore to be posted from Run()
1000 pthread
->m_semRun
.Wait();
1002 // test whether we should run the run at all - may be it was deleted
1003 // before it started to Run()?
1005 wxCriticalSectionLocker
lock(thread
->m_critsect
);
1007 dontRunAtAll
= pthread
->GetState() == STATE_NEW
&&
1008 pthread
->WasCancelled();
1011 if ( !dontRunAtAll
)
1013 pthread
->m_exitcode
= thread
->Entry();
1016 wxCriticalSectionLocker
lock(thread
->m_critsect
);
1017 pthread
->SetState(STATE_EXITED
);
1023 if ( pthread
->m_isDetached
)
1030 // on mac for the running code the correct thread termination is to
1033 // terminate the thread
1034 thread
->Exit(pthread
->m_exitcode
);
1036 return (OSStatus
) NULL
; // pthread->m_exitcode;
1040 bool wxThreadInternal::Create(wxThread
*thread
, unsigned int stackSize
)
1042 wxASSERT_MSG( m_state
== STATE_NEW
&& !m_tid
,
1043 _T("Create()ing thread twice?") );
1045 OSStatus err
= noErr
;
1048 if ( m_notifyQueueId
== kInvalidID
)
1050 OSStatus err
= MPCreateQueue( & m_notifyQueueId
);
1053 wxLogSysError(_("Cant create the thread event queue"));
1058 m_state
= STATE_NEW
;
1060 err
= MPCreateTask( MacThreadStart
,
1071 wxLogSysError(_("Can't create thread"));
1075 if ( m_prio
!= WXTHREAD_DEFAULT_PRIORITY
)
1077 SetPriority(m_prio
);
1083 void wxThreadInternal::SetPriority( int priority
)
1089 // Mac priorities range from 1 to 10,000, with a default of 100.
1090 // wxWindows priorities range from 0 to 100 with a default of 50.
1091 // We can map wxWindows to Mac priorities easily by assuming
1092 // the former uses a logarithmic scale.
1093 const unsigned int macPriority
= ( int)( exp( priority
/ 25.0 * log( 10.0)) + 0.5);
1095 MPSetTaskWeight( m_tid
, macPriority
);
1099 wxThreadError
wxThreadInternal::Run()
1101 wxCHECK_MSG( GetState() == STATE_NEW
, wxTHREAD_RUNNING
,
1102 wxT("thread may only be started once after Create()") );
1104 SetState(STATE_RUNNING
);
1106 // wake up threads waiting for our start
1109 return wxTHREAD_NO_ERROR
;
1112 void wxThreadInternal::Wait()
1114 wxCHECK_RET( !m_isDetached
, _T("can't wait for a detached thread") );
1116 // if the thread we're waiting for is waiting for the GUI mutex, we will
1117 // deadlock so make sure we release it temporarily
1118 if ( wxThread::IsMain() )
1122 wxCriticalSectionLocker
lock(m_csJoinFlag
);
1124 if ( m_shouldBeJoined
)
1130 OSStatus err
= MPWaitOnQueue ( m_notifyQueueId
,
1137 wxLogSysError( _( "Cannot wait on thread to exit."));
1141 // actually param1 would be the address of m_exitcode
1142 // but we don't need this here
1145 m_shouldBeJoined
= FALSE
;
1149 // reacquire GUI mutex
1150 if ( wxThread::IsMain() )
1154 void wxThreadInternal::Pause()
1156 // the state is set from the thread which pauses us first, this function
1157 // is called later so the state should have been already set
1158 wxCHECK_RET( m_state
== STATE_PAUSED
,
1159 wxT("thread must first be paused with wxThread::Pause().") );
1161 // wait until the semaphore is Post()ed from Resume()
1162 m_semSuspend
.Wait();
1165 void wxThreadInternal::Resume()
1167 wxCHECK_RET( m_state
== STATE_PAUSED
,
1168 wxT("can't resume thread which is not suspended.") );
1170 // the thread might be not actually paused yet - if there were no call to
1171 // TestDestroy() since the last call to Pause() for example
1172 if ( IsReallyPaused() )
1175 m_semSuspend
.Post();
1178 SetReallyPaused(FALSE
);
1181 SetState(STATE_RUNNING
);
1187 wxThread
*wxThread::This()
1189 wxThread
* thr
= (wxThread
*) MPGetTaskStorageValue( gs_tlsForWXThread
) ;
1193 bool wxThread::IsMain()
1195 return GetCurrentId() == gs_idMainThread
;
1202 void wxThread::Yield()
1204 #if TARGET_API_MAC_OSX
1205 CFRunLoopRunInMode( kCFRunLoopDefaultMode
, 0 , true ) ;
1211 void wxThread::Sleep(unsigned long milliseconds
)
1213 AbsoluteTime wakeup
= AddDurationToAbsolute( milliseconds
, UpTime());
1214 MPDelayUntil( & wakeup
);
1218 int wxThread::GetCPUCount()
1220 return MPProcessors();
1223 unsigned long wxThread::GetCurrentId()
1225 return (unsigned long)MPCurrentTaskID();
1229 bool wxThread::SetConcurrency(size_t level
)
1231 // Cannot be set in MacOS.
1236 wxThread::wxThread(wxThreadKind kind
)
1238 g_numberOfThreads
++;
1239 m_internal
= new wxThreadInternal();
1241 m_isDetached
= (kind
== wxTHREAD_DETACHED
);
1244 wxThread::~wxThread()
1246 wxASSERT_MSG( g_numberOfThreads
>0 , wxT("More threads deleted than created.") ) ;
1247 g_numberOfThreads
--;
1252 // check that the thread either exited or couldn't be created
1253 if ( m_internal
->GetState() != STATE_EXITED
&&
1254 m_internal
->GetState() != STATE_NEW
)
1256 wxLogDebug(_T("The thread %ld is being destroyed although it is still running! The application may crash."), GetId());
1260 #endif // __WXDEBUG__
1262 wxDELETE( m_internal
) ;
1266 wxThreadError
wxThread::Create(unsigned int stackSize
)
1268 wxCriticalSectionLocker
lock(m_critsect
);
1272 m_internal
->Detach() ;
1274 if ( m_internal
->Create(this, stackSize
) == false )
1276 m_internal
->SetState(STATE_EXITED
);
1277 return wxTHREAD_NO_RESOURCE
;
1280 return wxTHREAD_NO_ERROR
;
1283 wxThreadError
wxThread::Run()
1285 wxCriticalSectionLocker
lock(m_critsect
);
1287 wxCHECK_MSG( m_internal
->GetId(), wxTHREAD_MISC_ERROR
,
1288 wxT("must call wxThread::Create() first") );
1290 return m_internal
->Run();
1293 // -----------------------------------------------------------------------------
1295 // -----------------------------------------------------------------------------
1297 wxThreadError
wxThread::Pause()
1299 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
,
1300 _T("a thread can't pause itself") );
1302 wxCriticalSectionLocker
lock(m_critsect
);
1304 if ( m_internal
->GetState() != STATE_RUNNING
)
1306 wxLogDebug(wxT("Can't pause thread which is not running."));
1308 return wxTHREAD_NOT_RUNNING
;
1311 // just set a flag, the thread will be really paused only during the next
1312 // call to TestDestroy()
1313 m_internal
->SetState(STATE_PAUSED
);
1315 return wxTHREAD_NO_ERROR
;
1318 wxThreadError
wxThread::Resume()
1320 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
,
1321 _T("a thread can't resume itself") );
1323 wxCriticalSectionLocker
lock(m_critsect
);
1325 wxThreadState state
= m_internal
->GetState();
1330 m_internal
->Resume();
1331 return wxTHREAD_NO_ERROR
;
1333 return wxTHREAD_NO_ERROR
;
1336 wxLogDebug(_T("Attempt to resume a thread which is not paused."));
1338 return wxTHREAD_MISC_ERROR
;
1342 // -----------------------------------------------------------------------------
1344 // -----------------------------------------------------------------------------
1346 wxThread::ExitCode
wxThread::Wait()
1348 wxCHECK_MSG( This() != this, (ExitCode
)-1,
1349 _T("a thread can't wait for itself") );
1351 wxCHECK_MSG( !m_isDetached
, (ExitCode
)-1,
1352 _T("can't wait for detached thread") );
1356 return m_internal
->GetExitCode();
1359 wxThreadError
wxThread::Delete(ExitCode
*rc
)
1361 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
,
1362 _T("a thread can't delete itself") );
1364 bool isDetached
= m_isDetached
;
1367 wxThreadState state
= m_internal
->GetState();
1369 // ask the thread to stop
1370 m_internal
->SetCancelFlag();
1377 // we need to wake up the thread so that PthreadStart() will
1378 // terminate - right now it's blocking on run semaphore in
1380 m_internal
->SignalRun();
1389 // resume the thread first
1390 m_internal
->Resume();
1397 // wait until the thread stops
1402 // return the exit code of the thread
1403 *rc
= m_internal
->GetExitCode();
1406 //else: can't wait for detached threads
1409 return wxTHREAD_NO_ERROR
;
1412 wxThreadError
wxThread::Kill()
1414 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
,
1415 _T("a thread can't kill itself") );
1417 switch ( m_internal
->GetState() )
1421 return wxTHREAD_NOT_RUNNING
;
1424 // resume the thread first
1430 OSStatus err
= MPTerminateTask( m_internal
->GetId() , -1 ) ;
1433 wxLogError(_("Failed to terminate a thread."));
1435 return wxTHREAD_MISC_ERROR
;
1444 // this should be retrieved by Wait actually
1445 m_internal
->SetExitCode((void*)-1);
1448 return wxTHREAD_NO_ERROR
;
1452 void wxThread::Exit(ExitCode status
)
1454 wxASSERT_MSG( This() == this,
1455 _T("wxThread::Exit() can only be called in the context of the same thread") );
1457 // don't enter m_critsect before calling OnExit() because the user code
1458 // might deadlock if, for example, it signals a condition in OnExit() (a
1459 // common case) while the main thread calls any of functions entering
1460 // m_critsect on us (almost all of them do)
1463 MPTerminateTask( m_internal
->GetId() , (long) status
) ;
1471 // update the status of the joinable thread
1472 wxCriticalSectionLocker
lock(m_critsect
);
1473 m_internal
->SetState(STATE_EXITED
);
1477 // also test whether we were paused
1478 bool wxThread::TestDestroy()
1480 wxASSERT_MSG( This() == this,
1481 _T("wxThread::TestDestroy() can only be called in the context of the same thread") );
1485 if ( m_internal
->GetState() == STATE_PAUSED
)
1487 m_internal
->SetReallyPaused(TRUE
);
1489 // leave the crit section or the other threads will stop too if they
1490 // try to call any of (seemingly harmless) IsXXX() functions while we
1494 m_internal
->Pause();
1498 // thread wasn't requested to pause, nothing to do
1502 return m_internal
->WasCancelled();
1505 // -----------------------------------------------------------------------------
1507 // -----------------------------------------------------------------------------
1509 void wxThread::SetPriority(unsigned int prio
)
1511 wxCHECK_RET( ((int)WXTHREAD_MIN_PRIORITY
<= (int)prio
) &&
1512 ((int)prio
<= (int)WXTHREAD_MAX_PRIORITY
),
1513 wxT("invalid thread priority") );
1515 wxCriticalSectionLocker
lock(m_critsect
);
1517 switch ( m_internal
->GetState() )
1522 // thread not yet started, priority will be set when it is
1523 m_internal
->SetPriority(prio
);
1528 wxFAIL_MSG(wxT("impossible to set thread priority in this state"));
1532 unsigned int wxThread::GetPriority() const
1534 wxCriticalSectionLocker
lock((wxCriticalSection
&)m_critsect
); // const_cast
1536 return m_internal
->GetPriority();
1539 unsigned long wxThread::GetId() const
1541 wxCriticalSectionLocker
lock((wxCriticalSection
&)m_critsect
); // const_cast
1543 return (unsigned long)m_internal
->GetId();
1546 // -----------------------------------------------------------------------------
1548 // -----------------------------------------------------------------------------
1550 bool wxThread::IsRunning() const
1552 wxCriticalSectionLocker
lock((wxCriticalSection
&)m_critsect
);
1554 return m_internal
->GetState() == STATE_RUNNING
;
1557 bool wxThread::IsAlive() const
1559 wxCriticalSectionLocker
lock((wxCriticalSection
&)m_critsect
);
1561 switch ( m_internal
->GetState() )
1572 bool wxThread::IsPaused() const
1574 wxCriticalSectionLocker
lock((wxCriticalSection
&)m_critsect
);
1576 return (m_internal
->GetState() == STATE_PAUSED
);
1579 // ----------------------------------------------------------------------------
1580 // Automatic initialization for thread module
1581 // ----------------------------------------------------------------------------
1583 class wxThreadModule
: public wxModule
1586 virtual bool OnInit();
1587 virtual void OnExit();
1590 DECLARE_DYNAMIC_CLASS(wxThreadModule
)
1593 IMPLEMENT_DYNAMIC_CLASS(wxThreadModule
, wxModule
)
1595 bool wxThreadModule::OnInit()
1597 bool hasThreadManager
= false ;
1598 hasThreadManager
= MPLibraryIsLoaded();
1600 if ( !hasThreadManager
)
1602 wxLogError( _("MP Thread Support is not available on this System" ) ) ;
1606 verify_noerr( MPAllocateTaskStorageIndex( &gs_tlsForWXThread
) ) ;
1607 // main thread's This() is NULL
1608 verify_noerr( MPSetTaskStorageValue( gs_tlsForWXThread
, NULL
) ) ;
1610 gs_idMainThread
= wxThread::GetCurrentId() ;
1612 gs_critsectWaitingForGui
= new wxCriticalSection();
1614 gs_critsectGui
= new wxCriticalSection();
1615 gs_critsectGui
->Enter();
1620 void wxThreadModule::OnExit()
1622 if ( gs_critsectGui
)
1624 gs_critsectGui
->Leave();
1625 delete gs_critsectGui
;
1626 gs_critsectGui
= NULL
;
1629 delete gs_critsectWaitingForGui
;
1630 gs_critsectWaitingForGui
= NULL
;
1633 // ----------------------------------------------------------------------------
1634 // GUI Serialization copied from MSW implementation
1635 // ----------------------------------------------------------------------------
1637 void WXDLLIMPEXP_BASE
wxMutexGuiEnter()
1639 // this would dead lock everything...
1640 wxASSERT_MSG( !wxThread::IsMain(),
1641 wxT("main thread doesn't want to block in wxMutexGuiEnter()!") );
1643 // the order in which we enter the critical sections here is crucial!!
1645 // set the flag telling to the main thread that we want to do some GUI
1647 wxCriticalSectionLocker
enter(*gs_critsectWaitingForGui
);
1649 gs_nWaitingForGui
++;
1652 wxWakeUpMainThread();
1654 // now we may block here because the main thread will soon let us in
1655 // (during the next iteration of OnIdle())
1656 gs_critsectGui
->Enter();
1659 void WXDLLIMPEXP_BASE
wxMutexGuiLeave()
1661 wxCriticalSectionLocker
enter(*gs_critsectWaitingForGui
);
1663 if ( wxThread::IsMain() )
1665 gs_bGuiOwnedByMainThread
= false;
1669 // decrement the number of threads waiting for GUI access now
1670 wxASSERT_MSG( gs_nWaitingForGui
> 0,
1671 wxT("calling wxMutexGuiLeave() without entering it first?") );
1673 gs_nWaitingForGui
--;
1675 wxWakeUpMainThread();
1678 gs_critsectGui
->Leave();
1681 void WXDLLIMPEXP_BASE
wxMutexGuiLeaveOrEnter()
1683 wxASSERT_MSG( wxThread::IsMain(),
1684 wxT("only main thread may call wxMutexGuiLeaveOrEnter()!") );
1686 wxCriticalSectionLocker
enter(*gs_critsectWaitingForGui
);
1688 if ( gs_nWaitingForGui
== 0 )
1690 // no threads are waiting for GUI - so we may acquire the lock without
1691 // any danger (but only if we don't already have it)
1692 if ( !wxGuiOwnedByMainThread() )
1694 gs_critsectGui
->Enter();
1696 gs_bGuiOwnedByMainThread
= true;
1698 //else: already have it, nothing to do
1702 // some threads are waiting, release the GUI lock if we have it
1703 if ( wxGuiOwnedByMainThread() )
1707 //else: some other worker thread is doing GUI
1711 bool WXDLLIMPEXP_BASE
wxGuiOwnedByMainThread()
1713 return gs_bGuiOwnedByMainThread
;
1716 // wake up the main thread
1717 void WXDLLEXPORT
wxWakeUpMainThread()
1722 // ----------------------------------------------------------------------------
1723 // include common implementation code
1724 // ----------------------------------------------------------------------------
1726 #include "wx/thrimpl.cpp"
1728 #endif // wxUSE_THREADS