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 // ----------------------------------------------------------------------------
129 static bool wxMacMPThreadsInitVerify()
131 static bool hasThreadManager
= false ;
132 if ( !hasThreadManager
)
133 hasThreadManager
= MPLibraryIsLoaded();
135 if ( !hasThreadManager
)
137 wxMessageBox( wxT("Error") , wxT("MP Thread Support is not available on this System" ), wxOK
) ;
145 class wxMutexInternal
148 wxMutexInternal(wxMutexType mutexType
) ;
150 bool IsOk() const { return m_isOk
; }
152 wxMutexError
Lock() ;
153 wxMutexError
TryLock() ;
154 wxMutexError
Unlock();
156 MPSemaphoreID m_semaphore
;
160 wxMutexInternal::wxMutexInternal(wxMutexType mutexType
)
162 wxMacMPThreadsInitVerify() ;
165 m_semaphore
= kInvalidID
;
167 OSStatus err
= noErr
;
170 case wxMUTEX_DEFAULT
:
172 verify_noerr( MPCreateBinarySemaphore( & m_semaphore
) );
173 m_isOk
= ( m_semaphore
!= kInvalidID
) ;
176 case wxMUTEX_RECURSIVE
:
177 wxFAIL_MSG(wxT("Recursive Mutex not supported yet") ) ;
180 wxFAIL_MSG(wxT("Unknown mutex type") ) ;
185 wxMutexInternal::~wxMutexInternal()
187 if ( m_semaphore
!= kInvalidID
)
188 MPDeleteSemaphore( m_semaphore
);
191 wxMutexError
wxMutexInternal::Lock()
193 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") ) ;
194 OSStatus err
= MPWaitOnSemaphore( m_semaphore
, kDurationForever
);
197 wxLogSysError(wxT("Could not lock mutex"));
198 return wxMUTEX_MISC_ERROR
;
201 return wxMUTEX_NO_ERROR
;
204 wxMutexError
wxMutexInternal::TryLock()
206 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") ) ;
207 OSStatus err
= MPWaitOnSemaphore( m_semaphore
, kDurationImmediate
);
210 if ( err
== kMPTimeoutErr
)
214 wxLogSysError(wxT("Could not try lock mutex"));
215 return wxMUTEX_MISC_ERROR
;
218 return wxMUTEX_NO_ERROR
;
221 wxMutexError
wxMutexInternal::Unlock()
223 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") ) ;
224 OSStatus err
= MPSignalSemaphore( m_semaphore
);
227 wxLogSysError(_("Could not unlock mutex"));
228 return wxMUTEX_MISC_ERROR
;
231 return wxMUTEX_NO_ERROR
;
236 class wxMutexInternal
239 wxMutexInternal(wxMutexType mutexType
) ;
241 bool IsOk() const { return m_isOk
; }
243 wxMutexError
Lock() ;
244 wxMutexError
TryLock() ;
245 wxMutexError
Unlock();
247 MPCriticalRegionID m_critRegion
;
251 wxMutexInternal::wxMutexInternal(wxMutexType mutexType
)
253 wxMacMPThreadsInitVerify() ;
255 m_critRegion
= kInvalidID
;
257 verify_noerr( MPCreateCriticalRegion( & m_critRegion
) );
258 m_isOk
= ( m_critRegion
!= kInvalidID
) ;
261 wxFAIL_MSG(wxT("Error when creating mutex") ) ;
264 wxMutexInternal::~wxMutexInternal()
266 if ( m_critRegion
!= kInvalidID
)
267 MPDeleteCriticalRegion( m_critRegion
);
270 wxMutexError
wxMutexInternal::Lock()
272 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") ) ;
273 OSStatus err
= MPEnterCriticalRegion( m_critRegion
, kDurationForever
);
276 wxLogSysError(wxT("Could not lock mutex"));
277 return wxMUTEX_MISC_ERROR
;
280 return wxMUTEX_NO_ERROR
;
283 wxMutexError
wxMutexInternal::TryLock()
285 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") ) ;
286 OSStatus err
= MPEnterCriticalRegion( m_critRegion
, kDurationImmediate
);
289 if ( err
== kMPTimeoutErr
)
293 wxLogSysError(wxT("Could not try lock mutex"));
294 return wxMUTEX_MISC_ERROR
;
297 return wxMUTEX_NO_ERROR
;
300 wxMutexError
wxMutexInternal::Unlock()
302 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") ) ;
303 OSStatus err
= MPExitCriticalRegion( m_critRegion
);
306 wxLogSysError(_("Could not unlock mutex"));
307 return wxMUTEX_MISC_ERROR
;
310 return wxMUTEX_NO_ERROR
;
315 // --------------------------------------------------------------------------
317 // --------------------------------------------------------------------------
319 class wxSemaphoreInternal
322 wxSemaphoreInternal(int initialcount
, int maxcount
);
323 ~wxSemaphoreInternal();
325 bool IsOk() const { return m_isOk
; }
327 wxSemaError
WaitTimeout(unsigned long milliseconds
);
329 wxSemaError
Wait() { return WaitTimeout( kDurationForever
); }
331 wxSemaError
TryWait()
333 wxSemaError err
= WaitTimeout(kDurationImmediate
);
334 if ( err
== wxSEMA_TIMEOUT
)
341 MPSemaphoreID m_semaphore
;
345 wxSemaphoreInternal::wxSemaphoreInternal(int initialcount
, int maxcount
)
347 wxMacMPThreadsInitVerify() ;
349 m_semaphore
= kInvalidID
;
352 // make it practically infinite
355 verify_noerr( MPCreateSemaphore( maxcount
, initialcount
, & m_semaphore
) );
356 m_isOk
= ( m_semaphore
!= kInvalidID
) ;
359 wxFAIL_MSG(wxT("Error when creating semaphore") ) ;
362 wxSemaphoreInternal::~wxSemaphoreInternal()
364 if( m_semaphore
!= kInvalidID
)
365 MPDeleteSemaphore( m_semaphore
);
368 wxSemaError
wxSemaphoreInternal::WaitTimeout(unsigned long milliseconds
)
370 OSStatus err
= MPWaitOnSemaphore( m_semaphore
, milliseconds
);
373 if ( err
== kMPTimeoutErr
)
375 return wxSEMA_TIMEOUT
;
377 return wxSEMA_MISC_ERROR
;
379 return wxSEMA_NO_ERROR
;
382 wxSemaError
wxSemaphoreInternal::Post()
384 OSStatus err
= MPSignalSemaphore( m_semaphore
);
387 return wxSEMA_MISC_ERROR
;
389 return wxSEMA_NO_ERROR
;
392 // ----------------------------------------------------------------------------
393 // wxCondition implementation
394 // ----------------------------------------------------------------------------
398 class wxConditionInternal
402 wxConditionInternal(wxMutex
& mutex
)
412 ~wxConditionInternal()
416 bool IsOk() const { return m_mutex
.IsOk() ; }
420 return WaitTimeout( kDurationForever
);
423 wxCondError
WaitTimeout(unsigned long msectimeout
);
427 return DoSignal( false);
430 wxCondError
Broadcast()
432 return DoSignal( true);
437 wxCondError
DoSignal( bool signalAll
);
440 wxSemaphoreInternal m_semaphore
; // Signals the waiting threads.
441 wxSemaphoreInternal m_gate
;
442 wxCriticalSection m_varSection
;
443 size_t m_waiters
; // Number of threads waiting for a signal.
444 size_t m_signals
; // Number of signals to send.
445 size_t m_canceled
; // Number of canceled waiters in m_waiters.
449 wxCondError
wxConditionInternal::WaitTimeout(unsigned long msectimeout
)
452 if ( ++ m_waiters
== INT_MAX
)
454 m_varSection
.Enter();
455 m_waiters
-= m_canceled
;
456 m_signals
-= m_canceled
;
458 m_varSection
.Leave();
464 wxSemaError err
= m_semaphore
.WaitTimeout( msectimeout
);
465 wxASSERT( err
== wxSEMA_NO_ERROR
|| err
== wxSEMA_TIMEOUT
);
467 m_varSection
.Enter();
468 if ( err
!= wxSEMA_NO_ERROR
)
470 if ( m_signals
> m_canceled
)
472 // A signal is being sent after we timed out.
474 if ( m_waiters
== m_signals
)
476 // There are no excess waiters to catch the signal, so
477 // we must throw it away.
479 wxSemaError err2
= m_semaphore
.Wait();
480 if ( err2
!= wxSEMA_NO_ERROR
)
482 wxLogSysError(_("Error while waiting on semaphore"));
484 wxASSERT( err2
== wxSEMA_NO_ERROR
);
486 if ( -- m_signals
== m_canceled
)
488 // This was the last signal. open the gate.
489 wxASSERT( m_waiters
== m_canceled
);
495 // There are excess waiters to catch the signal, leave
502 // No signals is being sent.
503 // The gate may be open or closed, so we can't touch m_waiters.
510 // We caught a signal.
511 wxASSERT( m_signals
> m_canceled
);
513 if ( -- m_signals
== m_canceled
)
515 // This was the last signal. open the gate.
516 wxASSERT( m_waiters
== m_canceled
);
520 m_varSection
.Leave();
526 return err
== wxSEMA_TIMEOUT
? wxCOND_TIMEOUT
: wxCOND_MISC_ERROR
;
529 return wxCOND_NO_ERROR
;
533 wxCondError
wxConditionInternal::DoSignal( bool signalAll
)
536 m_varSection
.Enter();
538 wxASSERT( m_signals
== m_canceled
);
540 if ( m_waiters
== m_canceled
)
542 m_varSection
.Leave();
544 return wxCOND_NO_ERROR
;
549 m_waiters
-= m_canceled
;
554 m_signals
= signalAll
? m_waiters
: 1;
555 size_t n
= m_signals
;
557 m_varSection
.Leave();
559 // Let the waiters inherit the gate lock.
563 wxSemaError err
= m_semaphore
.Post();
564 wxASSERT( err
== wxSEMA_NO_ERROR
);
567 return wxCOND_NO_ERROR
;
571 class wxConditionInternal
574 wxConditionInternal(wxMutex
& mutex
);
576 bool IsOk() const { return m_mutex
.IsOk() && m_semaphore
.IsOk(); }
579 wxCondError
WaitTimeout(unsigned long milliseconds
);
581 wxCondError
Signal();
582 wxCondError
Broadcast();
585 // the number of threads currently waiting for this condition
588 // the critical section protecting m_numWaiters
589 wxCriticalSection m_csWaiters
;
592 wxSemaphore m_semaphore
;
594 DECLARE_NO_COPY_CLASS(wxConditionInternal
)
597 wxConditionInternal::wxConditionInternal(wxMutex
& mutex
)
600 // another thread can't access it until we return from ctor, so no need to
601 // protect access to m_numWaiters here
605 wxCondError
wxConditionInternal::Wait()
607 // increment the number of waiters
608 IncrementAtomic(&m_numWaiters
);
612 // a potential race condition can occur here
614 // after a thread increments nwaiters, and unlocks the mutex and before the
615 // semaphore.Wait() is called, if another thread can cause a signal to be
618 // this race condition is handled by using a semaphore and incrementing the
619 // semaphore only if 'nwaiters' is greater that zero since the semaphore,
620 // can 'remember' signals the race condition will not occur
622 // wait ( if necessary ) and decrement semaphore
623 wxSemaError err
= m_semaphore
.Wait();
626 return err
== wxSEMA_NO_ERROR
? wxCOND_NO_ERROR
: wxCOND_MISC_ERROR
;
629 wxCondError
wxConditionInternal::WaitTimeout(unsigned long milliseconds
)
631 IncrementAtomic(&m_numWaiters
);
635 // a race condition can occur at this point in the code
637 // please see the comments in Wait(), for details
639 wxSemaError err
= m_semaphore
.WaitTimeout(milliseconds
);
641 if ( err
== wxSEMA_BUSY
)
643 // another potential race condition exists here it is caused when a
644 // 'waiting' thread timesout, and returns from WaitForSingleObject, but
645 // has not yet decremented 'nwaiters'.
647 // at this point if another thread calls signal() then the semaphore
648 // will be incremented, but the waiting thread will miss it.
650 // to handle this particular case, the waiting thread calls
651 // WaitForSingleObject again with a timeout of 0, after locking
652 // 'nwaiters_mutex'. this call does not block because of the zero
653 // timeout, but will allow the waiting thread to catch the missed
655 wxCriticalSectionLocker
lock(m_csWaiters
);
657 err
= m_semaphore
.WaitTimeout(0);
659 if ( err
!= wxSEMA_NO_ERROR
)
667 return err
== wxSEMA_NO_ERROR
? wxCOND_NO_ERROR
: wxCOND_MISC_ERROR
;
670 wxCondError
wxConditionInternal::Signal()
672 wxCriticalSectionLocker
lock(m_csWaiters
);
674 if ( m_numWaiters
> 0 )
676 // increment the semaphore by 1
677 if ( m_semaphore
.Post() != wxSEMA_NO_ERROR
)
678 return wxCOND_MISC_ERROR
;
683 return wxCOND_NO_ERROR
;
686 wxCondError
wxConditionInternal::Broadcast()
688 wxCriticalSectionLocker
lock(m_csWaiters
);
690 while ( m_numWaiters
> 0 )
692 if ( m_semaphore
.Post() != wxSEMA_NO_ERROR
)
693 return wxCOND_MISC_ERROR
;
698 return wxCOND_NO_ERROR
;
702 // ----------------------------------------------------------------------------
703 // wxCriticalSection implementation
704 // ----------------------------------------------------------------------------
706 // XXX currently implemented as mutex in headers. Change to critical section.
708 // ----------------------------------------------------------------------------
709 // wxThread implementation
710 // ----------------------------------------------------------------------------
712 // wxThreadInternal class
713 // ----------------------
715 class wxThreadInternal
722 m_prio
= WXTHREAD_DEFAULT_PRIORITY
;
723 m_notifyQueueId
= kInvalidID
;
725 m_cancelled
= FALSE
;
727 // set to TRUE only when the thread starts waiting on m_semSuspend
730 // defaults for joinable threads
731 m_shouldBeJoined
= TRUE
;
732 m_isDetached
= FALSE
;
736 if ( m_notifyQueueId
)
738 MPDeleteQueue( m_notifyQueueId
);
739 m_notifyQueueId
= kInvalidID
;
744 static OSStatus
MacThreadStart(void* arg
);
746 // create a new (suspended) thread (for the given thread object)
747 bool Create(wxThread
*thread
, unsigned int stackSize
);
752 // unblock the thread allowing it to run
753 void SignalRun() { m_semRun
.Post(); }
754 // ask the thread to terminate
756 // go to sleep until Resume() is called
763 int GetPriority() const { return m_prio
; }
764 void SetPriority(int prio
) ;
766 wxThreadState
GetState() const { return m_state
; }
767 void SetState(wxThreadState state
) { m_state
= state
; }
769 // Get the ID of this thread's underlying MP Services task.
770 MPTaskID
GetId() const { return m_tid
; }
772 void SetCancelFlag() { m_cancelled
= TRUE
; }
773 bool WasCancelled() const { return m_cancelled
; }
775 void SetExitCode(wxThread::ExitCode exitcode
) { m_exitcode
= exitcode
; }
776 wxThread::ExitCode
GetExitCode() const { return m_exitcode
; }
779 void SetReallyPaused(bool paused
) { m_isPaused
= paused
; }
780 bool IsReallyPaused() const { return m_isPaused
; }
782 // tell the thread that it is a detached one
785 wxCriticalSectionLocker
lock(m_csJoinFlag
);
787 m_shouldBeJoined
= FALSE
;
792 // the thread we're associated with
795 MPTaskID m_tid
; // thread id
796 MPQueueID m_notifyQueueId
; // its notification queue
798 wxThreadState m_state
; // see wxThreadState enum
799 int m_prio
; // in wxWidgets units: from 0 to 100
801 // this flag is set when the thread should terminate
804 // this flag is set when the thread is blocking on m_semSuspend
807 // the thread exit code - only used for joinable (!detached) threads and
808 // is only valid after the thread termination
809 wxThread::ExitCode m_exitcode
;
811 // many threads may call Wait(), but only one of them should call
812 // pthread_join(), so we have to keep track of this
813 wxCriticalSection m_csJoinFlag
;
814 bool m_shouldBeJoined
;
817 // this semaphore is posted by Run() and the threads Entry() is not
818 // called before it is done
819 wxSemaphore m_semRun
;
821 // this one is signaled when the thread should resume after having been
823 wxSemaphore m_semSuspend
;
826 OSStatus
wxThreadInternal::MacThreadStart(void *parameter
)
828 wxThread
* thread
= (wxThread
*) parameter
;
829 wxThreadInternal
*pthread
= thread
->m_internal
;
831 // add to TLS so that This() will work
832 verify_noerr( MPSetTaskStorageValue( gs_tlsForWXThread
, (long) thread
) ) ;
834 // have to declare this before pthread_cleanup_push() which defines a
838 // wait for the semaphore to be posted from Run()
839 pthread
->m_semRun
.Wait();
841 // test whether we should run the run at all - may be it was deleted
842 // before it started to Run()?
844 wxCriticalSectionLocker
lock(thread
->m_critsect
);
846 dontRunAtAll
= pthread
->GetState() == STATE_NEW
&&
847 pthread
->WasCancelled();
852 pthread
->m_exitcode
= thread
->Entry();
855 wxCriticalSectionLocker
lock(thread
->m_critsect
);
856 pthread
->SetState(STATE_EXITED
);
862 if ( pthread
->m_isDetached
)
869 // on mac for the running code the correct thread termination is to
872 // terminate the thread
873 thread
->Exit(pthread
->m_exitcode
);
875 return (OSStatus
) NULL
; // pthread->m_exitcode;
879 bool wxThreadInternal::Create(wxThread
*thread
, unsigned int stackSize
)
881 wxMacMPThreadsInitVerify() ;
882 wxASSERT_MSG( m_state
== STATE_NEW
&& !m_tid
,
883 _T("Create()ing thread twice?") );
885 OSStatus err
= noErr
;
888 if ( m_notifyQueueId
== kInvalidID
)
890 OSStatus err
= MPCreateQueue( & m_notifyQueueId
);
893 wxLogSysError(_("Cant create the thread event queue"));
900 err
= MPCreateTask( MacThreadStart
,
911 wxLogSysError(_("Can't create thread"));
915 if ( m_prio
!= WXTHREAD_DEFAULT_PRIORITY
)
923 void wxThreadInternal::SetPriority( int priority
)
929 // Mac priorities range from 1 to 10,000, with a default of 100.
930 // wxWidgets priorities range from 0 to 100 with a default of 50.
931 // We can map wxWidgets to Mac priorities easily by assuming
932 // the former uses a logarithmic scale.
933 const unsigned int macPriority
= ( int)( exp( priority
/ 25.0 * log( 10.0)) + 0.5);
935 MPSetTaskWeight( m_tid
, macPriority
);
939 wxThreadError
wxThreadInternal::Run()
941 wxCHECK_MSG( GetState() == STATE_NEW
, wxTHREAD_RUNNING
,
942 wxT("thread may only be started once after Create()") );
944 SetState(STATE_RUNNING
);
946 // wake up threads waiting for our start
949 return wxTHREAD_NO_ERROR
;
952 void wxThreadInternal::Wait()
954 wxCHECK_RET( !m_isDetached
, _T("can't wait for a detached thread") );
956 // if the thread we're waiting for is waiting for the GUI mutex, we will
957 // deadlock so make sure we release it temporarily
958 if ( wxThread::IsMain() )
962 wxCriticalSectionLocker
lock(m_csJoinFlag
);
964 if ( m_shouldBeJoined
)
970 OSStatus err
= MPWaitOnQueue ( m_notifyQueueId
,
977 wxLogSysError( _( "Cannot wait on thread to exit."));
981 // actually param1 would be the address of m_exitcode
982 // but we don't need this here
985 m_shouldBeJoined
= FALSE
;
989 // reacquire GUI mutex
990 if ( wxThread::IsMain() )
994 void wxThreadInternal::Pause()
996 // the state is set from the thread which pauses us first, this function
997 // is called later so the state should have been already set
998 wxCHECK_RET( m_state
== STATE_PAUSED
,
999 wxT("thread must first be paused with wxThread::Pause().") );
1001 // wait until the semaphore is Post()ed from Resume()
1002 m_semSuspend
.Wait();
1005 void wxThreadInternal::Resume()
1007 wxCHECK_RET( m_state
== STATE_PAUSED
,
1008 wxT("can't resume thread which is not suspended.") );
1010 // the thread might be not actually paused yet - if there were no call to
1011 // TestDestroy() since the last call to Pause() for example
1012 if ( IsReallyPaused() )
1015 m_semSuspend
.Post();
1018 SetReallyPaused(FALSE
);
1021 SetState(STATE_RUNNING
);
1027 wxThread
*wxThread::This()
1029 wxThread
* thr
= (wxThread
*) MPGetTaskStorageValue( gs_tlsForWXThread
) ;
1033 bool wxThread::IsMain()
1035 return GetCurrentId() == gs_idMainThread
;
1042 void wxThread::Yield()
1044 #if TARGET_API_MAC_OSX
1045 CFRunLoopRunInMode( kCFRunLoopDefaultMode
, 0 , true ) ;
1051 void wxThread::Sleep(unsigned long milliseconds
)
1053 AbsoluteTime wakeup
= AddDurationToAbsolute( milliseconds
, UpTime());
1054 MPDelayUntil( & wakeup
);
1058 int wxThread::GetCPUCount()
1060 return MPProcessors();
1063 unsigned long wxThread::GetCurrentId()
1065 return (unsigned long)MPCurrentTaskID();
1069 bool wxThread::SetConcurrency(size_t level
)
1071 // Cannot be set in MacOS.
1076 wxThread::wxThread(wxThreadKind kind
)
1078 g_numberOfThreads
++;
1079 m_internal
= new wxThreadInternal();
1081 m_isDetached
= (kind
== wxTHREAD_DETACHED
);
1084 wxThread::~wxThread()
1086 wxASSERT_MSG( g_numberOfThreads
>0 , wxT("More threads deleted than created.") ) ;
1087 g_numberOfThreads
--;
1092 // check that the thread either exited or couldn't be created
1093 if ( m_internal
->GetState() != STATE_EXITED
&&
1094 m_internal
->GetState() != STATE_NEW
)
1096 wxLogDebug(_T("The thread %ld is being destroyed although it is still running! The application may crash."), GetId());
1100 #endif // __WXDEBUG__
1102 wxDELETE( m_internal
) ;
1106 wxThreadError
wxThread::Create(unsigned int stackSize
)
1108 wxCriticalSectionLocker
lock(m_critsect
);
1112 m_internal
->Detach() ;
1114 if ( m_internal
->Create(this, stackSize
) == false )
1116 m_internal
->SetState(STATE_EXITED
);
1117 return wxTHREAD_NO_RESOURCE
;
1120 return wxTHREAD_NO_ERROR
;
1123 wxThreadError
wxThread::Run()
1125 wxCriticalSectionLocker
lock(m_critsect
);
1127 wxCHECK_MSG( m_internal
->GetId(), wxTHREAD_MISC_ERROR
,
1128 wxT("must call wxThread::Create() first") );
1130 return m_internal
->Run();
1133 // -----------------------------------------------------------------------------
1135 // -----------------------------------------------------------------------------
1137 wxThreadError
wxThread::Pause()
1139 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
,
1140 _T("a thread can't pause itself") );
1142 wxCriticalSectionLocker
lock(m_critsect
);
1144 if ( m_internal
->GetState() != STATE_RUNNING
)
1146 wxLogDebug(wxT("Can't pause thread which is not running."));
1148 return wxTHREAD_NOT_RUNNING
;
1151 // just set a flag, the thread will be really paused only during the next
1152 // call to TestDestroy()
1153 m_internal
->SetState(STATE_PAUSED
);
1155 return wxTHREAD_NO_ERROR
;
1158 wxThreadError
wxThread::Resume()
1160 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
,
1161 _T("a thread can't resume itself") );
1163 wxCriticalSectionLocker
lock(m_critsect
);
1165 wxThreadState state
= m_internal
->GetState();
1170 m_internal
->Resume();
1171 return wxTHREAD_NO_ERROR
;
1173 return wxTHREAD_NO_ERROR
;
1176 wxLogDebug(_T("Attempt to resume a thread which is not paused."));
1178 return wxTHREAD_MISC_ERROR
;
1182 // -----------------------------------------------------------------------------
1184 // -----------------------------------------------------------------------------
1186 wxThread::ExitCode
wxThread::Wait()
1188 wxCHECK_MSG( This() != this, (ExitCode
)-1,
1189 _T("a thread can't wait for itself") );
1191 wxCHECK_MSG( !m_isDetached
, (ExitCode
)-1,
1192 _T("can't wait for detached thread") );
1196 return m_internal
->GetExitCode();
1199 wxThreadError
wxThread::Delete(ExitCode
*rc
)
1201 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
,
1202 _T("a thread can't delete itself") );
1204 bool isDetached
= m_isDetached
;
1207 wxThreadState state
= m_internal
->GetState();
1209 // ask the thread to stop
1210 m_internal
->SetCancelFlag();
1217 // we need to wake up the thread so that PthreadStart() will
1218 // terminate - right now it's blocking on run semaphore in
1220 m_internal
->SignalRun();
1229 // resume the thread first
1230 m_internal
->Resume();
1237 // wait until the thread stops
1242 // return the exit code of the thread
1243 *rc
= m_internal
->GetExitCode();
1246 //else: can't wait for detached threads
1249 return wxTHREAD_NO_ERROR
;
1252 wxThreadError
wxThread::Kill()
1254 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
,
1255 _T("a thread can't kill itself") );
1257 switch ( m_internal
->GetState() )
1261 return wxTHREAD_NOT_RUNNING
;
1264 // resume the thread first
1270 OSStatus err
= MPTerminateTask( m_internal
->GetId() , -1 ) ;
1273 wxLogError(_("Failed to terminate a thread."));
1275 return wxTHREAD_MISC_ERROR
;
1284 // this should be retrieved by Wait actually
1285 m_internal
->SetExitCode((void*)-1);
1288 return wxTHREAD_NO_ERROR
;
1292 void wxThread::Exit(ExitCode status
)
1294 wxASSERT_MSG( This() == this,
1295 _T("wxThread::Exit() can only be called in the context of the same thread") );
1297 // don't enter m_critsect before calling OnExit() because the user code
1298 // might deadlock if, for example, it signals a condition in OnExit() (a
1299 // common case) while the main thread calls any of functions entering
1300 // m_critsect on us (almost all of them do)
1303 MPTerminateTask( m_internal
->GetId() , (long) status
) ;
1311 // update the status of the joinable thread
1312 wxCriticalSectionLocker
lock(m_critsect
);
1313 m_internal
->SetState(STATE_EXITED
);
1317 // also test whether we were paused
1318 bool wxThread::TestDestroy()
1320 wxASSERT_MSG( This() == this,
1321 _T("wxThread::TestDestroy() can only be called in the context of the same thread") );
1325 if ( m_internal
->GetState() == STATE_PAUSED
)
1327 m_internal
->SetReallyPaused(TRUE
);
1329 // leave the crit section or the other threads will stop too if they
1330 // try to call any of (seemingly harmless) IsXXX() functions while we
1334 m_internal
->Pause();
1338 // thread wasn't requested to pause, nothing to do
1342 return m_internal
->WasCancelled();
1345 // -----------------------------------------------------------------------------
1347 // -----------------------------------------------------------------------------
1349 void wxThread::SetPriority(unsigned int prio
)
1351 wxCHECK_RET( ((int)WXTHREAD_MIN_PRIORITY
<= (int)prio
) &&
1352 ((int)prio
<= (int)WXTHREAD_MAX_PRIORITY
),
1353 wxT("invalid thread priority") );
1355 wxCriticalSectionLocker
lock(m_critsect
);
1357 switch ( m_internal
->GetState() )
1362 // thread not yet started, priority will be set when it is
1363 m_internal
->SetPriority(prio
);
1368 wxFAIL_MSG(wxT("impossible to set thread priority in this state"));
1372 unsigned int wxThread::GetPriority() const
1374 wxCriticalSectionLocker
lock((wxCriticalSection
&)m_critsect
); // const_cast
1376 return m_internal
->GetPriority();
1379 unsigned long wxThread::GetId() const
1381 wxCriticalSectionLocker
lock((wxCriticalSection
&)m_critsect
); // const_cast
1383 return (unsigned long)m_internal
->GetId();
1386 // -----------------------------------------------------------------------------
1388 // -----------------------------------------------------------------------------
1390 bool wxThread::IsRunning() const
1392 wxCriticalSectionLocker
lock((wxCriticalSection
&)m_critsect
);
1394 return m_internal
->GetState() == STATE_RUNNING
;
1397 bool wxThread::IsAlive() const
1399 wxCriticalSectionLocker
lock((wxCriticalSection
&)m_critsect
);
1401 switch ( m_internal
->GetState() )
1412 bool wxThread::IsPaused() const
1414 wxCriticalSectionLocker
lock((wxCriticalSection
&)m_critsect
);
1416 return (m_internal
->GetState() == STATE_PAUSED
);
1419 // ----------------------------------------------------------------------------
1420 // Automatic initialization for thread module
1421 // ----------------------------------------------------------------------------
1423 class wxThreadModule
: public wxModule
1426 virtual bool OnInit();
1427 virtual void OnExit();
1430 DECLARE_DYNAMIC_CLASS(wxThreadModule
)
1433 IMPLEMENT_DYNAMIC_CLASS(wxThreadModule
, wxModule
)
1435 bool wxThreadModule::OnInit()
1437 if ( !wxMacMPThreadsInitVerify() )
1442 verify_noerr( MPAllocateTaskStorageIndex( &gs_tlsForWXThread
) ) ;
1443 // main thread's This() is NULL
1444 verify_noerr( MPSetTaskStorageValue( gs_tlsForWXThread
, NULL
) ) ;
1446 gs_idMainThread
= wxThread::GetCurrentId() ;
1448 gs_critsectWaitingForGui
= new wxCriticalSection();
1450 gs_critsectGui
= new wxCriticalSection();
1451 gs_critsectGui
->Enter();
1456 void wxThreadModule::OnExit()
1458 if ( gs_critsectGui
)
1460 gs_critsectGui
->Leave();
1461 delete gs_critsectGui
;
1462 gs_critsectGui
= NULL
;
1465 delete gs_critsectWaitingForGui
;
1466 gs_critsectWaitingForGui
= NULL
;
1469 // ----------------------------------------------------------------------------
1470 // GUI Serialization copied from MSW implementation
1471 // ----------------------------------------------------------------------------
1473 void WXDLLIMPEXP_BASE
wxMutexGuiEnter()
1475 // this would dead lock everything...
1476 wxASSERT_MSG( !wxThread::IsMain(),
1477 wxT("main thread doesn't want to block in wxMutexGuiEnter()!") );
1479 // the order in which we enter the critical sections here is crucial!!
1481 // set the flag telling to the main thread that we want to do some GUI
1483 wxCriticalSectionLocker
enter(*gs_critsectWaitingForGui
);
1485 gs_nWaitingForGui
++;
1488 wxWakeUpMainThread();
1490 // now we may block here because the main thread will soon let us in
1491 // (during the next iteration of OnIdle())
1492 gs_critsectGui
->Enter();
1495 void WXDLLIMPEXP_BASE
wxMutexGuiLeave()
1497 wxCriticalSectionLocker
enter(*gs_critsectWaitingForGui
);
1499 if ( wxThread::IsMain() )
1501 gs_bGuiOwnedByMainThread
= false;
1505 // decrement the number of threads waiting for GUI access now
1506 wxASSERT_MSG( gs_nWaitingForGui
> 0,
1507 wxT("calling wxMutexGuiLeave() without entering it first?") );
1509 gs_nWaitingForGui
--;
1511 wxWakeUpMainThread();
1514 gs_critsectGui
->Leave();
1517 void WXDLLIMPEXP_BASE
wxMutexGuiLeaveOrEnter()
1519 wxASSERT_MSG( wxThread::IsMain(),
1520 wxT("only main thread may call wxMutexGuiLeaveOrEnter()!") );
1522 wxCriticalSectionLocker
enter(*gs_critsectWaitingForGui
);
1524 if ( gs_nWaitingForGui
== 0 )
1526 // no threads are waiting for GUI - so we may acquire the lock without
1527 // any danger (but only if we don't already have it)
1528 if ( !wxGuiOwnedByMainThread() )
1530 gs_critsectGui
->Enter();
1532 gs_bGuiOwnedByMainThread
= true;
1534 //else: already have it, nothing to do
1538 // some threads are waiting, release the GUI lock if we have it
1539 if ( wxGuiOwnedByMainThread() )
1543 //else: some other worker thread is doing GUI
1547 bool WXDLLIMPEXP_BASE
wxGuiOwnedByMainThread()
1549 return gs_bGuiOwnedByMainThread
;
1552 // wake up the main thread
1553 void WXDLLEXPORT
wxWakeUpMainThread()
1558 // ----------------------------------------------------------------------------
1559 // include common implementation code
1560 // ----------------------------------------------------------------------------
1562 #include "wx/thrimpl.cpp"
1564 #endif // wxUSE_THREADS