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 1
134 #define wxUSE_MAC_PTHREADS_MUTEX 0
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
);
353 wxMutexError
wxMutexInternal::Lock()
355 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") ) ;
356 OSStatus err
= MPWaitOnSemaphore( m_semaphore
, kDurationForever
);
359 wxLogSysError(wxT("Could not lock mutex"));
360 return wxMUTEX_MISC_ERROR
;
363 return wxMUTEX_NO_ERROR
;
366 wxMutexError
wxMutexInternal::TryLock()
368 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") ) ;
369 OSStatus err
= MPWaitOnSemaphore( m_semaphore
, kDurationImmediate
);
372 if ( err
== kMPTimeoutErr
)
376 wxLogSysError(wxT("Could not try lock mutex"));
377 return wxMUTEX_MISC_ERROR
;
380 return wxMUTEX_NO_ERROR
;
383 wxMutexError
wxMutexInternal::Unlock()
385 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") ) ;
386 OSStatus err
= MPSignalSemaphore( m_semaphore
);
390 wxLogSysError(_("Could not unlock mutex"));
391 return wxMUTEX_MISC_ERROR
;
393 return wxMUTEX_NO_ERROR
;
398 #if wxUSE_MAC_CRITICAL_REGION_MUTEX
400 class wxMutexInternal
403 wxMutexInternal(wxMutexType mutexType
) ;
405 bool IsOk() const { return m_isOk
; }
407 wxMutexError
Lock() ;
408 wxMutexError
TryLock() ;
409 wxMutexError
Unlock();
411 MPCriticalRegionID m_critRegion
;
415 wxMutexInternal::wxMutexInternal(wxMutexType mutexType
)
418 m_critRegion
= kInvalidID
;
420 verify_noerr( MPCreateCriticalRegion( & m_critRegion
) );
421 m_isOk
= ( m_critRegion
!= kInvalidID
) ;
424 wxFAIL_MSG(wxT("Error when creating mutex") ) ;
427 wxMutexInternal::~wxMutexInternal()
429 if ( m_critRegion
!= kInvalidID
)
430 MPDeleteCriticalRegion( m_critRegion
);
434 wxMutexError
wxMutexInternal::Lock()
436 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") ) ;
437 OSStatus err
= MPEnterCriticalRegion( m_critRegion
, kDurationForever
);
440 wxLogSysError(wxT("Could not lock mutex"));
441 return wxMUTEX_MISC_ERROR
;
444 return wxMUTEX_NO_ERROR
;
447 wxMutexError
wxMutexInternal::TryLock()
449 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") ) ;
450 OSStatus err
= MPEnterCriticalRegion( m_critRegion
, kDurationImmediate
);
453 if ( err
== kMPTimeoutErr
)
457 wxLogSysError(wxT("Could not try lock mutex"));
458 return wxMUTEX_MISC_ERROR
;
461 return wxMUTEX_NO_ERROR
;
464 wxMutexError
wxMutexInternal::Unlock()
466 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") ) ;
467 OSStatus err
= MPExitCriticalRegion( m_critRegion
);
471 wxLogSysError(_("Could not unlock mutex"));
472 return wxMUTEX_MISC_ERROR
;
475 return wxMUTEX_NO_ERROR
;
480 // --------------------------------------------------------------------------
482 // --------------------------------------------------------------------------
484 class wxSemaphoreInternal
487 wxSemaphoreInternal(int initialcount
, int maxcount
);
488 ~wxSemaphoreInternal();
490 bool IsOk() const { return m_isOk
; }
492 wxSemaError
WaitTimeout(unsigned long milliseconds
);
494 wxSemaError
Wait() { return WaitTimeout( kDurationForever
); }
496 wxSemaError
TryWait()
498 wxSemaError err
= WaitTimeout(kDurationImmediate
);
499 if ( err
== wxSEMA_TIMEOUT
)
506 MPSemaphoreID m_semaphore
;
510 wxSemaphoreInternal::wxSemaphoreInternal(int initialcount
, int maxcount
)
513 m_semaphore
= kInvalidID
;
516 // make it practically infinite
519 verify_noerr( MPCreateSemaphore( maxcount
, initialcount
, & m_semaphore
) );
520 m_isOk
= ( m_semaphore
!= kInvalidID
) ;
523 wxFAIL_MSG(wxT("Error when creating semaphore") ) ;
526 wxSemaphoreInternal::~wxSemaphoreInternal()
528 if( m_semaphore
!= kInvalidID
)
529 MPDeleteSemaphore( m_semaphore
);
533 wxSemaError
wxSemaphoreInternal::WaitTimeout(unsigned long milliseconds
)
535 OSStatus err
= MPWaitOnSemaphore( m_semaphore
, milliseconds
);
538 if ( err
== kMPTimeoutErr
)
540 return wxSEMA_TIMEOUT
;
542 return wxSEMA_MISC_ERROR
;
544 return wxSEMA_NO_ERROR
;
547 wxSemaError
wxSemaphoreInternal::Post()
549 OSStatus err
= MPSignalSemaphore( m_semaphore
);
553 return wxSEMA_MISC_ERROR
;
555 return wxSEMA_NO_ERROR
;
558 // ----------------------------------------------------------------------------
559 // wxCondition implementation
560 // ----------------------------------------------------------------------------
564 class wxConditionInternal
568 wxConditionInternal(wxMutex
& mutex
)
578 ~wxConditionInternal()
582 bool IsOk() const { return m_mutex
.IsOk() ; }
586 return WaitTimeout( kDurationForever
);
589 wxCondError
WaitTimeout(unsigned long msectimeout
);
593 return DoSignal( false);
596 wxCondError
Broadcast()
598 return DoSignal( true);
603 wxCondError
DoSignal( bool signalAll
);
606 wxSemaphoreInternal m_semaphore
; // Signals the waiting threads.
607 wxSemaphoreInternal m_gate
;
608 wxCriticalSection m_varSection
;
609 size_t m_waiters
; // Number of threads waiting for a signal.
610 size_t m_signals
; // Number of signals to send.
611 size_t m_canceled
; // Number of canceled waiters in m_waiters.
615 wxCondError
wxConditionInternal::WaitTimeout(unsigned long msectimeout
)
618 if ( ++ m_waiters
== INT_MAX
)
620 m_varSection
.Enter();
621 m_waiters
-= m_canceled
;
622 m_signals
-= m_canceled
;
624 m_varSection
.Leave();
630 wxSemaError err
= m_semaphore
.WaitTimeout( msectimeout
);
631 wxASSERT( err
== wxSEMA_NO_ERROR
|| err
== wxSEMA_TIMEOUT
);
633 m_varSection
.Enter();
634 if ( err
!= wxSEMA_NO_ERROR
)
636 if ( m_signals
> m_canceled
)
638 // A signal is being sent after we timed out.
640 if ( m_waiters
== m_signals
)
642 // There are no excess waiters to catch the signal, so
643 // we must throw it away.
645 wxSemaError err2
= m_semaphore
.Wait();
646 if ( err2
!= wxSEMA_NO_ERROR
)
648 wxLogSysError(_("Error while waiting on semaphore"));
650 wxASSERT( err2
== wxSEMA_NO_ERROR
);
652 if ( -- m_signals
== m_canceled
)
654 // This was the last signal. open the gate.
655 wxASSERT( m_waiters
== m_canceled
);
661 // There are excess waiters to catch the signal, leave
668 // No signals is being sent.
669 // The gate may be open or closed, so we can't touch m_waiters.
676 // We caught a signal.
677 wxASSERT( m_signals
> m_canceled
);
679 if ( -- m_signals
== m_canceled
)
681 // This was the last signal. open the gate.
682 wxASSERT( m_waiters
== m_canceled
);
686 m_varSection
.Leave();
692 return err
== wxSEMA_TIMEOUT
? wxCOND_TIMEOUT
: wxCOND_MISC_ERROR
;
695 return wxCOND_NO_ERROR
;
699 wxCondError
wxConditionInternal::DoSignal( bool signalAll
)
702 m_varSection
.Enter();
704 wxASSERT( m_signals
== m_canceled
);
706 if ( m_waiters
== m_canceled
)
708 m_varSection
.Leave();
710 return wxCOND_NO_ERROR
;
715 m_waiters
-= m_canceled
;
720 m_signals
= signalAll
? m_waiters
: 1;
721 size_t n
= m_signals
;
723 m_varSection
.Leave();
725 // Let the waiters inherit the gate lock.
729 wxSemaError err
= m_semaphore
.Post();
730 wxASSERT( err
== wxSEMA_NO_ERROR
);
733 return wxCOND_NO_ERROR
;
737 class wxConditionInternal
740 wxConditionInternal(wxMutex
& mutex
);
742 bool IsOk() const { return m_mutex
.IsOk() && m_semaphore
.IsOk(); }
745 wxCondError
WaitTimeout(unsigned long milliseconds
);
747 wxCondError
Signal();
748 wxCondError
Broadcast();
751 // the number of threads currently waiting for this condition
754 // the critical section protecting m_numWaiters
755 wxCriticalSection m_csWaiters
;
758 wxSemaphore m_semaphore
;
760 DECLARE_NO_COPY_CLASS(wxConditionInternal
)
763 wxConditionInternal::wxConditionInternal(wxMutex
& mutex
)
766 // another thread can't access it until we return from ctor, so no need to
767 // protect access to m_numWaiters here
771 wxCondError
wxConditionInternal::Wait()
773 // increment the number of waiters
774 IncrementAtomic(&m_numWaiters
);
778 // a potential race condition can occur here
780 // after a thread increments nwaiters, and unlocks the mutex and before the
781 // semaphore.Wait() is called, if another thread can cause a signal to be
784 // this race condition is handled by using a semaphore and incrementing the
785 // semaphore only if 'nwaiters' is greater that zero since the semaphore,
786 // can 'remember' signals the race condition will not occur
788 // wait ( if necessary ) and decrement semaphore
789 wxSemaError err
= m_semaphore
.Wait();
792 return err
== wxSEMA_NO_ERROR
? wxCOND_NO_ERROR
: wxCOND_MISC_ERROR
;
795 wxCondError
wxConditionInternal::WaitTimeout(unsigned long milliseconds
)
797 IncrementAtomic(&m_numWaiters
);
801 // a race condition can occur at this point in the code
803 // please see the comments in Wait(), for details
805 wxSemaError err
= m_semaphore
.WaitTimeout(milliseconds
);
807 if ( err
== wxSEMA_BUSY
)
809 // another potential race condition exists here it is caused when a
810 // 'waiting' thread timesout, and returns from WaitForSingleObject, but
811 // has not yet decremented 'nwaiters'.
813 // at this point if another thread calls signal() then the semaphore
814 // will be incremented, but the waiting thread will miss it.
816 // to handle this particular case, the waiting thread calls
817 // WaitForSingleObject again with a timeout of 0, after locking
818 // 'nwaiters_mutex'. this call does not block because of the zero
819 // timeout, but will allow the waiting thread to catch the missed
821 wxCriticalSectionLocker
lock(m_csWaiters
);
823 err
= m_semaphore
.WaitTimeout(0);
825 if ( err
!= wxSEMA_NO_ERROR
)
833 return err
== wxSEMA_NO_ERROR
? wxCOND_NO_ERROR
: wxCOND_MISC_ERROR
;
836 wxCondError
wxConditionInternal::Signal()
838 wxCriticalSectionLocker
lock(m_csWaiters
);
840 if ( m_numWaiters
> 0 )
842 // increment the semaphore by 1
843 if ( m_semaphore
.Post() != wxSEMA_NO_ERROR
)
844 return wxCOND_MISC_ERROR
;
849 return wxCOND_NO_ERROR
;
852 wxCondError
wxConditionInternal::Broadcast()
854 wxCriticalSectionLocker
lock(m_csWaiters
);
856 while ( m_numWaiters
> 0 )
858 if ( m_semaphore
.Post() != wxSEMA_NO_ERROR
)
859 return wxCOND_MISC_ERROR
;
864 return wxCOND_NO_ERROR
;
868 // ----------------------------------------------------------------------------
869 // wxCriticalSection implementation
870 // ----------------------------------------------------------------------------
872 // XXX currently implemented as mutex in headers. Change to critical section.
874 // ----------------------------------------------------------------------------
875 // wxThread implementation
876 // ----------------------------------------------------------------------------
878 // wxThreadInternal class
879 // ----------------------
881 class wxThreadInternal
888 m_prio
= WXTHREAD_DEFAULT_PRIORITY
;
889 m_notifyQueueId
= kInvalidID
;
891 m_cancelled
= FALSE
;
893 // set to TRUE only when the thread starts waiting on m_semSuspend
896 // defaults for joinable threads
897 m_shouldBeJoined
= TRUE
;
898 m_isDetached
= FALSE
;
902 if ( m_notifyQueueId
)
904 MPDeleteQueue( m_notifyQueueId
);
905 m_notifyQueueId
= kInvalidID
;
910 static OSStatus
MacThreadStart(void* arg
);
912 // create a new (suspended) thread (for the given thread object)
913 bool Create(wxThread
*thread
, unsigned int stackSize
);
918 // unblock the thread allowing it to run
919 void SignalRun() { m_semRun
.Post(); }
920 // ask the thread to terminate
922 // go to sleep until Resume() is called
929 int GetPriority() const { return m_prio
; }
930 void SetPriority(int prio
) ;
932 wxThreadState
GetState() const { return m_state
; }
933 void SetState(wxThreadState state
) { m_state
= state
; }
935 // Get the ID of this thread's underlying MP Services task.
936 MPTaskID
GetId() const { return m_tid
; }
938 void SetCancelFlag() { m_cancelled
= TRUE
; }
939 bool WasCancelled() const { return m_cancelled
; }
941 void SetExitCode(wxThread::ExitCode exitcode
) { m_exitcode
= exitcode
; }
942 wxThread::ExitCode
GetExitCode() const { return m_exitcode
; }
945 void SetReallyPaused(bool paused
) { m_isPaused
= paused
; }
946 bool IsReallyPaused() const { return m_isPaused
; }
948 // tell the thread that it is a detached one
951 wxCriticalSectionLocker
lock(m_csJoinFlag
);
953 m_shouldBeJoined
= FALSE
;
958 // the thread we're associated with
961 MPTaskID m_tid
; // thread id
962 MPQueueID m_notifyQueueId
; // its notification queue
964 wxThreadState m_state
; // see wxThreadState enum
965 int m_prio
; // in wxWindows units: from 0 to 100
967 // this flag is set when the thread should terminate
970 // this flag is set when the thread is blocking on m_semSuspend
973 // the thread exit code - only used for joinable (!detached) threads and
974 // is only valid after the thread termination
975 wxThread::ExitCode m_exitcode
;
977 // many threads may call Wait(), but only one of them should call
978 // pthread_join(), so we have to keep track of this
979 wxCriticalSection m_csJoinFlag
;
980 bool m_shouldBeJoined
;
983 // this semaphore is posted by Run() and the threads Entry() is not
984 // called before it is done
985 wxSemaphore m_semRun
;
987 // this one is signaled when the thread should resume after having been
989 wxSemaphore m_semSuspend
;
992 OSStatus
wxThreadInternal::MacThreadStart(void *parameter
)
994 wxThread
* thread
= (wxThread
*) parameter
;
995 wxThreadInternal
*pthread
= thread
->m_internal
;
997 // add to TLS so that This() will work
998 verify_noerr( MPSetTaskStorageValue( gs_tlsForWXThread
, (long) thread
) ) ;
1000 // have to declare this before pthread_cleanup_push() which defines a
1004 // wait for the semaphore to be posted from Run()
1005 pthread
->m_semRun
.Wait();
1007 // test whether we should run the run at all - may be it was deleted
1008 // before it started to Run()?
1010 wxCriticalSectionLocker
lock(thread
->m_critsect
);
1012 dontRunAtAll
= pthread
->GetState() == STATE_NEW
&&
1013 pthread
->WasCancelled();
1016 if ( !dontRunAtAll
)
1018 pthread
->m_exitcode
= thread
->Entry();
1021 wxCriticalSectionLocker
lock(thread
->m_critsect
);
1022 pthread
->SetState(STATE_EXITED
);
1028 if ( pthread
->m_isDetached
)
1035 // on mac for the running code the correct thread termination is to
1038 // terminate the thread
1039 thread
->Exit(pthread
->m_exitcode
);
1041 return (OSStatus
) NULL
; // pthread->m_exitcode;
1045 bool wxThreadInternal::Create(wxThread
*thread
, unsigned int stackSize
)
1047 wxASSERT_MSG( m_state
== STATE_NEW
&& !m_tid
,
1048 _T("Create()ing thread twice?") );
1050 OSStatus err
= noErr
;
1053 if ( m_notifyQueueId
== kInvalidID
)
1055 OSStatus err
= MPCreateQueue( & m_notifyQueueId
);
1058 wxLogSysError(_("Cant create the thread event queue"));
1063 m_state
= STATE_NEW
;
1065 err
= MPCreateTask( MacThreadStart
,
1076 wxLogSysError(_("Can't create thread"));
1080 if ( m_prio
!= WXTHREAD_DEFAULT_PRIORITY
)
1082 SetPriority(m_prio
);
1088 void wxThreadInternal::SetPriority( int priority
)
1094 // Mac priorities range from 1 to 10,000, with a default of 100.
1095 // wxWindows priorities range from 0 to 100 with a default of 50.
1096 // We can map wxWindows to Mac priorities easily by assuming
1097 // the former uses a logarithmic scale.
1098 const unsigned int macPriority
= ( int)( exp( priority
/ 25.0 * log( 10.0)) + 0.5);
1100 MPSetTaskWeight( m_tid
, macPriority
);
1104 wxThreadError
wxThreadInternal::Run()
1106 wxCHECK_MSG( GetState() == STATE_NEW
, wxTHREAD_RUNNING
,
1107 wxT("thread may only be started once after Create()") );
1109 SetState(STATE_RUNNING
);
1111 // wake up threads waiting for our start
1114 return wxTHREAD_NO_ERROR
;
1117 void wxThreadInternal::Wait()
1119 wxCHECK_RET( !m_isDetached
, _T("can't wait for a detached thread") );
1121 // if the thread we're waiting for is waiting for the GUI mutex, we will
1122 // deadlock so make sure we release it temporarily
1123 if ( wxThread::IsMain() )
1125 // give the thread we're waiting for chance to do the GUI call
1126 // it might be in, we don't do this conditionally as the to be waited on
1127 // thread might have to acquire the mutex later but before terminating
1128 if ( wxGuiOwnedByMainThread() )
1135 wxCriticalSectionLocker
lock(m_csJoinFlag
);
1137 if ( m_shouldBeJoined
)
1143 OSStatus err
= MPWaitOnQueue ( m_notifyQueueId
,
1150 wxLogSysError( _( "Cannot wait on thread to exit."));
1154 // actually param1 would be the address of m_exitcode
1155 // but we don't need this here
1158 m_shouldBeJoined
= FALSE
;
1163 void wxThreadInternal::Pause()
1165 // the state is set from the thread which pauses us first, this function
1166 // is called later so the state should have been already set
1167 wxCHECK_RET( m_state
== STATE_PAUSED
,
1168 wxT("thread must first be paused with wxThread::Pause().") );
1170 // wait until the semaphore is Post()ed from Resume()
1171 m_semSuspend
.Wait();
1174 void wxThreadInternal::Resume()
1176 wxCHECK_RET( m_state
== STATE_PAUSED
,
1177 wxT("can't resume thread which is not suspended.") );
1179 // the thread might be not actually paused yet - if there were no call to
1180 // TestDestroy() since the last call to Pause() for example
1181 if ( IsReallyPaused() )
1184 m_semSuspend
.Post();
1187 SetReallyPaused(FALSE
);
1190 SetState(STATE_RUNNING
);
1196 wxThread
*wxThread::This()
1198 wxThread
* thr
= (wxThread
*) MPGetTaskStorageValue( gs_tlsForWXThread
) ;
1202 bool wxThread::IsMain()
1204 return GetCurrentId() == gs_idMainThread
|| gs_idMainThread
== kInvalidID
;
1211 void wxThread::Yield()
1213 #if TARGET_API_MAC_OSX
1214 CFRunLoopRunInMode( kCFRunLoopDefaultMode
, 0 , true ) ;
1220 void wxThread::Sleep(unsigned long milliseconds
)
1222 AbsoluteTime wakeup
= AddDurationToAbsolute( milliseconds
, UpTime());
1223 MPDelayUntil( & wakeup
);
1227 int wxThread::GetCPUCount()
1229 return MPProcessors();
1232 unsigned long wxThread::GetCurrentId()
1234 return (unsigned long)MPCurrentTaskID();
1238 bool wxThread::SetConcurrency(size_t level
)
1240 // Cannot be set in MacOS.
1245 wxThread::wxThread(wxThreadKind kind
)
1247 g_numberOfThreads
++;
1248 m_internal
= new wxThreadInternal();
1250 m_isDetached
= (kind
== wxTHREAD_DETACHED
);
1253 wxThread::~wxThread()
1255 wxASSERT_MSG( g_numberOfThreads
>0 , wxT("More threads deleted than created.") ) ;
1256 g_numberOfThreads
--;
1261 // check that the thread either exited or couldn't be created
1262 if ( m_internal
->GetState() != STATE_EXITED
&&
1263 m_internal
->GetState() != STATE_NEW
)
1265 wxLogDebug(_T("The thread %ld is being destroyed although it is still running! The application may crash."), GetId());
1269 #endif // __WXDEBUG__
1271 wxDELETE( m_internal
) ;
1275 wxThreadError
wxThread::Create(unsigned int stackSize
)
1277 wxCriticalSectionLocker
lock(m_critsect
);
1281 m_internal
->Detach() ;
1283 if ( m_internal
->Create(this, stackSize
) == false )
1285 m_internal
->SetState(STATE_EXITED
);
1286 return wxTHREAD_NO_RESOURCE
;
1289 return wxTHREAD_NO_ERROR
;
1292 wxThreadError
wxThread::Run()
1294 wxCriticalSectionLocker
lock(m_critsect
);
1296 wxCHECK_MSG( m_internal
->GetId(), wxTHREAD_MISC_ERROR
,
1297 wxT("must call wxThread::Create() first") );
1299 return m_internal
->Run();
1302 // -----------------------------------------------------------------------------
1304 // -----------------------------------------------------------------------------
1306 wxThreadError
wxThread::Pause()
1308 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
,
1309 _T("a thread can't pause itself") );
1311 wxCriticalSectionLocker
lock(m_critsect
);
1313 if ( m_internal
->GetState() != STATE_RUNNING
)
1315 wxLogDebug(wxT("Can't pause thread which is not running."));
1317 return wxTHREAD_NOT_RUNNING
;
1320 // just set a flag, the thread will be really paused only during the next
1321 // call to TestDestroy()
1322 m_internal
->SetState(STATE_PAUSED
);
1324 return wxTHREAD_NO_ERROR
;
1327 wxThreadError
wxThread::Resume()
1329 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
,
1330 _T("a thread can't resume itself") );
1332 wxCriticalSectionLocker
lock(m_critsect
);
1334 wxThreadState state
= m_internal
->GetState();
1339 m_internal
->Resume();
1340 return wxTHREAD_NO_ERROR
;
1342 return wxTHREAD_NO_ERROR
;
1345 wxLogDebug(_T("Attempt to resume a thread which is not paused."));
1347 return wxTHREAD_MISC_ERROR
;
1351 // -----------------------------------------------------------------------------
1353 // -----------------------------------------------------------------------------
1355 wxThread::ExitCode
wxThread::Wait()
1357 wxCHECK_MSG( This() != this, (ExitCode
)-1,
1358 _T("a thread can't wait for itself") );
1360 wxCHECK_MSG( !m_isDetached
, (ExitCode
)-1,
1361 _T("can't wait for detached thread") );
1365 return m_internal
->GetExitCode();
1368 wxThreadError
wxThread::Delete(ExitCode
*rc
)
1370 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
,
1371 _T("a thread can't delete itself") );
1373 bool isDetached
= m_isDetached
;
1376 wxThreadState state
= m_internal
->GetState();
1378 // ask the thread to stop
1379 m_internal
->SetCancelFlag();
1386 // we need to wake up the thread so that PthreadStart() will
1387 // terminate - right now it's blocking on run semaphore in
1389 m_internal
->SignalRun();
1398 // resume the thread first
1399 m_internal
->Resume();
1406 // wait until the thread stops
1411 // return the exit code of the thread
1412 *rc
= m_internal
->GetExitCode();
1417 return wxTHREAD_NO_ERROR
;
1420 wxThreadError
wxThread::Kill()
1422 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
,
1423 _T("a thread can't kill itself") );
1425 switch ( m_internal
->GetState() )
1429 return wxTHREAD_NOT_RUNNING
;
1432 // resume the thread first
1438 OSStatus err
= MPTerminateTask( m_internal
->GetId() , -1 ) ;
1441 wxLogError(_("Failed to terminate a thread."));
1443 return wxTHREAD_MISC_ERROR
;
1452 // this should be retrieved by Wait actually
1453 m_internal
->SetExitCode((void*)-1);
1456 return wxTHREAD_NO_ERROR
;
1460 void wxThread::Exit(ExitCode status
)
1462 wxASSERT_MSG( This() == this,
1463 _T("wxThread::Exit() can only be called in the context of the same thread") );
1465 // don't enter m_critsect before calling OnExit() because the user code
1466 // might deadlock if, for example, it signals a condition in OnExit() (a
1467 // common case) while the main thread calls any of functions entering
1468 // m_critsect on us (almost all of them do)
1471 MPTaskID threadid
= m_internal
->GetId() ;
1479 // update the status of the joinable thread
1480 wxCriticalSectionLocker
lock(m_critsect
);
1481 m_internal
->SetState(STATE_EXITED
);
1483 MPTerminateTask( threadid
, (long) status
) ;
1486 // also test whether we were paused
1487 bool wxThread::TestDestroy()
1489 wxASSERT_MSG( This() == this,
1490 _T("wxThread::TestDestroy() can only be called in the context of the same thread") );
1494 if ( m_internal
->GetState() == STATE_PAUSED
)
1496 m_internal
->SetReallyPaused(TRUE
);
1498 // leave the crit section or the other threads will stop too if they
1499 // try to call any of (seemingly harmless) IsXXX() functions while we
1503 m_internal
->Pause();
1507 // thread wasn't requested to pause, nothing to do
1511 return m_internal
->WasCancelled();
1514 // -----------------------------------------------------------------------------
1516 // -----------------------------------------------------------------------------
1518 void wxThread::SetPriority(unsigned int prio
)
1520 wxCHECK_RET( ((int)WXTHREAD_MIN_PRIORITY
<= (int)prio
) &&
1521 ((int)prio
<= (int)WXTHREAD_MAX_PRIORITY
),
1522 wxT("invalid thread priority") );
1524 wxCriticalSectionLocker
lock(m_critsect
);
1526 switch ( m_internal
->GetState() )
1531 // thread not yet started, priority will be set when it is
1532 m_internal
->SetPriority(prio
);
1537 wxFAIL_MSG(wxT("impossible to set thread priority in this state"));
1541 unsigned int wxThread::GetPriority() const
1543 wxCriticalSectionLocker
lock((wxCriticalSection
&)m_critsect
); // const_cast
1545 return m_internal
->GetPriority();
1548 unsigned long wxThread::GetId() const
1550 wxCriticalSectionLocker
lock((wxCriticalSection
&)m_critsect
); // const_cast
1552 return (unsigned long)m_internal
->GetId();
1555 // -----------------------------------------------------------------------------
1557 // -----------------------------------------------------------------------------
1559 bool wxThread::IsRunning() const
1561 wxCriticalSectionLocker
lock((wxCriticalSection
&)m_critsect
);
1563 return m_internal
->GetState() == STATE_RUNNING
;
1566 bool wxThread::IsAlive() const
1568 wxCriticalSectionLocker
lock((wxCriticalSection
&)m_critsect
);
1570 switch ( m_internal
->GetState() )
1581 bool wxThread::IsPaused() const
1583 wxCriticalSectionLocker
lock((wxCriticalSection
&)m_critsect
);
1585 return (m_internal
->GetState() == STATE_PAUSED
);
1588 // ----------------------------------------------------------------------------
1589 // Automatic initialization for thread module
1590 // ----------------------------------------------------------------------------
1592 class wxThreadModule
: public wxModule
1595 virtual bool OnInit();
1596 virtual void OnExit();
1599 DECLARE_DYNAMIC_CLASS(wxThreadModule
)
1602 IMPLEMENT_DYNAMIC_CLASS(wxThreadModule
, wxModule
)
1604 bool wxThreadModule::OnInit()
1606 bool hasThreadManager
= false ;
1607 hasThreadManager
= MPLibraryIsLoaded();
1609 if ( !hasThreadManager
)
1611 wxLogError( _("MP Thread Support is not available on this System" ) ) ;
1615 verify_noerr( MPAllocateTaskStorageIndex( &gs_tlsForWXThread
) ) ;
1616 // main thread's This() is NULL
1617 verify_noerr( MPSetTaskStorageValue( gs_tlsForWXThread
, NULL
) ) ;
1619 gs_idMainThread
= wxThread::GetCurrentId() ;
1621 gs_critsectWaitingForGui
= new wxCriticalSection();
1623 gs_critsectGui
= new wxCriticalSection();
1624 gs_critsectGui
->Enter();
1629 void wxThreadModule::OnExit()
1631 if ( gs_critsectGui
)
1633 gs_critsectGui
->Leave();
1634 delete gs_critsectGui
;
1635 gs_critsectGui
= NULL
;
1638 delete gs_critsectWaitingForGui
;
1639 gs_critsectWaitingForGui
= NULL
;
1642 // ----------------------------------------------------------------------------
1643 // GUI Serialization copied from MSW implementation
1644 // ----------------------------------------------------------------------------
1646 void WXDLLIMPEXP_BASE
wxMutexGuiEnter()
1648 // this would dead lock everything...
1649 wxASSERT_MSG( !wxThread::IsMain(),
1650 wxT("main thread doesn't want to block in wxMutexGuiEnter()!") );
1652 // the order in which we enter the critical sections here is crucial!!
1654 // set the flag telling to the main thread that we want to do some GUI
1656 wxCriticalSectionLocker
enter(*gs_critsectWaitingForGui
);
1658 gs_nWaitingForGui
++;
1661 wxWakeUpMainThread();
1663 // now we may block here because the main thread will soon let us in
1664 // (during the next iteration of OnIdle())
1665 gs_critsectGui
->Enter();
1668 void WXDLLIMPEXP_BASE
wxMutexGuiLeave()
1670 wxCriticalSectionLocker
enter(*gs_critsectWaitingForGui
);
1672 if ( wxThread::IsMain() )
1674 gs_bGuiOwnedByMainThread
= false;
1678 // decrement the number of threads waiting for GUI access now
1679 wxASSERT_MSG( gs_nWaitingForGui
> 0,
1680 wxT("calling wxMutexGuiLeave() without entering it first?") );
1682 gs_nWaitingForGui
--;
1684 wxWakeUpMainThread();
1687 gs_critsectGui
->Leave();
1690 void WXDLLIMPEXP_BASE
wxMutexGuiLeaveOrEnter()
1692 wxASSERT_MSG( wxThread::IsMain(),
1693 wxT("only main thread may call wxMutexGuiLeaveOrEnter()!") );
1695 wxCriticalSectionLocker
enter(*gs_critsectWaitingForGui
);
1697 if ( gs_nWaitingForGui
== 0 )
1699 // no threads are waiting for GUI - so we may acquire the lock without
1700 // any danger (but only if we don't already have it)
1701 if ( !wxGuiOwnedByMainThread() )
1703 gs_critsectGui
->Enter();
1705 gs_bGuiOwnedByMainThread
= true;
1707 //else: already have it, nothing to do
1711 // some threads are waiting, release the GUI lock if we have it
1712 if ( wxGuiOwnedByMainThread() )
1716 //else: some other worker thread is doing GUI
1720 bool WXDLLIMPEXP_BASE
wxGuiOwnedByMainThread()
1722 return gs_bGuiOwnedByMainThread
;
1725 // wake up the main thread
1726 void WXDLLEXPORT
wxWakeUpMainThread()
1731 // ----------------------------------------------------------------------------
1732 // include common implementation code
1733 // ----------------------------------------------------------------------------
1735 #include "wx/thrimpl.cpp"
1737 #endif // wxUSE_THREADS