1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/osx/carbon/thread.cpp
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 /////////////////////////////////////////////////////////////////////////////
13 #include "wx/wxprec.h"
15 #if defined(__BORLANDC__)
21 #include "wx/module.h"
26 #include "wx/thread.h"
28 #if wxOSX_USE_COCOA_OR_CARBON
29 #include <CoreServices/CoreServices.h>
31 #include <Foundation/Foundation.h>
34 #include "wx/osx/uma.h"
36 // the possible states of the thread:
37 // ("=>" shows all possible transitions from this state)
40 STATE_NEW
, // didn't start execution yet (=> RUNNING)
41 STATE_RUNNING
, // thread is running (=> PAUSED, CANCELED)
42 STATE_PAUSED
, // thread is temporarily suspended (=> RUNNING)
43 STATE_CANCELED
, // thread should terminate a.s.a.p. (=> EXITED)
44 STATE_EXITED
// thread is terminating
47 // ----------------------------------------------------------------------------
49 // ----------------------------------------------------------------------------
51 // the task ID of the main thread
52 static wxThreadIdType gs_idMainThread
= kInvalidID
;
54 // this is the Per-Task Storage for the pointer to the appropriate wxThread
55 TaskStorageIndex gs_tlsForWXThread
= 0;
57 // if it's false, some secondary thread is holding the GUI lock
58 static bool gs_bGuiOwnedByMainThread
= true;
60 // critical section which controls access to all GUI functions: any secondary
61 // thread (i.e. except the main one) must enter this crit section before doing
63 static wxCriticalSection
*gs_critsectGui
= NULL
;
65 // critical section which protects gs_nWaitingForGui variable
66 static wxCriticalSection
*gs_critsectWaitingForGui
= NULL
;
68 // number of threads waiting for GUI in wxMutexGuiEnter()
69 static size_t gs_nWaitingForGui
= 0;
71 // overall number of threads, needed for determining
72 // the sleep value of the main event loop
73 size_t g_numberOfThreads
= 0;
77 MPCriticalRegionID gs_guiCritical
= kInvalidID
;
80 // ============================================================================
81 // MacOS implementation of thread classes
82 // ============================================================================
87 The implementation is very close to the phtreads implementation, the reason for
88 using MPServices is the fact that these are also available under OS 9. Thus allowing
89 for one common API for all current builds.
91 As soon as wxThreads are on a 64 bit address space, the TLS must be extended
92 to use two indices one for each 32 bit part as the MP implementation is limited
95 I have three implementations for mutexes :
96 version A based on a binary semaphore, problem - not reentrant, version B based
97 on a critical region, allows for reentrancy, performance implications not
98 yet tested, and third a plain pthreads implementation
100 The same for condition internal, one implementation by Aj Lavin and the other one
101 copied from the thrimpl.cpp which I assume has been more broadly tested, I've just
102 replaced the interlock increment with the appropriate PPC calls
105 // ----------------------------------------------------------------------------
107 // ----------------------------------------------------------------------------
109 wxCriticalSection::wxCriticalSection( wxCriticalSectionType
WXUNUSED(critSecType
) )
111 MPCreateCriticalRegion( (MPCriticalRegionID
*) &m_critRegion
);
114 wxCriticalSection::~wxCriticalSection()
116 MPDeleteCriticalRegion( (MPCriticalRegionID
) m_critRegion
);
119 void wxCriticalSection::Enter()
121 MPEnterCriticalRegion( (MPCriticalRegionID
) m_critRegion
, kDurationForever
);
124 void wxCriticalSection::Leave()
126 MPExitCriticalRegion( (MPCriticalRegionID
) m_critRegion
);
129 // ----------------------------------------------------------------------------
130 // wxMutex implementation
131 // ----------------------------------------------------------------------------
133 #define wxUSE_MAC_SEMAPHORE_MUTEX 0
134 #define wxUSE_MAC_CRITICAL_REGION_MUTEX 1
135 #define wxUSE_MAC_PTHREADS_MUTEX 0
137 #if wxUSE_MAC_CRITICAL_REGION_MUTEX
139 class wxMutexInternal
142 wxMutexInternal( wxMutexType mutexType
);
143 virtual ~wxMutexInternal();
145 bool IsOk() const { return m_isOk
; }
147 wxMutexError
Lock() { return Lock(kDurationForever
); }
148 wxMutexError
Lock(unsigned long ms
);
149 wxMutexError
TryLock();
150 wxMutexError
Unlock();
153 MPCriticalRegionID m_critRegion
;
157 wxMutexInternal::wxMutexInternal( wxMutexType
WXUNUSED(mutexType
) )
160 m_critRegion
= kInvalidID
;
162 verify_noerr( MPCreateCriticalRegion( &m_critRegion
) );
163 m_isOk
= ( m_critRegion
!= kInvalidID
);
166 wxFAIL_MSG( wxT("Error when creating mutex") );
170 wxMutexInternal::~wxMutexInternal()
172 if ( m_critRegion
!= kInvalidID
)
173 MPDeleteCriticalRegion( m_critRegion
);
178 wxMutexError
wxMutexInternal::Lock(unsigned long ms
)
180 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") );
182 OSStatus err
= MPEnterCriticalRegion( m_critRegion
, ms
);
189 wxASSERT_MSG( ms
!= kDurationForever
, wxT("unexpected timeout") );
190 return wxMUTEX_TIMEOUT
;
193 wxLogSysError(wxT("Could not lock mutex"));
194 return wxMUTEX_MISC_ERROR
;
197 return wxMUTEX_NO_ERROR
;
200 wxMutexError
wxMutexInternal::TryLock()
202 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") ) ;
204 OSStatus err
= MPEnterCriticalRegion( m_critRegion
, kDurationImmediate
);
207 if ( err
== kMPTimeoutErr
)
210 wxLogSysError( wxT("Could not try lock mutex") );
211 return wxMUTEX_MISC_ERROR
;
214 return wxMUTEX_NO_ERROR
;
217 wxMutexError
wxMutexInternal::Unlock()
219 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") ) ;
221 OSStatus err
= MPExitCriticalRegion( m_critRegion
);
226 wxLogSysError( wxT("Could not unlock mutex") );
228 return wxMUTEX_MISC_ERROR
;
231 return wxMUTEX_NO_ERROR
;
236 // --------------------------------------------------------------------------
238 // --------------------------------------------------------------------------
240 class wxSemaphoreInternal
243 wxSemaphoreInternal( int initialcount
, int maxcount
);
244 virtual ~wxSemaphoreInternal();
250 wxSemaError
WaitTimeout( unsigned long milliseconds
);
253 { return WaitTimeout( kDurationForever
); }
255 wxSemaError
TryWait()
257 wxSemaError err
= WaitTimeout( kDurationImmediate
);
258 if (err
== wxSEMA_TIMEOUT
)
265 MPSemaphoreID m_semaphore
;
269 wxSemaphoreInternal::wxSemaphoreInternal( int initialcount
, int maxcount
)
272 m_semaphore
= kInvalidID
;
274 // make it practically infinite
277 verify_noerr( MPCreateSemaphore( maxcount
, initialcount
, &m_semaphore
) );
278 m_isOk
= ( m_semaphore
!= kInvalidID
);
282 wxFAIL_MSG( wxT("Error when creating semaphore") );
286 wxSemaphoreInternal::~wxSemaphoreInternal()
288 if (m_semaphore
!= kInvalidID
)
289 MPDeleteSemaphore( m_semaphore
);
294 wxSemaError
wxSemaphoreInternal::WaitTimeout( unsigned long milliseconds
)
296 OSStatus err
= MPWaitOnSemaphore( m_semaphore
, milliseconds
);
299 if (err
== kMPTimeoutErr
)
300 return wxSEMA_TIMEOUT
;
302 return wxSEMA_MISC_ERROR
;
305 return wxSEMA_NO_ERROR
;
308 wxSemaError
wxSemaphoreInternal::Post()
310 OSStatus err
= MPSignalSemaphore( m_semaphore
);
313 return wxSEMA_MISC_ERROR
;
315 return wxSEMA_NO_ERROR
;
318 // ----------------------------------------------------------------------------
319 // wxCondition implementation
320 // ----------------------------------------------------------------------------
322 class wxConditionInternal
325 wxConditionInternal( wxMutex
& mutex
);
328 { return m_mutex
.IsOk() && m_semaphore
.IsOk(); }
331 wxCondError
WaitTimeout( unsigned long milliseconds
);
333 wxCondError
Signal();
334 wxCondError
Broadcast();
337 // the number of threads currently waiting for this condition
340 // the critical section protecting m_numWaiters
341 wxCriticalSection m_csWaiters
;
344 wxSemaphore m_semaphore
;
346 wxDECLARE_NO_COPY_CLASS(wxConditionInternal
);
349 wxConditionInternal::wxConditionInternal( wxMutex
& mutex
)
352 // another thread can't access it until we return from ctor, so no need to
353 // protect access to m_numWaiters here
357 wxCondError
wxConditionInternal::Wait()
359 // increment the number of waiters
360 IncrementAtomic( &m_numWaiters
);
364 // a potential race condition can occur here
366 // after a thread increments nwaiters, and unlocks the mutex and before the
367 // semaphore.Wait() is called, if another thread can cause a signal to be
370 // this race condition is handled by using a semaphore and incrementing the
371 // semaphore only if 'nwaiters' is greater that zero since the semaphore,
372 // can 'remember' signals the race condition will not occur
374 // wait ( if necessary ) and decrement semaphore
375 wxSemaError err
= m_semaphore
.Wait();
378 return err
== wxSEMA_NO_ERROR
? wxCOND_NO_ERROR
: wxCOND_MISC_ERROR
;
381 wxCondError
wxConditionInternal::WaitTimeout( unsigned long milliseconds
)
383 IncrementAtomic( &m_numWaiters
);
387 // a race condition can occur at this point in the code
389 // please see the comments in Wait(), for details
391 wxSemaError err
= m_semaphore
.WaitTimeout(milliseconds
);
393 if ( err
== wxSEMA_TIMEOUT
)
395 // another potential race condition exists here it is caused when a
396 // 'waiting' thread timesout, and returns from WaitForSingleObject, but
397 // has not yet decremented 'nwaiters'.
399 // at this point if another thread calls signal() then the semaphore
400 // will be incremented, but the waiting thread will miss it.
402 // to handle this particular case, the waiting thread calls
403 // WaitForSingleObject again with a timeout of 0, after locking
404 // 'nwaiters_mutex'. this call does not block because of the zero
405 // timeout, but will allow the waiting thread to catch the missed
407 wxCriticalSectionLocker
lock(m_csWaiters
);
409 err
= m_semaphore
.WaitTimeout(0);
411 if ( err
!= wxSEMA_NO_ERROR
)
419 return err
== wxSEMA_NO_ERROR
? wxCOND_NO_ERROR
: wxCOND_MISC_ERROR
;
422 wxCondError
wxConditionInternal::Signal()
424 wxCriticalSectionLocker
lock(m_csWaiters
);
426 if ( m_numWaiters
> 0 )
428 // increment the semaphore by 1
429 if ( m_semaphore
.Post() != wxSEMA_NO_ERROR
)
430 return wxCOND_MISC_ERROR
;
435 return wxCOND_NO_ERROR
;
438 wxCondError
wxConditionInternal::Broadcast()
440 wxCriticalSectionLocker
lock(m_csWaiters
);
442 while ( m_numWaiters
> 0 )
444 if ( m_semaphore
.Post() != wxSEMA_NO_ERROR
)
445 return wxCOND_MISC_ERROR
;
450 return wxCOND_NO_ERROR
;
453 // ----------------------------------------------------------------------------
454 // wxCriticalSection implementation
455 // ----------------------------------------------------------------------------
457 // XXX currently implemented as mutex in headers. Change to critical section.
459 // ----------------------------------------------------------------------------
460 // wxThread implementation
461 // ----------------------------------------------------------------------------
463 // wxThreadInternal class
464 // ----------------------
466 class wxThreadInternal
473 m_prio
= WXTHREAD_DEFAULT_PRIORITY
;
474 m_notifyQueueId
= kInvalidID
;
476 m_cancelled
= false ;
478 // set to true only when the thread starts waiting on m_semSuspend
481 // defaults for joinable threads
482 m_shouldBeJoined
= true;
483 m_isDetached
= false;
486 virtual ~wxThreadInternal()
488 if ( m_notifyQueueId
)
490 MPDeleteQueue( m_notifyQueueId
);
491 m_notifyQueueId
= kInvalidID
;
496 static OSStatus
MacThreadStart(void* arg
);
498 // create a new (suspended) thread (for the given thread object)
499 bool Create(wxThread
*thread
, unsigned int stackSize
);
506 // unblock the thread allowing it to run
507 void SignalRun() { m_semRun
.Post(); }
509 // ask the thread to terminate
512 // go to sleep until Resume() is called
520 int GetPriority() const
522 void SetPriority(int prio
);
525 wxThreadState
GetState() const
527 void SetState(wxThreadState state
)
530 // Get the ID of this thread's underlying MP Services task.
531 MPTaskID
GetId() const
535 { m_cancelled
= true; }
537 bool WasCancelled() const
538 { return m_cancelled
; }
541 void SetExitCode(wxThread::ExitCode exitcode
)
542 { m_exitcode
= exitcode
; }
543 wxThread::ExitCode
GetExitCode() const
544 { return m_exitcode
; }
547 void SetReallyPaused(bool paused
)
548 { m_isPaused
= paused
; }
549 bool IsReallyPaused() const
550 { return m_isPaused
; }
552 // tell the thread that it is a detached one
555 wxCriticalSectionLocker
lock(m_csJoinFlag
);
557 m_shouldBeJoined
= false;
562 // the thread we're associated with
565 MPTaskID m_tid
; // thread id
566 MPQueueID m_notifyQueueId
; // its notification queue
568 wxThreadState m_state
; // see wxThreadState enum
569 int m_prio
; // in wxWidgets units: from 0 to 100
571 // this flag is set when the thread should terminate
574 // this flag is set when the thread is blocking on m_semSuspend
577 // the thread exit code - only used for joinable (!detached) threads and
578 // is only valid after the thread termination
579 wxThread::ExitCode m_exitcode
;
581 // many threads may call Wait(), but only one of them should call
582 // pthread_join(), so we have to keep track of this
583 wxCriticalSection m_csJoinFlag
;
584 bool m_shouldBeJoined
;
587 // this semaphore is posted by Run() and the threads Entry() is not
588 // called before it is done
589 wxSemaphore m_semRun
;
591 // this one is signaled when the thread should resume after having been
593 wxSemaphore m_semSuspend
;
596 OSStatus
wxThreadInternal::MacThreadStart(void *parameter
)
598 wxThread
* thread
= (wxThread
*) parameter
;
599 wxThreadInternal
*pthread
= thread
->m_internal
;
601 // add to TLS so that This() will work
602 verify_noerr( MPSetTaskStorageValue( gs_tlsForWXThread
, (TaskStorageValue
) thread
) ) ;
604 // have to declare this before pthread_cleanup_push() which defines a
608 // wait for the semaphore to be posted from Run()
609 pthread
->m_semRun
.Wait();
611 // test whether we should run the run at all - may be it was deleted
612 // before it started to Run()?
614 wxCriticalSectionLocker
lock(thread
->m_critsect
);
616 dontRunAtAll
= pthread
->GetState() == STATE_NEW
&&
617 pthread
->WasCancelled();
622 pthread
->m_exitcode
= thread
->Entry();
625 wxCriticalSectionLocker
lock(thread
->m_critsect
);
626 pthread
->SetState( STATE_EXITED
);
632 if ( pthread
->m_isDetached
)
639 // on Mac for the running code,
640 // the correct thread termination is to return
642 // terminate the thread
643 thread
->Exit( pthread
->m_exitcode
);
645 return (OSStatus
) NULL
; // pthread->m_exitcode;
649 bool wxThreadInternal::Create( wxThread
*thread
, unsigned int stackSize
)
651 wxASSERT_MSG( m_state
== STATE_NEW
&& !m_tid
,
652 wxT("Create()ing thread twice?") );
654 OSStatus err
= noErr
;
657 if ( m_notifyQueueId
== kInvalidID
)
659 OSStatus err
= MPCreateQueue( &m_notifyQueueId
);
662 wxLogSysError( wxT("Cant create the thread event queue") );
671 MacThreadStart
, (void*)m_thread
, stackSize
,
672 m_notifyQueueId
, &m_exitcode
, 0, 0, &m_tid
);
676 wxLogSysError( wxT("Can't create thread") );
681 if ( m_prio
!= WXTHREAD_DEFAULT_PRIORITY
)
682 SetPriority( m_prio
);
687 void wxThreadInternal::SetPriority( int priority
)
693 // Mac priorities range from 1 to 10,000, with a default of 100.
694 // wxWidgets priorities range from 0 to 100 with a default of 50.
695 // We can map wxWidgets to Mac priorities easily by assuming
696 // the former uses a logarithmic scale.
697 const unsigned int macPriority
= (int)( exp( priority
/ 25.0 * log( 10.0)) + 0.5);
699 MPSetTaskWeight( m_tid
, macPriority
);
703 wxThreadError
wxThreadInternal::Run()
705 wxCHECK_MSG( GetState() == STATE_NEW
, wxTHREAD_RUNNING
,
706 wxT("thread may only be started once after Create()") );
708 SetState( STATE_RUNNING
);
710 // wake up threads waiting for our start
713 return wxTHREAD_NO_ERROR
;
716 void wxThreadInternal::Wait()
718 wxCHECK_RET( !m_isDetached
, wxT("can't wait for a detached thread") );
720 // if the thread we're waiting for is waiting for the GUI mutex, we will
721 // deadlock so make sure we release it temporarily
722 if ( wxThread::IsMain() )
724 // give the thread we're waiting for chance to do the GUI call
725 // it might be in, we don't do this conditionally as the to be waited on
726 // thread might have to acquire the mutex later but before terminating
727 if ( wxGuiOwnedByMainThread() )
732 wxCriticalSectionLocker
lock(m_csJoinFlag
);
734 if ( m_shouldBeJoined
)
736 void *param1
, *param2
, *rc
;
738 OSStatus err
= MPWaitOnQueue(
746 wxLogSysError( wxT( "Cannot wait for thread termination."));
750 // actually param1 would be the address of m_exitcode
751 // but we don't need this here
754 m_shouldBeJoined
= false;
759 void wxThreadInternal::Pause()
761 // the state is set from the thread which pauses us first, this function
762 // is called later so the state should have been already set
763 wxCHECK_RET( m_state
== STATE_PAUSED
,
764 wxT("thread must first be paused with wxThread::Pause().") );
766 // wait until the semaphore is Post()ed from Resume()
770 void wxThreadInternal::Resume()
772 wxCHECK_RET( m_state
== STATE_PAUSED
,
773 wxT("can't resume thread which is not suspended.") );
775 // the thread might be not actually paused yet - if there were no call to
776 // TestDestroy() since the last call to Pause() for example
777 if ( IsReallyPaused() )
783 SetReallyPaused( false );
786 SetState( STATE_RUNNING
);
792 wxThread
*wxThread::This()
794 wxThread
* thr
= (wxThread
*) MPGetTaskStorageValue( gs_tlsForWXThread
) ;
799 bool wxThread::IsMain()
801 return GetCurrentId() == gs_idMainThread
|| gs_idMainThread
== kInvalidID
;
808 void wxThread::Yield()
810 CFRunLoopRunInMode( kCFRunLoopDefaultMode
, 0 , true ) ;
815 void wxThread::Sleep( unsigned long milliseconds
)
817 AbsoluteTime wakeup
= AddDurationToAbsolute( milliseconds
, UpTime() );
818 MPDelayUntil( &wakeup
);
821 int wxThread::GetCPUCount()
823 return MPProcessors();
826 unsigned long wxThread::GetCurrentId()
828 return (unsigned long)MPCurrentTaskID();
831 bool wxThread::SetConcurrency( size_t WXUNUSED(level
) )
833 // Cannot be set in MacOS.
837 wxThread::wxThread( wxThreadKind kind
)
840 m_internal
= new wxThreadInternal();
842 m_isDetached
= (kind
== wxTHREAD_DETACHED
);
845 wxThread::~wxThread()
847 wxASSERT_MSG( g_numberOfThreads
>0 , wxT("More threads deleted than created.") ) ;
854 // check that the thread either exited or couldn't be created
855 if ( m_internal
->GetState() != STATE_EXITED
&&
856 m_internal
->GetState() != STATE_NEW
)
859 wxT("The thread %ld is being destroyed although it is still running! The application may crash."),
866 wxDELETE( m_internal
) ;
869 wxThreadError
wxThread::Create( unsigned int stackSize
)
871 wxCriticalSectionLocker
lock(m_critsect
);
874 m_internal
->Detach() ;
876 if ( !m_internal
->Create(this, stackSize
) )
878 m_internal
->SetState( STATE_EXITED
);
880 return wxTHREAD_NO_RESOURCE
;
883 return wxTHREAD_NO_ERROR
;
886 wxThreadError
wxThread::Run()
888 wxCriticalSectionLocker
lock(m_critsect
);
890 wxCHECK_MSG( m_internal
->GetId(), wxTHREAD_MISC_ERROR
,
891 wxT("must call wxThread::Create() first") );
893 return m_internal
->Run();
896 // -----------------------------------------------------------------------------
898 // -----------------------------------------------------------------------------
900 wxThreadError
wxThread::Pause()
902 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
,
903 _T("a thread can't pause itself") );
905 wxCriticalSectionLocker
lock(m_critsect
);
907 if ( m_internal
->GetState() != STATE_RUNNING
)
909 wxLogDebug( wxT("Can't pause thread which is not running.") );
911 return wxTHREAD_NOT_RUNNING
;
914 // just set a flag, the thread will be really paused only during the next
915 // call to TestDestroy()
916 m_internal
->SetState( STATE_PAUSED
);
918 return wxTHREAD_NO_ERROR
;
921 wxThreadError
wxThread::Resume()
923 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
,
924 wxT("a thread can't resume itself") );
926 wxCriticalSectionLocker
lock(m_critsect
);
928 wxThreadState state
= m_internal
->GetState();
933 m_internal
->Resume();
934 return wxTHREAD_NO_ERROR
;
937 return wxTHREAD_NO_ERROR
;
940 wxLogDebug( wxT("Attempt to resume a thread which is not paused.") );
942 return wxTHREAD_MISC_ERROR
;
946 // -----------------------------------------------------------------------------
948 // -----------------------------------------------------------------------------
950 wxThread::ExitCode
wxThread::Wait()
952 wxCHECK_MSG( This() != this, (ExitCode
)-1,
953 wxT("a thread can't wait for itself") );
955 wxCHECK_MSG( !m_isDetached
, (ExitCode
)-1,
956 wxT("can't wait for detached thread") );
960 return m_internal
->GetExitCode();
963 wxThreadError
wxThread::Delete(ExitCode
*rc
)
965 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
,
966 wxT("a thread can't delete itself") );
968 bool isDetached
= m_isDetached
;
971 wxThreadState state
= m_internal
->GetState();
973 // ask the thread to stop
974 m_internal
->SetCancelFlag();
981 // we need to wake up the thread so that PthreadStart() will
982 // terminate - right now it's blocking on run semaphore in
984 m_internal
->SignalRun();
993 // resume the thread first
994 m_internal
->Resume();
1001 // wait until the thread stops
1006 // return the exit code of the thread
1007 *rc
= m_internal
->GetExitCode();
1012 return wxTHREAD_NO_ERROR
;
1015 wxThreadError
wxThread::Kill()
1017 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
,
1018 wxT("a thread can't kill itself") );
1020 switch ( m_internal
->GetState() )
1024 return wxTHREAD_NOT_RUNNING
;
1027 // resume the thread first
1033 OSStatus err
= MPTerminateTask( m_internal
->GetId() , -1 ) ;
1036 wxLogError( wxT("Failed to terminate a thread.") );
1038 return wxTHREAD_MISC_ERROR
;
1047 // this should be retrieved by Wait actually
1048 m_internal
->SetExitCode( (void*)-1 );
1051 return wxTHREAD_NO_ERROR
;
1055 void wxThread::Exit( ExitCode status
)
1057 wxASSERT_MSG( This() == this,
1058 wxT("wxThread::Exit() can only be called in the context of the same thread") );
1060 // don't enter m_critsect before calling OnExit() because the user code
1061 // might deadlock if, for example, it signals a condition in OnExit() (a
1062 // common case) while the main thread calls any of functions entering
1063 // m_critsect on us (almost all of them do)
1066 MPTaskID threadid
= m_internal
->GetId();
1074 // update the status of the joinable thread
1075 wxCriticalSectionLocker
lock( m_critsect
);
1076 m_internal
->SetState( STATE_EXITED
);
1079 MPTerminateTask( threadid
, (long)status
);
1082 // also test whether we were paused
1083 bool wxThread::TestDestroy()
1085 wxASSERT_MSG( This() == this,
1086 wxT("wxThread::TestDestroy() can only be called in the context of the same thread") );
1090 if ( m_internal
->GetState() == STATE_PAUSED
)
1092 m_internal
->SetReallyPaused( true );
1094 // leave the crit section or the other threads will stop too if they attempt
1095 // to call any of (seemingly harmless) IsXXX() functions while we sleep
1098 m_internal
->Pause();
1102 // thread wasn't requested to pause, nothing to do
1106 return m_internal
->WasCancelled();
1109 // -----------------------------------------------------------------------------
1111 // -----------------------------------------------------------------------------
1113 void wxThread::SetPriority(unsigned int prio
)
1115 wxCHECK_RET( ((int)WXTHREAD_MIN_PRIORITY
<= (int)prio
) &&
1116 ((int)prio
<= (int)WXTHREAD_MAX_PRIORITY
),
1117 wxT("invalid thread priority") );
1119 wxCriticalSectionLocker
lock(m_critsect
);
1121 switch ( m_internal
->GetState() )
1126 // thread not yet started, priority will be set when it is
1127 m_internal
->SetPriority( prio
);
1132 wxFAIL_MSG( wxT("impossible to set thread priority in this state") );
1136 unsigned int wxThread::GetPriority() const
1138 wxCriticalSectionLocker
lock((wxCriticalSection
&)m_critsect
); // const_cast
1140 return m_internal
->GetPriority();
1143 unsigned long wxThread::GetId() const
1145 wxCriticalSectionLocker
lock((wxCriticalSection
&)m_critsect
); // const_cast
1147 return (unsigned long)m_internal
->GetId();
1150 // -----------------------------------------------------------------------------
1152 // -----------------------------------------------------------------------------
1154 bool wxThread::IsRunning() const
1156 wxCriticalSectionLocker
lock((wxCriticalSection
&)m_critsect
);
1158 return m_internal
->GetState() == STATE_RUNNING
;
1161 bool wxThread::IsAlive() const
1163 wxCriticalSectionLocker
lock((wxCriticalSection
&)m_critsect
);
1165 switch ( m_internal
->GetState() )
1176 bool wxThread::IsPaused() const
1178 wxCriticalSectionLocker
lock((wxCriticalSection
&)m_critsect
);
1180 return (m_internal
->GetState() == STATE_PAUSED
);
1183 // ----------------------------------------------------------------------------
1184 // Automatic initialization for thread module
1185 // ----------------------------------------------------------------------------
1187 class wxThreadModule
: public wxModule
1190 virtual bool OnInit();
1191 virtual void OnExit();
1194 DECLARE_DYNAMIC_CLASS(wxThreadModule
)
1197 IMPLEMENT_DYNAMIC_CLASS(wxThreadModule
, wxModule
)
1199 bool wxThreadModule::OnInit()
1201 bool hasThreadManager
=
1203 true ; // TODO VERIFY IN NEXT BUILD
1205 MPLibraryIsLoaded();
1208 if ( !hasThreadManager
)
1210 wxLogError( wxT("MP thread support is not available on this system" ) ) ;
1215 // main thread's This() is NULL
1216 verify_noerr( MPAllocateTaskStorageIndex( &gs_tlsForWXThread
) ) ;
1217 verify_noerr( MPSetTaskStorageValue( gs_tlsForWXThread
, 0 ) ) ;
1219 gs_idMainThread
= wxThread::GetCurrentId();
1220 gs_critsectWaitingForGui
= new wxCriticalSection();
1222 gs_critsectGui
= new wxCriticalSection();
1223 gs_critsectGui
->Enter();
1228 void wxThreadModule::OnExit()
1230 if ( gs_critsectGui
)
1232 if ( !wxGuiOwnedByMainThread() )
1234 gs_critsectGui
->Enter();
1235 gs_bGuiOwnedByMainThread
= true;
1238 gs_critsectGui
->Leave();
1239 delete gs_critsectGui
;
1240 gs_critsectGui
= NULL
;
1243 delete gs_critsectWaitingForGui
;
1244 gs_critsectWaitingForGui
= NULL
;
1247 // ----------------------------------------------------------------------------
1248 // GUI Serialization copied from MSW implementation
1249 // ----------------------------------------------------------------------------
1251 void wxMutexGuiEnterImpl()
1253 // this would dead lock everything...
1254 wxASSERT_MSG( !wxThread::IsMain(),
1255 wxT("main thread doesn't want to block in wxMutexGuiEnter()!") );
1257 // the order in which we enter the critical sections here is crucial!!
1259 // set the flag telling to the main thread that we want to do some GUI
1261 wxCriticalSectionLocker
enter(*gs_critsectWaitingForGui
);
1263 gs_nWaitingForGui
++;
1266 wxWakeUpMainThread();
1268 // now we may block here because the main thread will soon let us in
1269 // (during the next iteration of OnIdle())
1270 gs_critsectGui
->Enter();
1273 void wxMutexGuiLeaveImpl()
1275 wxCriticalSectionLocker
enter(*gs_critsectWaitingForGui
);
1277 if ( wxThread::IsMain() )
1279 gs_bGuiOwnedByMainThread
= false;
1283 // decrement the number of threads waiting for GUI access now
1284 wxASSERT_MSG( gs_nWaitingForGui
> 0,
1285 wxT("calling wxMutexGuiLeave() without entering it first?") );
1287 gs_nWaitingForGui
--;
1289 wxWakeUpMainThread();
1292 gs_critsectGui
->Leave();
1295 void WXDLLIMPEXP_BASE
wxMutexGuiLeaveOrEnter()
1297 wxASSERT_MSG( wxThread::IsMain(),
1298 wxT("only main thread may call wxMutexGuiLeaveOrEnter()!") );
1300 if ( !gs_critsectWaitingForGui
)
1303 wxCriticalSectionLocker
enter(*gs_critsectWaitingForGui
);
1305 if ( gs_nWaitingForGui
== 0 )
1307 // no threads are waiting for GUI - so we may acquire the lock without
1308 // any danger (but only if we don't already have it)
1309 if ( !wxGuiOwnedByMainThread() )
1311 gs_critsectGui
->Enter();
1313 gs_bGuiOwnedByMainThread
= true;
1315 //else: already have it, nothing to do
1319 // some threads are waiting, release the GUI lock if we have it
1320 if ( wxGuiOwnedByMainThread() )
1322 //else: some other worker thread is doing GUI
1326 bool WXDLLIMPEXP_BASE
wxGuiOwnedByMainThread()
1328 return gs_bGuiOwnedByMainThread
;
1331 // wake up the main thread
1332 void WXDLLEXPORT
wxWakeUpMainThread()
1337 // ----------------------------------------------------------------------------
1338 // include common implementation code
1339 // ----------------------------------------------------------------------------
1341 #include "wx/thrimpl.cpp"
1343 #endif // wxUSE_THREADS