1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/mac/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"
30 #include <CoreServices/CoreServices.h>
32 #include <DriverServices.h>
33 #include <Multiprocessing.h>
36 #include "wx/mac/uma.h"
39 // the possible states of the thread:
40 // ("=>" shows all possible transitions from this state)
43 STATE_NEW
, // didn't start execution yet (=> RUNNING)
44 STATE_RUNNING
, // thread is running (=> PAUSED, CANCELED)
45 STATE_PAUSED
, // thread is temporarily suspended (=> RUNNING)
46 STATE_CANCELED
, // thread should terminate a.s.a.p. (=> EXITED)
47 STATE_EXITED
// thread is terminating
50 // ----------------------------------------------------------------------------
52 // ----------------------------------------------------------------------------
54 // the task ID of the main thread
55 static wxThreadIdType gs_idMainThread
= kInvalidID
;
57 // this is the Per-Task Storage for the pointer to the appropriate wxThread
58 TaskStorageIndex gs_tlsForWXThread
= 0;
60 // if it's false, some secondary thread is holding the GUI lock
61 static bool gs_bGuiOwnedByMainThread
= true;
63 // critical section which controls access to all GUI functions: any secondary
64 // thread (i.e. except the main one) must enter this crit section before doing
66 static wxCriticalSection
*gs_critsectGui
= NULL
;
68 // critical section which protects gs_nWaitingForGui variable
69 static wxCriticalSection
*gs_critsectWaitingForGui
= NULL
;
71 // number of threads waiting for GUI in wxMutexGuiEnter()
72 static size_t gs_nWaitingForGui
= 0;
74 // overall number of threads, needed for determining
75 // the sleep value of the main event loop
76 size_t g_numberOfThreads
= 0;
80 MPCriticalRegionID gs_guiCritical
= kInvalidID
;
83 // ============================================================================
84 // MacOS implementation of thread classes
85 // ============================================================================
90 The implementation is very close to the phtreads implementation, the reason for
91 using MPServices is the fact that these are also available under OS 9. Thus allowing
92 for one common API for all current builds.
94 As soon as wxThreads are on a 64 bit address space, the TLS must be extended
95 to use two indices one for each 32 bit part as the MP implementation is limited
98 I have three implementations for mutexes :
99 version A based on a binary semaphore, problem - not reentrant, version B based
100 on a critical region, allows for reentrancy, performance implications not
101 yet tested, and third a plain pthreads implementation
103 The same for condition internal, one implementation by Aj Lavin and the other one
104 copied from the thrimpl.cpp which I assume has been more broadly tested, I've just
105 replaced the interlock increment with the appropriate PPC calls
108 // ----------------------------------------------------------------------------
110 // ----------------------------------------------------------------------------
112 wxCriticalSection::wxCriticalSection()
114 MPCreateCriticalRegion( (MPCriticalRegionID
*) &m_critRegion
);
117 wxCriticalSection::~wxCriticalSection()
119 MPDeleteCriticalRegion( (MPCriticalRegionID
) m_critRegion
);
122 void wxCriticalSection::Enter()
124 MPEnterCriticalRegion( (MPCriticalRegionID
) m_critRegion
, kDurationForever
);
127 void wxCriticalSection::Leave()
129 MPExitCriticalRegion( (MPCriticalRegionID
) m_critRegion
);
132 // ----------------------------------------------------------------------------
133 // wxMutex implementation
134 // ----------------------------------------------------------------------------
136 #if TARGET_API_MAC_OSX
137 #define wxUSE_MAC_SEMAPHORE_MUTEX 0
138 #define wxUSE_MAC_CRITICAL_REGION_MUTEX 1
139 #define wxUSE_MAC_PTHREADS_MUTEX 0
141 #define wxUSE_MAC_SEMAPHORE_MUTEX 0
142 #define wxUSE_MAC_CRITICAL_REGION_MUTEX 1
143 #define wxUSE_MAC_PTHREADS_MUTEX 0
146 #if wxUSE_MAC_PTHREADS_MUTEX
151 class wxMutexInternal
154 wxMutexInternal( wxMutexType mutexType
);
158 wxMutexError
TryLock();
159 wxMutexError
Unlock();
165 pthread_mutex_t m_mutex
;
168 // wxConditionInternal uses our m_mutex
169 friend class wxConditionInternal
;
172 #ifdef HAVE_PTHREAD_MUTEXATTR_T
173 // on some systems pthread_mutexattr_settype() is not in the headers (but it is
174 // in the library, otherwise we wouldn't compile this code at all)
175 extern "C" int pthread_mutexattr_settype( pthread_mutexattr_t
*, int );
178 wxMutexInternal::wxMutexInternal( wxMutexType mutexType
)
183 case wxMUTEX_RECURSIVE
:
184 // support recursive locks like Win32, i.e. a thread can lock a
185 // mutex which it had itself already locked
187 // unfortunately initialization of recursive mutexes is non
188 // portable, so try several methods
189 #ifdef HAVE_PTHREAD_MUTEXATTR_T
191 pthread_mutexattr_t attr
;
192 pthread_mutexattr_init( &attr
);
193 pthread_mutexattr_settype( &attr
, PTHREAD_MUTEX_RECURSIVE
);
195 err
= pthread_mutex_init( &m_mutex
, &attr
);
197 #elif defined(HAVE_PTHREAD_RECURSIVE_MUTEX_INITIALIZER)
198 // we can use this only as initializer so we have to assign it
199 // first to a temp var - assigning directly to m_mutex wouldn't
202 pthread_mutex_t mutex
= PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
;
205 #else // no recursive mutexes
207 #endif // HAVE_PTHREAD_MUTEXATTR_T/...
211 wxFAIL_MSG( wxT("unknown mutex type") );
214 case wxMUTEX_DEFAULT
:
215 err
= pthread_mutex_init( &m_mutex
, NULL
);
222 wxLogApiError( wxT("pthread_mutex_init()"), err
);
226 wxMutexInternal::~wxMutexInternal()
230 int err
= pthread_mutex_destroy( &m_mutex
);
233 wxLogApiError( wxT("pthread_mutex_destroy()"), err
);
238 wxMutexError
wxMutexInternal::Lock()
240 int err
= pthread_mutex_lock( &m_mutex
);
244 // only error checking mutexes return this value and so it's an
245 // unexpected situation -- hence use assert, not wxLogDebug
246 wxFAIL_MSG( wxT("mutex deadlock prevented") );
247 return wxMUTEX_DEAD_LOCK
;
250 wxLogDebug( wxT("pthread_mutex_lock(): mutex not initialized.") );
254 return wxMUTEX_NO_ERROR
;
257 wxLogApiError( wxT("pthread_mutex_lock()"), err
);
260 return wxMUTEX_MISC_ERROR
;
263 wxMutexError
wxMutexInternal::TryLock()
265 int err
= pthread_mutex_trylock( &m_mutex
);
269 // not an error: mutex is already locked, but we're prepared for this case
273 wxLogDebug( wxT("pthread_mutex_trylock(): mutex not initialized.") );
277 return wxMUTEX_NO_ERROR
;
280 wxLogApiError( wxT("pthread_mutex_trylock()"), err
);
283 return wxMUTEX_MISC_ERROR
;
286 wxMutexError
wxMutexInternal::Unlock()
288 int err
= pthread_mutex_unlock( &m_mutex
);
292 // we don't own the mutex
293 return wxMUTEX_UNLOCKED
;
296 wxLogDebug( wxT("pthread_mutex_unlock(): mutex not initialized.") );
300 return wxMUTEX_NO_ERROR
;
303 wxLogApiError( wxT("pthread_mutex_unlock()"), err
);
306 return wxMUTEX_MISC_ERROR
;
311 #if wxUSE_MAC_SEMAPHORE_MUTEX
313 class wxMutexInternal
316 wxMutexInternal( wxMutexType mutexType
);
317 virtual ~wxMutexInternal();
323 wxMutexError
TryLock();
324 wxMutexError
Unlock();
327 MPSemaphoreID m_semaphore
;
331 wxMutexInternal::wxMutexInternal(wxMutexType mutexType
)
334 m_semaphore
= kInvalidID
;
335 OSStatus err
= noErr
;
339 case wxMUTEX_DEFAULT
:
340 verify_noerr( MPCreateBinarySemaphore( &m_semaphore
) );
341 m_isOk
= ( m_semaphore
!= kInvalidID
);
344 case wxMUTEX_RECURSIVE
:
345 wxFAIL_MSG( wxT("Recursive Mutex not supported yet") );
349 wxFAIL_MSG( wxT("Unknown mutex type") );
354 wxMutexInternal::~wxMutexInternal()
356 if ( m_semaphore
!= kInvalidID
)
357 MPDeleteSemaphore( m_semaphore
);
362 wxMutexError
wxMutexInternal::Lock()
364 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") );
365 OSStatus err
= MPWaitOnSemaphore( m_semaphore
, kDurationForever
);
368 wxLogSysError( wxT("Could not lock mutex") );
370 return wxMUTEX_MISC_ERROR
;
373 return wxMUTEX_NO_ERROR
;
376 wxMutexError
wxMutexInternal::TryLock()
378 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") );
379 OSStatus err
= MPWaitOnSemaphore( m_semaphore
, kDurationImmediate
);
382 if (err
== kMPTimeoutErr
)
385 wxLogSysError( wxT("Could not try lock mutex") );
387 return wxMUTEX_MISC_ERROR
;
390 return wxMUTEX_NO_ERROR
;
393 wxMutexError
wxMutexInternal::Unlock()
395 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") );
396 OSStatus err
= MPSignalSemaphore( m_semaphore
);
401 wxLogSysError( wxT("Could not unlock mutex") );
402 return wxMUTEX_MISC_ERROR
;
405 return wxMUTEX_NO_ERROR
;
410 #if wxUSE_MAC_CRITICAL_REGION_MUTEX
412 class wxMutexInternal
415 wxMutexInternal( wxMutexType mutexType
);
416 virtual ~wxMutexInternal();
418 bool IsOk() const { return m_isOk
; }
420 wxMutexError
Lock() { return Lock(kDurationForever
); }
421 wxMutexError
Lock(unsigned long ms
);
422 wxMutexError
TryLock();
423 wxMutexError
Unlock();
426 MPCriticalRegionID m_critRegion
;
430 wxMutexInternal::wxMutexInternal( wxMutexType
WXUNUSED(mutexType
) )
433 m_critRegion
= kInvalidID
;
435 verify_noerr( MPCreateCriticalRegion( &m_critRegion
) );
436 m_isOk
= ( m_critRegion
!= kInvalidID
);
439 wxFAIL_MSG( wxT("Error when creating mutex") );
443 wxMutexInternal::~wxMutexInternal()
445 if ( m_critRegion
!= kInvalidID
)
446 MPDeleteCriticalRegion( m_critRegion
);
451 wxMutexError
wxMutexInternal::Lock(unsigned long ms
)
453 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") );
455 OSStatus err
= MPEnterCriticalRegion( m_critRegion
, ms
);
462 wxASSERT_MSG( ms
!= kDurationForever
, wxT("unexpected timeout") );
463 return wxMUTEX_TIMEOUT
;
466 wxLogSysError(wxT("Could not lock mutex"));
467 return wxMUTEX_MISC_ERROR
;
470 return wxMUTEX_NO_ERROR
;
473 wxMutexError
wxMutexInternal::TryLock()
475 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") ) ;
477 OSStatus err
= MPEnterCriticalRegion( m_critRegion
, kDurationImmediate
);
480 if ( err
== kMPTimeoutErr
)
483 wxLogSysError( wxT("Could not try lock mutex") );
484 return wxMUTEX_MISC_ERROR
;
487 return wxMUTEX_NO_ERROR
;
490 wxMutexError
wxMutexInternal::Unlock()
492 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") ) ;
494 OSStatus err
= MPExitCriticalRegion( m_critRegion
);
499 wxLogSysError( wxT("Could not unlock mutex") );
501 return wxMUTEX_MISC_ERROR
;
504 return wxMUTEX_NO_ERROR
;
509 // --------------------------------------------------------------------------
511 // --------------------------------------------------------------------------
513 class wxSemaphoreInternal
516 wxSemaphoreInternal( int initialcount
, int maxcount
);
517 virtual ~wxSemaphoreInternal();
523 wxSemaError
WaitTimeout( unsigned long milliseconds
);
526 { return WaitTimeout( kDurationForever
); }
528 wxSemaError
TryWait()
530 wxSemaError err
= WaitTimeout( kDurationImmediate
);
531 if (err
== wxSEMA_TIMEOUT
)
538 MPSemaphoreID m_semaphore
;
542 wxSemaphoreInternal::wxSemaphoreInternal( int initialcount
, int maxcount
)
545 m_semaphore
= kInvalidID
;
547 // make it practically infinite
550 verify_noerr( MPCreateSemaphore( maxcount
, initialcount
, &m_semaphore
) );
551 m_isOk
= ( m_semaphore
!= kInvalidID
);
555 wxFAIL_MSG( wxT("Error when creating semaphore") );
559 wxSemaphoreInternal::~wxSemaphoreInternal()
561 if (m_semaphore
!= kInvalidID
)
562 MPDeleteSemaphore( m_semaphore
);
567 wxSemaError
wxSemaphoreInternal::WaitTimeout( unsigned long milliseconds
)
569 OSStatus err
= MPWaitOnSemaphore( m_semaphore
, milliseconds
);
572 if (err
== kMPTimeoutErr
)
573 return wxSEMA_TIMEOUT
;
575 return wxSEMA_MISC_ERROR
;
578 return wxSEMA_NO_ERROR
;
581 wxSemaError
wxSemaphoreInternal::Post()
583 OSStatus err
= MPSignalSemaphore( m_semaphore
);
586 return wxSEMA_MISC_ERROR
;
588 return wxSEMA_NO_ERROR
;
591 // ----------------------------------------------------------------------------
592 // wxCondition implementation
593 // ----------------------------------------------------------------------------
597 class wxConditionInternal
600 wxConditionInternal( wxMutex
& mutex
)
611 virtual ~wxConditionInternal() {}
614 { return m_mutex
.IsOk(); }
617 { return WaitTimeout( kDurationForever
); }
619 wxCondError
WaitTimeout( unsigned long msectimeout
);
622 { return DoSignal( false); }
624 wxCondError
Broadcast()
625 { return DoSignal( true ); }
628 wxCondError
DoSignal( bool signalAll
);
631 wxSemaphoreInternal m_semaphore
; // Signals the waiting threads.
632 wxSemaphoreInternal m_gate
;
633 wxCriticalSection m_varSection
;
634 size_t m_waiters
; // Number of threads waiting for a signal.
635 size_t m_signals
; // Number of signals to send.
636 size_t m_canceled
; // Number of canceled waiters in m_waiters.
639 wxCondError
wxConditionInternal::WaitTimeout( unsigned long msectimeout
)
643 if ( ++ m_waiters
== INT_MAX
)
645 m_varSection
.Enter();
647 m_waiters
-= m_canceled
;
648 m_signals
-= m_canceled
;
651 m_varSection
.Leave();
657 wxSemaError err
= m_semaphore
.WaitTimeout( msectimeout
);
658 wxASSERT( err
== wxSEMA_NO_ERROR
|| err
== wxSEMA_TIMEOUT
);
660 m_varSection
.Enter();
662 if ( err
!= wxSEMA_NO_ERROR
)
664 if ( m_signals
> m_canceled
)
666 // A signal is being sent after we timed out.
667 if ( m_waiters
== m_signals
)
669 // There are no excess waiters to catch the signal, so
670 // we must throw it away.
671 wxSemaError err2
= m_semaphore
.Wait();
672 if ( err2
!= wxSEMA_NO_ERROR
)
674 wxLogSysError( wx("Error while waiting on semaphore") );
677 wxASSERT( err2
== wxSEMA_NO_ERROR
);
680 if ( --m_signals
== m_canceled
)
682 // This was the last signal. open the gate.
683 wxASSERT( m_waiters
== m_canceled
);
689 // There are excess waiters to catch the signal, leave it be.
695 // No signals is being sent:
696 // the gate may be open or closed, so we can't touch m_waiters.
703 // We caught a signal.
704 wxASSERT( m_signals
> m_canceled
);
708 if ( --m_signals
== m_canceled
)
710 // This was the last signal. open the gate.
711 wxASSERT( m_waiters
== m_canceled
);
717 m_varSection
.Leave();
721 return err
== wxSEMA_TIMEOUT
? wxCOND_TIMEOUT
: wxCOND_MISC_ERROR
;
723 return wxCOND_NO_ERROR
;
727 wxCondError
wxConditionInternal::DoSignal( bool signalAll
)
730 m_varSection
.Enter();
732 wxASSERT( m_signals
== m_canceled
);
734 if ( m_waiters
== m_canceled
)
736 m_varSection
.Leave();
738 return wxCOND_NO_ERROR
;
743 m_waiters
-= m_canceled
;
748 m_signals
= signalAll
? m_waiters
: 1;
749 size_t n
= m_signals
;
751 m_varSection
.Leave();
753 // Let the waiters inherit the gate lock.
757 wxSemaError err
= m_semaphore
.Post();
758 wxASSERT( err
== wxSEMA_NO_ERROR
);
762 return wxCOND_NO_ERROR
;
766 class wxConditionInternal
769 wxConditionInternal( wxMutex
& mutex
);
772 { return m_mutex
.IsOk() && m_semaphore
.IsOk(); }
775 wxCondError
WaitTimeout( unsigned long milliseconds
);
777 wxCondError
Signal();
778 wxCondError
Broadcast();
781 // the number of threads currently waiting for this condition
784 // the critical section protecting m_numWaiters
785 wxCriticalSection m_csWaiters
;
788 wxSemaphore m_semaphore
;
790 DECLARE_NO_COPY_CLASS(wxConditionInternal
)
793 wxConditionInternal::wxConditionInternal( wxMutex
& mutex
)
796 // another thread can't access it until we return from ctor, so no need to
797 // protect access to m_numWaiters here
801 wxCondError
wxConditionInternal::Wait()
803 // increment the number of waiters
804 IncrementAtomic( &m_numWaiters
);
808 // a potential race condition can occur here
810 // after a thread increments nwaiters, and unlocks the mutex and before the
811 // semaphore.Wait() is called, if another thread can cause a signal to be
814 // this race condition is handled by using a semaphore and incrementing the
815 // semaphore only if 'nwaiters' is greater that zero since the semaphore,
816 // can 'remember' signals the race condition will not occur
818 // wait ( if necessary ) and decrement semaphore
819 wxSemaError err
= m_semaphore
.Wait();
822 return err
== wxSEMA_NO_ERROR
? wxCOND_NO_ERROR
: wxCOND_MISC_ERROR
;
825 wxCondError
wxConditionInternal::WaitTimeout( unsigned long milliseconds
)
827 IncrementAtomic( &m_numWaiters
);
831 // a race condition can occur at this point in the code
833 // please see the comments in Wait(), for details
835 wxSemaError err
= m_semaphore
.WaitTimeout(milliseconds
);
837 if ( err
== wxSEMA_TIMEOUT
)
839 // another potential race condition exists here it is caused when a
840 // 'waiting' thread timesout, and returns from WaitForSingleObject, but
841 // has not yet decremented 'nwaiters'.
843 // at this point if another thread calls signal() then the semaphore
844 // will be incremented, but the waiting thread will miss it.
846 // to handle this particular case, the waiting thread calls
847 // WaitForSingleObject again with a timeout of 0, after locking
848 // 'nwaiters_mutex'. this call does not block because of the zero
849 // timeout, but will allow the waiting thread to catch the missed
851 wxCriticalSectionLocker
lock(m_csWaiters
);
853 err
= m_semaphore
.WaitTimeout(0);
855 if ( err
!= wxSEMA_NO_ERROR
)
863 return err
== wxSEMA_NO_ERROR
? wxCOND_NO_ERROR
: wxCOND_MISC_ERROR
;
866 wxCondError
wxConditionInternal::Signal()
868 wxCriticalSectionLocker
lock(m_csWaiters
);
870 if ( m_numWaiters
> 0 )
872 // increment the semaphore by 1
873 if ( m_semaphore
.Post() != wxSEMA_NO_ERROR
)
874 return wxCOND_MISC_ERROR
;
879 return wxCOND_NO_ERROR
;
882 wxCondError
wxConditionInternal::Broadcast()
884 wxCriticalSectionLocker
lock(m_csWaiters
);
886 while ( m_numWaiters
> 0 )
888 if ( m_semaphore
.Post() != wxSEMA_NO_ERROR
)
889 return wxCOND_MISC_ERROR
;
894 return wxCOND_NO_ERROR
;
898 // ----------------------------------------------------------------------------
899 // wxCriticalSection implementation
900 // ----------------------------------------------------------------------------
902 // XXX currently implemented as mutex in headers. Change to critical section.
904 // ----------------------------------------------------------------------------
905 // wxThread implementation
906 // ----------------------------------------------------------------------------
908 // wxThreadInternal class
909 // ----------------------
911 class wxThreadInternal
918 m_prio
= WXTHREAD_DEFAULT_PRIORITY
;
919 m_notifyQueueId
= kInvalidID
;
921 m_cancelled
= false ;
923 // set to true only when the thread starts waiting on m_semSuspend
926 // defaults for joinable threads
927 m_shouldBeJoined
= true;
928 m_isDetached
= false;
931 virtual ~wxThreadInternal()
933 if ( m_notifyQueueId
)
935 MPDeleteQueue( m_notifyQueueId
);
936 m_notifyQueueId
= kInvalidID
;
941 static OSStatus
MacThreadStart(void* arg
);
943 // create a new (suspended) thread (for the given thread object)
944 bool Create(wxThread
*thread
, unsigned int stackSize
);
951 // unblock the thread allowing it to run
952 void SignalRun() { m_semRun
.Post(); }
954 // ask the thread to terminate
957 // go to sleep until Resume() is called
965 int GetPriority() const
967 void SetPriority(int prio
);
970 wxThreadState
GetState() const
972 void SetState(wxThreadState state
)
975 // Get the ID of this thread's underlying MP Services task.
976 MPTaskID
GetId() const
980 { m_cancelled
= true; }
982 bool WasCancelled() const
983 { return m_cancelled
; }
986 void SetExitCode(wxThread::ExitCode exitcode
)
987 { m_exitcode
= exitcode
; }
988 wxThread::ExitCode
GetExitCode() const
989 { return m_exitcode
; }
992 void SetReallyPaused(bool paused
)
993 { m_isPaused
= paused
; }
994 bool IsReallyPaused() const
995 { return m_isPaused
; }
997 // tell the thread that it is a detached one
1000 wxCriticalSectionLocker
lock(m_csJoinFlag
);
1002 m_shouldBeJoined
= false;
1003 m_isDetached
= true;
1007 // the thread we're associated with
1008 wxThread
* m_thread
;
1010 MPTaskID m_tid
; // thread id
1011 MPQueueID m_notifyQueueId
; // its notification queue
1013 wxThreadState m_state
; // see wxThreadState enum
1014 int m_prio
; // in wxWidgets units: from 0 to 100
1016 // this flag is set when the thread should terminate
1019 // this flag is set when the thread is blocking on m_semSuspend
1022 // the thread exit code - only used for joinable (!detached) threads and
1023 // is only valid after the thread termination
1024 wxThread::ExitCode m_exitcode
;
1026 // many threads may call Wait(), but only one of them should call
1027 // pthread_join(), so we have to keep track of this
1028 wxCriticalSection m_csJoinFlag
;
1029 bool m_shouldBeJoined
;
1032 // this semaphore is posted by Run() and the threads Entry() is not
1033 // called before it is done
1034 wxSemaphore m_semRun
;
1036 // this one is signaled when the thread should resume after having been
1038 wxSemaphore m_semSuspend
;
1041 OSStatus
wxThreadInternal::MacThreadStart(void *parameter
)
1043 wxThread
* thread
= (wxThread
*) parameter
;
1044 wxThreadInternal
*pthread
= thread
->m_internal
;
1046 // add to TLS so that This() will work
1047 verify_noerr( MPSetTaskStorageValue( gs_tlsForWXThread
, (TaskStorageValue
) thread
) ) ;
1049 // have to declare this before pthread_cleanup_push() which defines a
1053 // wait for the semaphore to be posted from Run()
1054 pthread
->m_semRun
.Wait();
1056 // test whether we should run the run at all - may be it was deleted
1057 // before it started to Run()?
1059 wxCriticalSectionLocker
lock(thread
->m_critsect
);
1061 dontRunAtAll
= pthread
->GetState() == STATE_NEW
&&
1062 pthread
->WasCancelled();
1065 if ( !dontRunAtAll
)
1067 pthread
->m_exitcode
= thread
->Entry();
1070 wxCriticalSectionLocker
lock(thread
->m_critsect
);
1071 pthread
->SetState( STATE_EXITED
);
1077 if ( pthread
->m_isDetached
)
1084 // on Mac for the running code,
1085 // the correct thread termination is to return
1087 // terminate the thread
1088 thread
->Exit( pthread
->m_exitcode
);
1090 return (OSStatus
) NULL
; // pthread->m_exitcode;
1094 bool wxThreadInternal::Create( wxThread
*thread
, unsigned int stackSize
)
1096 wxASSERT_MSG( m_state
== STATE_NEW
&& !m_tid
,
1097 wxT("Create()ing thread twice?") );
1099 OSStatus err
= noErr
;
1102 if ( m_notifyQueueId
== kInvalidID
)
1104 OSStatus err
= MPCreateQueue( &m_notifyQueueId
);
1107 wxLogSysError( wxT("Cant create the thread event queue") );
1113 m_state
= STATE_NEW
;
1116 MacThreadStart
, (void*)m_thread
, stackSize
,
1117 m_notifyQueueId
, &m_exitcode
, 0, 0, &m_tid
);
1121 wxLogSysError( wxT("Can't create thread") );
1126 if ( m_prio
!= WXTHREAD_DEFAULT_PRIORITY
)
1127 SetPriority( m_prio
);
1132 void wxThreadInternal::SetPriority( int priority
)
1138 // Mac priorities range from 1 to 10,000, with a default of 100.
1139 // wxWidgets priorities range from 0 to 100 with a default of 50.
1140 // We can map wxWidgets to Mac priorities easily by assuming
1141 // the former uses a logarithmic scale.
1142 const unsigned int macPriority
= (int)( exp( priority
/ 25.0 * log( 10.0)) + 0.5);
1144 MPSetTaskWeight( m_tid
, macPriority
);
1148 wxThreadError
wxThreadInternal::Run()
1150 wxCHECK_MSG( GetState() == STATE_NEW
, wxTHREAD_RUNNING
,
1151 wxT("thread may only be started once after Create()") );
1153 SetState( STATE_RUNNING
);
1155 // wake up threads waiting for our start
1158 return wxTHREAD_NO_ERROR
;
1161 void wxThreadInternal::Wait()
1163 wxCHECK_RET( !m_isDetached
, wxT("can't wait for a detached thread") );
1165 // if the thread we're waiting for is waiting for the GUI mutex, we will
1166 // deadlock so make sure we release it temporarily
1167 if ( wxThread::IsMain() )
1169 // give the thread we're waiting for chance to do the GUI call
1170 // it might be in, we don't do this conditionally as the to be waited on
1171 // thread might have to acquire the mutex later but before terminating
1172 if ( wxGuiOwnedByMainThread() )
1177 wxCriticalSectionLocker
lock(m_csJoinFlag
);
1179 if ( m_shouldBeJoined
)
1181 void *param1
, *param2
, *rc
;
1183 OSStatus err
= MPWaitOnQueue(
1191 wxLogSysError( wxT( "Cannot wait for thread termination."));
1195 // actually param1 would be the address of m_exitcode
1196 // but we don't need this here
1199 m_shouldBeJoined
= false;
1204 void wxThreadInternal::Pause()
1206 // the state is set from the thread which pauses us first, this function
1207 // is called later so the state should have been already set
1208 wxCHECK_RET( m_state
== STATE_PAUSED
,
1209 wxT("thread must first be paused with wxThread::Pause().") );
1211 // wait until the semaphore is Post()ed from Resume()
1212 m_semSuspend
.Wait();
1215 void wxThreadInternal::Resume()
1217 wxCHECK_RET( m_state
== STATE_PAUSED
,
1218 wxT("can't resume thread which is not suspended.") );
1220 // the thread might be not actually paused yet - if there were no call to
1221 // TestDestroy() since the last call to Pause() for example
1222 if ( IsReallyPaused() )
1225 m_semSuspend
.Post();
1228 SetReallyPaused( false );
1231 SetState( STATE_RUNNING
);
1237 wxThread
*wxThread::This()
1239 wxThread
* thr
= (wxThread
*) MPGetTaskStorageValue( gs_tlsForWXThread
) ;
1244 bool wxThread::IsMain()
1246 return GetCurrentId() == gs_idMainThread
|| gs_idMainThread
== kInvalidID
;
1253 void wxThread::Yield()
1255 #if TARGET_API_MAC_OSX
1256 CFRunLoopRunInMode( kCFRunLoopDefaultMode
, 0 , true ) ;
1262 void wxThread::Sleep( unsigned long milliseconds
)
1264 AbsoluteTime wakeup
= AddDurationToAbsolute( milliseconds
, UpTime() );
1265 MPDelayUntil( &wakeup
);
1268 int wxThread::GetCPUCount()
1270 return MPProcessors();
1273 unsigned long wxThread::GetCurrentId()
1275 return (unsigned long)MPCurrentTaskID();
1278 bool wxThread::SetConcurrency( size_t WXUNUSED(level
) )
1280 // Cannot be set in MacOS.
1284 wxThread::wxThread( wxThreadKind kind
)
1286 g_numberOfThreads
++;
1287 m_internal
= new wxThreadInternal();
1289 m_isDetached
= (kind
== wxTHREAD_DETACHED
);
1292 wxThread::~wxThread()
1294 wxASSERT_MSG( g_numberOfThreads
>0 , wxT("More threads deleted than created.") ) ;
1296 g_numberOfThreads
--;
1301 // check that the thread either exited or couldn't be created
1302 if ( m_internal
->GetState() != STATE_EXITED
&&
1303 m_internal
->GetState() != STATE_NEW
)
1306 wxT("The thread %ld is being destroyed although it is still running! The application may crash."),
1313 wxDELETE( m_internal
) ;
1316 wxThreadError
wxThread::Create( unsigned int stackSize
)
1318 wxCriticalSectionLocker
lock(m_critsect
);
1321 m_internal
->Detach() ;
1323 if ( !m_internal
->Create(this, stackSize
) )
1325 m_internal
->SetState( STATE_EXITED
);
1327 return wxTHREAD_NO_RESOURCE
;
1330 return wxTHREAD_NO_ERROR
;
1333 wxThreadError
wxThread::Run()
1335 wxCriticalSectionLocker
lock(m_critsect
);
1337 wxCHECK_MSG( m_internal
->GetId(), wxTHREAD_MISC_ERROR
,
1338 wxT("must call wxThread::Create() first") );
1340 return m_internal
->Run();
1343 // -----------------------------------------------------------------------------
1345 // -----------------------------------------------------------------------------
1347 wxThreadError
wxThread::Pause()
1349 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
,
1350 _T("a thread can't pause itself") );
1352 wxCriticalSectionLocker
lock(m_critsect
);
1354 if ( m_internal
->GetState() != STATE_RUNNING
)
1356 wxLogDebug( wxT("Can't pause thread which is not running.") );
1358 return wxTHREAD_NOT_RUNNING
;
1361 // just set a flag, the thread will be really paused only during the next
1362 // call to TestDestroy()
1363 m_internal
->SetState( STATE_PAUSED
);
1365 return wxTHREAD_NO_ERROR
;
1368 wxThreadError
wxThread::Resume()
1370 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
,
1371 wxT("a thread can't resume itself") );
1373 wxCriticalSectionLocker
lock(m_critsect
);
1375 wxThreadState state
= m_internal
->GetState();
1380 m_internal
->Resume();
1381 return wxTHREAD_NO_ERROR
;
1384 return wxTHREAD_NO_ERROR
;
1387 wxLogDebug( wxT("Attempt to resume a thread which is not paused.") );
1389 return wxTHREAD_MISC_ERROR
;
1393 // -----------------------------------------------------------------------------
1395 // -----------------------------------------------------------------------------
1397 wxThread::ExitCode
wxThread::Wait()
1399 wxCHECK_MSG( This() != this, (ExitCode
)-1,
1400 wxT("a thread can't wait for itself") );
1402 wxCHECK_MSG( !m_isDetached
, (ExitCode
)-1,
1403 wxT("can't wait for detached thread") );
1407 return m_internal
->GetExitCode();
1410 wxThreadError
wxThread::Delete(ExitCode
*rc
)
1412 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
,
1413 wxT("a thread can't delete itself") );
1415 bool isDetached
= m_isDetached
;
1418 wxThreadState state
= m_internal
->GetState();
1420 // ask the thread to stop
1421 m_internal
->SetCancelFlag();
1428 // we need to wake up the thread so that PthreadStart() will
1429 // terminate - right now it's blocking on run semaphore in
1431 m_internal
->SignalRun();
1440 // resume the thread first
1441 m_internal
->Resume();
1448 // wait until the thread stops
1453 // return the exit code of the thread
1454 *rc
= m_internal
->GetExitCode();
1459 return wxTHREAD_NO_ERROR
;
1462 wxThreadError
wxThread::Kill()
1464 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
,
1465 wxT("a thread can't kill itself") );
1467 switch ( m_internal
->GetState() )
1471 return wxTHREAD_NOT_RUNNING
;
1474 // resume the thread first
1480 OSStatus err
= MPTerminateTask( m_internal
->GetId() , -1 ) ;
1483 wxLogError( wxT("Failed to terminate a thread.") );
1485 return wxTHREAD_MISC_ERROR
;
1494 // this should be retrieved by Wait actually
1495 m_internal
->SetExitCode( (void*)-1 );
1498 return wxTHREAD_NO_ERROR
;
1502 void wxThread::Exit( ExitCode status
)
1504 wxASSERT_MSG( This() == this,
1505 wxT("wxThread::Exit() can only be called in the context of the same thread") );
1507 // don't enter m_critsect before calling OnExit() because the user code
1508 // might deadlock if, for example, it signals a condition in OnExit() (a
1509 // common case) while the main thread calls any of functions entering
1510 // m_critsect on us (almost all of them do)
1513 MPTaskID threadid
= m_internal
->GetId();
1521 // update the status of the joinable thread
1522 wxCriticalSectionLocker
lock( m_critsect
);
1523 m_internal
->SetState( STATE_EXITED
);
1526 MPTerminateTask( threadid
, (long)status
);
1529 // also test whether we were paused
1530 bool wxThread::TestDestroy()
1532 wxASSERT_MSG( This() == this,
1533 wxT("wxThread::TestDestroy() can only be called in the context of the same thread") );
1537 if ( m_internal
->GetState() == STATE_PAUSED
)
1539 m_internal
->SetReallyPaused( true );
1541 // leave the crit section or the other threads will stop too if they attempt
1542 // to call any of (seemingly harmless) IsXXX() functions while we sleep
1545 m_internal
->Pause();
1549 // thread wasn't requested to pause, nothing to do
1553 return m_internal
->WasCancelled();
1556 // -----------------------------------------------------------------------------
1558 // -----------------------------------------------------------------------------
1560 void wxThread::SetPriority(unsigned int prio
)
1562 wxCHECK_RET( ((int)WXTHREAD_MIN_PRIORITY
<= (int)prio
) &&
1563 ((int)prio
<= (int)WXTHREAD_MAX_PRIORITY
),
1564 wxT("invalid thread priority") );
1566 wxCriticalSectionLocker
lock(m_critsect
);
1568 switch ( m_internal
->GetState() )
1573 // thread not yet started, priority will be set when it is
1574 m_internal
->SetPriority( prio
);
1579 wxFAIL_MSG( wxT("impossible to set thread priority in this state") );
1583 unsigned int wxThread::GetPriority() const
1585 wxCriticalSectionLocker
lock((wxCriticalSection
&)m_critsect
); // const_cast
1587 return m_internal
->GetPriority();
1590 unsigned long wxThread::GetId() const
1592 wxCriticalSectionLocker
lock((wxCriticalSection
&)m_critsect
); // const_cast
1594 return (unsigned long)m_internal
->GetId();
1597 // -----------------------------------------------------------------------------
1599 // -----------------------------------------------------------------------------
1601 bool wxThread::IsRunning() const
1603 wxCriticalSectionLocker
lock((wxCriticalSection
&)m_critsect
);
1605 return m_internal
->GetState() == STATE_RUNNING
;
1608 bool wxThread::IsAlive() const
1610 wxCriticalSectionLocker
lock((wxCriticalSection
&)m_critsect
);
1612 switch ( m_internal
->GetState() )
1623 bool wxThread::IsPaused() const
1625 wxCriticalSectionLocker
lock((wxCriticalSection
&)m_critsect
);
1627 return (m_internal
->GetState() == STATE_PAUSED
);
1630 // ----------------------------------------------------------------------------
1631 // Automatic initialization for thread module
1632 // ----------------------------------------------------------------------------
1634 class wxThreadModule
: public wxModule
1637 virtual bool OnInit();
1638 virtual void OnExit();
1641 DECLARE_DYNAMIC_CLASS(wxThreadModule
)
1644 IMPLEMENT_DYNAMIC_CLASS(wxThreadModule
, wxModule
)
1646 bool wxThreadModule::OnInit()
1648 bool hasThreadManager
=
1650 true ; // TODO VERIFY IN NEXT BUILD
1652 MPLibraryIsLoaded();
1655 if ( !hasThreadManager
)
1657 wxLogError( wxT("MP thread support is not available on this system" ) ) ;
1662 // main thread's This() is NULL
1663 verify_noerr( MPAllocateTaskStorageIndex( &gs_tlsForWXThread
) ) ;
1664 verify_noerr( MPSetTaskStorageValue( gs_tlsForWXThread
, 0 ) ) ;
1666 gs_idMainThread
= wxThread::GetCurrentId();
1667 gs_critsectWaitingForGui
= new wxCriticalSection();
1669 gs_critsectGui
= new wxCriticalSection();
1670 gs_critsectGui
->Enter();
1675 void wxThreadModule::OnExit()
1677 if ( gs_critsectGui
)
1679 if ( !wxGuiOwnedByMainThread() )
1681 gs_critsectGui
->Enter();
1682 gs_bGuiOwnedByMainThread
= true;
1685 gs_critsectGui
->Leave();
1686 delete gs_critsectGui
;
1687 gs_critsectGui
= NULL
;
1690 delete gs_critsectWaitingForGui
;
1691 gs_critsectWaitingForGui
= NULL
;
1694 // ----------------------------------------------------------------------------
1695 // GUI Serialization copied from MSW implementation
1696 // ----------------------------------------------------------------------------
1698 void WXDLLIMPEXP_BASE
wxMutexGuiEnter()
1700 // this would dead lock everything...
1701 wxASSERT_MSG( !wxThread::IsMain(),
1702 wxT("main thread doesn't want to block in wxMutexGuiEnter()!") );
1704 // the order in which we enter the critical sections here is crucial!!
1706 // set the flag telling to the main thread that we want to do some GUI
1708 wxCriticalSectionLocker
enter(*gs_critsectWaitingForGui
);
1710 gs_nWaitingForGui
++;
1713 wxWakeUpMainThread();
1715 // now we may block here because the main thread will soon let us in
1716 // (during the next iteration of OnIdle())
1717 gs_critsectGui
->Enter();
1720 void WXDLLIMPEXP_BASE
wxMutexGuiLeave()
1722 wxCriticalSectionLocker
enter(*gs_critsectWaitingForGui
);
1724 if ( wxThread::IsMain() )
1726 gs_bGuiOwnedByMainThread
= false;
1730 // decrement the number of threads waiting for GUI access now
1731 wxASSERT_MSG( gs_nWaitingForGui
> 0,
1732 wxT("calling wxMutexGuiLeave() without entering it first?") );
1734 gs_nWaitingForGui
--;
1736 wxWakeUpMainThread();
1739 gs_critsectGui
->Leave();
1742 void WXDLLIMPEXP_BASE
wxMutexGuiLeaveOrEnter()
1744 wxASSERT_MSG( wxThread::IsMain(),
1745 wxT("only main thread may call wxMutexGuiLeaveOrEnter()!") );
1747 if ( !gs_critsectWaitingForGui
)
1750 wxCriticalSectionLocker
enter(*gs_critsectWaitingForGui
);
1752 if ( gs_nWaitingForGui
== 0 )
1754 // no threads are waiting for GUI - so we may acquire the lock without
1755 // any danger (but only if we don't already have it)
1756 if ( !wxGuiOwnedByMainThread() )
1758 gs_critsectGui
->Enter();
1760 gs_bGuiOwnedByMainThread
= true;
1762 //else: already have it, nothing to do
1766 // some threads are waiting, release the GUI lock if we have it
1767 if ( wxGuiOwnedByMainThread() )
1769 //else: some other worker thread is doing GUI
1773 bool WXDLLIMPEXP_BASE
wxGuiOwnedByMainThread()
1775 return gs_bGuiOwnedByMainThread
;
1778 // wake up the main thread
1779 void WXDLLEXPORT
wxWakeUpMainThread()
1784 // ----------------------------------------------------------------------------
1785 // include common implementation code
1786 // ----------------------------------------------------------------------------
1788 #include "wx/thrimpl.cpp"
1790 #endif // wxUSE_THREADS