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 #include <CoreServices/CoreServices.h>
39 #include "wx/mac/uma.h"
42 // trace mask for wxThread operations
43 #define TRACE_THREADS _T("thread")
45 // you can get additional debugging messages for the semaphore operations
46 #define TRACE_SEMA _T("semaphore")
49 // ----------------------------------------------------------------------------
51 // ----------------------------------------------------------------------------
53 // the possible states of the thread ("=>" shows all possible transitions from
57 STATE_NEW
, // didn't start execution yet (=> RUNNING)
58 STATE_RUNNING
, // thread is running (=> PAUSED, CANCELED)
59 STATE_PAUSED
, // thread is temporarily suspended (=> RUNNING)
60 STATE_CANCELED
, // thread should terminate a.s.a.p. (=> EXITED)
61 STATE_EXITED
// thread is terminating
64 // ----------------------------------------------------------------------------
65 // this module globals
66 // ----------------------------------------------------------------------------
69 // the task ID of the main thread
70 static wxThreadIdType gs_idMainThread
= kInvalidID
;
72 // this is the Per-Task Storage for the pointer to the appropriate wxThread
73 TaskStorageIndex gs_tlsForWXThread
= 0 ;
75 // if it's false, some secondary thread is holding the GUI lock
76 static bool gs_bGuiOwnedByMainThread
= true;
78 // critical section which controls access to all GUI functions: any secondary
79 // thread (i.e. except the main one) must enter this crit section before doing
81 static wxCriticalSection
*gs_critsectGui
= NULL
;
83 // critical section which protects gs_nWaitingForGui variable
84 static wxCriticalSection
*gs_critsectWaitingForGui
= NULL
;
86 // number of threads waiting for GUI in wxMutexGuiEnter()
87 static size_t gs_nWaitingForGui
= 0;
89 // overall number of threads, needed for determining the sleep value of the main
91 size_t g_numberOfThreads
= 0;
97 MPCriticalRegionID gs_guiCritical
= kInvalidID
;
101 // ============================================================================
102 // MacOS implementation of thread classes
103 // ============================================================================
108 The implementation is very close to the phtreads implementation, the reason for
109 using MPServices is the fact that these are also available under OS 9. Thus allowing
110 for one common API for all current builds.
112 As soon as wxThreads are on a 64 bit address space, the TLS must be extended
113 to use two indices one for each 32 bit part as the MP implementation is limited
116 I have two implementations for mutexes :
117 version A based on a binary semaphore, problem - not reentrant, version B based
118 on a critical region, allows for reentrancy, performance implications not
121 The same for condition internal, one implementation by Aj Lavin and the other one
122 copied from the thrimpl.cpp which I assume has been more broadly tested, I've just
123 replaced the interlock increment with the appropriate PPC calls
126 // ----------------------------------------------------------------------------
127 // wxMutex implementation
128 // ----------------------------------------------------------------------------
132 class wxMutexInternal
135 wxMutexInternal(wxMutexType mutexType
) ;
137 bool IsOk() const { return m_isOk
; }
139 wxMutexError
Lock() ;
140 wxMutexError
TryLock() ;
141 wxMutexError
Unlock();
143 MPSemaphoreID m_semaphore
;
147 wxMutexInternal::wxMutexInternal(wxMutexType mutexType
)
150 m_semaphore
= kInvalidID
;
152 OSStatus err
= noErr
;
155 case wxMUTEX_DEFAULT
:
157 verify_noerr( MPCreateBinarySemaphore( & m_semaphore
) );
158 m_isOk
= ( m_semaphore
!= kInvalidID
) ;
161 case wxMUTEX_RECURSIVE
:
162 wxFAIL_MSG(wxT("Recursive Mutex not supported yet") ) ;
165 wxFAIL_MSG(wxT("Unknown mutex type") ) ;
170 wxMutexInternal::~wxMutexInternal()
172 if ( m_semaphore
!= kInvalidID
)
173 MPDeleteSemaphore( m_semaphore
);
176 wxMutexError
wxMutexInternal::Lock()
178 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") ) ;
179 OSStatus err
= MPWaitOnSemaphore( m_semaphore
, kDurationForever
);
182 wxLogSysError(wxT("Could not lock mutex"));
183 return wxMUTEX_MISC_ERROR
;
186 return wxMUTEX_NO_ERROR
;
189 wxMutexError
wxMutexInternal::TryLock()
191 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") ) ;
192 OSStatus err
= MPWaitOnSemaphore( m_semaphore
, kDurationImmediate
);
195 if ( err
== kMPTimeoutErr
)
199 wxLogSysError(wxT("Could not try lock mutex"));
200 return wxMUTEX_MISC_ERROR
;
203 return wxMUTEX_NO_ERROR
;
206 wxMutexError
wxMutexInternal::Unlock()
208 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") ) ;
209 OSStatus err
= MPSignalSemaphore( m_semaphore
);
212 wxLogSysError(_("Could not unlock mutex"));
213 return wxMUTEX_MISC_ERROR
;
216 return wxMUTEX_NO_ERROR
;
221 class wxMutexInternal
224 wxMutexInternal(wxMutexType mutexType
) ;
226 bool IsOk() const { return m_isOk
; }
228 wxMutexError
Lock() ;
229 wxMutexError
TryLock() ;
230 wxMutexError
Unlock();
232 MPCriticalRegionID m_critRegion
;
236 wxMutexInternal::wxMutexInternal(wxMutexType mutexType
)
239 m_critRegion
= kInvalidID
;
241 verify_noerr( MPCreateCriticalRegion( & m_critRegion
) );
242 m_isOk
= ( m_critRegion
!= kInvalidID
) ;
245 wxFAIL_MSG(wxT("Error when creating mutex") ) ;
248 wxMutexInternal::~wxMutexInternal()
250 if ( m_critRegion
!= kInvalidID
)
251 MPDeleteCriticalRegion( m_critRegion
);
254 wxMutexError
wxMutexInternal::Lock()
256 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") ) ;
257 OSStatus err
= MPEnterCriticalRegion( m_critRegion
, kDurationForever
);
260 wxLogSysError(wxT("Could not lock mutex"));
261 return wxMUTEX_MISC_ERROR
;
264 return wxMUTEX_NO_ERROR
;
267 wxMutexError
wxMutexInternal::TryLock()
269 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") ) ;
270 OSStatus err
= MPEnterCriticalRegion( m_critRegion
, kDurationImmediate
);
273 if ( err
== kMPTimeoutErr
)
277 wxLogSysError(wxT("Could not try lock mutex"));
278 return wxMUTEX_MISC_ERROR
;
281 return wxMUTEX_NO_ERROR
;
284 wxMutexError
wxMutexInternal::Unlock()
286 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") ) ;
287 OSStatus err
= MPExitCriticalRegion( m_critRegion
);
290 wxLogSysError(_("Could not unlock mutex"));
291 return wxMUTEX_MISC_ERROR
;
294 return wxMUTEX_NO_ERROR
;
299 // --------------------------------------------------------------------------
301 // --------------------------------------------------------------------------
303 class wxSemaphoreInternal
306 wxSemaphoreInternal(int initialcount
, int maxcount
);
307 ~wxSemaphoreInternal();
309 bool IsOk() const { return m_isOk
; }
311 wxSemaError
WaitTimeout(unsigned long milliseconds
);
313 wxSemaError
Wait() { return WaitTimeout( kDurationForever
); }
315 wxSemaError
TryWait()
317 wxSemaError err
= WaitTimeout(kDurationImmediate
);
318 if ( err
== wxSEMA_TIMEOUT
)
325 MPSemaphoreID m_semaphore
;
329 wxSemaphoreInternal::wxSemaphoreInternal(int initialcount
, int maxcount
)
332 m_semaphore
= kInvalidID
;
335 // make it practically infinite
338 verify_noerr( MPCreateSemaphore( maxcount
, initialcount
, & m_semaphore
) );
339 m_isOk
= ( m_semaphore
!= kInvalidID
) ;
342 wxFAIL_MSG(wxT("Error when creating semaphore") ) ;
345 wxSemaphoreInternal::~wxSemaphoreInternal()
347 if( m_semaphore
!= kInvalidID
)
348 MPDeleteSemaphore( m_semaphore
);
351 wxSemaError
wxSemaphoreInternal::WaitTimeout(unsigned long milliseconds
)
353 OSStatus err
= MPWaitOnSemaphore( m_semaphore
, milliseconds
);
356 if ( err
== kMPTimeoutErr
)
358 return wxSEMA_TIMEOUT
;
360 return wxSEMA_MISC_ERROR
;
362 return wxSEMA_NO_ERROR
;
365 wxSemaError
wxSemaphoreInternal::Post()
367 OSStatus err
= MPSignalSemaphore( m_semaphore
);
370 return wxSEMA_MISC_ERROR
;
372 return wxSEMA_NO_ERROR
;
375 // ----------------------------------------------------------------------------
376 // wxCondition implementation
377 // ----------------------------------------------------------------------------
381 class wxConditionInternal
385 wxConditionInternal(wxMutex
& mutex
)
395 ~wxConditionInternal()
399 bool IsOk() const { return m_mutex
.IsOk() ; }
403 return WaitTimeout( kDurationForever
);
406 wxCondError
WaitTimeout(unsigned long msectimeout
);
410 return DoSignal( false);
413 wxCondError
Broadcast()
415 return DoSignal( true);
420 wxCondError
DoSignal( bool signalAll
);
423 wxSemaphoreInternal m_semaphore
; // Signals the waiting threads.
424 wxSemaphoreInternal m_gate
;
425 wxCriticalSection m_varSection
;
426 size_t m_waiters
; // Number of threads waiting for a signal.
427 size_t m_signals
; // Number of signals to send.
428 size_t m_canceled
; // Number of canceled waiters in m_waiters.
432 wxCondError
wxConditionInternal::WaitTimeout(unsigned long msectimeout
)
435 if ( ++ m_waiters
== INT_MAX
)
437 m_varSection
.Enter();
438 m_waiters
-= m_canceled
;
439 m_signals
-= m_canceled
;
441 m_varSection
.Leave();
447 wxSemaError err
= m_semaphore
.WaitTimeout( msectimeout
);
448 wxASSERT( err
== wxSEMA_NO_ERROR
|| err
== wxSEMA_TIMEOUT
);
450 m_varSection
.Enter();
451 if ( err
!= wxSEMA_NO_ERROR
)
453 if ( m_signals
> m_canceled
)
455 // A signal is being sent after we timed out.
457 if ( m_waiters
== m_signals
)
459 // There are no excess waiters to catch the signal, so
460 // we must throw it away.
462 wxSemaError err2
= m_semaphore
.Wait();
463 if ( err2
!= wxSEMA_NO_ERROR
)
465 wxLogSysError(_("Error while waiting on semaphore"));
467 wxASSERT( err2
== wxSEMA_NO_ERROR
);
469 if ( -- m_signals
== m_canceled
)
471 // This was the last signal. open the gate.
472 wxASSERT( m_waiters
== m_canceled
);
478 // There are excess waiters to catch the signal, leave
485 // No signals is being sent.
486 // The gate may be open or closed, so we can't touch m_waiters.
493 // We caught a signal.
494 wxASSERT( m_signals
> m_canceled
);
496 if ( -- m_signals
== m_canceled
)
498 // This was the last signal. open the gate.
499 wxASSERT( m_waiters
== m_canceled
);
503 m_varSection
.Leave();
509 return err
== wxSEMA_TIMEOUT
? wxCOND_TIMEOUT
: wxCOND_MISC_ERROR
;
512 return wxCOND_NO_ERROR
;
516 wxCondError
wxConditionInternal::DoSignal( bool signalAll
)
519 m_varSection
.Enter();
521 wxASSERT( m_signals
== m_canceled
);
523 if ( m_waiters
== m_canceled
)
525 m_varSection
.Leave();
527 return wxCOND_NO_ERROR
;
532 m_waiters
-= m_canceled
;
537 m_signals
= signalAll
? m_waiters
: 1;
538 size_t n
= m_signals
;
540 m_varSection
.Leave();
542 // Let the waiters inherit the gate lock.
546 wxSemaError err
= m_semaphore
.Post();
547 wxASSERT( err
== wxSEMA_NO_ERROR
);
550 return wxCOND_NO_ERROR
;
554 class wxConditionInternal
557 wxConditionInternal(wxMutex
& mutex
);
559 bool IsOk() const { return m_mutex
.IsOk() && m_semaphore
.IsOk(); }
562 wxCondError
WaitTimeout(unsigned long milliseconds
);
564 wxCondError
Signal();
565 wxCondError
Broadcast();
568 // the number of threads currently waiting for this condition
571 // the critical section protecting m_numWaiters
572 wxCriticalSection m_csWaiters
;
575 wxSemaphore m_semaphore
;
577 DECLARE_NO_COPY_CLASS(wxConditionInternal
)
580 wxConditionInternal::wxConditionInternal(wxMutex
& mutex
)
583 // another thread can't access it until we return from ctor, so no need to
584 // protect access to m_numWaiters here
588 wxCondError
wxConditionInternal::Wait()
590 // increment the number of waiters
591 IncrementAtomic(&m_numWaiters
);
595 // a potential race condition can occur here
597 // after a thread increments nwaiters, and unlocks the mutex and before the
598 // semaphore.Wait() is called, if another thread can cause a signal to be
601 // this race condition is handled by using a semaphore and incrementing the
602 // semaphore only if 'nwaiters' is greater that zero since the semaphore,
603 // can 'remember' signals the race condition will not occur
605 // wait ( if necessary ) and decrement semaphore
606 wxSemaError err
= m_semaphore
.Wait();
609 return err
== wxSEMA_NO_ERROR
? wxCOND_NO_ERROR
: wxCOND_MISC_ERROR
;
612 wxCondError
wxConditionInternal::WaitTimeout(unsigned long milliseconds
)
614 IncrementAtomic(&m_numWaiters
);
618 // a race condition can occur at this point in the code
620 // please see the comments in Wait(), for details
622 wxSemaError err
= m_semaphore
.WaitTimeout(milliseconds
);
624 if ( err
== wxSEMA_BUSY
)
626 // another potential race condition exists here it is caused when a
627 // 'waiting' thread timesout, and returns from WaitForSingleObject, but
628 // has not yet decremented 'nwaiters'.
630 // at this point if another thread calls signal() then the semaphore
631 // will be incremented, but the waiting thread will miss it.
633 // to handle this particular case, the waiting thread calls
634 // WaitForSingleObject again with a timeout of 0, after locking
635 // 'nwaiters_mutex'. this call does not block because of the zero
636 // timeout, but will allow the waiting thread to catch the missed
638 wxCriticalSectionLocker
lock(m_csWaiters
);
640 err
= m_semaphore
.WaitTimeout(0);
642 if ( err
!= wxSEMA_NO_ERROR
)
650 return err
== wxSEMA_NO_ERROR
? wxCOND_NO_ERROR
: wxCOND_MISC_ERROR
;
653 wxCondError
wxConditionInternal::Signal()
655 wxCriticalSectionLocker
lock(m_csWaiters
);
657 if ( m_numWaiters
> 0 )
659 // increment the semaphore by 1
660 if ( m_semaphore
.Post() != wxSEMA_NO_ERROR
)
661 return wxCOND_MISC_ERROR
;
666 return wxCOND_NO_ERROR
;
669 wxCondError
wxConditionInternal::Broadcast()
671 wxCriticalSectionLocker
lock(m_csWaiters
);
673 while ( m_numWaiters
> 0 )
675 if ( m_semaphore
.Post() != wxSEMA_NO_ERROR
)
676 return wxCOND_MISC_ERROR
;
681 return wxCOND_NO_ERROR
;
685 // ----------------------------------------------------------------------------
686 // wxCriticalSection implementation
687 // ----------------------------------------------------------------------------
689 // XXX currently implemented as mutex in headers. Change to critical section.
691 // ----------------------------------------------------------------------------
692 // wxThread implementation
693 // ----------------------------------------------------------------------------
695 // wxThreadInternal class
696 // ----------------------
698 class wxThreadInternal
705 m_prio
= WXTHREAD_DEFAULT_PRIORITY
;
706 m_notifyQueueId
= kInvalidID
;
708 m_cancelled
= FALSE
;
710 // set to TRUE only when the thread starts waiting on m_semSuspend
713 // defaults for joinable threads
714 m_shouldBeJoined
= TRUE
;
715 m_isDetached
= FALSE
;
719 if ( m_notifyQueueId
)
721 MPDeleteQueue( m_notifyQueueId
);
722 m_notifyQueueId
= kInvalidID
;
727 static OSStatus
MacThreadStart(void* arg
);
729 // create a new (suspended) thread (for the given thread object)
730 bool Create(wxThread
*thread
, unsigned int stackSize
);
735 // unblock the thread allowing it to run
736 void SignalRun() { m_semRun
.Post(); }
737 // ask the thread to terminate
739 // go to sleep until Resume() is called
746 int GetPriority() const { return m_prio
; }
747 void SetPriority(int prio
) ;
749 wxThreadState
GetState() const { return m_state
; }
750 void SetState(wxThreadState state
) { m_state
= state
; }
752 // Get the ID of this thread's underlying MP Services task.
753 MPTaskID
GetId() const { return m_tid
; }
755 void SetCancelFlag() { m_cancelled
= TRUE
; }
756 bool WasCancelled() const { return m_cancelled
; }
758 void SetExitCode(wxThread::ExitCode exitcode
) { m_exitcode
= exitcode
; }
759 wxThread::ExitCode
GetExitCode() const { return m_exitcode
; }
762 void SetReallyPaused(bool paused
) { m_isPaused
= paused
; }
763 bool IsReallyPaused() const { return m_isPaused
; }
765 // tell the thread that it is a detached one
768 wxCriticalSectionLocker
lock(m_csJoinFlag
);
770 m_shouldBeJoined
= FALSE
;
775 // the thread we're associated with
778 MPTaskID m_tid
; // thread id
779 MPQueueID m_notifyQueueId
; // its notification queue
781 wxThreadState m_state
; // see wxThreadState enum
782 int m_prio
; // in wxWindows units: from 0 to 100
784 // this flag is set when the thread should terminate
787 // this flag is set when the thread is blocking on m_semSuspend
790 // the thread exit code - only used for joinable (!detached) threads and
791 // is only valid after the thread termination
792 wxThread::ExitCode m_exitcode
;
794 // many threads may call Wait(), but only one of them should call
795 // pthread_join(), so we have to keep track of this
796 wxCriticalSection m_csJoinFlag
;
797 bool m_shouldBeJoined
;
800 // this semaphore is posted by Run() and the threads Entry() is not
801 // called before it is done
802 wxSemaphore m_semRun
;
804 // this one is signaled when the thread should resume after having been
806 wxSemaphore m_semSuspend
;
809 OSStatus
wxThreadInternal::MacThreadStart(void *parameter
)
811 wxThread
* thread
= (wxThread
*) parameter
;
812 wxThreadInternal
*pthread
= thread
->m_internal
;
814 // add to TLS so that This() will work
815 verify_noerr( MPSetTaskStorageValue( gs_tlsForWXThread
, (long) thread
) ) ;
817 // have to declare this before pthread_cleanup_push() which defines a
821 // wait for the semaphore to be posted from Run()
822 pthread
->m_semRun
.Wait();
824 // test whether we should run the run at all - may be it was deleted
825 // before it started to Run()?
827 wxCriticalSectionLocker
lock(thread
->m_critsect
);
829 dontRunAtAll
= pthread
->GetState() == STATE_NEW
&&
830 pthread
->WasCancelled();
835 pthread
->m_exitcode
= thread
->Entry();
838 wxCriticalSectionLocker
lock(thread
->m_critsect
);
839 pthread
->SetState(STATE_EXITED
);
845 if ( pthread
->m_isDetached
)
852 // on mac for the running code the correct thread termination is to
855 // terminate the thread
856 thread
->Exit(pthread
->m_exitcode
);
858 return (OSStatus
) NULL
; // pthread->m_exitcode;
862 bool wxThreadInternal::Create(wxThread
*thread
, unsigned int stackSize
)
864 wxASSERT_MSG( m_state
== STATE_NEW
&& !m_tid
,
865 _T("Create()ing thread twice?") );
867 OSStatus err
= noErr
;
870 if ( m_notifyQueueId
== kInvalidID
)
872 OSStatus err
= MPCreateQueue( & m_notifyQueueId
);
875 wxLogSysError(_("Cant create the thread event queue"));
882 err
= MPCreateTask( MacThreadStart
,
893 wxLogSysError(_("Can't create thread"));
897 if ( m_prio
!= WXTHREAD_DEFAULT_PRIORITY
)
905 void wxThreadInternal::SetPriority( int priority
)
911 // Mac priorities range from 1 to 10,000, with a default of 100.
912 // wxWindows priorities range from 0 to 100 with a default of 50.
913 // We can map wxWindows to Mac priorities easily by assuming
914 // the former uses a logarithmic scale.
915 const unsigned int macPriority
= ( int)( exp( priority
/ 25.0 * log( 10.0)) + 0.5);
917 MPSetTaskWeight( m_tid
, macPriority
);
921 wxThreadError
wxThreadInternal::Run()
923 wxCHECK_MSG( GetState() == STATE_NEW
, wxTHREAD_RUNNING
,
924 wxT("thread may only be started once after Create()") );
926 SetState(STATE_RUNNING
);
928 // wake up threads waiting for our start
931 return wxTHREAD_NO_ERROR
;
934 void wxThreadInternal::Wait()
936 wxCHECK_RET( !m_isDetached
, _T("can't wait for a detached thread") );
938 // if the thread we're waiting for is waiting for the GUI mutex, we will
939 // deadlock so make sure we release it temporarily
940 if ( wxThread::IsMain() )
944 wxCriticalSectionLocker
lock(m_csJoinFlag
);
946 if ( m_shouldBeJoined
)
952 OSStatus err
= MPWaitOnQueue ( m_notifyQueueId
,
959 wxLogSysError( _( "Cannot wait on thread to exit."));
963 // actually param1 would be the address of m_exitcode
964 // but we don't need this here
967 m_shouldBeJoined
= FALSE
;
971 // reacquire GUI mutex
972 if ( wxThread::IsMain() )
976 void wxThreadInternal::Pause()
978 // the state is set from the thread which pauses us first, this function
979 // is called later so the state should have been already set
980 wxCHECK_RET( m_state
== STATE_PAUSED
,
981 wxT("thread must first be paused with wxThread::Pause().") );
983 // wait until the semaphore is Post()ed from Resume()
987 void wxThreadInternal::Resume()
989 wxCHECK_RET( m_state
== STATE_PAUSED
,
990 wxT("can't resume thread which is not suspended.") );
992 // the thread might be not actually paused yet - if there were no call to
993 // TestDestroy() since the last call to Pause() for example
994 if ( IsReallyPaused() )
1000 SetReallyPaused(FALSE
);
1003 SetState(STATE_RUNNING
);
1009 wxThread
*wxThread::This()
1011 wxThread
* thr
= (wxThread
*) MPGetTaskStorageValue( gs_tlsForWXThread
) ;
1015 bool wxThread::IsMain()
1017 return GetCurrentId() == gs_idMainThread
;
1024 void wxThread::Yield()
1026 #if TARGET_API_MAC_OSX
1027 CFRunLoopRunInMode( kCFRunLoopDefaultMode
, 0 , true ) ;
1033 void wxThread::Sleep(unsigned long milliseconds
)
1035 AbsoluteTime wakeup
= AddDurationToAbsolute( milliseconds
, UpTime());
1036 MPDelayUntil( & wakeup
);
1040 int wxThread::GetCPUCount()
1042 return MPProcessors();
1045 unsigned long wxThread::GetCurrentId()
1047 return (unsigned long)MPCurrentTaskID();
1051 bool wxThread::SetConcurrency(size_t level
)
1053 // Cannot be set in MacOS.
1058 wxThread::wxThread(wxThreadKind kind
)
1060 g_numberOfThreads
++;
1061 m_internal
= new wxThreadInternal();
1063 m_isDetached
= (kind
== wxTHREAD_DETACHED
);
1066 wxThread::~wxThread()
1068 wxASSERT_MSG( g_numberOfThreads
>0 , wxT("More threads deleted than created.") ) ;
1069 g_numberOfThreads
--;
1074 // check that the thread either exited or couldn't be created
1075 if ( m_internal
->GetState() != STATE_EXITED
&&
1076 m_internal
->GetState() != STATE_NEW
)
1078 wxLogDebug(_T("The thread %ld is being destroyed although it is still running! The application may crash."), GetId());
1082 #endif // __WXDEBUG__
1084 wxDELETE( m_internal
) ;
1088 wxThreadError
wxThread::Create(unsigned int stackSize
)
1090 wxCriticalSectionLocker
lock(m_critsect
);
1094 m_internal
->Detach() ;
1096 if ( m_internal
->Create(this, stackSize
) == false )
1098 m_internal
->SetState(STATE_EXITED
);
1099 return wxTHREAD_NO_RESOURCE
;
1102 return wxTHREAD_NO_ERROR
;
1105 wxThreadError
wxThread::Run()
1107 wxCriticalSectionLocker
lock(m_critsect
);
1109 wxCHECK_MSG( m_internal
->GetId(), wxTHREAD_MISC_ERROR
,
1110 wxT("must call wxThread::Create() first") );
1112 return m_internal
->Run();
1115 // -----------------------------------------------------------------------------
1117 // -----------------------------------------------------------------------------
1119 wxThreadError
wxThread::Pause()
1121 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
,
1122 _T("a thread can't pause itself") );
1124 wxCriticalSectionLocker
lock(m_critsect
);
1126 if ( m_internal
->GetState() != STATE_RUNNING
)
1128 wxLogDebug(wxT("Can't pause thread which is not running."));
1130 return wxTHREAD_NOT_RUNNING
;
1133 // just set a flag, the thread will be really paused only during the next
1134 // call to TestDestroy()
1135 m_internal
->SetState(STATE_PAUSED
);
1137 return wxTHREAD_NO_ERROR
;
1140 wxThreadError
wxThread::Resume()
1142 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
,
1143 _T("a thread can't resume itself") );
1145 wxCriticalSectionLocker
lock(m_critsect
);
1147 wxThreadState state
= m_internal
->GetState();
1152 wxLogTrace(TRACE_THREADS
, _T("Thread %ld suspended, resuming."),
1155 m_internal
->Resume();
1157 return wxTHREAD_NO_ERROR
;
1160 wxLogTrace(TRACE_THREADS
, _T("Thread %ld exited, won't resume."),
1162 return wxTHREAD_NO_ERROR
;
1165 wxLogDebug(_T("Attempt to resume a thread which is not paused."));
1167 return wxTHREAD_MISC_ERROR
;
1171 // -----------------------------------------------------------------------------
1173 // -----------------------------------------------------------------------------
1175 wxThread::ExitCode
wxThread::Wait()
1177 wxCHECK_MSG( This() != this, (ExitCode
)-1,
1178 _T("a thread can't wait for itself") );
1180 wxCHECK_MSG( !m_isDetached
, (ExitCode
)-1,
1181 _T("can't wait for detached thread") );
1185 return m_internal
->GetExitCode();
1188 wxThreadError
wxThread::Delete(ExitCode
*rc
)
1190 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
,
1191 _T("a thread can't delete itself") );
1193 bool isDetached
= m_isDetached
;
1196 wxThreadState state
= m_internal
->GetState();
1198 // ask the thread to stop
1199 m_internal
->SetCancelFlag();
1206 // we need to wake up the thread so that PthreadStart() will
1207 // terminate - right now it's blocking on run semaphore in
1209 m_internal
->SignalRun();
1218 // resume the thread first
1219 m_internal
->Resume();
1226 // wait until the thread stops
1231 // return the exit code of the thread
1232 *rc
= m_internal
->GetExitCode();
1235 //else: can't wait for detached threads
1238 return wxTHREAD_NO_ERROR
;
1241 wxThreadError
wxThread::Kill()
1243 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
,
1244 _T("a thread can't kill itself") );
1246 switch ( m_internal
->GetState() )
1250 return wxTHREAD_NOT_RUNNING
;
1253 // resume the thread first
1259 OSStatus err
= MPTerminateTask( m_internal
->GetId() , -1 ) ;
1262 wxLogError(_("Failed to terminate a thread."));
1264 return wxTHREAD_MISC_ERROR
;
1273 // this should be retrieved by Wait actually
1274 m_internal
->SetExitCode((void*)-1);
1277 return wxTHREAD_NO_ERROR
;
1281 void wxThread::Exit(ExitCode status
)
1283 wxASSERT_MSG( This() == this,
1284 _T("wxThread::Exit() can only be called in the context of the same thread") );
1286 // don't enter m_critsect before calling OnExit() because the user code
1287 // might deadlock if, for example, it signals a condition in OnExit() (a
1288 // common case) while the main thread calls any of functions entering
1289 // m_critsect on us (almost all of them do)
1292 MPTerminateTask( m_internal
->GetId() , (long) status
) ;
1300 // update the status of the joinable thread
1301 wxCriticalSectionLocker
lock(m_critsect
);
1302 m_internal
->SetState(STATE_EXITED
);
1306 // also test whether we were paused
1307 bool wxThread::TestDestroy()
1309 wxASSERT_MSG( This() == this,
1310 _T("wxThread::TestDestroy() can only be called in the context of the same thread") );
1314 if ( m_internal
->GetState() == STATE_PAUSED
)
1316 m_internal
->SetReallyPaused(TRUE
);
1318 // leave the crit section or the other threads will stop too if they
1319 // try to call any of (seemingly harmless) IsXXX() functions while we
1323 m_internal
->Pause();
1327 // thread wasn't requested to pause, nothing to do
1331 return m_internal
->WasCancelled();
1334 // -----------------------------------------------------------------------------
1336 // -----------------------------------------------------------------------------
1338 void wxThread::SetPriority(unsigned int prio
)
1340 wxCHECK_RET( ((int)WXTHREAD_MIN_PRIORITY
<= (int)prio
) &&
1341 ((int)prio
<= (int)WXTHREAD_MAX_PRIORITY
),
1342 wxT("invalid thread priority") );
1344 wxCriticalSectionLocker
lock(m_critsect
);
1346 switch ( m_internal
->GetState() )
1351 // thread not yet started, priority will be set when it is
1352 m_internal
->SetPriority(prio
);
1357 wxFAIL_MSG(wxT("impossible to set thread priority in this state"));
1361 unsigned int wxThread::GetPriority() const
1363 wxCriticalSectionLocker
lock((wxCriticalSection
&)m_critsect
); // const_cast
1365 return m_internal
->GetPriority();
1368 unsigned long wxThread::GetId() const
1370 wxCriticalSectionLocker
lock((wxCriticalSection
&)m_critsect
); // const_cast
1372 return (unsigned long)m_internal
->GetId();
1375 // -----------------------------------------------------------------------------
1377 // -----------------------------------------------------------------------------
1379 bool wxThread::IsRunning() const
1381 wxCriticalSectionLocker
lock((wxCriticalSection
&)m_critsect
);
1383 return m_internal
->GetState() == STATE_RUNNING
;
1386 bool wxThread::IsAlive() const
1388 wxCriticalSectionLocker
lock((wxCriticalSection
&)m_critsect
);
1390 switch ( m_internal
->GetState() )
1401 bool wxThread::IsPaused() const
1403 wxCriticalSectionLocker
lock((wxCriticalSection
&)m_critsect
);
1405 return (m_internal
->GetState() == STATE_PAUSED
);
1408 // ----------------------------------------------------------------------------
1409 // Automatic initialization for thread module
1410 // ----------------------------------------------------------------------------
1412 class wxThreadModule
: public wxModule
1415 virtual bool OnInit();
1416 virtual void OnExit();
1419 DECLARE_DYNAMIC_CLASS(wxThreadModule
)
1422 IMPLEMENT_DYNAMIC_CLASS(wxThreadModule
, wxModule
)
1424 bool wxThreadModule::OnInit()
1426 bool hasThreadManager
= false ;
1427 hasThreadManager
= MPLibraryIsLoaded();
1429 if ( !hasThreadManager
)
1431 wxMessageBox( "Error" , "MP Thread Support is not available on this System" , wxOK
) ;
1435 verify_noerr( MPAllocateTaskStorageIndex( &gs_tlsForWXThread
) ) ;
1436 // main thread's This() is NULL
1437 verify_noerr( MPSetTaskStorageValue( gs_tlsForWXThread
, NULL
) ) ;
1439 gs_idMainThread
= wxThread::GetCurrentId() ;
1441 gs_critsectWaitingForGui
= new wxCriticalSection();
1443 gs_critsectGui
= new wxCriticalSection();
1444 gs_critsectGui
->Enter();
1449 void wxThreadModule::OnExit()
1451 if ( gs_critsectGui
)
1453 gs_critsectGui
->Leave();
1454 delete gs_critsectGui
;
1455 gs_critsectGui
= NULL
;
1458 delete gs_critsectWaitingForGui
;
1459 gs_critsectWaitingForGui
= NULL
;
1462 // ----------------------------------------------------------------------------
1463 // GUI Serialization copied from MSW implementation
1464 // ----------------------------------------------------------------------------
1466 void WXDLLIMPEXP_BASE
wxMutexGuiEnter()
1468 // this would dead lock everything...
1469 wxASSERT_MSG( !wxThread::IsMain(),
1470 wxT("main thread doesn't want to block in wxMutexGuiEnter()!") );
1472 // the order in which we enter the critical sections here is crucial!!
1474 // set the flag telling to the main thread that we want to do some GUI
1476 wxCriticalSectionLocker
enter(*gs_critsectWaitingForGui
);
1478 gs_nWaitingForGui
++;
1481 wxWakeUpMainThread();
1483 // now we may block here because the main thread will soon let us in
1484 // (during the next iteration of OnIdle())
1485 gs_critsectGui
->Enter();
1488 void WXDLLIMPEXP_BASE
wxMutexGuiLeave()
1490 wxCriticalSectionLocker
enter(*gs_critsectWaitingForGui
);
1492 if ( wxThread::IsMain() )
1494 gs_bGuiOwnedByMainThread
= false;
1498 // decrement the number of threads waiting for GUI access now
1499 wxASSERT_MSG( gs_nWaitingForGui
> 0,
1500 wxT("calling wxMutexGuiLeave() without entering it first?") );
1502 gs_nWaitingForGui
--;
1504 wxWakeUpMainThread();
1507 gs_critsectGui
->Leave();
1510 void WXDLLIMPEXP_BASE
wxMutexGuiLeaveOrEnter()
1512 wxASSERT_MSG( wxThread::IsMain(),
1513 wxT("only main thread may call wxMutexGuiLeaveOrEnter()!") );
1515 wxCriticalSectionLocker
enter(*gs_critsectWaitingForGui
);
1517 if ( gs_nWaitingForGui
== 0 )
1519 // no threads are waiting for GUI - so we may acquire the lock without
1520 // any danger (but only if we don't already have it)
1521 if ( !wxGuiOwnedByMainThread() )
1523 gs_critsectGui
->Enter();
1525 gs_bGuiOwnedByMainThread
= true;
1527 //else: already have it, nothing to do
1531 // some threads are waiting, release the GUI lock if we have it
1532 if ( wxGuiOwnedByMainThread() )
1536 //else: some other worker thread is doing GUI
1540 bool WXDLLIMPEXP_BASE
wxGuiOwnedByMainThread()
1542 return gs_bGuiOwnedByMainThread
;
1545 // wake up the main thread
1546 void WXDLLEXPORT
wxWakeUpMainThread()
1551 // ----------------------------------------------------------------------------
1552 // include common implementation code
1553 // ----------------------------------------------------------------------------
1555 #include "wx/thrimpl.cpp"
1557 #endif // wxUSE_THREADS