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();
421 bool IsOk() const { return m_isOk
; }
423 wxMutexError
Lock() { return Lock(kDurationForever
); }
424 wxMutexError
Lock(unsigned long ms
);
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(unsigned long ms
)
456 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") );
458 OSStatus err
= MPEnterCriticalRegion( m_critRegion
, ms
);
465 wxASSERT_MSG( ms
!= kDurationForever
, wxT("unexpected timeout") );
466 return wxMUTEX_TIMEOUT
;
469 wxLogSysError(wxT("Could not lock mutex"));
470 return wxMUTEX_MISC_ERROR
;
473 return wxMUTEX_NO_ERROR
;
476 wxMutexError
wxMutexInternal::TryLock()
478 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") ) ;
480 OSStatus err
= MPEnterCriticalRegion( m_critRegion
, kDurationImmediate
);
483 if ( err
== kMPTimeoutErr
)
486 wxLogSysError( wxT("Could not try lock mutex") );
487 return wxMUTEX_MISC_ERROR
;
490 return wxMUTEX_NO_ERROR
;
493 wxMutexError
wxMutexInternal::Unlock()
495 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") ) ;
497 OSStatus err
= MPExitCriticalRegion( m_critRegion
);
502 wxLogSysError( wxT("Could not unlock mutex") );
504 return wxMUTEX_MISC_ERROR
;
507 return wxMUTEX_NO_ERROR
;
512 // --------------------------------------------------------------------------
514 // --------------------------------------------------------------------------
516 class wxSemaphoreInternal
519 wxSemaphoreInternal( int initialcount
, int maxcount
);
520 virtual ~wxSemaphoreInternal();
526 wxSemaError
WaitTimeout( unsigned long milliseconds
);
529 { return WaitTimeout( kDurationForever
); }
531 wxSemaError
TryWait()
533 wxSemaError err
= WaitTimeout( kDurationImmediate
);
534 if (err
== wxSEMA_TIMEOUT
)
541 MPSemaphoreID m_semaphore
;
545 wxSemaphoreInternal::wxSemaphoreInternal( int initialcount
, int maxcount
)
548 m_semaphore
= kInvalidID
;
550 // make it practically infinite
553 verify_noerr( MPCreateSemaphore( maxcount
, initialcount
, &m_semaphore
) );
554 m_isOk
= ( m_semaphore
!= kInvalidID
);
558 wxFAIL_MSG( wxT("Error when creating semaphore") );
562 wxSemaphoreInternal::~wxSemaphoreInternal()
564 if (m_semaphore
!= kInvalidID
)
565 MPDeleteSemaphore( m_semaphore
);
570 wxSemaError
wxSemaphoreInternal::WaitTimeout( unsigned long milliseconds
)
572 OSStatus err
= MPWaitOnSemaphore( m_semaphore
, milliseconds
);
575 if (err
== kMPTimeoutErr
)
576 return wxSEMA_TIMEOUT
;
578 return wxSEMA_MISC_ERROR
;
581 return wxSEMA_NO_ERROR
;
584 wxSemaError
wxSemaphoreInternal::Post()
586 OSStatus err
= MPSignalSemaphore( m_semaphore
);
589 return wxSEMA_MISC_ERROR
;
591 return wxSEMA_NO_ERROR
;
594 // ----------------------------------------------------------------------------
595 // wxCondition implementation
596 // ----------------------------------------------------------------------------
600 class wxConditionInternal
603 wxConditionInternal( wxMutex
& mutex
)
614 virtual ~wxConditionInternal() {}
617 { return m_mutex
.IsOk(); }
620 { return WaitTimeout( kDurationForever
); }
622 wxCondError
WaitTimeout( unsigned long msectimeout
);
625 { return DoSignal( false); }
627 wxCondError
Broadcast()
628 { return DoSignal( true ); }
631 wxCondError
DoSignal( bool signalAll
);
634 wxSemaphoreInternal m_semaphore
; // Signals the waiting threads.
635 wxSemaphoreInternal m_gate
;
636 wxCriticalSection m_varSection
;
637 size_t m_waiters
; // Number of threads waiting for a signal.
638 size_t m_signals
; // Number of signals to send.
639 size_t m_canceled
; // Number of canceled waiters in m_waiters.
642 wxCondError
wxConditionInternal::WaitTimeout( unsigned long msectimeout
)
646 if ( ++ m_waiters
== INT_MAX
)
648 m_varSection
.Enter();
650 m_waiters
-= m_canceled
;
651 m_signals
-= m_canceled
;
654 m_varSection
.Leave();
660 wxSemaError err
= m_semaphore
.WaitTimeout( msectimeout
);
661 wxASSERT( err
== wxSEMA_NO_ERROR
|| err
== wxSEMA_TIMEOUT
);
663 m_varSection
.Enter();
665 if ( err
!= wxSEMA_NO_ERROR
)
667 if ( m_signals
> m_canceled
)
669 // A signal is being sent after we timed out.
670 if ( m_waiters
== m_signals
)
672 // There are no excess waiters to catch the signal, so
673 // we must throw it away.
674 wxSemaError err2
= m_semaphore
.Wait();
675 if ( err2
!= wxSEMA_NO_ERROR
)
677 wxLogSysError( wx("Error while waiting on semaphore") );
680 wxASSERT( err2
== wxSEMA_NO_ERROR
);
683 if ( --m_signals
== m_canceled
)
685 // This was the last signal. open the gate.
686 wxASSERT( m_waiters
== m_canceled
);
692 // There are excess waiters to catch the signal, leave it be.
698 // No signals is being sent:
699 // the gate may be open or closed, so we can't touch m_waiters.
706 // We caught a signal.
707 wxASSERT( m_signals
> m_canceled
);
711 if ( --m_signals
== m_canceled
)
713 // This was the last signal. open the gate.
714 wxASSERT( m_waiters
== m_canceled
);
720 m_varSection
.Leave();
724 return err
== wxSEMA_TIMEOUT
? wxCOND_TIMEOUT
: wxCOND_MISC_ERROR
;
726 return wxCOND_NO_ERROR
;
730 wxCondError
wxConditionInternal::DoSignal( bool signalAll
)
733 m_varSection
.Enter();
735 wxASSERT( m_signals
== m_canceled
);
737 if ( m_waiters
== m_canceled
)
739 m_varSection
.Leave();
741 return wxCOND_NO_ERROR
;
746 m_waiters
-= m_canceled
;
751 m_signals
= signalAll
? m_waiters
: 1;
752 size_t n
= m_signals
;
754 m_varSection
.Leave();
756 // Let the waiters inherit the gate lock.
760 wxSemaError err
= m_semaphore
.Post();
761 wxASSERT( err
== wxSEMA_NO_ERROR
);
765 return wxCOND_NO_ERROR
;
769 class wxConditionInternal
772 wxConditionInternal( wxMutex
& mutex
);
775 { return m_mutex
.IsOk() && m_semaphore
.IsOk(); }
778 wxCondError
WaitTimeout( unsigned long milliseconds
);
780 wxCondError
Signal();
781 wxCondError
Broadcast();
784 // the number of threads currently waiting for this condition
787 // the critical section protecting m_numWaiters
788 wxCriticalSection m_csWaiters
;
791 wxSemaphore m_semaphore
;
793 DECLARE_NO_COPY_CLASS(wxConditionInternal
)
796 wxConditionInternal::wxConditionInternal( wxMutex
& mutex
)
799 // another thread can't access it until we return from ctor, so no need to
800 // protect access to m_numWaiters here
804 wxCondError
wxConditionInternal::Wait()
806 // increment the number of waiters
807 IncrementAtomic( &m_numWaiters
);
811 // a potential race condition can occur here
813 // after a thread increments nwaiters, and unlocks the mutex and before the
814 // semaphore.Wait() is called, if another thread can cause a signal to be
817 // this race condition is handled by using a semaphore and incrementing the
818 // semaphore only if 'nwaiters' is greater that zero since the semaphore,
819 // can 'remember' signals the race condition will not occur
821 // wait ( if necessary ) and decrement semaphore
822 wxSemaError err
= m_semaphore
.Wait();
825 return err
== wxSEMA_NO_ERROR
? wxCOND_NO_ERROR
: wxCOND_MISC_ERROR
;
828 wxCondError
wxConditionInternal::WaitTimeout( unsigned long milliseconds
)
830 IncrementAtomic( &m_numWaiters
);
834 // a race condition can occur at this point in the code
836 // please see the comments in Wait(), for details
838 wxSemaError err
= m_semaphore
.WaitTimeout(milliseconds
);
840 if ( err
== wxSEMA_TIMEOUT
)
842 // another potential race condition exists here it is caused when a
843 // 'waiting' thread timesout, and returns from WaitForSingleObject, but
844 // has not yet decremented 'nwaiters'.
846 // at this point if another thread calls signal() then the semaphore
847 // will be incremented, but the waiting thread will miss it.
849 // to handle this particular case, the waiting thread calls
850 // WaitForSingleObject again with a timeout of 0, after locking
851 // 'nwaiters_mutex'. this call does not block because of the zero
852 // timeout, but will allow the waiting thread to catch the missed
854 wxCriticalSectionLocker
lock(m_csWaiters
);
856 err
= m_semaphore
.WaitTimeout(0);
858 if ( err
!= wxSEMA_NO_ERROR
)
866 return err
== wxSEMA_NO_ERROR
? wxCOND_NO_ERROR
: wxCOND_MISC_ERROR
;
869 wxCondError
wxConditionInternal::Signal()
871 wxCriticalSectionLocker
lock(m_csWaiters
);
873 if ( m_numWaiters
> 0 )
875 // increment the semaphore by 1
876 if ( m_semaphore
.Post() != wxSEMA_NO_ERROR
)
877 return wxCOND_MISC_ERROR
;
882 return wxCOND_NO_ERROR
;
885 wxCondError
wxConditionInternal::Broadcast()
887 wxCriticalSectionLocker
lock(m_csWaiters
);
889 while ( m_numWaiters
> 0 )
891 if ( m_semaphore
.Post() != wxSEMA_NO_ERROR
)
892 return wxCOND_MISC_ERROR
;
897 return wxCOND_NO_ERROR
;
901 // ----------------------------------------------------------------------------
902 // wxCriticalSection implementation
903 // ----------------------------------------------------------------------------
905 // XXX currently implemented as mutex in headers. Change to critical section.
907 // ----------------------------------------------------------------------------
908 // wxThread implementation
909 // ----------------------------------------------------------------------------
911 // wxThreadInternal class
912 // ----------------------
914 class wxThreadInternal
921 m_prio
= WXTHREAD_DEFAULT_PRIORITY
;
922 m_notifyQueueId
= kInvalidID
;
924 m_cancelled
= false ;
926 // set to true only when the thread starts waiting on m_semSuspend
929 // defaults for joinable threads
930 m_shouldBeJoined
= true;
931 m_isDetached
= false;
934 virtual ~wxThreadInternal()
936 if ( m_notifyQueueId
)
938 MPDeleteQueue( m_notifyQueueId
);
939 m_notifyQueueId
= kInvalidID
;
944 static OSStatus
MacThreadStart(void* arg
);
946 // create a new (suspended) thread (for the given thread object)
947 bool Create(wxThread
*thread
, unsigned int stackSize
);
954 // unblock the thread allowing it to run
955 void SignalRun() { m_semRun
.Post(); }
957 // ask the thread to terminate
960 // go to sleep until Resume() is called
968 int GetPriority() const
970 void SetPriority(int prio
);
973 wxThreadState
GetState() const
975 void SetState(wxThreadState state
)
978 // Get the ID of this thread's underlying MP Services task.
979 MPTaskID
GetId() const
983 { m_cancelled
= true; }
985 bool WasCancelled() const
986 { return m_cancelled
; }
989 void SetExitCode(wxThread::ExitCode exitcode
)
990 { m_exitcode
= exitcode
; }
991 wxThread::ExitCode
GetExitCode() const
992 { return m_exitcode
; }
995 void SetReallyPaused(bool paused
)
996 { m_isPaused
= paused
; }
997 bool IsReallyPaused() const
998 { return m_isPaused
; }
1000 // tell the thread that it is a detached one
1003 wxCriticalSectionLocker
lock(m_csJoinFlag
);
1005 m_shouldBeJoined
= false;
1006 m_isDetached
= true;
1010 // the thread we're associated with
1011 wxThread
* m_thread
;
1013 MPTaskID m_tid
; // thread id
1014 MPQueueID m_notifyQueueId
; // its notification queue
1016 wxThreadState m_state
; // see wxThreadState enum
1017 int m_prio
; // in wxWidgets units: from 0 to 100
1019 // this flag is set when the thread should terminate
1022 // this flag is set when the thread is blocking on m_semSuspend
1025 // the thread exit code - only used for joinable (!detached) threads and
1026 // is only valid after the thread termination
1027 wxThread::ExitCode m_exitcode
;
1029 // many threads may call Wait(), but only one of them should call
1030 // pthread_join(), so we have to keep track of this
1031 wxCriticalSection m_csJoinFlag
;
1032 bool m_shouldBeJoined
;
1035 // this semaphore is posted by Run() and the threads Entry() is not
1036 // called before it is done
1037 wxSemaphore m_semRun
;
1039 // this one is signaled when the thread should resume after having been
1041 wxSemaphore m_semSuspend
;
1044 OSStatus
wxThreadInternal::MacThreadStart(void *parameter
)
1046 wxThread
* thread
= (wxThread
*) parameter
;
1047 wxThreadInternal
*pthread
= thread
->m_internal
;
1049 // add to TLS so that This() will work
1050 verify_noerr( MPSetTaskStorageValue( gs_tlsForWXThread
, (TaskStorageValue
) thread
) ) ;
1052 // have to declare this before pthread_cleanup_push() which defines a
1056 // wait for the semaphore to be posted from Run()
1057 pthread
->m_semRun
.Wait();
1059 // test whether we should run the run at all - may be it was deleted
1060 // before it started to Run()?
1062 wxCriticalSectionLocker
lock(thread
->m_critsect
);
1064 dontRunAtAll
= pthread
->GetState() == STATE_NEW
&&
1065 pthread
->WasCancelled();
1068 if ( !dontRunAtAll
)
1070 pthread
->m_exitcode
= thread
->Entry();
1073 wxCriticalSectionLocker
lock(thread
->m_critsect
);
1074 pthread
->SetState( STATE_EXITED
);
1080 if ( pthread
->m_isDetached
)
1087 // on Mac for the running code,
1088 // the correct thread termination is to return
1090 // terminate the thread
1091 thread
->Exit( pthread
->m_exitcode
);
1093 return (OSStatus
) NULL
; // pthread->m_exitcode;
1097 bool wxThreadInternal::Create( wxThread
*thread
, unsigned int stackSize
)
1099 wxASSERT_MSG( m_state
== STATE_NEW
&& !m_tid
,
1100 wxT("Create()ing thread twice?") );
1102 OSStatus err
= noErr
;
1105 if ( m_notifyQueueId
== kInvalidID
)
1107 OSStatus err
= MPCreateQueue( &m_notifyQueueId
);
1110 wxLogSysError( wxT("Cant create the thread event queue") );
1116 m_state
= STATE_NEW
;
1119 MacThreadStart
, (void*)m_thread
, stackSize
,
1120 m_notifyQueueId
, &m_exitcode
, 0, 0, &m_tid
);
1124 wxLogSysError( wxT("Can't create thread") );
1129 if ( m_prio
!= WXTHREAD_DEFAULT_PRIORITY
)
1130 SetPriority( m_prio
);
1135 void wxThreadInternal::SetPriority( int priority
)
1141 // Mac priorities range from 1 to 10,000, with a default of 100.
1142 // wxWidgets priorities range from 0 to 100 with a default of 50.
1143 // We can map wxWidgets to Mac priorities easily by assuming
1144 // the former uses a logarithmic scale.
1145 const unsigned int macPriority
= (int)( exp( priority
/ 25.0 * log( 10.0)) + 0.5);
1147 MPSetTaskWeight( m_tid
, macPriority
);
1151 wxThreadError
wxThreadInternal::Run()
1153 wxCHECK_MSG( GetState() == STATE_NEW
, wxTHREAD_RUNNING
,
1154 wxT("thread may only be started once after Create()") );
1156 SetState( STATE_RUNNING
);
1158 // wake up threads waiting for our start
1161 return wxTHREAD_NO_ERROR
;
1164 void wxThreadInternal::Wait()
1166 wxCHECK_RET( !m_isDetached
, wxT("can't wait for a detached thread") );
1168 // if the thread we're waiting for is waiting for the GUI mutex, we will
1169 // deadlock so make sure we release it temporarily
1170 if ( wxThread::IsMain() )
1172 // give the thread we're waiting for chance to do the GUI call
1173 // it might be in, we don't do this conditionally as the to be waited on
1174 // thread might have to acquire the mutex later but before terminating
1175 if ( wxGuiOwnedByMainThread() )
1180 wxCriticalSectionLocker
lock(m_csJoinFlag
);
1182 if ( m_shouldBeJoined
)
1184 void *param1
, *param2
, *rc
;
1186 OSStatus err
= MPWaitOnQueue(
1194 wxLogSysError( wxT( "Cannot wait for thread termination."));
1198 // actually param1 would be the address of m_exitcode
1199 // but we don't need this here
1202 m_shouldBeJoined
= false;
1207 void wxThreadInternal::Pause()
1209 // the state is set from the thread which pauses us first, this function
1210 // is called later so the state should have been already set
1211 wxCHECK_RET( m_state
== STATE_PAUSED
,
1212 wxT("thread must first be paused with wxThread::Pause().") );
1214 // wait until the semaphore is Post()ed from Resume()
1215 m_semSuspend
.Wait();
1218 void wxThreadInternal::Resume()
1220 wxCHECK_RET( m_state
== STATE_PAUSED
,
1221 wxT("can't resume thread which is not suspended.") );
1223 // the thread might be not actually paused yet - if there were no call to
1224 // TestDestroy() since the last call to Pause() for example
1225 if ( IsReallyPaused() )
1228 m_semSuspend
.Post();
1231 SetReallyPaused( false );
1234 SetState( STATE_RUNNING
);
1240 wxThread
*wxThread::This()
1242 wxThread
* thr
= (wxThread
*) MPGetTaskStorageValue( gs_tlsForWXThread
) ;
1247 bool wxThread::IsMain()
1249 return GetCurrentId() == gs_idMainThread
|| gs_idMainThread
== kInvalidID
;
1256 void wxThread::Yield()
1258 #if TARGET_API_MAC_OSX
1259 CFRunLoopRunInMode( kCFRunLoopDefaultMode
, 0 , true ) ;
1265 void wxThread::Sleep( unsigned long milliseconds
)
1267 AbsoluteTime wakeup
= AddDurationToAbsolute( milliseconds
, UpTime() );
1268 MPDelayUntil( &wakeup
);
1271 int wxThread::GetCPUCount()
1273 return MPProcessors();
1276 unsigned long wxThread::GetCurrentId()
1278 return (unsigned long)MPCurrentTaskID();
1281 bool wxThread::SetConcurrency( size_t level
)
1283 // Cannot be set in MacOS.
1287 wxThread::wxThread( wxThreadKind kind
)
1289 g_numberOfThreads
++;
1290 m_internal
= new wxThreadInternal();
1292 m_isDetached
= (kind
== wxTHREAD_DETACHED
);
1295 wxThread::~wxThread()
1297 wxASSERT_MSG( g_numberOfThreads
>0 , wxT("More threads deleted than created.") ) ;
1299 g_numberOfThreads
--;
1304 // check that the thread either exited or couldn't be created
1305 if ( m_internal
->GetState() != STATE_EXITED
&&
1306 m_internal
->GetState() != STATE_NEW
)
1309 wxT("The thread %ld is being destroyed although it is still running! The application may crash."),
1316 wxDELETE( m_internal
) ;
1319 wxThreadError
wxThread::Create( unsigned int stackSize
)
1321 wxCriticalSectionLocker
lock(m_critsect
);
1324 m_internal
->Detach() ;
1326 if ( !m_internal
->Create(this, stackSize
) )
1328 m_internal
->SetState( STATE_EXITED
);
1330 return wxTHREAD_NO_RESOURCE
;
1333 return wxTHREAD_NO_ERROR
;
1336 wxThreadError
wxThread::Run()
1338 wxCriticalSectionLocker
lock(m_critsect
);
1340 wxCHECK_MSG( m_internal
->GetId(), wxTHREAD_MISC_ERROR
,
1341 wxT("must call wxThread::Create() first") );
1343 return m_internal
->Run();
1346 // -----------------------------------------------------------------------------
1348 // -----------------------------------------------------------------------------
1350 wxThreadError
wxThread::Pause()
1352 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
,
1353 _T("a thread can't pause itself") );
1355 wxCriticalSectionLocker
lock(m_critsect
);
1357 if ( m_internal
->GetState() != STATE_RUNNING
)
1359 wxLogDebug( wxT("Can't pause thread which is not running.") );
1361 return wxTHREAD_NOT_RUNNING
;
1364 // just set a flag, the thread will be really paused only during the next
1365 // call to TestDestroy()
1366 m_internal
->SetState( STATE_PAUSED
);
1368 return wxTHREAD_NO_ERROR
;
1371 wxThreadError
wxThread::Resume()
1373 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
,
1374 wxT("a thread can't resume itself") );
1376 wxCriticalSectionLocker
lock(m_critsect
);
1378 wxThreadState state
= m_internal
->GetState();
1383 m_internal
->Resume();
1384 return wxTHREAD_NO_ERROR
;
1387 return wxTHREAD_NO_ERROR
;
1390 wxLogDebug( wxT("Attempt to resume a thread which is not paused.") );
1392 return wxTHREAD_MISC_ERROR
;
1396 // -----------------------------------------------------------------------------
1398 // -----------------------------------------------------------------------------
1400 wxThread::ExitCode
wxThread::Wait()
1402 wxCHECK_MSG( This() != this, (ExitCode
)-1,
1403 wxT("a thread can't wait for itself") );
1405 wxCHECK_MSG( !m_isDetached
, (ExitCode
)-1,
1406 wxT("can't wait for detached thread") );
1410 return m_internal
->GetExitCode();
1413 wxThreadError
wxThread::Delete(ExitCode
*rc
)
1415 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
,
1416 wxT("a thread can't delete itself") );
1418 bool isDetached
= m_isDetached
;
1421 wxThreadState state
= m_internal
->GetState();
1423 // ask the thread to stop
1424 m_internal
->SetCancelFlag();
1431 // we need to wake up the thread so that PthreadStart() will
1432 // terminate - right now it's blocking on run semaphore in
1434 m_internal
->SignalRun();
1443 // resume the thread first
1444 m_internal
->Resume();
1451 // wait until the thread stops
1456 // return the exit code of the thread
1457 *rc
= m_internal
->GetExitCode();
1462 return wxTHREAD_NO_ERROR
;
1465 wxThreadError
wxThread::Kill()
1467 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
,
1468 wxT("a thread can't kill itself") );
1470 switch ( m_internal
->GetState() )
1474 return wxTHREAD_NOT_RUNNING
;
1477 // resume the thread first
1483 OSStatus err
= MPTerminateTask( m_internal
->GetId() , -1 ) ;
1486 wxLogError( wxT("Failed to terminate a thread.") );
1488 return wxTHREAD_MISC_ERROR
;
1497 // this should be retrieved by Wait actually
1498 m_internal
->SetExitCode( (void*)-1 );
1501 return wxTHREAD_NO_ERROR
;
1505 void wxThread::Exit( ExitCode status
)
1507 wxASSERT_MSG( This() == this,
1508 wxT("wxThread::Exit() can only be called in the context of the same thread") );
1510 // don't enter m_critsect before calling OnExit() because the user code
1511 // might deadlock if, for example, it signals a condition in OnExit() (a
1512 // common case) while the main thread calls any of functions entering
1513 // m_critsect on us (almost all of them do)
1516 MPTaskID threadid
= m_internal
->GetId();
1524 // update the status of the joinable thread
1525 wxCriticalSectionLocker
lock( m_critsect
);
1526 m_internal
->SetState( STATE_EXITED
);
1529 MPTerminateTask( threadid
, (long)status
);
1532 // also test whether we were paused
1533 bool wxThread::TestDestroy()
1535 wxASSERT_MSG( This() == this,
1536 wxT("wxThread::TestDestroy() can only be called in the context of the same thread") );
1540 if ( m_internal
->GetState() == STATE_PAUSED
)
1542 m_internal
->SetReallyPaused( true );
1544 // leave the crit section or the other threads will stop too if they attempt
1545 // to call any of (seemingly harmless) IsXXX() functions while we sleep
1548 m_internal
->Pause();
1552 // thread wasn't requested to pause, nothing to do
1556 return m_internal
->WasCancelled();
1559 // -----------------------------------------------------------------------------
1561 // -----------------------------------------------------------------------------
1563 void wxThread::SetPriority(unsigned int prio
)
1565 wxCHECK_RET( ((int)WXTHREAD_MIN_PRIORITY
<= (int)prio
) &&
1566 ((int)prio
<= (int)WXTHREAD_MAX_PRIORITY
),
1567 wxT("invalid thread priority") );
1569 wxCriticalSectionLocker
lock(m_critsect
);
1571 switch ( m_internal
->GetState() )
1576 // thread not yet started, priority will be set when it is
1577 m_internal
->SetPriority( prio
);
1582 wxFAIL_MSG( wxT("impossible to set thread priority in this state") );
1586 unsigned int wxThread::GetPriority() const
1588 wxCriticalSectionLocker
lock((wxCriticalSection
&)m_critsect
); // const_cast
1590 return m_internal
->GetPriority();
1593 unsigned long wxThread::GetId() const
1595 wxCriticalSectionLocker
lock((wxCriticalSection
&)m_critsect
); // const_cast
1597 return (unsigned long)m_internal
->GetId();
1600 // -----------------------------------------------------------------------------
1602 // -----------------------------------------------------------------------------
1604 bool wxThread::IsRunning() const
1606 wxCriticalSectionLocker
lock((wxCriticalSection
&)m_critsect
);
1608 return m_internal
->GetState() == STATE_RUNNING
;
1611 bool wxThread::IsAlive() const
1613 wxCriticalSectionLocker
lock((wxCriticalSection
&)m_critsect
);
1615 switch ( m_internal
->GetState() )
1626 bool wxThread::IsPaused() const
1628 wxCriticalSectionLocker
lock((wxCriticalSection
&)m_critsect
);
1630 return (m_internal
->GetState() == STATE_PAUSED
);
1633 // ----------------------------------------------------------------------------
1634 // Automatic initialization for thread module
1635 // ----------------------------------------------------------------------------
1637 class wxThreadModule
: public wxModule
1640 virtual bool OnInit();
1641 virtual void OnExit();
1644 DECLARE_DYNAMIC_CLASS(wxThreadModule
)
1647 IMPLEMENT_DYNAMIC_CLASS(wxThreadModule
, wxModule
)
1649 bool wxThreadModule::OnInit()
1651 bool hasThreadManager
=
1653 true ; // TODO VERIFY IN NEXT BUILD
1655 MPLibraryIsLoaded();
1658 if ( !hasThreadManager
)
1660 wxLogError( wxT("MP thread support is not available on this system" ) ) ;
1665 // main thread's This() is NULL
1666 verify_noerr( MPAllocateTaskStorageIndex( &gs_tlsForWXThread
) ) ;
1667 verify_noerr( MPSetTaskStorageValue( gs_tlsForWXThread
, 0 ) ) ;
1669 gs_idMainThread
= wxThread::GetCurrentId();
1670 gs_critsectWaitingForGui
= new wxCriticalSection();
1672 gs_critsectGui
= new wxCriticalSection();
1673 gs_critsectGui
->Enter();
1678 void wxThreadModule::OnExit()
1680 if ( gs_critsectGui
)
1682 if ( !wxGuiOwnedByMainThread() )
1684 gs_critsectGui
->Enter();
1685 gs_bGuiOwnedByMainThread
= true;
1688 gs_critsectGui
->Leave();
1689 delete gs_critsectGui
;
1690 gs_critsectGui
= NULL
;
1693 delete gs_critsectWaitingForGui
;
1694 gs_critsectWaitingForGui
= NULL
;
1697 // ----------------------------------------------------------------------------
1698 // GUI Serialization copied from MSW implementation
1699 // ----------------------------------------------------------------------------
1701 void WXDLLIMPEXP_BASE
wxMutexGuiEnter()
1703 // this would dead lock everything...
1704 wxASSERT_MSG( !wxThread::IsMain(),
1705 wxT("main thread doesn't want to block in wxMutexGuiEnter()!") );
1707 // the order in which we enter the critical sections here is crucial!!
1709 // set the flag telling to the main thread that we want to do some GUI
1711 wxCriticalSectionLocker
enter(*gs_critsectWaitingForGui
);
1713 gs_nWaitingForGui
++;
1716 wxWakeUpMainThread();
1718 // now we may block here because the main thread will soon let us in
1719 // (during the next iteration of OnIdle())
1720 gs_critsectGui
->Enter();
1723 void WXDLLIMPEXP_BASE
wxMutexGuiLeave()
1725 wxCriticalSectionLocker
enter(*gs_critsectWaitingForGui
);
1727 if ( wxThread::IsMain() )
1729 gs_bGuiOwnedByMainThread
= false;
1733 // decrement the number of threads waiting for GUI access now
1734 wxASSERT_MSG( gs_nWaitingForGui
> 0,
1735 wxT("calling wxMutexGuiLeave() without entering it first?") );
1737 gs_nWaitingForGui
--;
1739 wxWakeUpMainThread();
1742 gs_critsectGui
->Leave();
1745 void WXDLLIMPEXP_BASE
wxMutexGuiLeaveOrEnter()
1747 wxASSERT_MSG( wxThread::IsMain(),
1748 wxT("only main thread may call wxMutexGuiLeaveOrEnter()!") );
1750 if ( !gs_critsectWaitingForGui
)
1753 wxCriticalSectionLocker
enter(*gs_critsectWaitingForGui
);
1755 if ( gs_nWaitingForGui
== 0 )
1757 // no threads are waiting for GUI - so we may acquire the lock without
1758 // any danger (but only if we don't already have it)
1759 if ( !wxGuiOwnedByMainThread() )
1761 gs_critsectGui
->Enter();
1763 gs_bGuiOwnedByMainThread
= true;
1765 //else: already have it, nothing to do
1769 // some threads are waiting, release the GUI lock if we have it
1770 if ( wxGuiOwnedByMainThread() )
1772 //else: some other worker thread is doing GUI
1776 bool WXDLLIMPEXP_BASE
wxGuiOwnedByMainThread()
1778 return gs_bGuiOwnedByMainThread
;
1781 // wake up the main thread
1782 void WXDLLEXPORT
wxWakeUpMainThread()
1787 // ----------------------------------------------------------------------------
1788 // include common implementation code
1789 // ----------------------------------------------------------------------------
1791 #include "wx/thrimpl.cpp"
1793 #endif // wxUSE_THREADS