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 #include "wx/mac/macnotfy.h"
42 // the possible states of the thread:
43 // ("=>" shows all possible transitions from this state)
46 STATE_NEW
, // didn't start execution yet (=> RUNNING)
47 STATE_RUNNING
, // thread is running (=> PAUSED, CANCELED)
48 STATE_PAUSED
, // thread is temporarily suspended (=> RUNNING)
49 STATE_CANCELED
, // thread should terminate a.s.a.p. (=> EXITED)
50 STATE_EXITED
// thread is terminating
53 // ----------------------------------------------------------------------------
55 // ----------------------------------------------------------------------------
57 // the task ID of the main thread
58 static wxThreadIdType gs_idMainThread
= kInvalidID
;
60 // this is the Per-Task Storage for the pointer to the appropriate wxThread
61 TaskStorageIndex gs_tlsForWXThread
= 0;
63 // if it's false, some secondary thread is holding the GUI lock
64 static bool gs_bGuiOwnedByMainThread
= true;
66 // critical section which controls access to all GUI functions: any secondary
67 // thread (i.e. except the main one) must enter this crit section before doing
69 static wxCriticalSection
*gs_critsectGui
= NULL
;
71 // critical section which protects gs_nWaitingForGui variable
72 static wxCriticalSection
*gs_critsectWaitingForGui
= NULL
;
74 // number of threads waiting for GUI in wxMutexGuiEnter()
75 static size_t gs_nWaitingForGui
= 0;
77 // overall number of threads, needed for determining
78 // the sleep value of the main event loop
79 size_t g_numberOfThreads
= 0;
83 MPCriticalRegionID gs_guiCritical
= kInvalidID
;
86 // ============================================================================
87 // MacOS implementation of thread classes
88 // ============================================================================
93 The implementation is very close to the phtreads implementation, the reason for
94 using MPServices is the fact that these are also available under OS 9. Thus allowing
95 for one common API for all current builds.
97 As soon as wxThreads are on a 64 bit address space, the TLS must be extended
98 to use two indices one for each 32 bit part as the MP implementation is limited
101 I have three implementations for mutexes :
102 version A based on a binary semaphore, problem - not reentrant, version B based
103 on a critical region, allows for reentrancy, performance implications not
104 yet tested, and third a plain pthreads implementation
106 The same for condition internal, one implementation by Aj Lavin and the other one
107 copied from the thrimpl.cpp which I assume has been more broadly tested, I've just
108 replaced the interlock increment with the appropriate PPC calls
111 // ----------------------------------------------------------------------------
113 // ----------------------------------------------------------------------------
115 wxCriticalSection::wxCriticalSection()
117 MPCreateCriticalRegion( (MPCriticalRegionID
*) &m_critRegion
);
120 wxCriticalSection::~wxCriticalSection()
122 MPDeleteCriticalRegion( (MPCriticalRegionID
) m_critRegion
);
125 void wxCriticalSection::Enter()
127 MPEnterCriticalRegion( (MPCriticalRegionID
) m_critRegion
, kDurationForever
);
130 void wxCriticalSection::Leave()
132 MPExitCriticalRegion( (MPCriticalRegionID
) m_critRegion
);
135 // ----------------------------------------------------------------------------
136 // wxMutex implementation
137 // ----------------------------------------------------------------------------
139 #if TARGET_API_MAC_OSX
140 #define wxUSE_MAC_SEMAPHORE_MUTEX 0
141 #define wxUSE_MAC_CRITICAL_REGION_MUTEX 1
142 #define wxUSE_MAC_PTHREADS_MUTEX 0
144 #define wxUSE_MAC_SEMAPHORE_MUTEX 0
145 #define wxUSE_MAC_CRITICAL_REGION_MUTEX 1
146 #define wxUSE_MAC_PTHREADS_MUTEX 0
149 #if wxUSE_MAC_PTHREADS_MUTEX
154 class wxMutexInternal
157 wxMutexInternal( wxMutexType mutexType
);
161 wxMutexError
TryLock();
162 wxMutexError
Unlock();
168 pthread_mutex_t m_mutex
;
171 // wxConditionInternal uses our m_mutex
172 friend class wxConditionInternal
;
175 #ifdef HAVE_PTHREAD_MUTEXATTR_T
176 // on some systems pthread_mutexattr_settype() is not in the headers (but it is
177 // in the library, otherwise we wouldn't compile this code at all)
178 extern "C" int pthread_mutexattr_settype( pthread_mutexattr_t
*, int );
181 wxMutexInternal::wxMutexInternal( wxMutexType mutexType
)
186 case wxMUTEX_RECURSIVE
:
187 // support recursive locks like Win32, i.e. a thread can lock a
188 // mutex which it had itself already locked
190 // unfortunately initialization of recursive mutexes is non
191 // portable, so try several methods
192 #ifdef HAVE_PTHREAD_MUTEXATTR_T
194 pthread_mutexattr_t attr
;
195 pthread_mutexattr_init( &attr
);
196 pthread_mutexattr_settype( &attr
, PTHREAD_MUTEX_RECURSIVE
);
198 err
= pthread_mutex_init( &m_mutex
, &attr
);
200 #elif defined(HAVE_PTHREAD_RECURSIVE_MUTEX_INITIALIZER)
201 // we can use this only as initializer so we have to assign it
202 // first to a temp var - assigning directly to m_mutex wouldn't
205 pthread_mutex_t mutex
= PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
;
208 #else // no recursive mutexes
210 #endif // HAVE_PTHREAD_MUTEXATTR_T/...
214 wxFAIL_MSG( wxT("unknown mutex type") );
217 case wxMUTEX_DEFAULT
:
218 err
= pthread_mutex_init( &m_mutex
, NULL
);
225 wxLogApiError( wxT("pthread_mutex_init()"), err
);
229 wxMutexInternal::~wxMutexInternal()
233 int err
= pthread_mutex_destroy( &m_mutex
);
236 wxLogApiError( wxT("pthread_mutex_destroy()"), err
);
241 wxMutexError
wxMutexInternal::Lock()
243 int err
= pthread_mutex_lock( &m_mutex
);
247 // only error checking mutexes return this value and so it's an
248 // unexpected situation -- hence use assert, not wxLogDebug
249 wxFAIL_MSG( wxT("mutex deadlock prevented") );
250 return wxMUTEX_DEAD_LOCK
;
253 wxLogDebug( wxT("pthread_mutex_lock(): mutex not initialized.") );
257 return wxMUTEX_NO_ERROR
;
260 wxLogApiError( wxT("pthread_mutex_lock()"), err
);
263 return wxMUTEX_MISC_ERROR
;
266 wxMutexError
wxMutexInternal::TryLock()
268 int err
= pthread_mutex_trylock( &m_mutex
);
272 // not an error: mutex is already locked, but we're prepared for this case
276 wxLogDebug( wxT("pthread_mutex_trylock(): mutex not initialized.") );
280 return wxMUTEX_NO_ERROR
;
283 wxLogApiError( wxT("pthread_mutex_trylock()"), err
);
286 return wxMUTEX_MISC_ERROR
;
289 wxMutexError
wxMutexInternal::Unlock()
291 int err
= pthread_mutex_unlock( &m_mutex
);
295 // we don't own the mutex
296 return wxMUTEX_UNLOCKED
;
299 wxLogDebug( wxT("pthread_mutex_unlock(): mutex not initialized.") );
303 return wxMUTEX_NO_ERROR
;
306 wxLogApiError( wxT("pthread_mutex_unlock()"), err
);
309 return wxMUTEX_MISC_ERROR
;
314 #if wxUSE_MAC_SEMAPHORE_MUTEX
316 class wxMutexInternal
319 wxMutexInternal( wxMutexType mutexType
);
320 virtual ~wxMutexInternal();
326 wxMutexError
TryLock();
327 wxMutexError
Unlock();
330 MPSemaphoreID m_semaphore
;
334 wxMutexInternal::wxMutexInternal(wxMutexType mutexType
)
337 m_semaphore
= kInvalidID
;
338 OSStatus err
= noErr
;
342 case wxMUTEX_DEFAULT
:
343 verify_noerr( MPCreateBinarySemaphore( &m_semaphore
) );
344 m_isOk
= ( m_semaphore
!= kInvalidID
);
347 case wxMUTEX_RECURSIVE
:
348 wxFAIL_MSG( wxT("Recursive Mutex not supported yet") );
352 wxFAIL_MSG( wxT("Unknown mutex type") );
357 wxMutexInternal::~wxMutexInternal()
359 if ( m_semaphore
!= kInvalidID
)
360 MPDeleteSemaphore( m_semaphore
);
365 wxMutexError
wxMutexInternal::Lock()
367 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") );
368 OSStatus err
= MPWaitOnSemaphore( m_semaphore
, kDurationForever
);
371 wxLogSysError( wxT("Could not lock mutex") );
373 return wxMUTEX_MISC_ERROR
;
376 return wxMUTEX_NO_ERROR
;
379 wxMutexError
wxMutexInternal::TryLock()
381 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") );
382 OSStatus err
= MPWaitOnSemaphore( m_semaphore
, kDurationImmediate
);
385 if (err
== kMPTimeoutErr
)
388 wxLogSysError( wxT("Could not try lock mutex") );
390 return wxMUTEX_MISC_ERROR
;
393 return wxMUTEX_NO_ERROR
;
396 wxMutexError
wxMutexInternal::Unlock()
398 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") );
399 OSStatus err
= MPSignalSemaphore( m_semaphore
);
404 wxLogSysError( wxT("Could not unlock mutex") );
405 return wxMUTEX_MISC_ERROR
;
408 return wxMUTEX_NO_ERROR
;
413 #if wxUSE_MAC_CRITICAL_REGION_MUTEX
415 class wxMutexInternal
418 wxMutexInternal( wxMutexType mutexType
);
419 virtual ~wxMutexInternal();
424 wxMutexError
Lock() ;
425 wxMutexError
TryLock();
426 wxMutexError
Unlock();
429 MPCriticalRegionID m_critRegion
;
433 wxMutexInternal::wxMutexInternal( wxMutexType mutexType
)
436 m_critRegion
= kInvalidID
;
438 verify_noerr( MPCreateCriticalRegion( &m_critRegion
) );
439 m_isOk
= ( m_critRegion
!= kInvalidID
);
442 wxFAIL_MSG( wxT("Error when creating mutex") );
446 wxMutexInternal::~wxMutexInternal()
448 if ( m_critRegion
!= kInvalidID
)
449 MPDeleteCriticalRegion( m_critRegion
);
454 wxMutexError
wxMutexInternal::Lock()
456 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") );
458 OSStatus err
= MPEnterCriticalRegion( m_critRegion
, kDurationForever
);
461 wxLogSysError(wxT("Could not lock mutex"));
462 return wxMUTEX_MISC_ERROR
;
465 return wxMUTEX_NO_ERROR
;
468 wxMutexError
wxMutexInternal::TryLock()
470 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") ) ;
472 OSStatus err
= MPEnterCriticalRegion( m_critRegion
, kDurationImmediate
);
475 if ( err
== kMPTimeoutErr
)
478 wxLogSysError( wxT("Could not try lock mutex") );
479 return wxMUTEX_MISC_ERROR
;
482 return wxMUTEX_NO_ERROR
;
485 wxMutexError
wxMutexInternal::Unlock()
487 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") ) ;
489 OSStatus err
= MPExitCriticalRegion( m_critRegion
);
494 wxLogSysError( wxT("Could not unlock mutex") );
496 return wxMUTEX_MISC_ERROR
;
499 return wxMUTEX_NO_ERROR
;
504 // --------------------------------------------------------------------------
506 // --------------------------------------------------------------------------
508 class wxSemaphoreInternal
511 wxSemaphoreInternal( int initialcount
, int maxcount
);
512 virtual ~wxSemaphoreInternal();
518 wxSemaError
WaitTimeout( unsigned long milliseconds
);
521 { return WaitTimeout( kDurationForever
); }
523 wxSemaError
TryWait()
525 wxSemaError err
= WaitTimeout( kDurationImmediate
);
526 if (err
== wxSEMA_TIMEOUT
)
533 MPSemaphoreID m_semaphore
;
537 wxSemaphoreInternal::wxSemaphoreInternal( int initialcount
, int maxcount
)
540 m_semaphore
= kInvalidID
;
542 // make it practically infinite
545 verify_noerr( MPCreateSemaphore( maxcount
, initialcount
, &m_semaphore
) );
546 m_isOk
= ( m_semaphore
!= kInvalidID
);
550 wxFAIL_MSG( wxT("Error when creating semaphore") );
554 wxSemaphoreInternal::~wxSemaphoreInternal()
556 if (m_semaphore
!= kInvalidID
)
557 MPDeleteSemaphore( m_semaphore
);
562 wxSemaError
wxSemaphoreInternal::WaitTimeout( unsigned long milliseconds
)
564 OSStatus err
= MPWaitOnSemaphore( m_semaphore
, milliseconds
);
567 if (err
== kMPTimeoutErr
)
568 return wxSEMA_TIMEOUT
;
570 return wxSEMA_MISC_ERROR
;
573 return wxSEMA_NO_ERROR
;
576 wxSemaError
wxSemaphoreInternal::Post()
578 OSStatus err
= MPSignalSemaphore( m_semaphore
);
581 return wxSEMA_MISC_ERROR
;
583 return wxSEMA_NO_ERROR
;
586 // ----------------------------------------------------------------------------
587 // wxCondition implementation
588 // ----------------------------------------------------------------------------
592 class wxConditionInternal
595 wxConditionInternal( wxMutex
& mutex
)
606 virtual ~wxConditionInternal() {}
609 { return m_mutex
.IsOk(); }
612 { return WaitTimeout( kDurationForever
); }
614 wxCondError
WaitTimeout( unsigned long msectimeout
);
617 { return DoSignal( false); }
619 wxCondError
Broadcast()
620 { return DoSignal( true ); }
623 wxCondError
DoSignal( bool signalAll
);
626 wxSemaphoreInternal m_semaphore
; // Signals the waiting threads.
627 wxSemaphoreInternal m_gate
;
628 wxCriticalSection m_varSection
;
629 size_t m_waiters
; // Number of threads waiting for a signal.
630 size_t m_signals
; // Number of signals to send.
631 size_t m_canceled
; // Number of canceled waiters in m_waiters.
634 wxCondError
wxConditionInternal::WaitTimeout( unsigned long msectimeout
)
638 if ( ++ m_waiters
== INT_MAX
)
640 m_varSection
.Enter();
642 m_waiters
-= m_canceled
;
643 m_signals
-= m_canceled
;
646 m_varSection
.Leave();
652 wxSemaError err
= m_semaphore
.WaitTimeout( msectimeout
);
653 wxASSERT( err
== wxSEMA_NO_ERROR
|| err
== wxSEMA_TIMEOUT
);
655 m_varSection
.Enter();
657 if ( err
!= wxSEMA_NO_ERROR
)
659 if ( m_signals
> m_canceled
)
661 // A signal is being sent after we timed out.
662 if ( m_waiters
== m_signals
)
664 // There are no excess waiters to catch the signal, so
665 // we must throw it away.
666 wxSemaError err2
= m_semaphore
.Wait();
667 if ( err2
!= wxSEMA_NO_ERROR
)
669 wxLogSysError( wx("Error while waiting on semaphore") );
672 wxASSERT( err2
== wxSEMA_NO_ERROR
);
675 if ( --m_signals
== m_canceled
)
677 // This was the last signal. open the gate.
678 wxASSERT( m_waiters
== m_canceled
);
684 // There are excess waiters to catch the signal, leave it be.
690 // No signals is being sent:
691 // the gate may be open or closed, so we can't touch m_waiters.
698 // We caught a signal.
699 wxASSERT( m_signals
> m_canceled
);
703 if ( --m_signals
== m_canceled
)
705 // This was the last signal. open the gate.
706 wxASSERT( m_waiters
== m_canceled
);
712 m_varSection
.Leave();
716 return err
== wxSEMA_TIMEOUT
? wxCOND_TIMEOUT
: wxCOND_MISC_ERROR
;
718 return wxCOND_NO_ERROR
;
722 wxCondError
wxConditionInternal::DoSignal( bool signalAll
)
725 m_varSection
.Enter();
727 wxASSERT( m_signals
== m_canceled
);
729 if ( m_waiters
== m_canceled
)
731 m_varSection
.Leave();
733 return wxCOND_NO_ERROR
;
738 m_waiters
-= m_canceled
;
743 m_signals
= signalAll
? m_waiters
: 1;
744 size_t n
= m_signals
;
746 m_varSection
.Leave();
748 // Let the waiters inherit the gate lock.
752 wxSemaError err
= m_semaphore
.Post();
753 wxASSERT( err
== wxSEMA_NO_ERROR
);
757 return wxCOND_NO_ERROR
;
761 class wxConditionInternal
764 wxConditionInternal( wxMutex
& mutex
);
767 { return m_mutex
.IsOk() && m_semaphore
.IsOk(); }
770 wxCondError
WaitTimeout( unsigned long milliseconds
);
772 wxCondError
Signal();
773 wxCondError
Broadcast();
776 // the number of threads currently waiting for this condition
779 // the critical section protecting m_numWaiters
780 wxCriticalSection m_csWaiters
;
783 wxSemaphore m_semaphore
;
785 DECLARE_NO_COPY_CLASS(wxConditionInternal
)
788 wxConditionInternal::wxConditionInternal( wxMutex
& mutex
)
791 // another thread can't access it until we return from ctor, so no need to
792 // protect access to m_numWaiters here
796 wxCondError
wxConditionInternal::Wait()
798 // increment the number of waiters
799 IncrementAtomic( &m_numWaiters
);
803 // a potential race condition can occur here
805 // after a thread increments nwaiters, and unlocks the mutex and before the
806 // semaphore.Wait() is called, if another thread can cause a signal to be
809 // this race condition is handled by using a semaphore and incrementing the
810 // semaphore only if 'nwaiters' is greater that zero since the semaphore,
811 // can 'remember' signals the race condition will not occur
813 // wait ( if necessary ) and decrement semaphore
814 wxSemaError err
= m_semaphore
.Wait();
817 return err
== wxSEMA_NO_ERROR
? wxCOND_NO_ERROR
: wxCOND_MISC_ERROR
;
820 wxCondError
wxConditionInternal::WaitTimeout( unsigned long milliseconds
)
822 IncrementAtomic( &m_numWaiters
);
826 // a race condition can occur at this point in the code
828 // please see the comments in Wait(), for details
830 wxSemaError err
= m_semaphore
.WaitTimeout(milliseconds
);
832 if ( err
== wxSEMA_BUSY
)
834 // another potential race condition exists here it is caused when a
835 // 'waiting' thread timesout, and returns from WaitForSingleObject, but
836 // has not yet decremented 'nwaiters'.
838 // at this point if another thread calls signal() then the semaphore
839 // will be incremented, but the waiting thread will miss it.
841 // to handle this particular case, the waiting thread calls
842 // WaitForSingleObject again with a timeout of 0, after locking
843 // 'nwaiters_mutex'. this call does not block because of the zero
844 // timeout, but will allow the waiting thread to catch the missed
846 wxCriticalSectionLocker
lock(m_csWaiters
);
848 err
= m_semaphore
.WaitTimeout(0);
850 if ( err
!= wxSEMA_NO_ERROR
)
858 return err
== wxSEMA_NO_ERROR
? wxCOND_NO_ERROR
: wxCOND_MISC_ERROR
;
861 wxCondError
wxConditionInternal::Signal()
863 wxCriticalSectionLocker
lock(m_csWaiters
);
865 if ( m_numWaiters
> 0 )
867 // increment the semaphore by 1
868 if ( m_semaphore
.Post() != wxSEMA_NO_ERROR
)
869 return wxCOND_MISC_ERROR
;
874 return wxCOND_NO_ERROR
;
877 wxCondError
wxConditionInternal::Broadcast()
879 wxCriticalSectionLocker
lock(m_csWaiters
);
881 while ( m_numWaiters
> 0 )
883 if ( m_semaphore
.Post() != wxSEMA_NO_ERROR
)
884 return wxCOND_MISC_ERROR
;
889 return wxCOND_NO_ERROR
;
893 // ----------------------------------------------------------------------------
894 // wxCriticalSection implementation
895 // ----------------------------------------------------------------------------
897 // XXX currently implemented as mutex in headers. Change to critical section.
899 // ----------------------------------------------------------------------------
900 // wxThread implementation
901 // ----------------------------------------------------------------------------
903 // wxThreadInternal class
904 // ----------------------
906 class wxThreadInternal
913 m_prio
= WXTHREAD_DEFAULT_PRIORITY
;
914 m_notifyQueueId
= kInvalidID
;
916 m_cancelled
= false ;
918 // set to true only when the thread starts waiting on m_semSuspend
921 // defaults for joinable threads
922 m_shouldBeJoined
= true;
923 m_isDetached
= false;
926 virtual ~wxThreadInternal()
928 if ( m_notifyQueueId
)
930 MPDeleteQueue( m_notifyQueueId
);
931 m_notifyQueueId
= kInvalidID
;
936 static OSStatus
MacThreadStart(void* arg
);
938 // create a new (suspended) thread (for the given thread object)
939 bool Create(wxThread
*thread
, unsigned int stackSize
);
946 // unblock the thread allowing it to run
947 void SignalRun() { m_semRun
.Post(); }
949 // ask the thread to terminate
952 // go to sleep until Resume() is called
960 int GetPriority() const
962 void SetPriority(int prio
);
965 wxThreadState
GetState() const
967 void SetState(wxThreadState state
)
970 // Get the ID of this thread's underlying MP Services task.
971 MPTaskID
GetId() const
975 { m_cancelled
= true; }
977 bool WasCancelled() const
978 { return m_cancelled
; }
981 void SetExitCode(wxThread::ExitCode exitcode
)
982 { m_exitcode
= exitcode
; }
983 wxThread::ExitCode
GetExitCode() const
984 { return m_exitcode
; }
987 void SetReallyPaused(bool paused
)
988 { m_isPaused
= paused
; }
989 bool IsReallyPaused() const
990 { return m_isPaused
; }
992 // tell the thread that it is a detached one
995 wxCriticalSectionLocker
lock(m_csJoinFlag
);
997 m_shouldBeJoined
= false;
1002 // the thread we're associated with
1003 wxThread
* m_thread
;
1005 MPTaskID m_tid
; // thread id
1006 MPQueueID m_notifyQueueId
; // its notification queue
1008 wxThreadState m_state
; // see wxThreadState enum
1009 int m_prio
; // in wxWidgets units: from 0 to 100
1011 // this flag is set when the thread should terminate
1014 // this flag is set when the thread is blocking on m_semSuspend
1017 // the thread exit code - only used for joinable (!detached) threads and
1018 // is only valid after the thread termination
1019 wxThread::ExitCode m_exitcode
;
1021 // many threads may call Wait(), but only one of them should call
1022 // pthread_join(), so we have to keep track of this
1023 wxCriticalSection m_csJoinFlag
;
1024 bool m_shouldBeJoined
;
1027 // this semaphore is posted by Run() and the threads Entry() is not
1028 // called before it is done
1029 wxSemaphore m_semRun
;
1031 // this one is signaled when the thread should resume after having been
1033 wxSemaphore m_semSuspend
;
1036 OSStatus
wxThreadInternal::MacThreadStart(void *parameter
)
1038 wxThread
* thread
= (wxThread
*) parameter
;
1039 wxThreadInternal
*pthread
= thread
->m_internal
;
1041 // add to TLS so that This() will work
1042 verify_noerr( MPSetTaskStorageValue( gs_tlsForWXThread
, (TaskStorageValue
) thread
) ) ;
1044 // have to declare this before pthread_cleanup_push() which defines a
1048 // wait for the semaphore to be posted from Run()
1049 pthread
->m_semRun
.Wait();
1051 // test whether we should run the run at all - may be it was deleted
1052 // before it started to Run()?
1054 wxCriticalSectionLocker
lock(thread
->m_critsect
);
1056 dontRunAtAll
= pthread
->GetState() == STATE_NEW
&&
1057 pthread
->WasCancelled();
1060 if ( !dontRunAtAll
)
1062 pthread
->m_exitcode
= thread
->Entry();
1065 wxCriticalSectionLocker
lock(thread
->m_critsect
);
1066 pthread
->SetState( STATE_EXITED
);
1072 if ( pthread
->m_isDetached
)
1079 // on Mac for the running code,
1080 // the correct thread termination is to return
1082 // terminate the thread
1083 thread
->Exit( pthread
->m_exitcode
);
1085 return (OSStatus
) NULL
; // pthread->m_exitcode;
1089 bool wxThreadInternal::Create( wxThread
*thread
, unsigned int stackSize
)
1091 wxASSERT_MSG( m_state
== STATE_NEW
&& !m_tid
,
1092 wxT("Create()ing thread twice?") );
1094 OSStatus err
= noErr
;
1097 if ( m_notifyQueueId
== kInvalidID
)
1099 OSStatus err
= MPCreateQueue( &m_notifyQueueId
);
1102 wxLogSysError( wxT("Cant create the thread event queue") );
1108 m_state
= STATE_NEW
;
1111 MacThreadStart
, (void*)m_thread
, stackSize
,
1112 m_notifyQueueId
, &m_exitcode
, 0, 0, &m_tid
);
1116 wxLogSysError( wxT("Can't create thread") );
1121 if ( m_prio
!= WXTHREAD_DEFAULT_PRIORITY
)
1122 SetPriority( m_prio
);
1127 void wxThreadInternal::SetPriority( int priority
)
1133 // Mac priorities range from 1 to 10,000, with a default of 100.
1134 // wxWidgets priorities range from 0 to 100 with a default of 50.
1135 // We can map wxWidgets to Mac priorities easily by assuming
1136 // the former uses a logarithmic scale.
1137 const unsigned int macPriority
= (int)( exp( priority
/ 25.0 * log( 10.0)) + 0.5);
1139 MPSetTaskWeight( m_tid
, macPriority
);
1143 wxThreadError
wxThreadInternal::Run()
1145 wxCHECK_MSG( GetState() == STATE_NEW
, wxTHREAD_RUNNING
,
1146 wxT("thread may only be started once after Create()") );
1148 SetState( STATE_RUNNING
);
1150 // wake up threads waiting for our start
1153 return wxTHREAD_NO_ERROR
;
1156 void wxThreadInternal::Wait()
1158 wxCHECK_RET( !m_isDetached
, wxT("can't wait for a detached thread") );
1160 // if the thread we're waiting for is waiting for the GUI mutex, we will
1161 // deadlock so make sure we release it temporarily
1162 if ( wxThread::IsMain() )
1164 // give the thread we're waiting for chance to do the GUI call
1165 // it might be in, we don't do this conditionally as the to be waited on
1166 // thread might have to acquire the mutex later but before terminating
1167 if ( wxGuiOwnedByMainThread() )
1172 wxCriticalSectionLocker
lock(m_csJoinFlag
);
1174 if ( m_shouldBeJoined
)
1176 void *param1
, *param2
, *rc
;
1178 OSStatus err
= MPWaitOnQueue(
1186 wxLogSysError( wxT( "Cannot wait for thread termination."));
1190 // actually param1 would be the address of m_exitcode
1191 // but we don't need this here
1194 m_shouldBeJoined
= false;
1199 void wxThreadInternal::Pause()
1201 // the state is set from the thread which pauses us first, this function
1202 // is called later so the state should have been already set
1203 wxCHECK_RET( m_state
== STATE_PAUSED
,
1204 wxT("thread must first be paused with wxThread::Pause().") );
1206 // wait until the semaphore is Post()ed from Resume()
1207 m_semSuspend
.Wait();
1210 void wxThreadInternal::Resume()
1212 wxCHECK_RET( m_state
== STATE_PAUSED
,
1213 wxT("can't resume thread which is not suspended.") );
1215 // the thread might be not actually paused yet - if there were no call to
1216 // TestDestroy() since the last call to Pause() for example
1217 if ( IsReallyPaused() )
1220 m_semSuspend
.Post();
1223 SetReallyPaused( false );
1226 SetState( STATE_RUNNING
);
1232 wxThread
*wxThread::This()
1234 wxThread
* thr
= (wxThread
*) MPGetTaskStorageValue( gs_tlsForWXThread
) ;
1239 bool wxThread::IsMain()
1241 return GetCurrentId() == gs_idMainThread
|| gs_idMainThread
== kInvalidID
;
1248 void wxThread::Yield()
1250 #if TARGET_API_MAC_OSX
1251 CFRunLoopRunInMode( kCFRunLoopDefaultMode
, 0 , true ) ;
1257 void wxThread::Sleep( unsigned long milliseconds
)
1259 AbsoluteTime wakeup
= AddDurationToAbsolute( milliseconds
, UpTime() );
1260 MPDelayUntil( &wakeup
);
1263 int wxThread::GetCPUCount()
1265 return MPProcessors();
1268 unsigned long wxThread::GetCurrentId()
1270 return (unsigned long)MPCurrentTaskID();
1273 bool wxThread::SetConcurrency( size_t level
)
1275 // Cannot be set in MacOS.
1279 wxThread::wxThread( wxThreadKind kind
)
1281 g_numberOfThreads
++;
1282 m_internal
= new wxThreadInternal();
1284 m_isDetached
= (kind
== wxTHREAD_DETACHED
);
1287 wxThread::~wxThread()
1289 wxASSERT_MSG( g_numberOfThreads
>0 , wxT("More threads deleted than created.") ) ;
1291 g_numberOfThreads
--;
1296 // check that the thread either exited or couldn't be created
1297 if ( m_internal
->GetState() != STATE_EXITED
&&
1298 m_internal
->GetState() != STATE_NEW
)
1301 wxT("The thread %ld is being destroyed although it is still running! The application may crash."),
1308 wxDELETE( m_internal
) ;
1311 wxThreadError
wxThread::Create( unsigned int stackSize
)
1313 wxCriticalSectionLocker
lock(m_critsect
);
1316 m_internal
->Detach() ;
1318 if ( !m_internal
->Create(this, stackSize
) )
1320 m_internal
->SetState( STATE_EXITED
);
1322 return wxTHREAD_NO_RESOURCE
;
1325 return wxTHREAD_NO_ERROR
;
1328 wxThreadError
wxThread::Run()
1330 wxCriticalSectionLocker
lock(m_critsect
);
1332 wxCHECK_MSG( m_internal
->GetId(), wxTHREAD_MISC_ERROR
,
1333 wxT("must call wxThread::Create() first") );
1335 return m_internal
->Run();
1338 // -----------------------------------------------------------------------------
1340 // -----------------------------------------------------------------------------
1342 wxThreadError
wxThread::Pause()
1344 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
,
1345 _T("a thread can't pause itself") );
1347 wxCriticalSectionLocker
lock(m_critsect
);
1349 if ( m_internal
->GetState() != STATE_RUNNING
)
1351 wxLogDebug( wxT("Can't pause thread which is not running.") );
1353 return wxTHREAD_NOT_RUNNING
;
1356 // just set a flag, the thread will be really paused only during the next
1357 // call to TestDestroy()
1358 m_internal
->SetState( STATE_PAUSED
);
1360 return wxTHREAD_NO_ERROR
;
1363 wxThreadError
wxThread::Resume()
1365 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
,
1366 wxT("a thread can't resume itself") );
1368 wxCriticalSectionLocker
lock(m_critsect
);
1370 wxThreadState state
= m_internal
->GetState();
1375 m_internal
->Resume();
1376 return wxTHREAD_NO_ERROR
;
1379 return wxTHREAD_NO_ERROR
;
1382 wxLogDebug( wxT("Attempt to resume a thread which is not paused.") );
1384 return wxTHREAD_MISC_ERROR
;
1388 // -----------------------------------------------------------------------------
1390 // -----------------------------------------------------------------------------
1392 wxThread::ExitCode
wxThread::Wait()
1394 wxCHECK_MSG( This() != this, (ExitCode
)-1,
1395 wxT("a thread can't wait for itself") );
1397 wxCHECK_MSG( !m_isDetached
, (ExitCode
)-1,
1398 wxT("can't wait for detached thread") );
1402 return m_internal
->GetExitCode();
1405 wxThreadError
wxThread::Delete(ExitCode
*rc
)
1407 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
,
1408 wxT("a thread can't delete itself") );
1410 bool isDetached
= m_isDetached
;
1413 wxThreadState state
= m_internal
->GetState();
1415 // ask the thread to stop
1416 m_internal
->SetCancelFlag();
1423 // we need to wake up the thread so that PthreadStart() will
1424 // terminate - right now it's blocking on run semaphore in
1426 m_internal
->SignalRun();
1435 // resume the thread first
1436 m_internal
->Resume();
1443 // wait until the thread stops
1448 // return the exit code of the thread
1449 *rc
= m_internal
->GetExitCode();
1454 return wxTHREAD_NO_ERROR
;
1457 wxThreadError
wxThread::Kill()
1459 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
,
1460 wxT("a thread can't kill itself") );
1462 switch ( m_internal
->GetState() )
1466 return wxTHREAD_NOT_RUNNING
;
1469 // resume the thread first
1475 OSStatus err
= MPTerminateTask( m_internal
->GetId() , -1 ) ;
1478 wxLogError( wxT("Failed to terminate a thread.") );
1480 return wxTHREAD_MISC_ERROR
;
1489 // this should be retrieved by Wait actually
1490 m_internal
->SetExitCode( (void*)-1 );
1493 return wxTHREAD_NO_ERROR
;
1497 void wxThread::Exit( ExitCode status
)
1499 wxASSERT_MSG( This() == this,
1500 wxT("wxThread::Exit() can only be called in the context of the same thread") );
1502 // don't enter m_critsect before calling OnExit() because the user code
1503 // might deadlock if, for example, it signals a condition in OnExit() (a
1504 // common case) while the main thread calls any of functions entering
1505 // m_critsect on us (almost all of them do)
1508 MPTaskID threadid
= m_internal
->GetId();
1516 // update the status of the joinable thread
1517 wxCriticalSectionLocker
lock( m_critsect
);
1518 m_internal
->SetState( STATE_EXITED
);
1521 MPTerminateTask( threadid
, (long)status
);
1524 // also test whether we were paused
1525 bool wxThread::TestDestroy()
1527 wxASSERT_MSG( This() == this,
1528 wxT("wxThread::TestDestroy() can only be called in the context of the same thread") );
1532 if ( m_internal
->GetState() == STATE_PAUSED
)
1534 m_internal
->SetReallyPaused( true );
1536 // leave the crit section or the other threads will stop too if they attempt
1537 // to call any of (seemingly harmless) IsXXX() functions while we sleep
1540 m_internal
->Pause();
1544 // thread wasn't requested to pause, nothing to do
1548 return m_internal
->WasCancelled();
1551 // -----------------------------------------------------------------------------
1553 // -----------------------------------------------------------------------------
1555 void wxThread::SetPriority(unsigned int prio
)
1557 wxCHECK_RET( ((int)WXTHREAD_MIN_PRIORITY
<= (int)prio
) &&
1558 ((int)prio
<= (int)WXTHREAD_MAX_PRIORITY
),
1559 wxT("invalid thread priority") );
1561 wxCriticalSectionLocker
lock(m_critsect
);
1563 switch ( m_internal
->GetState() )
1568 // thread not yet started, priority will be set when it is
1569 m_internal
->SetPriority( prio
);
1574 wxFAIL_MSG( wxT("impossible to set thread priority in this state") );
1578 unsigned int wxThread::GetPriority() const
1580 wxCriticalSectionLocker
lock((wxCriticalSection
&)m_critsect
); // const_cast
1582 return m_internal
->GetPriority();
1585 unsigned long wxThread::GetId() const
1587 wxCriticalSectionLocker
lock((wxCriticalSection
&)m_critsect
); // const_cast
1589 return (unsigned long)m_internal
->GetId();
1592 // -----------------------------------------------------------------------------
1594 // -----------------------------------------------------------------------------
1596 bool wxThread::IsRunning() const
1598 wxCriticalSectionLocker
lock((wxCriticalSection
&)m_critsect
);
1600 return m_internal
->GetState() == STATE_RUNNING
;
1603 bool wxThread::IsAlive() const
1605 wxCriticalSectionLocker
lock((wxCriticalSection
&)m_critsect
);
1607 switch ( m_internal
->GetState() )
1618 bool wxThread::IsPaused() const
1620 wxCriticalSectionLocker
lock((wxCriticalSection
&)m_critsect
);
1622 return (m_internal
->GetState() == STATE_PAUSED
);
1625 // ----------------------------------------------------------------------------
1626 // Automatic initialization for thread module
1627 // ----------------------------------------------------------------------------
1629 class wxThreadModule
: public wxModule
1632 virtual bool OnInit();
1633 virtual void OnExit();
1636 DECLARE_DYNAMIC_CLASS(wxThreadModule
)
1639 IMPLEMENT_DYNAMIC_CLASS(wxThreadModule
, wxModule
)
1641 bool wxThreadModule::OnInit()
1643 bool hasThreadManager
=
1645 true ; // TODO VERIFY IN NEXT BUILD
1647 MPLibraryIsLoaded();
1650 if ( !hasThreadManager
)
1652 wxLogError( wxT("MP thread support is not available on this system" ) ) ;
1657 // main thread's This() is NULL
1658 verify_noerr( MPAllocateTaskStorageIndex( &gs_tlsForWXThread
) ) ;
1659 verify_noerr( MPSetTaskStorageValue( gs_tlsForWXThread
, 0 ) ) ;
1661 gs_idMainThread
= wxThread::GetCurrentId();
1662 gs_critsectWaitingForGui
= new wxCriticalSection();
1664 gs_critsectGui
= new wxCriticalSection();
1665 gs_critsectGui
->Enter();
1670 void wxThreadModule::OnExit()
1672 if ( gs_critsectGui
)
1674 if ( !wxGuiOwnedByMainThread() )
1676 gs_critsectGui
->Enter();
1677 gs_bGuiOwnedByMainThread
= true;
1680 gs_critsectGui
->Leave();
1681 delete gs_critsectGui
;
1682 gs_critsectGui
= NULL
;
1685 delete gs_critsectWaitingForGui
;
1686 gs_critsectWaitingForGui
= NULL
;
1689 // ----------------------------------------------------------------------------
1690 // GUI Serialization copied from MSW implementation
1691 // ----------------------------------------------------------------------------
1693 void WXDLLIMPEXP_BASE
wxMutexGuiEnter()
1695 // this would dead lock everything...
1696 wxASSERT_MSG( !wxThread::IsMain(),
1697 wxT("main thread doesn't want to block in wxMutexGuiEnter()!") );
1699 // the order in which we enter the critical sections here is crucial!!
1701 // set the flag telling to the main thread that we want to do some GUI
1703 wxCriticalSectionLocker
enter(*gs_critsectWaitingForGui
);
1705 gs_nWaitingForGui
++;
1708 wxWakeUpMainThread();
1710 // now we may block here because the main thread will soon let us in
1711 // (during the next iteration of OnIdle())
1712 gs_critsectGui
->Enter();
1715 void WXDLLIMPEXP_BASE
wxMutexGuiLeave()
1717 wxCriticalSectionLocker
enter(*gs_critsectWaitingForGui
);
1719 if ( wxThread::IsMain() )
1721 gs_bGuiOwnedByMainThread
= false;
1725 // decrement the number of threads waiting for GUI access now
1726 wxASSERT_MSG( gs_nWaitingForGui
> 0,
1727 wxT("calling wxMutexGuiLeave() without entering it first?") );
1729 gs_nWaitingForGui
--;
1731 wxWakeUpMainThread();
1734 gs_critsectGui
->Leave();
1737 void WXDLLIMPEXP_BASE
wxMutexGuiLeaveOrEnter()
1739 wxASSERT_MSG( wxThread::IsMain(),
1740 wxT("only main thread may call wxMutexGuiLeaveOrEnter()!") );
1742 if ( !gs_critsectWaitingForGui
)
1745 wxCriticalSectionLocker
enter(*gs_critsectWaitingForGui
);
1747 if ( gs_nWaitingForGui
== 0 )
1749 // no threads are waiting for GUI - so we may acquire the lock without
1750 // any danger (but only if we don't already have it)
1751 if ( !wxGuiOwnedByMainThread() )
1753 gs_critsectGui
->Enter();
1755 gs_bGuiOwnedByMainThread
= true;
1757 //else: already have it, nothing to do
1761 // some threads are waiting, release the GUI lock if we have it
1762 if ( wxGuiOwnedByMainThread() )
1764 //else: some other worker thread is doing GUI
1768 bool WXDLLIMPEXP_BASE
wxGuiOwnedByMainThread()
1770 return gs_bGuiOwnedByMainThread
;
1773 // wake up the main thread
1774 void WXDLLEXPORT
wxWakeUpMainThread()
1779 // ----------------------------------------------------------------------------
1780 // include common implementation code
1781 // ----------------------------------------------------------------------------
1783 #include "wx/thrimpl.cpp"
1785 #endif // wxUSE_THREADS