1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxThread Implementation
4 // Author: Original from Wolfram Gloger/Guilhem Lavaux/Vadim Zeitlin
5 // Modified by: Aj Lavin, Stefan Csomor
8 // Copyright: (c) Wolfram Gloger (1996, 1997); Guilhem Lavaux (1998),
9 // Vadim Zeitlin (1999) , Stefan Csomor (2000)
10 // Licence: wxWindows licence
11 /////////////////////////////////////////////////////////////////////////////
14 #pragma implementation "thread.h"
17 // ----------------------------------------------------------------------------
19 // ----------------------------------------------------------------------------
21 // For compilers that support precompilation, includes "wx.h".
22 #include "wx/wxprec.h"
24 #if defined(__BORLANDC__)
34 #include "wx/module.h"
35 #include "wx/thread.h"
38 #if TARGET_API_MAC_OSX
39 #include <CoreServices/CoreServices.h>
41 #include <DriverServices.h>
42 #include <Multiprocessing.h>
45 #include "wx/mac/uma.h"
48 #include "wx/mac/macnotfy.h"
50 // ----------------------------------------------------------------------------
52 // ----------------------------------------------------------------------------
54 // the possible states of the thread ("=>" shows all possible transitions from
58 STATE_NEW
, // didn't start execution yet (=> RUNNING)
59 STATE_RUNNING
, // thread is running (=> PAUSED, CANCELED)
60 STATE_PAUSED
, // thread is temporarily suspended (=> RUNNING)
61 STATE_CANCELED
, // thread should terminate a.s.a.p. (=> EXITED)
62 STATE_EXITED
// thread is terminating
65 // ----------------------------------------------------------------------------
66 // this module globals
67 // ----------------------------------------------------------------------------
70 // the task ID of the main thread
71 static wxThreadIdType gs_idMainThread
= kInvalidID
;
73 // this is the Per-Task Storage for the pointer to the appropriate wxThread
74 TaskStorageIndex gs_tlsForWXThread
= 0 ;
76 // if it's false, some secondary thread is holding the GUI lock
77 static bool gs_bGuiOwnedByMainThread
= true;
79 // critical section which controls access to all GUI functions: any secondary
80 // thread (i.e. except the main one) must enter this crit section before doing
82 static wxCriticalSection
*gs_critsectGui
= NULL
;
84 // critical section which protects gs_nWaitingForGui variable
85 static wxCriticalSection
*gs_critsectWaitingForGui
= NULL
;
87 // number of threads waiting for GUI in wxMutexGuiEnter()
88 static size_t gs_nWaitingForGui
= 0;
90 // overall number of threads, needed for determining the sleep value of the main
92 size_t g_numberOfThreads
= 0;
98 MPCriticalRegionID gs_guiCritical
= kInvalidID
;
102 // ============================================================================
103 // MacOS implementation of thread classes
104 // ============================================================================
109 The implementation is very close to the phtreads implementation, the reason for
110 using MPServices is the fact that these are also available under OS 9. Thus allowing
111 for one common API for all current builds.
113 As soon as wxThreads are on a 64 bit address space, the TLS must be extended
114 to use two indices one for each 32 bit part as the MP implementation is limited
117 I have two implementations for mutexes :
118 version A based on a binary semaphore, problem - not reentrant, version B based
119 on a critical region, allows for reentrancy, performance implications not
122 The same for condition internal, one implementation by Aj Lavin and the other one
123 copied from the thrimpl.cpp which I assume has been more broadly tested, I've just
124 replaced the interlock increment with the appropriate PPC calls
127 // ----------------------------------------------------------------------------
128 // wxMutex implementation
129 // ----------------------------------------------------------------------------
133 class wxMutexInternal
136 wxMutexInternal(wxMutexType mutexType
) ;
138 bool IsOk() const { return m_isOk
; }
140 wxMutexError
Lock() ;
141 wxMutexError
TryLock() ;
142 wxMutexError
Unlock();
144 MPSemaphoreID m_semaphore
;
148 wxMutexInternal::wxMutexInternal(wxMutexType mutexType
)
151 m_semaphore
= kInvalidID
;
153 OSStatus err
= noErr
;
156 case wxMUTEX_DEFAULT
:
158 verify_noerr( MPCreateBinarySemaphore( & m_semaphore
) );
159 m_isOk
= ( m_semaphore
!= kInvalidID
) ;
162 case wxMUTEX_RECURSIVE
:
163 wxFAIL_MSG(wxT("Recursive Mutex not supported yet") ) ;
166 wxFAIL_MSG(wxT("Unknown mutex type") ) ;
171 wxMutexInternal::~wxMutexInternal()
173 if ( m_semaphore
!= kInvalidID
)
174 MPDeleteSemaphore( m_semaphore
);
177 wxMutexError
wxMutexInternal::Lock()
179 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") ) ;
180 OSStatus err
= MPWaitOnSemaphore( m_semaphore
, kDurationForever
);
183 wxLogSysError(wxT("Could not lock mutex"));
184 return wxMUTEX_MISC_ERROR
;
187 return wxMUTEX_NO_ERROR
;
190 wxMutexError
wxMutexInternal::TryLock()
192 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") ) ;
193 OSStatus err
= MPWaitOnSemaphore( m_semaphore
, kDurationImmediate
);
196 if ( err
== kMPTimeoutErr
)
200 wxLogSysError(wxT("Could not try lock mutex"));
201 return wxMUTEX_MISC_ERROR
;
204 return wxMUTEX_NO_ERROR
;
207 wxMutexError
wxMutexInternal::Unlock()
209 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") ) ;
210 OSStatus err
= MPSignalSemaphore( m_semaphore
);
213 wxLogSysError(_("Could not unlock mutex"));
214 return wxMUTEX_MISC_ERROR
;
217 return wxMUTEX_NO_ERROR
;
222 class wxMutexInternal
225 wxMutexInternal(wxMutexType mutexType
) ;
227 bool IsOk() const { return m_isOk
; }
229 wxMutexError
Lock() ;
230 wxMutexError
TryLock() ;
231 wxMutexError
Unlock();
233 MPCriticalRegionID m_critRegion
;
237 wxMutexInternal::wxMutexInternal(wxMutexType mutexType
)
240 m_critRegion
= kInvalidID
;
242 verify_noerr( MPCreateCriticalRegion( & m_critRegion
) );
243 m_isOk
= ( m_critRegion
!= kInvalidID
) ;
246 wxFAIL_MSG(wxT("Error when creating mutex") ) ;
249 wxMutexInternal::~wxMutexInternal()
251 if ( m_critRegion
!= kInvalidID
)
252 MPDeleteCriticalRegion( m_critRegion
);
255 wxMutexError
wxMutexInternal::Lock()
257 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") ) ;
258 OSStatus err
= MPEnterCriticalRegion( m_critRegion
, kDurationForever
);
261 wxLogSysError(wxT("Could not lock mutex"));
262 return wxMUTEX_MISC_ERROR
;
265 return wxMUTEX_NO_ERROR
;
268 wxMutexError
wxMutexInternal::TryLock()
270 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") ) ;
271 OSStatus err
= MPEnterCriticalRegion( m_critRegion
, kDurationImmediate
);
274 if ( err
== kMPTimeoutErr
)
278 wxLogSysError(wxT("Could not try lock mutex"));
279 return wxMUTEX_MISC_ERROR
;
282 return wxMUTEX_NO_ERROR
;
285 wxMutexError
wxMutexInternal::Unlock()
287 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") ) ;
288 OSStatus err
= MPExitCriticalRegion( m_critRegion
);
291 wxLogSysError(_("Could not unlock mutex"));
292 return wxMUTEX_MISC_ERROR
;
295 return wxMUTEX_NO_ERROR
;
300 // --------------------------------------------------------------------------
302 // --------------------------------------------------------------------------
304 class wxSemaphoreInternal
307 wxSemaphoreInternal(int initialcount
, int maxcount
);
308 ~wxSemaphoreInternal();
310 bool IsOk() const { return m_isOk
; }
312 wxSemaError
WaitTimeout(unsigned long milliseconds
);
314 wxSemaError
Wait() { return WaitTimeout( kDurationForever
); }
316 wxSemaError
TryWait()
318 wxSemaError err
= WaitTimeout(kDurationImmediate
);
319 if ( err
== wxSEMA_TIMEOUT
)
326 MPSemaphoreID m_semaphore
;
330 wxSemaphoreInternal::wxSemaphoreInternal(int initialcount
, int maxcount
)
333 m_semaphore
= kInvalidID
;
336 // make it practically infinite
339 verify_noerr( MPCreateSemaphore( maxcount
, initialcount
, & m_semaphore
) );
340 m_isOk
= ( m_semaphore
!= kInvalidID
) ;
343 wxFAIL_MSG(wxT("Error when creating semaphore") ) ;
346 wxSemaphoreInternal::~wxSemaphoreInternal()
348 if( m_semaphore
!= kInvalidID
)
349 MPDeleteSemaphore( m_semaphore
);
352 wxSemaError
wxSemaphoreInternal::WaitTimeout(unsigned long milliseconds
)
354 OSStatus err
= MPWaitOnSemaphore( m_semaphore
, milliseconds
);
357 if ( err
== kMPTimeoutErr
)
359 return wxSEMA_TIMEOUT
;
361 return wxSEMA_MISC_ERROR
;
363 return wxSEMA_NO_ERROR
;
366 wxSemaError
wxSemaphoreInternal::Post()
368 OSStatus err
= MPSignalSemaphore( m_semaphore
);
371 return wxSEMA_MISC_ERROR
;
373 return wxSEMA_NO_ERROR
;
376 // ----------------------------------------------------------------------------
377 // wxCondition implementation
378 // ----------------------------------------------------------------------------
382 class wxConditionInternal
386 wxConditionInternal(wxMutex
& mutex
)
396 ~wxConditionInternal()
400 bool IsOk() const { return m_mutex
.IsOk() ; }
404 return WaitTimeout( kDurationForever
);
407 wxCondError
WaitTimeout(unsigned long msectimeout
);
411 return DoSignal( false);
414 wxCondError
Broadcast()
416 return DoSignal( true);
421 wxCondError
DoSignal( bool signalAll
);
424 wxSemaphoreInternal m_semaphore
; // Signals the waiting threads.
425 wxSemaphoreInternal m_gate
;
426 wxCriticalSection m_varSection
;
427 size_t m_waiters
; // Number of threads waiting for a signal.
428 size_t m_signals
; // Number of signals to send.
429 size_t m_canceled
; // Number of canceled waiters in m_waiters.
433 wxCondError
wxConditionInternal::WaitTimeout(unsigned long msectimeout
)
436 if ( ++ m_waiters
== INT_MAX
)
438 m_varSection
.Enter();
439 m_waiters
-= m_canceled
;
440 m_signals
-= m_canceled
;
442 m_varSection
.Leave();
448 wxSemaError err
= m_semaphore
.WaitTimeout( msectimeout
);
449 wxASSERT( err
== wxSEMA_NO_ERROR
|| err
== wxSEMA_TIMEOUT
);
451 m_varSection
.Enter();
452 if ( err
!= wxSEMA_NO_ERROR
)
454 if ( m_signals
> m_canceled
)
456 // A signal is being sent after we timed out.
458 if ( m_waiters
== m_signals
)
460 // There are no excess waiters to catch the signal, so
461 // we must throw it away.
463 wxSemaError err2
= m_semaphore
.Wait();
464 if ( err2
!= wxSEMA_NO_ERROR
)
466 wxLogSysError(_("Error while waiting on semaphore"));
468 wxASSERT( err2
== wxSEMA_NO_ERROR
);
470 if ( -- m_signals
== m_canceled
)
472 // This was the last signal. open the gate.
473 wxASSERT( m_waiters
== m_canceled
);
479 // There are excess waiters to catch the signal, leave
486 // No signals is being sent.
487 // The gate may be open or closed, so we can't touch m_waiters.
494 // We caught a signal.
495 wxASSERT( m_signals
> m_canceled
);
497 if ( -- m_signals
== m_canceled
)
499 // This was the last signal. open the gate.
500 wxASSERT( m_waiters
== m_canceled
);
504 m_varSection
.Leave();
510 return err
== wxSEMA_TIMEOUT
? wxCOND_TIMEOUT
: wxCOND_MISC_ERROR
;
513 return wxCOND_NO_ERROR
;
517 wxCondError
wxConditionInternal::DoSignal( bool signalAll
)
520 m_varSection
.Enter();
522 wxASSERT( m_signals
== m_canceled
);
524 if ( m_waiters
== m_canceled
)
526 m_varSection
.Leave();
528 return wxCOND_NO_ERROR
;
533 m_waiters
-= m_canceled
;
538 m_signals
= signalAll
? m_waiters
: 1;
539 size_t n
= m_signals
;
541 m_varSection
.Leave();
543 // Let the waiters inherit the gate lock.
547 wxSemaError err
= m_semaphore
.Post();
548 wxASSERT( err
== wxSEMA_NO_ERROR
);
551 return wxCOND_NO_ERROR
;
555 class wxConditionInternal
558 wxConditionInternal(wxMutex
& mutex
);
560 bool IsOk() const { return m_mutex
.IsOk() && m_semaphore
.IsOk(); }
563 wxCondError
WaitTimeout(unsigned long milliseconds
);
565 wxCondError
Signal();
566 wxCondError
Broadcast();
569 // the number of threads currently waiting for this condition
572 // the critical section protecting m_numWaiters
573 wxCriticalSection m_csWaiters
;
576 wxSemaphore m_semaphore
;
578 DECLARE_NO_COPY_CLASS(wxConditionInternal
)
581 wxConditionInternal::wxConditionInternal(wxMutex
& mutex
)
584 // another thread can't access it until we return from ctor, so no need to
585 // protect access to m_numWaiters here
589 wxCondError
wxConditionInternal::Wait()
591 // increment the number of waiters
592 IncrementAtomic(&m_numWaiters
);
596 // a potential race condition can occur here
598 // after a thread increments nwaiters, and unlocks the mutex and before the
599 // semaphore.Wait() is called, if another thread can cause a signal to be
602 // this race condition is handled by using a semaphore and incrementing the
603 // semaphore only if 'nwaiters' is greater that zero since the semaphore,
604 // can 'remember' signals the race condition will not occur
606 // wait ( if necessary ) and decrement semaphore
607 wxSemaError err
= m_semaphore
.Wait();
610 return err
== wxSEMA_NO_ERROR
? wxCOND_NO_ERROR
: wxCOND_MISC_ERROR
;
613 wxCondError
wxConditionInternal::WaitTimeout(unsigned long milliseconds
)
615 IncrementAtomic(&m_numWaiters
);
619 // a race condition can occur at this point in the code
621 // please see the comments in Wait(), for details
623 wxSemaError err
= m_semaphore
.WaitTimeout(milliseconds
);
625 if ( err
== wxSEMA_BUSY
)
627 // another potential race condition exists here it is caused when a
628 // 'waiting' thread timesout, and returns from WaitForSingleObject, but
629 // has not yet decremented 'nwaiters'.
631 // at this point if another thread calls signal() then the semaphore
632 // will be incremented, but the waiting thread will miss it.
634 // to handle this particular case, the waiting thread calls
635 // WaitForSingleObject again with a timeout of 0, after locking
636 // 'nwaiters_mutex'. this call does not block because of the zero
637 // timeout, but will allow the waiting thread to catch the missed
639 wxCriticalSectionLocker
lock(m_csWaiters
);
641 err
= m_semaphore
.WaitTimeout(0);
643 if ( err
!= wxSEMA_NO_ERROR
)
651 return err
== wxSEMA_NO_ERROR
? wxCOND_NO_ERROR
: wxCOND_MISC_ERROR
;
654 wxCondError
wxConditionInternal::Signal()
656 wxCriticalSectionLocker
lock(m_csWaiters
);
658 if ( m_numWaiters
> 0 )
660 // increment the semaphore by 1
661 if ( m_semaphore
.Post() != wxSEMA_NO_ERROR
)
662 return wxCOND_MISC_ERROR
;
667 return wxCOND_NO_ERROR
;
670 wxCondError
wxConditionInternal::Broadcast()
672 wxCriticalSectionLocker
lock(m_csWaiters
);
674 while ( m_numWaiters
> 0 )
676 if ( m_semaphore
.Post() != wxSEMA_NO_ERROR
)
677 return wxCOND_MISC_ERROR
;
682 return wxCOND_NO_ERROR
;
686 // ----------------------------------------------------------------------------
687 // wxCriticalSection implementation
688 // ----------------------------------------------------------------------------
690 // XXX currently implemented as mutex in headers. Change to critical section.
692 // ----------------------------------------------------------------------------
693 // wxThread implementation
694 // ----------------------------------------------------------------------------
696 // wxThreadInternal class
697 // ----------------------
699 class wxThreadInternal
706 m_prio
= WXTHREAD_DEFAULT_PRIORITY
;
707 m_notifyQueueId
= kInvalidID
;
709 m_cancelled
= FALSE
;
711 // set to TRUE only when the thread starts waiting on m_semSuspend
714 // defaults for joinable threads
715 m_shouldBeJoined
= TRUE
;
716 m_isDetached
= FALSE
;
720 if ( m_notifyQueueId
)
722 MPDeleteQueue( m_notifyQueueId
);
723 m_notifyQueueId
= kInvalidID
;
728 static OSStatus
MacThreadStart(void* arg
);
730 // create a new (suspended) thread (for the given thread object)
731 bool Create(wxThread
*thread
, unsigned int stackSize
);
736 // unblock the thread allowing it to run
737 void SignalRun() { m_semRun
.Post(); }
738 // ask the thread to terminate
740 // go to sleep until Resume() is called
747 int GetPriority() const { return m_prio
; }
748 void SetPriority(int prio
) ;
750 wxThreadState
GetState() const { return m_state
; }
751 void SetState(wxThreadState state
) { m_state
= state
; }
753 // Get the ID of this thread's underlying MP Services task.
754 MPTaskID
GetId() const { return m_tid
; }
756 void SetCancelFlag() { m_cancelled
= TRUE
; }
757 bool WasCancelled() const { return m_cancelled
; }
759 void SetExitCode(wxThread::ExitCode exitcode
) { m_exitcode
= exitcode
; }
760 wxThread::ExitCode
GetExitCode() const { return m_exitcode
; }
763 void SetReallyPaused(bool paused
) { m_isPaused
= paused
; }
764 bool IsReallyPaused() const { return m_isPaused
; }
766 // tell the thread that it is a detached one
769 wxCriticalSectionLocker
lock(m_csJoinFlag
);
771 m_shouldBeJoined
= FALSE
;
776 // the thread we're associated with
779 MPTaskID m_tid
; // thread id
780 MPQueueID m_notifyQueueId
; // its notification queue
782 wxThreadState m_state
; // see wxThreadState enum
783 int m_prio
; // in wxWindows units: from 0 to 100
785 // this flag is set when the thread should terminate
788 // this flag is set when the thread is blocking on m_semSuspend
791 // the thread exit code - only used for joinable (!detached) threads and
792 // is only valid after the thread termination
793 wxThread::ExitCode m_exitcode
;
795 // many threads may call Wait(), but only one of them should call
796 // pthread_join(), so we have to keep track of this
797 wxCriticalSection m_csJoinFlag
;
798 bool m_shouldBeJoined
;
801 // this semaphore is posted by Run() and the threads Entry() is not
802 // called before it is done
803 wxSemaphore m_semRun
;
805 // this one is signaled when the thread should resume after having been
807 wxSemaphore m_semSuspend
;
810 OSStatus
wxThreadInternal::MacThreadStart(void *parameter
)
812 wxThread
* thread
= (wxThread
*) parameter
;
813 wxThreadInternal
*pthread
= thread
->m_internal
;
815 // add to TLS so that This() will work
816 verify_noerr( MPSetTaskStorageValue( gs_tlsForWXThread
, (long) thread
) ) ;
818 // have to declare this before pthread_cleanup_push() which defines a
822 // wait for the semaphore to be posted from Run()
823 pthread
->m_semRun
.Wait();
825 // test whether we should run the run at all - may be it was deleted
826 // before it started to Run()?
828 wxCriticalSectionLocker
lock(thread
->m_critsect
);
830 dontRunAtAll
= pthread
->GetState() == STATE_NEW
&&
831 pthread
->WasCancelled();
836 pthread
->m_exitcode
= thread
->Entry();
839 wxCriticalSectionLocker
lock(thread
->m_critsect
);
840 pthread
->SetState(STATE_EXITED
);
846 if ( pthread
->m_isDetached
)
853 // on mac for the running code the correct thread termination is to
856 // terminate the thread
857 thread
->Exit(pthread
->m_exitcode
);
859 return (OSStatus
) NULL
; // pthread->m_exitcode;
863 bool wxThreadInternal::Create(wxThread
*thread
, unsigned int stackSize
)
865 wxASSERT_MSG( m_state
== STATE_NEW
&& !m_tid
,
866 _T("Create()ing thread twice?") );
868 OSStatus err
= noErr
;
871 if ( m_notifyQueueId
== kInvalidID
)
873 OSStatus err
= MPCreateQueue( & m_notifyQueueId
);
876 wxLogSysError(_("Cant create the thread event queue"));
883 err
= MPCreateTask( MacThreadStart
,
894 wxLogSysError(_("Can't create thread"));
898 if ( m_prio
!= WXTHREAD_DEFAULT_PRIORITY
)
906 void wxThreadInternal::SetPriority( int priority
)
912 // Mac priorities range from 1 to 10,000, with a default of 100.
913 // wxWindows priorities range from 0 to 100 with a default of 50.
914 // We can map wxWindows to Mac priorities easily by assuming
915 // the former uses a logarithmic scale.
916 const unsigned int macPriority
= ( int)( exp( priority
/ 25.0 * log( 10.0)) + 0.5);
918 MPSetTaskWeight( m_tid
, macPriority
);
922 wxThreadError
wxThreadInternal::Run()
924 wxCHECK_MSG( GetState() == STATE_NEW
, wxTHREAD_RUNNING
,
925 wxT("thread may only be started once after Create()") );
927 SetState(STATE_RUNNING
);
929 // wake up threads waiting for our start
932 return wxTHREAD_NO_ERROR
;
935 void wxThreadInternal::Wait()
937 wxCHECK_RET( !m_isDetached
, _T("can't wait for a detached thread") );
939 // if the thread we're waiting for is waiting for the GUI mutex, we will
940 // deadlock so make sure we release it temporarily
941 if ( wxThread::IsMain() )
945 wxCriticalSectionLocker
lock(m_csJoinFlag
);
947 if ( m_shouldBeJoined
)
953 OSStatus err
= MPWaitOnQueue ( m_notifyQueueId
,
960 wxLogSysError( _( "Cannot wait on thread to exit."));
964 // actually param1 would be the address of m_exitcode
965 // but we don't need this here
968 m_shouldBeJoined
= FALSE
;
972 // reacquire GUI mutex
973 if ( wxThread::IsMain() )
977 void wxThreadInternal::Pause()
979 // the state is set from the thread which pauses us first, this function
980 // is called later so the state should have been already set
981 wxCHECK_RET( m_state
== STATE_PAUSED
,
982 wxT("thread must first be paused with wxThread::Pause().") );
984 // wait until the semaphore is Post()ed from Resume()
988 void wxThreadInternal::Resume()
990 wxCHECK_RET( m_state
== STATE_PAUSED
,
991 wxT("can't resume thread which is not suspended.") );
993 // the thread might be not actually paused yet - if there were no call to
994 // TestDestroy() since the last call to Pause() for example
995 if ( IsReallyPaused() )
1001 SetReallyPaused(FALSE
);
1004 SetState(STATE_RUNNING
);
1010 wxThread
*wxThread::This()
1012 wxThread
* thr
= (wxThread
*) MPGetTaskStorageValue( gs_tlsForWXThread
) ;
1016 bool wxThread::IsMain()
1018 return GetCurrentId() == gs_idMainThread
;
1025 void wxThread::Yield()
1027 #if TARGET_API_MAC_OSX
1028 CFRunLoopRunInMode( kCFRunLoopDefaultMode
, 0 , true ) ;
1034 void wxThread::Sleep(unsigned long milliseconds
)
1036 AbsoluteTime wakeup
= AddDurationToAbsolute( milliseconds
, UpTime());
1037 MPDelayUntil( & wakeup
);
1041 int wxThread::GetCPUCount()
1043 return MPProcessors();
1046 unsigned long wxThread::GetCurrentId()
1048 return (unsigned long)MPCurrentTaskID();
1052 bool wxThread::SetConcurrency(size_t level
)
1054 // Cannot be set in MacOS.
1059 wxThread::wxThread(wxThreadKind kind
)
1061 g_numberOfThreads
++;
1062 m_internal
= new wxThreadInternal();
1064 m_isDetached
= (kind
== wxTHREAD_DETACHED
);
1067 wxThread::~wxThread()
1069 wxASSERT_MSG( g_numberOfThreads
>0 , wxT("More threads deleted than created.") ) ;
1070 g_numberOfThreads
--;
1075 // check that the thread either exited or couldn't be created
1076 if ( m_internal
->GetState() != STATE_EXITED
&&
1077 m_internal
->GetState() != STATE_NEW
)
1079 wxLogDebug(_T("The thread %ld is being destroyed although it is still running! The application may crash."), GetId());
1083 #endif // __WXDEBUG__
1085 wxDELETE( m_internal
) ;
1089 wxThreadError
wxThread::Create(unsigned int stackSize
)
1091 wxCriticalSectionLocker
lock(m_critsect
);
1095 m_internal
->Detach() ;
1097 if ( m_internal
->Create(this, stackSize
) == false )
1099 m_internal
->SetState(STATE_EXITED
);
1100 return wxTHREAD_NO_RESOURCE
;
1103 return wxTHREAD_NO_ERROR
;
1106 wxThreadError
wxThread::Run()
1108 wxCriticalSectionLocker
lock(m_critsect
);
1110 wxCHECK_MSG( m_internal
->GetId(), wxTHREAD_MISC_ERROR
,
1111 wxT("must call wxThread::Create() first") );
1113 return m_internal
->Run();
1116 // -----------------------------------------------------------------------------
1118 // -----------------------------------------------------------------------------
1120 wxThreadError
wxThread::Pause()
1122 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
,
1123 _T("a thread can't pause itself") );
1125 wxCriticalSectionLocker
lock(m_critsect
);
1127 if ( m_internal
->GetState() != STATE_RUNNING
)
1129 wxLogDebug(wxT("Can't pause thread which is not running."));
1131 return wxTHREAD_NOT_RUNNING
;
1134 // just set a flag, the thread will be really paused only during the next
1135 // call to TestDestroy()
1136 m_internal
->SetState(STATE_PAUSED
);
1138 return wxTHREAD_NO_ERROR
;
1141 wxThreadError
wxThread::Resume()
1143 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
,
1144 _T("a thread can't resume itself") );
1146 wxCriticalSectionLocker
lock(m_critsect
);
1148 wxThreadState state
= m_internal
->GetState();
1153 m_internal
->Resume();
1154 return wxTHREAD_NO_ERROR
;
1156 return wxTHREAD_NO_ERROR
;
1159 wxLogDebug(_T("Attempt to resume a thread which is not paused."));
1161 return wxTHREAD_MISC_ERROR
;
1165 // -----------------------------------------------------------------------------
1167 // -----------------------------------------------------------------------------
1169 wxThread::ExitCode
wxThread::Wait()
1171 wxCHECK_MSG( This() != this, (ExitCode
)-1,
1172 _T("a thread can't wait for itself") );
1174 wxCHECK_MSG( !m_isDetached
, (ExitCode
)-1,
1175 _T("can't wait for detached thread") );
1179 return m_internal
->GetExitCode();
1182 wxThreadError
wxThread::Delete(ExitCode
*rc
)
1184 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
,
1185 _T("a thread can't delete itself") );
1187 bool isDetached
= m_isDetached
;
1190 wxThreadState state
= m_internal
->GetState();
1192 // ask the thread to stop
1193 m_internal
->SetCancelFlag();
1200 // we need to wake up the thread so that PthreadStart() will
1201 // terminate - right now it's blocking on run semaphore in
1203 m_internal
->SignalRun();
1212 // resume the thread first
1213 m_internal
->Resume();
1220 // wait until the thread stops
1225 // return the exit code of the thread
1226 *rc
= m_internal
->GetExitCode();
1229 //else: can't wait for detached threads
1232 return wxTHREAD_NO_ERROR
;
1235 wxThreadError
wxThread::Kill()
1237 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
,
1238 _T("a thread can't kill itself") );
1240 switch ( m_internal
->GetState() )
1244 return wxTHREAD_NOT_RUNNING
;
1247 // resume the thread first
1253 OSStatus err
= MPTerminateTask( m_internal
->GetId() , -1 ) ;
1256 wxLogError(_("Failed to terminate a thread."));
1258 return wxTHREAD_MISC_ERROR
;
1267 // this should be retrieved by Wait actually
1268 m_internal
->SetExitCode((void*)-1);
1271 return wxTHREAD_NO_ERROR
;
1275 void wxThread::Exit(ExitCode status
)
1277 wxASSERT_MSG( This() == this,
1278 _T("wxThread::Exit() can only be called in the context of the same thread") );
1280 // don't enter m_critsect before calling OnExit() because the user code
1281 // might deadlock if, for example, it signals a condition in OnExit() (a
1282 // common case) while the main thread calls any of functions entering
1283 // m_critsect on us (almost all of them do)
1286 MPTerminateTask( m_internal
->GetId() , (long) status
) ;
1294 // update the status of the joinable thread
1295 wxCriticalSectionLocker
lock(m_critsect
);
1296 m_internal
->SetState(STATE_EXITED
);
1300 // also test whether we were paused
1301 bool wxThread::TestDestroy()
1303 wxASSERT_MSG( This() == this,
1304 _T("wxThread::TestDestroy() can only be called in the context of the same thread") );
1308 if ( m_internal
->GetState() == STATE_PAUSED
)
1310 m_internal
->SetReallyPaused(TRUE
);
1312 // leave the crit section or the other threads will stop too if they
1313 // try to call any of (seemingly harmless) IsXXX() functions while we
1317 m_internal
->Pause();
1321 // thread wasn't requested to pause, nothing to do
1325 return m_internal
->WasCancelled();
1328 // -----------------------------------------------------------------------------
1330 // -----------------------------------------------------------------------------
1332 void wxThread::SetPriority(unsigned int prio
)
1334 wxCHECK_RET( ((int)WXTHREAD_MIN_PRIORITY
<= (int)prio
) &&
1335 ((int)prio
<= (int)WXTHREAD_MAX_PRIORITY
),
1336 wxT("invalid thread priority") );
1338 wxCriticalSectionLocker
lock(m_critsect
);
1340 switch ( m_internal
->GetState() )
1345 // thread not yet started, priority will be set when it is
1346 m_internal
->SetPriority(prio
);
1351 wxFAIL_MSG(wxT("impossible to set thread priority in this state"));
1355 unsigned int wxThread::GetPriority() const
1357 wxCriticalSectionLocker
lock((wxCriticalSection
&)m_critsect
); // const_cast
1359 return m_internal
->GetPriority();
1362 unsigned long wxThread::GetId() const
1364 wxCriticalSectionLocker
lock((wxCriticalSection
&)m_critsect
); // const_cast
1366 return (unsigned long)m_internal
->GetId();
1369 // -----------------------------------------------------------------------------
1371 // -----------------------------------------------------------------------------
1373 bool wxThread::IsRunning() const
1375 wxCriticalSectionLocker
lock((wxCriticalSection
&)m_critsect
);
1377 return m_internal
->GetState() == STATE_RUNNING
;
1380 bool wxThread::IsAlive() const
1382 wxCriticalSectionLocker
lock((wxCriticalSection
&)m_critsect
);
1384 switch ( m_internal
->GetState() )
1395 bool wxThread::IsPaused() const
1397 wxCriticalSectionLocker
lock((wxCriticalSection
&)m_critsect
);
1399 return (m_internal
->GetState() == STATE_PAUSED
);
1402 // ----------------------------------------------------------------------------
1403 // Automatic initialization for thread module
1404 // ----------------------------------------------------------------------------
1406 class wxThreadModule
: public wxModule
1409 virtual bool OnInit();
1410 virtual void OnExit();
1413 DECLARE_DYNAMIC_CLASS(wxThreadModule
)
1416 IMPLEMENT_DYNAMIC_CLASS(wxThreadModule
, wxModule
)
1418 bool wxThreadModule::OnInit()
1420 bool hasThreadManager
= false ;
1421 hasThreadManager
= MPLibraryIsLoaded();
1423 if ( !hasThreadManager
)
1425 wxLogError( _("MP Thread Support is not available on this System" ) ) ;
1429 verify_noerr( MPAllocateTaskStorageIndex( &gs_tlsForWXThread
) ) ;
1430 // main thread's This() is NULL
1431 verify_noerr( MPSetTaskStorageValue( gs_tlsForWXThread
, NULL
) ) ;
1433 gs_idMainThread
= wxThread::GetCurrentId() ;
1435 gs_critsectWaitingForGui
= new wxCriticalSection();
1437 gs_critsectGui
= new wxCriticalSection();
1438 gs_critsectGui
->Enter();
1443 void wxThreadModule::OnExit()
1445 if ( gs_critsectGui
)
1447 gs_critsectGui
->Leave();
1448 delete gs_critsectGui
;
1449 gs_critsectGui
= NULL
;
1452 delete gs_critsectWaitingForGui
;
1453 gs_critsectWaitingForGui
= NULL
;
1456 // ----------------------------------------------------------------------------
1457 // GUI Serialization copied from MSW implementation
1458 // ----------------------------------------------------------------------------
1460 void WXDLLIMPEXP_BASE
wxMutexGuiEnter()
1462 // this would dead lock everything...
1463 wxASSERT_MSG( !wxThread::IsMain(),
1464 wxT("main thread doesn't want to block in wxMutexGuiEnter()!") );
1466 // the order in which we enter the critical sections here is crucial!!
1468 // set the flag telling to the main thread that we want to do some GUI
1470 wxCriticalSectionLocker
enter(*gs_critsectWaitingForGui
);
1472 gs_nWaitingForGui
++;
1475 wxWakeUpMainThread();
1477 // now we may block here because the main thread will soon let us in
1478 // (during the next iteration of OnIdle())
1479 gs_critsectGui
->Enter();
1482 void WXDLLIMPEXP_BASE
wxMutexGuiLeave()
1484 wxCriticalSectionLocker
enter(*gs_critsectWaitingForGui
);
1486 if ( wxThread::IsMain() )
1488 gs_bGuiOwnedByMainThread
= false;
1492 // decrement the number of threads waiting for GUI access now
1493 wxASSERT_MSG( gs_nWaitingForGui
> 0,
1494 wxT("calling wxMutexGuiLeave() without entering it first?") );
1496 gs_nWaitingForGui
--;
1498 wxWakeUpMainThread();
1501 gs_critsectGui
->Leave();
1504 void WXDLLIMPEXP_BASE
wxMutexGuiLeaveOrEnter()
1506 wxASSERT_MSG( wxThread::IsMain(),
1507 wxT("only main thread may call wxMutexGuiLeaveOrEnter()!") );
1509 wxCriticalSectionLocker
enter(*gs_critsectWaitingForGui
);
1511 if ( gs_nWaitingForGui
== 0 )
1513 // no threads are waiting for GUI - so we may acquire the lock without
1514 // any danger (but only if we don't already have it)
1515 if ( !wxGuiOwnedByMainThread() )
1517 gs_critsectGui
->Enter();
1519 gs_bGuiOwnedByMainThread
= true;
1521 //else: already have it, nothing to do
1525 // some threads are waiting, release the GUI lock if we have it
1526 if ( wxGuiOwnedByMainThread() )
1530 //else: some other worker thread is doing GUI
1534 bool WXDLLIMPEXP_BASE
wxGuiOwnedByMainThread()
1536 return gs_bGuiOwnedByMainThread
;
1539 // wake up the main thread
1540 void WXDLLEXPORT
wxWakeUpMainThread()
1545 // ----------------------------------------------------------------------------
1546 // include common implementation code
1547 // ----------------------------------------------------------------------------
1549 #include "wx/thrimpl.cpp"
1551 #endif // wxUSE_THREADS