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 // ----------------------------------------------------------------------------
50 // ----------------------------------------------------------------------------
52 // the possible states of the thread ("=>" shows all possible transitions from
56 STATE_NEW
, // didn't start execution yet (=> RUNNING)
57 STATE_RUNNING
, // thread is running (=> PAUSED, CANCELED)
58 STATE_PAUSED
, // thread is temporarily suspended (=> RUNNING)
59 STATE_CANCELED
, // thread should terminate a.s.a.p. (=> EXITED)
60 STATE_EXITED
// thread is terminating
63 // ----------------------------------------------------------------------------
64 // this module globals
65 // ----------------------------------------------------------------------------
68 // the task ID of the main thread
69 static wxThreadIdType gs_idMainThread
= kInvalidID
;
71 // this is the Per-Task Storage for the pointer to the appropriate wxThread
72 TaskStorageIndex gs_tlsForWXThread
= 0 ;
74 // if it's false, some secondary thread is holding the GUI lock
75 static bool gs_bGuiOwnedByMainThread
= true;
77 // critical section which controls access to all GUI functions: any secondary
78 // thread (i.e. except the main one) must enter this crit section before doing
80 static wxCriticalSection
*gs_critsectGui
= NULL
;
82 // critical section which protects gs_nWaitingForGui variable
83 static wxCriticalSection
*gs_critsectWaitingForGui
= NULL
;
85 // number of threads waiting for GUI in wxMutexGuiEnter()
86 static size_t gs_nWaitingForGui
= 0;
88 // overall number of threads, needed for determining the sleep value of the main
90 size_t g_numberOfThreads
= 0;
96 MPCriticalRegionID gs_guiCritical
= kInvalidID
;
100 // ============================================================================
101 // MacOS implementation of thread classes
102 // ============================================================================
107 The implementation is very close to the phtreads implementation, the reason for
108 using MPServices is the fact that these are also available under OS 9. Thus allowing
109 for one common API for all current builds.
111 As soon as wxThreads are on a 64 bit address space, the TLS must be extended
112 to use two indices one for each 32 bit part as the MP implementation is limited
115 I have two implementations for mutexes :
116 version A based on a binary semaphore, problem - not reentrant, version B based
117 on a critical region, allows for reentrancy, performance implications not
120 The same for condition internal, one implementation by Aj Lavin and the other one
121 copied from the thrimpl.cpp which I assume has been more broadly tested, I've just
122 replaced the interlock increment with the appropriate PPC calls
125 // ----------------------------------------------------------------------------
126 // wxMutex implementation
127 // ----------------------------------------------------------------------------
131 class wxMutexInternal
134 wxMutexInternal(wxMutexType mutexType
) ;
136 bool IsOk() const { return m_isOk
; }
138 wxMutexError
Lock() ;
139 wxMutexError
TryLock() ;
140 wxMutexError
Unlock();
142 MPSemaphoreID m_semaphore
;
146 wxMutexInternal::wxMutexInternal(wxMutexType mutexType
)
149 m_semaphore
= kInvalidID
;
151 OSStatus err
= noErr
;
154 case wxMUTEX_DEFAULT
:
156 verify_noerr( MPCreateBinarySemaphore( & m_semaphore
) );
157 m_isOk
= ( m_semaphore
!= kInvalidID
) ;
160 case wxMUTEX_RECURSIVE
:
161 wxFAIL_MSG(wxT("Recursive Mutex not supported yet") ) ;
164 wxFAIL_MSG(wxT("Unknown mutex type") ) ;
169 wxMutexInternal::~wxMutexInternal()
171 if ( m_semaphore
!= kInvalidID
)
172 MPDeleteSemaphore( m_semaphore
);
175 wxMutexError
wxMutexInternal::Lock()
177 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") ) ;
178 OSStatus err
= MPWaitOnSemaphore( m_semaphore
, kDurationForever
);
181 wxLogSysError(wxT("Could not lock mutex"));
182 return wxMUTEX_MISC_ERROR
;
185 return wxMUTEX_NO_ERROR
;
188 wxMutexError
wxMutexInternal::TryLock()
190 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") ) ;
191 OSStatus err
= MPWaitOnSemaphore( m_semaphore
, kDurationImmediate
);
194 if ( err
== kMPTimeoutErr
)
198 wxLogSysError(wxT("Could not try lock mutex"));
199 return wxMUTEX_MISC_ERROR
;
202 return wxMUTEX_NO_ERROR
;
205 wxMutexError
wxMutexInternal::Unlock()
207 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") ) ;
208 OSStatus err
= MPSignalSemaphore( m_semaphore
);
211 wxLogSysError(_("Could not unlock mutex"));
212 return wxMUTEX_MISC_ERROR
;
215 return wxMUTEX_NO_ERROR
;
220 class wxMutexInternal
223 wxMutexInternal(wxMutexType mutexType
) ;
225 bool IsOk() const { return m_isOk
; }
227 wxMutexError
Lock() ;
228 wxMutexError
TryLock() ;
229 wxMutexError
Unlock();
231 MPCriticalRegionID m_critRegion
;
235 wxMutexInternal::wxMutexInternal(wxMutexType mutexType
)
238 m_critRegion
= kInvalidID
;
240 verify_noerr( MPCreateCriticalRegion( & m_critRegion
) );
241 m_isOk
= ( m_critRegion
!= kInvalidID
) ;
244 wxFAIL_MSG(wxT("Error when creating mutex") ) ;
247 wxMutexInternal::~wxMutexInternal()
249 if ( m_critRegion
!= kInvalidID
)
250 MPDeleteCriticalRegion( m_critRegion
);
253 wxMutexError
wxMutexInternal::Lock()
255 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") ) ;
256 OSStatus err
= MPEnterCriticalRegion( m_critRegion
, kDurationForever
);
259 wxLogSysError(wxT("Could not lock mutex"));
260 return wxMUTEX_MISC_ERROR
;
263 return wxMUTEX_NO_ERROR
;
266 wxMutexError
wxMutexInternal::TryLock()
268 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") ) ;
269 OSStatus err
= MPEnterCriticalRegion( m_critRegion
, kDurationImmediate
);
272 if ( err
== kMPTimeoutErr
)
276 wxLogSysError(wxT("Could not try lock mutex"));
277 return wxMUTEX_MISC_ERROR
;
280 return wxMUTEX_NO_ERROR
;
283 wxMutexError
wxMutexInternal::Unlock()
285 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") ) ;
286 OSStatus err
= MPExitCriticalRegion( m_critRegion
);
289 wxLogSysError(_("Could not unlock mutex"));
290 return wxMUTEX_MISC_ERROR
;
293 return wxMUTEX_NO_ERROR
;
298 // --------------------------------------------------------------------------
300 // --------------------------------------------------------------------------
302 class wxSemaphoreInternal
305 wxSemaphoreInternal(int initialcount
, int maxcount
);
306 ~wxSemaphoreInternal();
308 bool IsOk() const { return m_isOk
; }
310 wxSemaError
WaitTimeout(unsigned long milliseconds
);
312 wxSemaError
Wait() { return WaitTimeout( kDurationForever
); }
314 wxSemaError
TryWait()
316 wxSemaError err
= WaitTimeout(kDurationImmediate
);
317 if ( err
== wxSEMA_TIMEOUT
)
324 MPSemaphoreID m_semaphore
;
328 wxSemaphoreInternal::wxSemaphoreInternal(int initialcount
, int maxcount
)
331 m_semaphore
= kInvalidID
;
334 // make it practically infinite
337 verify_noerr( MPCreateSemaphore( maxcount
, initialcount
, & m_semaphore
) );
338 m_isOk
= ( m_semaphore
!= kInvalidID
) ;
341 wxFAIL_MSG(wxT("Error when creating semaphore") ) ;
344 wxSemaphoreInternal::~wxSemaphoreInternal()
346 if( m_semaphore
!= kInvalidID
)
347 MPDeleteSemaphore( m_semaphore
);
350 wxSemaError
wxSemaphoreInternal::WaitTimeout(unsigned long milliseconds
)
352 OSStatus err
= MPWaitOnSemaphore( m_semaphore
, milliseconds
);
355 if ( err
== kMPTimeoutErr
)
357 return wxSEMA_TIMEOUT
;
359 return wxSEMA_MISC_ERROR
;
361 return wxSEMA_NO_ERROR
;
364 wxSemaError
wxSemaphoreInternal::Post()
366 OSStatus err
= MPSignalSemaphore( m_semaphore
);
369 return wxSEMA_MISC_ERROR
;
371 return wxSEMA_NO_ERROR
;
374 // ----------------------------------------------------------------------------
375 // wxCondition implementation
376 // ----------------------------------------------------------------------------
380 class wxConditionInternal
384 wxConditionInternal(wxMutex
& mutex
)
394 ~wxConditionInternal()
398 bool IsOk() const { return m_mutex
.IsOk() ; }
402 return WaitTimeout( kDurationForever
);
405 wxCondError
WaitTimeout(unsigned long msectimeout
);
409 return DoSignal( false);
412 wxCondError
Broadcast()
414 return DoSignal( true);
419 wxCondError
DoSignal( bool signalAll
);
422 wxSemaphoreInternal m_semaphore
; // Signals the waiting threads.
423 wxSemaphoreInternal m_gate
;
424 wxCriticalSection m_varSection
;
425 size_t m_waiters
; // Number of threads waiting for a signal.
426 size_t m_signals
; // Number of signals to send.
427 size_t m_canceled
; // Number of canceled waiters in m_waiters.
431 wxCondError
wxConditionInternal::WaitTimeout(unsigned long msectimeout
)
434 if ( ++ m_waiters
== INT_MAX
)
436 m_varSection
.Enter();
437 m_waiters
-= m_canceled
;
438 m_signals
-= m_canceled
;
440 m_varSection
.Leave();
446 wxSemaError err
= m_semaphore
.WaitTimeout( msectimeout
);
447 wxASSERT( err
== wxSEMA_NO_ERROR
|| err
== wxSEMA_TIMEOUT
);
449 m_varSection
.Enter();
450 if ( err
!= wxSEMA_NO_ERROR
)
452 if ( m_signals
> m_canceled
)
454 // A signal is being sent after we timed out.
456 if ( m_waiters
== m_signals
)
458 // There are no excess waiters to catch the signal, so
459 // we must throw it away.
461 wxSemaError err2
= m_semaphore
.Wait();
462 if ( err2
!= wxSEMA_NO_ERROR
)
464 wxLogSysError(_("Error while waiting on semaphore"));
466 wxASSERT( err2
== wxSEMA_NO_ERROR
);
468 if ( -- m_signals
== m_canceled
)
470 // This was the last signal. open the gate.
471 wxASSERT( m_waiters
== m_canceled
);
477 // There are excess waiters to catch the signal, leave
484 // No signals is being sent.
485 // The gate may be open or closed, so we can't touch m_waiters.
492 // We caught a signal.
493 wxASSERT( m_signals
> m_canceled
);
495 if ( -- m_signals
== m_canceled
)
497 // This was the last signal. open the gate.
498 wxASSERT( m_waiters
== m_canceled
);
502 m_varSection
.Leave();
508 return err
== wxSEMA_TIMEOUT
? wxCOND_TIMEOUT
: wxCOND_MISC_ERROR
;
511 return wxCOND_NO_ERROR
;
515 wxCondError
wxConditionInternal::DoSignal( bool signalAll
)
518 m_varSection
.Enter();
520 wxASSERT( m_signals
== m_canceled
);
522 if ( m_waiters
== m_canceled
)
524 m_varSection
.Leave();
526 return wxCOND_NO_ERROR
;
531 m_waiters
-= m_canceled
;
536 m_signals
= signalAll
? m_waiters
: 1;
537 size_t n
= m_signals
;
539 m_varSection
.Leave();
541 // Let the waiters inherit the gate lock.
545 wxSemaError err
= m_semaphore
.Post();
546 wxASSERT( err
== wxSEMA_NO_ERROR
);
549 return wxCOND_NO_ERROR
;
553 class wxConditionInternal
556 wxConditionInternal(wxMutex
& mutex
);
558 bool IsOk() const { return m_mutex
.IsOk() && m_semaphore
.IsOk(); }
561 wxCondError
WaitTimeout(unsigned long milliseconds
);
563 wxCondError
Signal();
564 wxCondError
Broadcast();
567 // the number of threads currently waiting for this condition
570 // the critical section protecting m_numWaiters
571 wxCriticalSection m_csWaiters
;
574 wxSemaphore m_semaphore
;
576 DECLARE_NO_COPY_CLASS(wxConditionInternal
)
579 wxConditionInternal::wxConditionInternal(wxMutex
& mutex
)
582 // another thread can't access it until we return from ctor, so no need to
583 // protect access to m_numWaiters here
587 wxCondError
wxConditionInternal::Wait()
589 // increment the number of waiters
590 IncrementAtomic(&m_numWaiters
);
594 // a potential race condition can occur here
596 // after a thread increments nwaiters, and unlocks the mutex and before the
597 // semaphore.Wait() is called, if another thread can cause a signal to be
600 // this race condition is handled by using a semaphore and incrementing the
601 // semaphore only if 'nwaiters' is greater that zero since the semaphore,
602 // can 'remember' signals the race condition will not occur
604 // wait ( if necessary ) and decrement semaphore
605 wxSemaError err
= m_semaphore
.Wait();
608 return err
== wxSEMA_NO_ERROR
? wxCOND_NO_ERROR
: wxCOND_MISC_ERROR
;
611 wxCondError
wxConditionInternal::WaitTimeout(unsigned long milliseconds
)
613 IncrementAtomic(&m_numWaiters
);
617 // a race condition can occur at this point in the code
619 // please see the comments in Wait(), for details
621 wxSemaError err
= m_semaphore
.WaitTimeout(milliseconds
);
623 if ( err
== wxSEMA_BUSY
)
625 // another potential race condition exists here it is caused when a
626 // 'waiting' thread timesout, and returns from WaitForSingleObject, but
627 // has not yet decremented 'nwaiters'.
629 // at this point if another thread calls signal() then the semaphore
630 // will be incremented, but the waiting thread will miss it.
632 // to handle this particular case, the waiting thread calls
633 // WaitForSingleObject again with a timeout of 0, after locking
634 // 'nwaiters_mutex'. this call does not block because of the zero
635 // timeout, but will allow the waiting thread to catch the missed
637 wxCriticalSectionLocker
lock(m_csWaiters
);
639 err
= m_semaphore
.WaitTimeout(0);
641 if ( err
!= wxSEMA_NO_ERROR
)
649 return err
== wxSEMA_NO_ERROR
? wxCOND_NO_ERROR
: wxCOND_MISC_ERROR
;
652 wxCondError
wxConditionInternal::Signal()
654 wxCriticalSectionLocker
lock(m_csWaiters
);
656 if ( m_numWaiters
> 0 )
658 // increment the semaphore by 1
659 if ( m_semaphore
.Post() != wxSEMA_NO_ERROR
)
660 return wxCOND_MISC_ERROR
;
665 return wxCOND_NO_ERROR
;
668 wxCondError
wxConditionInternal::Broadcast()
670 wxCriticalSectionLocker
lock(m_csWaiters
);
672 while ( m_numWaiters
> 0 )
674 if ( m_semaphore
.Post() != wxSEMA_NO_ERROR
)
675 return wxCOND_MISC_ERROR
;
680 return wxCOND_NO_ERROR
;
684 // ----------------------------------------------------------------------------
685 // wxCriticalSection implementation
686 // ----------------------------------------------------------------------------
688 // XXX currently implemented as mutex in headers. Change to critical section.
690 // ----------------------------------------------------------------------------
691 // wxThread implementation
692 // ----------------------------------------------------------------------------
694 // wxThreadInternal class
695 // ----------------------
697 class wxThreadInternal
704 m_prio
= WXTHREAD_DEFAULT_PRIORITY
;
705 m_notifyQueueId
= kInvalidID
;
707 m_cancelled
= FALSE
;
709 // set to TRUE only when the thread starts waiting on m_semSuspend
712 // defaults for joinable threads
713 m_shouldBeJoined
= TRUE
;
714 m_isDetached
= FALSE
;
718 if ( m_notifyQueueId
)
720 MPDeleteQueue( m_notifyQueueId
);
721 m_notifyQueueId
= kInvalidID
;
726 static OSStatus
MacThreadStart(void* arg
);
728 // create a new (suspended) thread (for the given thread object)
729 bool Create(wxThread
*thread
, unsigned int stackSize
);
734 // unblock the thread allowing it to run
735 void SignalRun() { m_semRun
.Post(); }
736 // ask the thread to terminate
738 // go to sleep until Resume() is called
745 int GetPriority() const { return m_prio
; }
746 void SetPriority(int prio
) ;
748 wxThreadState
GetState() const { return m_state
; }
749 void SetState(wxThreadState state
) { m_state
= state
; }
751 // Get the ID of this thread's underlying MP Services task.
752 MPTaskID
GetId() const { return m_tid
; }
754 void SetCancelFlag() { m_cancelled
= TRUE
; }
755 bool WasCancelled() const { return m_cancelled
; }
757 void SetExitCode(wxThread::ExitCode exitcode
) { m_exitcode
= exitcode
; }
758 wxThread::ExitCode
GetExitCode() const { return m_exitcode
; }
761 void SetReallyPaused(bool paused
) { m_isPaused
= paused
; }
762 bool IsReallyPaused() const { return m_isPaused
; }
764 // tell the thread that it is a detached one
767 wxCriticalSectionLocker
lock(m_csJoinFlag
);
769 m_shouldBeJoined
= FALSE
;
774 // the thread we're associated with
777 MPTaskID m_tid
; // thread id
778 MPQueueID m_notifyQueueId
; // its notification queue
780 wxThreadState m_state
; // see wxThreadState enum
781 int m_prio
; // in wxWindows units: from 0 to 100
783 // this flag is set when the thread should terminate
786 // this flag is set when the thread is blocking on m_semSuspend
789 // the thread exit code - only used for joinable (!detached) threads and
790 // is only valid after the thread termination
791 wxThread::ExitCode m_exitcode
;
793 // many threads may call Wait(), but only one of them should call
794 // pthread_join(), so we have to keep track of this
795 wxCriticalSection m_csJoinFlag
;
796 bool m_shouldBeJoined
;
799 // this semaphore is posted by Run() and the threads Entry() is not
800 // called before it is done
801 wxSemaphore m_semRun
;
803 // this one is signaled when the thread should resume after having been
805 wxSemaphore m_semSuspend
;
808 OSStatus
wxThreadInternal::MacThreadStart(void *parameter
)
810 wxThread
* thread
= (wxThread
*) parameter
;
811 wxThreadInternal
*pthread
= thread
->m_internal
;
813 // add to TLS so that This() will work
814 verify_noerr( MPSetTaskStorageValue( gs_tlsForWXThread
, (long) thread
) ) ;
816 // have to declare this before pthread_cleanup_push() which defines a
820 // wait for the semaphore to be posted from Run()
821 pthread
->m_semRun
.Wait();
823 // test whether we should run the run at all - may be it was deleted
824 // before it started to Run()?
826 wxCriticalSectionLocker
lock(thread
->m_critsect
);
828 dontRunAtAll
= pthread
->GetState() == STATE_NEW
&&
829 pthread
->WasCancelled();
834 pthread
->m_exitcode
= thread
->Entry();
837 wxCriticalSectionLocker
lock(thread
->m_critsect
);
838 pthread
->SetState(STATE_EXITED
);
844 if ( pthread
->m_isDetached
)
851 // on mac for the running code the correct thread termination is to
854 // terminate the thread
855 thread
->Exit(pthread
->m_exitcode
);
857 return (OSStatus
) NULL
; // pthread->m_exitcode;
861 bool wxThreadInternal::Create(wxThread
*thread
, unsigned int stackSize
)
863 wxASSERT_MSG( m_state
== STATE_NEW
&& !m_tid
,
864 _T("Create()ing thread twice?") );
866 OSStatus err
= noErr
;
869 if ( m_notifyQueueId
== kInvalidID
)
871 OSStatus err
= MPCreateQueue( & m_notifyQueueId
);
874 wxLogSysError(_("Cant create the thread event queue"));
881 err
= MPCreateTask( MacThreadStart
,
892 wxLogSysError(_("Can't create thread"));
896 if ( m_prio
!= WXTHREAD_DEFAULT_PRIORITY
)
904 void wxThreadInternal::SetPriority( int priority
)
910 // Mac priorities range from 1 to 10,000, with a default of 100.
911 // wxWindows priorities range from 0 to 100 with a default of 50.
912 // We can map wxWindows to Mac priorities easily by assuming
913 // the former uses a logarithmic scale.
914 const unsigned int macPriority
= ( int)( exp( priority
/ 25.0 * log( 10.0)) + 0.5);
916 MPSetTaskWeight( m_tid
, macPriority
);
920 wxThreadError
wxThreadInternal::Run()
922 wxCHECK_MSG( GetState() == STATE_NEW
, wxTHREAD_RUNNING
,
923 wxT("thread may only be started once after Create()") );
925 SetState(STATE_RUNNING
);
927 // wake up threads waiting for our start
930 return wxTHREAD_NO_ERROR
;
933 void wxThreadInternal::Wait()
935 wxCHECK_RET( !m_isDetached
, _T("can't wait for a detached thread") );
937 // if the thread we're waiting for is waiting for the GUI mutex, we will
938 // deadlock so make sure we release it temporarily
939 if ( wxThread::IsMain() )
943 wxCriticalSectionLocker
lock(m_csJoinFlag
);
945 if ( m_shouldBeJoined
)
951 OSStatus err
= MPWaitOnQueue ( m_notifyQueueId
,
958 wxLogSysError( _( "Cannot wait on thread to exit."));
962 // actually param1 would be the address of m_exitcode
963 // but we don't need this here
966 m_shouldBeJoined
= FALSE
;
970 // reacquire GUI mutex
971 if ( wxThread::IsMain() )
975 void wxThreadInternal::Pause()
977 // the state is set from the thread which pauses us first, this function
978 // is called later so the state should have been already set
979 wxCHECK_RET( m_state
== STATE_PAUSED
,
980 wxT("thread must first be paused with wxThread::Pause().") );
982 // wait until the semaphore is Post()ed from Resume()
986 void wxThreadInternal::Resume()
988 wxCHECK_RET( m_state
== STATE_PAUSED
,
989 wxT("can't resume thread which is not suspended.") );
991 // the thread might be not actually paused yet - if there were no call to
992 // TestDestroy() since the last call to Pause() for example
993 if ( IsReallyPaused() )
999 SetReallyPaused(FALSE
);
1002 SetState(STATE_RUNNING
);
1008 wxThread
*wxThread::This()
1010 wxThread
* thr
= (wxThread
*) MPGetTaskStorageValue( gs_tlsForWXThread
) ;
1014 bool wxThread::IsMain()
1016 return GetCurrentId() == gs_idMainThread
;
1023 void wxThread::Yield()
1025 #if TARGET_API_MAC_OSX
1026 CFRunLoopRunInMode( kCFRunLoopDefaultMode
, 0 , true ) ;
1032 void wxThread::Sleep(unsigned long milliseconds
)
1034 AbsoluteTime wakeup
= AddDurationToAbsolute( milliseconds
, UpTime());
1035 MPDelayUntil( & wakeup
);
1039 int wxThread::GetCPUCount()
1041 return MPProcessors();
1044 unsigned long wxThread::GetCurrentId()
1046 return (unsigned long)MPCurrentTaskID();
1050 bool wxThread::SetConcurrency(size_t level
)
1052 // Cannot be set in MacOS.
1057 wxThread::wxThread(wxThreadKind kind
)
1059 g_numberOfThreads
++;
1060 m_internal
= new wxThreadInternal();
1062 m_isDetached
= (kind
== wxTHREAD_DETACHED
);
1065 wxThread::~wxThread()
1067 wxASSERT_MSG( g_numberOfThreads
>0 , wxT("More threads deleted than created.") ) ;
1068 g_numberOfThreads
--;
1073 // check that the thread either exited or couldn't be created
1074 if ( m_internal
->GetState() != STATE_EXITED
&&
1075 m_internal
->GetState() != STATE_NEW
)
1077 wxLogDebug(_T("The thread %ld is being destroyed although it is still running! The application may crash."), GetId());
1081 #endif // __WXDEBUG__
1083 wxDELETE( m_internal
) ;
1087 wxThreadError
wxThread::Create(unsigned int stackSize
)
1089 wxCriticalSectionLocker
lock(m_critsect
);
1093 m_internal
->Detach() ;
1095 if ( m_internal
->Create(this, stackSize
) == false )
1097 m_internal
->SetState(STATE_EXITED
);
1098 return wxTHREAD_NO_RESOURCE
;
1101 return wxTHREAD_NO_ERROR
;
1104 wxThreadError
wxThread::Run()
1106 wxCriticalSectionLocker
lock(m_critsect
);
1108 wxCHECK_MSG( m_internal
->GetId(), wxTHREAD_MISC_ERROR
,
1109 wxT("must call wxThread::Create() first") );
1111 return m_internal
->Run();
1114 // -----------------------------------------------------------------------------
1116 // -----------------------------------------------------------------------------
1118 wxThreadError
wxThread::Pause()
1120 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
,
1121 _T("a thread can't pause itself") );
1123 wxCriticalSectionLocker
lock(m_critsect
);
1125 if ( m_internal
->GetState() != STATE_RUNNING
)
1127 wxLogDebug(wxT("Can't pause thread which is not running."));
1129 return wxTHREAD_NOT_RUNNING
;
1132 // just set a flag, the thread will be really paused only during the next
1133 // call to TestDestroy()
1134 m_internal
->SetState(STATE_PAUSED
);
1136 return wxTHREAD_NO_ERROR
;
1139 wxThreadError
wxThread::Resume()
1141 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
,
1142 _T("a thread can't resume itself") );
1144 wxCriticalSectionLocker
lock(m_critsect
);
1146 wxThreadState state
= m_internal
->GetState();
1151 m_internal
->Resume();
1152 return wxTHREAD_NO_ERROR
;
1154 return wxTHREAD_NO_ERROR
;
1157 wxLogDebug(_T("Attempt to resume a thread which is not paused."));
1159 return wxTHREAD_MISC_ERROR
;
1163 // -----------------------------------------------------------------------------
1165 // -----------------------------------------------------------------------------
1167 wxThread::ExitCode
wxThread::Wait()
1169 wxCHECK_MSG( This() != this, (ExitCode
)-1,
1170 _T("a thread can't wait for itself") );
1172 wxCHECK_MSG( !m_isDetached
, (ExitCode
)-1,
1173 _T("can't wait for detached thread") );
1177 return m_internal
->GetExitCode();
1180 wxThreadError
wxThread::Delete(ExitCode
*rc
)
1182 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
,
1183 _T("a thread can't delete itself") );
1185 bool isDetached
= m_isDetached
;
1188 wxThreadState state
= m_internal
->GetState();
1190 // ask the thread to stop
1191 m_internal
->SetCancelFlag();
1198 // we need to wake up the thread so that PthreadStart() will
1199 // terminate - right now it's blocking on run semaphore in
1201 m_internal
->SignalRun();
1210 // resume the thread first
1211 m_internal
->Resume();
1218 // wait until the thread stops
1223 // return the exit code of the thread
1224 *rc
= m_internal
->GetExitCode();
1227 //else: can't wait for detached threads
1230 return wxTHREAD_NO_ERROR
;
1233 wxThreadError
wxThread::Kill()
1235 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
,
1236 _T("a thread can't kill itself") );
1238 switch ( m_internal
->GetState() )
1242 return wxTHREAD_NOT_RUNNING
;
1245 // resume the thread first
1251 OSStatus err
= MPTerminateTask( m_internal
->GetId() , -1 ) ;
1254 wxLogError(_("Failed to terminate a thread."));
1256 return wxTHREAD_MISC_ERROR
;
1265 // this should be retrieved by Wait actually
1266 m_internal
->SetExitCode((void*)-1);
1269 return wxTHREAD_NO_ERROR
;
1273 void wxThread::Exit(ExitCode status
)
1275 wxASSERT_MSG( This() == this,
1276 _T("wxThread::Exit() can only be called in the context of the same thread") );
1278 // don't enter m_critsect before calling OnExit() because the user code
1279 // might deadlock if, for example, it signals a condition in OnExit() (a
1280 // common case) while the main thread calls any of functions entering
1281 // m_critsect on us (almost all of them do)
1284 MPTerminateTask( m_internal
->GetId() , (long) status
) ;
1292 // update the status of the joinable thread
1293 wxCriticalSectionLocker
lock(m_critsect
);
1294 m_internal
->SetState(STATE_EXITED
);
1298 // also test whether we were paused
1299 bool wxThread::TestDestroy()
1301 wxASSERT_MSG( This() == this,
1302 _T("wxThread::TestDestroy() can only be called in the context of the same thread") );
1306 if ( m_internal
->GetState() == STATE_PAUSED
)
1308 m_internal
->SetReallyPaused(TRUE
);
1310 // leave the crit section or the other threads will stop too if they
1311 // try to call any of (seemingly harmless) IsXXX() functions while we
1315 m_internal
->Pause();
1319 // thread wasn't requested to pause, nothing to do
1323 return m_internal
->WasCancelled();
1326 // -----------------------------------------------------------------------------
1328 // -----------------------------------------------------------------------------
1330 void wxThread::SetPriority(unsigned int prio
)
1332 wxCHECK_RET( ((int)WXTHREAD_MIN_PRIORITY
<= (int)prio
) &&
1333 ((int)prio
<= (int)WXTHREAD_MAX_PRIORITY
),
1334 wxT("invalid thread priority") );
1336 wxCriticalSectionLocker
lock(m_critsect
);
1338 switch ( m_internal
->GetState() )
1343 // thread not yet started, priority will be set when it is
1344 m_internal
->SetPriority(prio
);
1349 wxFAIL_MSG(wxT("impossible to set thread priority in this state"));
1353 unsigned int wxThread::GetPriority() const
1355 wxCriticalSectionLocker
lock((wxCriticalSection
&)m_critsect
); // const_cast
1357 return m_internal
->GetPriority();
1360 unsigned long wxThread::GetId() const
1362 wxCriticalSectionLocker
lock((wxCriticalSection
&)m_critsect
); // const_cast
1364 return (unsigned long)m_internal
->GetId();
1367 // -----------------------------------------------------------------------------
1369 // -----------------------------------------------------------------------------
1371 bool wxThread::IsRunning() const
1373 wxCriticalSectionLocker
lock((wxCriticalSection
&)m_critsect
);
1375 return m_internal
->GetState() == STATE_RUNNING
;
1378 bool wxThread::IsAlive() const
1380 wxCriticalSectionLocker
lock((wxCriticalSection
&)m_critsect
);
1382 switch ( m_internal
->GetState() )
1393 bool wxThread::IsPaused() const
1395 wxCriticalSectionLocker
lock((wxCriticalSection
&)m_critsect
);
1397 return (m_internal
->GetState() == STATE_PAUSED
);
1400 // ----------------------------------------------------------------------------
1401 // Automatic initialization for thread module
1402 // ----------------------------------------------------------------------------
1404 class wxThreadModule
: public wxModule
1407 virtual bool OnInit();
1408 virtual void OnExit();
1411 DECLARE_DYNAMIC_CLASS(wxThreadModule
)
1414 IMPLEMENT_DYNAMIC_CLASS(wxThreadModule
, wxModule
)
1416 bool wxThreadModule::OnInit()
1418 bool hasThreadManager
= false ;
1419 hasThreadManager
= MPLibraryIsLoaded();
1421 if ( !hasThreadManager
)
1423 wxMessageBox( wxT("Error") , wxT("MP Thread Support is not available on this System" ), wxOK
) ;
1427 verify_noerr( MPAllocateTaskStorageIndex( &gs_tlsForWXThread
) ) ;
1428 // main thread's This() is NULL
1429 verify_noerr( MPSetTaskStorageValue( gs_tlsForWXThread
, NULL
) ) ;
1431 gs_idMainThread
= wxThread::GetCurrentId() ;
1433 gs_critsectWaitingForGui
= new wxCriticalSection();
1435 gs_critsectGui
= new wxCriticalSection();
1436 gs_critsectGui
->Enter();
1441 void wxThreadModule::OnExit()
1443 if ( gs_critsectGui
)
1445 gs_critsectGui
->Leave();
1446 delete gs_critsectGui
;
1447 gs_critsectGui
= NULL
;
1450 delete gs_critsectWaitingForGui
;
1451 gs_critsectWaitingForGui
= NULL
;
1454 // ----------------------------------------------------------------------------
1455 // GUI Serialization copied from MSW implementation
1456 // ----------------------------------------------------------------------------
1458 void WXDLLIMPEXP_BASE
wxMutexGuiEnter()
1460 // this would dead lock everything...
1461 wxASSERT_MSG( !wxThread::IsMain(),
1462 wxT("main thread doesn't want to block in wxMutexGuiEnter()!") );
1464 // the order in which we enter the critical sections here is crucial!!
1466 // set the flag telling to the main thread that we want to do some GUI
1468 wxCriticalSectionLocker
enter(*gs_critsectWaitingForGui
);
1470 gs_nWaitingForGui
++;
1473 wxWakeUpMainThread();
1475 // now we may block here because the main thread will soon let us in
1476 // (during the next iteration of OnIdle())
1477 gs_critsectGui
->Enter();
1480 void WXDLLIMPEXP_BASE
wxMutexGuiLeave()
1482 wxCriticalSectionLocker
enter(*gs_critsectWaitingForGui
);
1484 if ( wxThread::IsMain() )
1486 gs_bGuiOwnedByMainThread
= false;
1490 // decrement the number of threads waiting for GUI access now
1491 wxASSERT_MSG( gs_nWaitingForGui
> 0,
1492 wxT("calling wxMutexGuiLeave() without entering it first?") );
1494 gs_nWaitingForGui
--;
1496 wxWakeUpMainThread();
1499 gs_critsectGui
->Leave();
1502 void WXDLLIMPEXP_BASE
wxMutexGuiLeaveOrEnter()
1504 wxASSERT_MSG( wxThread::IsMain(),
1505 wxT("only main thread may call wxMutexGuiLeaveOrEnter()!") );
1507 wxCriticalSectionLocker
enter(*gs_critsectWaitingForGui
);
1509 if ( gs_nWaitingForGui
== 0 )
1511 // no threads are waiting for GUI - so we may acquire the lock without
1512 // any danger (but only if we don't already have it)
1513 if ( !wxGuiOwnedByMainThread() )
1515 gs_critsectGui
->Enter();
1517 gs_bGuiOwnedByMainThread
= true;
1519 //else: already have it, nothing to do
1523 // some threads are waiting, release the GUI lock if we have it
1524 if ( wxGuiOwnedByMainThread() )
1528 //else: some other worker thread is doing GUI
1532 bool WXDLLIMPEXP_BASE
wxGuiOwnedByMainThread()
1534 return gs_bGuiOwnedByMainThread
;
1537 // wake up the main thread
1538 void WXDLLEXPORT
wxWakeUpMainThread()
1543 // ----------------------------------------------------------------------------
1544 // include common implementation code
1545 // ----------------------------------------------------------------------------
1547 #include "wx/thrimpl.cpp"
1549 #endif // wxUSE_THREADS