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__)
25 #include "wx/module.h"
26 #include "wx/thread.h"
30 #include <CoreServices/CoreServices.h>
32 #include <DriverServices.h>
33 #include <Multiprocessing.h>
37 #include "wx/mac/uma.h"
40 #include "wx/mac/macnotfy.h"
43 // the possible states of the thread:
44 // ("=>" shows all possible transitions from this state)
47 STATE_NEW
, // didn't start execution yet (=> RUNNING)
48 STATE_RUNNING
, // thread is running (=> PAUSED, CANCELED)
49 STATE_PAUSED
, // thread is temporarily suspended (=> RUNNING)
50 STATE_CANCELED
, // thread should terminate a.s.a.p. (=> EXITED)
51 STATE_EXITED
// thread is terminating
54 // ----------------------------------------------------------------------------
56 // ----------------------------------------------------------------------------
58 // the task ID of the main thread
59 static wxThreadIdType gs_idMainThread
= kInvalidID
;
61 // this is the Per-Task Storage for the pointer to the appropriate wxThread
62 TaskStorageIndex gs_tlsForWXThread
= 0;
64 // if it's false, some secondary thread is holding the GUI lock
65 static bool gs_bGuiOwnedByMainThread
= true;
67 // critical section which controls access to all GUI functions: any secondary
68 // thread (i.e. except the main one) must enter this crit section before doing
70 static wxCriticalSection
*gs_critsectGui
= NULL
;
72 // critical section which protects gs_nWaitingForGui variable
73 static wxCriticalSection
*gs_critsectWaitingForGui
= NULL
;
75 // number of threads waiting for GUI in wxMutexGuiEnter()
76 static size_t gs_nWaitingForGui
= 0;
78 // overall number of threads, needed for determining
79 // the sleep value of the main event loop
80 size_t g_numberOfThreads
= 0;
84 MPCriticalRegionID gs_guiCritical
= kInvalidID
;
87 // ============================================================================
88 // MacOS implementation of thread classes
89 // ============================================================================
94 The implementation is very close to the phtreads implementation, the reason for
95 using MPServices is the fact that these are also available under OS 9. Thus allowing
96 for one common API for all current builds.
98 As soon as wxThreads are on a 64 bit address space, the TLS must be extended
99 to use two indices one for each 32 bit part as the MP implementation is limited
102 I have three implementations for mutexes :
103 version A based on a binary semaphore, problem - not reentrant, version B based
104 on a critical region, allows for reentrancy, performance implications not
105 yet tested, and third a plain pthreads implementation
107 The same for condition internal, one implementation by Aj Lavin and the other one
108 copied from the thrimpl.cpp which I assume has been more broadly tested, I've just
109 replaced the interlock increment with the appropriate PPC calls
112 // ----------------------------------------------------------------------------
114 // ----------------------------------------------------------------------------
116 wxCriticalSection::wxCriticalSection()
118 MPCreateCriticalRegion( (MPCriticalRegionID
*) &m_critRegion
);
121 wxCriticalSection::~wxCriticalSection()
123 MPDeleteCriticalRegion( (MPCriticalRegionID
) m_critRegion
);
126 void wxCriticalSection::Enter()
128 MPEnterCriticalRegion( (MPCriticalRegionID
) m_critRegion
, kDurationForever
);
131 void wxCriticalSection::Leave()
133 MPExitCriticalRegion( (MPCriticalRegionID
) m_critRegion
);
136 // ----------------------------------------------------------------------------
137 // wxMutex implementation
138 // ----------------------------------------------------------------------------
140 #if TARGET_API_MAC_OSX
141 #define wxUSE_MAC_SEMAPHORE_MUTEX 0
142 #define wxUSE_MAC_CRITICAL_REGION_MUTEX 1
143 #define wxUSE_MAC_PTHREADS_MUTEX 0
145 #define wxUSE_MAC_SEMAPHORE_MUTEX 0
146 #define wxUSE_MAC_CRITICAL_REGION_MUTEX 1
147 #define wxUSE_MAC_PTHREADS_MUTEX 0
150 #if wxUSE_MAC_PTHREADS_MUTEX
155 class wxMutexInternal
158 wxMutexInternal( wxMutexType mutexType
);
162 wxMutexError
TryLock();
163 wxMutexError
Unlock();
169 pthread_mutex_t m_mutex
;
172 // wxConditionInternal uses our m_mutex
173 friend class wxConditionInternal
;
176 #ifdef HAVE_PTHREAD_MUTEXATTR_T
177 // on some systems pthread_mutexattr_settype() is not in the headers (but it is
178 // in the library, otherwise we wouldn't compile this code at all)
179 extern "C" int pthread_mutexattr_settype( pthread_mutexattr_t
*, int );
182 wxMutexInternal::wxMutexInternal( wxMutexType mutexType
)
187 case wxMUTEX_RECURSIVE
:
188 // support recursive locks like Win32, i.e. a thread can lock a
189 // mutex which it had itself already locked
191 // unfortunately initialization of recursive mutexes is non
192 // portable, so try several methods
193 #ifdef HAVE_PTHREAD_MUTEXATTR_T
195 pthread_mutexattr_t attr
;
196 pthread_mutexattr_init( &attr
);
197 pthread_mutexattr_settype( &attr
, PTHREAD_MUTEX_RECURSIVE
);
199 err
= pthread_mutex_init( &m_mutex
, &attr
);
201 #elif defined(HAVE_PTHREAD_RECURSIVE_MUTEX_INITIALIZER)
202 // we can use this only as initializer so we have to assign it
203 // first to a temp var - assigning directly to m_mutex wouldn't
206 pthread_mutex_t mutex
= PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
;
209 #else // no recursive mutexes
211 #endif // HAVE_PTHREAD_MUTEXATTR_T/...
215 wxFAIL_MSG( wxT("unknown mutex type") );
218 case wxMUTEX_DEFAULT
:
219 err
= pthread_mutex_init( &m_mutex
, NULL
);
226 wxLogApiError( wxT("pthread_mutex_init()"), err
);
230 wxMutexInternal::~wxMutexInternal()
234 int err
= pthread_mutex_destroy( &m_mutex
);
237 wxLogApiError( wxT("pthread_mutex_destroy()"), err
);
242 wxMutexError
wxMutexInternal::Lock()
244 int err
= pthread_mutex_lock( &m_mutex
);
248 // only error checking mutexes return this value and so it's an
249 // unexpected situation -- hence use assert, not wxLogDebug
250 wxFAIL_MSG( wxT("mutex deadlock prevented") );
251 return wxMUTEX_DEAD_LOCK
;
254 wxLogDebug( wxT("pthread_mutex_lock(): mutex not initialized.") );
258 return wxMUTEX_NO_ERROR
;
261 wxLogApiError( wxT("pthread_mutex_lock()"), err
);
264 return wxMUTEX_MISC_ERROR
;
267 wxMutexError
wxMutexInternal::TryLock()
269 int err
= pthread_mutex_trylock( &m_mutex
);
273 // not an error: mutex is already locked, but we're prepared for this case
277 wxLogDebug( wxT("pthread_mutex_trylock(): mutex not initialized.") );
281 return wxMUTEX_NO_ERROR
;
284 wxLogApiError( wxT("pthread_mutex_trylock()"), err
);
287 return wxMUTEX_MISC_ERROR
;
290 wxMutexError
wxMutexInternal::Unlock()
292 int err
= pthread_mutex_unlock( &m_mutex
);
296 // we don't own the mutex
297 return wxMUTEX_UNLOCKED
;
300 wxLogDebug( wxT("pthread_mutex_unlock(): mutex not initialized.") );
304 return wxMUTEX_NO_ERROR
;
307 wxLogApiError( wxT("pthread_mutex_unlock()"), err
);
310 return wxMUTEX_MISC_ERROR
;
315 #if wxUSE_MAC_SEMAPHORE_MUTEX
317 class wxMutexInternal
320 wxMutexInternal( wxMutexType mutexType
);
321 virtual ~wxMutexInternal();
327 wxMutexError
TryLock();
328 wxMutexError
Unlock();
331 MPSemaphoreID m_semaphore
;
335 wxMutexInternal::wxMutexInternal(wxMutexType mutexType
)
338 m_semaphore
= kInvalidID
;
339 OSStatus err
= noErr
;
343 case wxMUTEX_DEFAULT
:
344 verify_noerr( MPCreateBinarySemaphore( &m_semaphore
) );
345 m_isOk
= ( m_semaphore
!= kInvalidID
);
348 case wxMUTEX_RECURSIVE
:
349 wxFAIL_MSG( wxT("Recursive Mutex not supported yet") );
353 wxFAIL_MSG( wxT("Unknown mutex type") );
358 wxMutexInternal::~wxMutexInternal()
360 if ( m_semaphore
!= kInvalidID
)
361 MPDeleteSemaphore( m_semaphore
);
366 wxMutexError
wxMutexInternal::Lock()
368 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") );
369 OSStatus err
= MPWaitOnSemaphore( m_semaphore
, kDurationForever
);
372 wxLogSysError( wxT("Could not lock mutex") );
374 return wxMUTEX_MISC_ERROR
;
377 return wxMUTEX_NO_ERROR
;
380 wxMutexError
wxMutexInternal::TryLock()
382 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") );
383 OSStatus err
= MPWaitOnSemaphore( m_semaphore
, kDurationImmediate
);
386 if (err
== kMPTimeoutErr
)
389 wxLogSysError( wxT("Could not try lock mutex") );
391 return wxMUTEX_MISC_ERROR
;
394 return wxMUTEX_NO_ERROR
;
397 wxMutexError
wxMutexInternal::Unlock()
399 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") );
400 OSStatus err
= MPSignalSemaphore( m_semaphore
);
405 wxLogSysError( wxT("Could not unlock mutex") );
406 return wxMUTEX_MISC_ERROR
;
409 return wxMUTEX_NO_ERROR
;
414 #if wxUSE_MAC_CRITICAL_REGION_MUTEX
416 class wxMutexInternal
419 wxMutexInternal( wxMutexType mutexType
);
420 virtual ~wxMutexInternal();
425 wxMutexError
Lock() ;
426 wxMutexError
TryLock();
427 wxMutexError
Unlock();
430 MPCriticalRegionID m_critRegion
;
434 wxMutexInternal::wxMutexInternal( wxMutexType mutexType
)
437 m_critRegion
= kInvalidID
;
439 verify_noerr( MPCreateCriticalRegion( &m_critRegion
) );
440 m_isOk
= ( m_critRegion
!= kInvalidID
);
443 wxFAIL_MSG( wxT("Error when creating mutex") );
447 wxMutexInternal::~wxMutexInternal()
449 if ( m_critRegion
!= kInvalidID
)
450 MPDeleteCriticalRegion( m_critRegion
);
455 wxMutexError
wxMutexInternal::Lock()
457 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") );
459 OSStatus err
= MPEnterCriticalRegion( m_critRegion
, kDurationForever
);
462 wxLogSysError(wxT("Could not lock mutex"));
463 return wxMUTEX_MISC_ERROR
;
466 return wxMUTEX_NO_ERROR
;
469 wxMutexError
wxMutexInternal::TryLock()
471 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") ) ;
473 OSStatus err
= MPEnterCriticalRegion( m_critRegion
, kDurationImmediate
);
476 if ( err
== kMPTimeoutErr
)
479 wxLogSysError( wxT("Could not try lock mutex") );
480 return wxMUTEX_MISC_ERROR
;
483 return wxMUTEX_NO_ERROR
;
486 wxMutexError
wxMutexInternal::Unlock()
488 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") ) ;
490 OSStatus err
= MPExitCriticalRegion( m_critRegion
);
495 wxLogSysError( wxT("Could not unlock mutex") );
497 return wxMUTEX_MISC_ERROR
;
500 return wxMUTEX_NO_ERROR
;
505 // --------------------------------------------------------------------------
507 // --------------------------------------------------------------------------
509 class wxSemaphoreInternal
512 wxSemaphoreInternal( int initialcount
, int maxcount
);
513 virtual ~wxSemaphoreInternal();
519 wxSemaError
WaitTimeout( unsigned long milliseconds
);
522 { return WaitTimeout( kDurationForever
); }
524 wxSemaError
TryWait()
526 wxSemaError err
= WaitTimeout( kDurationImmediate
);
527 if (err
== wxSEMA_TIMEOUT
)
534 MPSemaphoreID m_semaphore
;
538 wxSemaphoreInternal::wxSemaphoreInternal( int initialcount
, int maxcount
)
541 m_semaphore
= kInvalidID
;
543 // make it practically infinite
546 verify_noerr( MPCreateSemaphore( maxcount
, initialcount
, &m_semaphore
) );
547 m_isOk
= ( m_semaphore
!= kInvalidID
);
551 wxFAIL_MSG( wxT("Error when creating semaphore") );
555 wxSemaphoreInternal::~wxSemaphoreInternal()
557 if (m_semaphore
!= kInvalidID
)
558 MPDeleteSemaphore( m_semaphore
);
563 wxSemaError
wxSemaphoreInternal::WaitTimeout( unsigned long milliseconds
)
565 OSStatus err
= MPWaitOnSemaphore( m_semaphore
, milliseconds
);
568 if (err
== kMPTimeoutErr
)
569 return wxSEMA_TIMEOUT
;
571 return wxSEMA_MISC_ERROR
;
574 return wxSEMA_NO_ERROR
;
577 wxSemaError
wxSemaphoreInternal::Post()
579 OSStatus err
= MPSignalSemaphore( m_semaphore
);
582 return wxSEMA_MISC_ERROR
;
584 return wxSEMA_NO_ERROR
;
587 // ----------------------------------------------------------------------------
588 // wxCondition implementation
589 // ----------------------------------------------------------------------------
593 class wxConditionInternal
596 wxConditionInternal( wxMutex
& mutex
)
607 virtual ~wxConditionInternal() {}
610 { return m_mutex
.IsOk(); }
613 { return WaitTimeout( kDurationForever
); }
615 wxCondError
WaitTimeout( unsigned long msectimeout
);
618 { return DoSignal( false); }
620 wxCondError
Broadcast()
621 { return DoSignal( true ); }
624 wxCondError
DoSignal( bool signalAll
);
627 wxSemaphoreInternal m_semaphore
; // Signals the waiting threads.
628 wxSemaphoreInternal m_gate
;
629 wxCriticalSection m_varSection
;
630 size_t m_waiters
; // Number of threads waiting for a signal.
631 size_t m_signals
; // Number of signals to send.
632 size_t m_canceled
; // Number of canceled waiters in m_waiters.
635 wxCondError
wxConditionInternal::WaitTimeout( unsigned long msectimeout
)
639 if ( ++ m_waiters
== INT_MAX
)
641 m_varSection
.Enter();
643 m_waiters
-= m_canceled
;
644 m_signals
-= m_canceled
;
647 m_varSection
.Leave();
653 wxSemaError err
= m_semaphore
.WaitTimeout( msectimeout
);
654 wxASSERT( err
== wxSEMA_NO_ERROR
|| err
== wxSEMA_TIMEOUT
);
656 m_varSection
.Enter();
658 if ( err
!= wxSEMA_NO_ERROR
)
660 if ( m_signals
> m_canceled
)
662 // A signal is being sent after we timed out.
663 if ( m_waiters
== m_signals
)
665 // There are no excess waiters to catch the signal, so
666 // we must throw it away.
667 wxSemaError err2
= m_semaphore
.Wait();
668 if ( err2
!= wxSEMA_NO_ERROR
)
670 wxLogSysError( wx("Error while waiting on semaphore") );
673 wxASSERT( err2
== wxSEMA_NO_ERROR
);
676 if ( --m_signals
== m_canceled
)
678 // This was the last signal. open the gate.
679 wxASSERT( m_waiters
== m_canceled
);
685 // There are excess waiters to catch the signal, leave it be.
691 // No signals is being sent:
692 // the gate may be open or closed, so we can't touch m_waiters.
699 // We caught a signal.
700 wxASSERT( m_signals
> m_canceled
);
704 if ( --m_signals
== m_canceled
)
706 // This was the last signal. open the gate.
707 wxASSERT( m_waiters
== m_canceled
);
713 m_varSection
.Leave();
717 return err
== wxSEMA_TIMEOUT
? wxCOND_TIMEOUT
: wxCOND_MISC_ERROR
;
719 return wxCOND_NO_ERROR
;
723 wxCondError
wxConditionInternal::DoSignal( bool signalAll
)
726 m_varSection
.Enter();
728 wxASSERT( m_signals
== m_canceled
);
730 if ( m_waiters
== m_canceled
)
732 m_varSection
.Leave();
734 return wxCOND_NO_ERROR
;
739 m_waiters
-= m_canceled
;
744 m_signals
= signalAll
? m_waiters
: 1;
745 size_t n
= m_signals
;
747 m_varSection
.Leave();
749 // Let the waiters inherit the gate lock.
753 wxSemaError err
= m_semaphore
.Post();
754 wxASSERT( err
== wxSEMA_NO_ERROR
);
758 return wxCOND_NO_ERROR
;
762 class wxConditionInternal
765 wxConditionInternal( wxMutex
& mutex
);
768 { return m_mutex
.IsOk() && m_semaphore
.IsOk(); }
771 wxCondError
WaitTimeout( unsigned long milliseconds
);
773 wxCondError
Signal();
774 wxCondError
Broadcast();
777 // the number of threads currently waiting for this condition
780 // the critical section protecting m_numWaiters
781 wxCriticalSection m_csWaiters
;
784 wxSemaphore m_semaphore
;
786 DECLARE_NO_COPY_CLASS(wxConditionInternal
)
789 wxConditionInternal::wxConditionInternal( wxMutex
& mutex
)
792 // another thread can't access it until we return from ctor, so no need to
793 // protect access to m_numWaiters here
797 wxCondError
wxConditionInternal::Wait()
799 // increment the number of waiters
800 IncrementAtomic( &m_numWaiters
);
804 // a potential race condition can occur here
806 // after a thread increments nwaiters, and unlocks the mutex and before the
807 // semaphore.Wait() is called, if another thread can cause a signal to be
810 // this race condition is handled by using a semaphore and incrementing the
811 // semaphore only if 'nwaiters' is greater that zero since the semaphore,
812 // can 'remember' signals the race condition will not occur
814 // wait ( if necessary ) and decrement semaphore
815 wxSemaError err
= m_semaphore
.Wait();
818 return err
== wxSEMA_NO_ERROR
? wxCOND_NO_ERROR
: wxCOND_MISC_ERROR
;
821 wxCondError
wxConditionInternal::WaitTimeout( unsigned long milliseconds
)
823 IncrementAtomic( &m_numWaiters
);
827 // a race condition can occur at this point in the code
829 // please see the comments in Wait(), for details
831 wxSemaError err
= m_semaphore
.WaitTimeout(milliseconds
);
833 if ( err
== wxSEMA_BUSY
)
835 // another potential race condition exists here it is caused when a
836 // 'waiting' thread timesout, and returns from WaitForSingleObject, but
837 // has not yet decremented 'nwaiters'.
839 // at this point if another thread calls signal() then the semaphore
840 // will be incremented, but the waiting thread will miss it.
842 // to handle this particular case, the waiting thread calls
843 // WaitForSingleObject again with a timeout of 0, after locking
844 // 'nwaiters_mutex'. this call does not block because of the zero
845 // timeout, but will allow the waiting thread to catch the missed
847 wxCriticalSectionLocker
lock(m_csWaiters
);
849 err
= m_semaphore
.WaitTimeout(0);
851 if ( err
!= wxSEMA_NO_ERROR
)
859 return err
== wxSEMA_NO_ERROR
? wxCOND_NO_ERROR
: wxCOND_MISC_ERROR
;
862 wxCondError
wxConditionInternal::Signal()
864 wxCriticalSectionLocker
lock(m_csWaiters
);
866 if ( m_numWaiters
> 0 )
868 // increment the semaphore by 1
869 if ( m_semaphore
.Post() != wxSEMA_NO_ERROR
)
870 return wxCOND_MISC_ERROR
;
875 return wxCOND_NO_ERROR
;
878 wxCondError
wxConditionInternal::Broadcast()
880 wxCriticalSectionLocker
lock(m_csWaiters
);
882 while ( m_numWaiters
> 0 )
884 if ( m_semaphore
.Post() != wxSEMA_NO_ERROR
)
885 return wxCOND_MISC_ERROR
;
890 return wxCOND_NO_ERROR
;
894 // ----------------------------------------------------------------------------
895 // wxCriticalSection implementation
896 // ----------------------------------------------------------------------------
898 // XXX currently implemented as mutex in headers. Change to critical section.
900 // ----------------------------------------------------------------------------
901 // wxThread implementation
902 // ----------------------------------------------------------------------------
904 // wxThreadInternal class
905 // ----------------------
907 class wxThreadInternal
914 m_prio
= WXTHREAD_DEFAULT_PRIORITY
;
915 m_notifyQueueId
= kInvalidID
;
917 m_cancelled
= false ;
919 // set to true only when the thread starts waiting on m_semSuspend
922 // defaults for joinable threads
923 m_shouldBeJoined
= true;
924 m_isDetached
= false;
927 virtual ~wxThreadInternal()
929 if ( m_notifyQueueId
)
931 MPDeleteQueue( m_notifyQueueId
);
932 m_notifyQueueId
= kInvalidID
;
937 static OSStatus
MacThreadStart(void* arg
);
939 // create a new (suspended) thread (for the given thread object)
940 bool Create(wxThread
*thread
, unsigned int stackSize
);
947 // unblock the thread allowing it to run
948 void SignalRun() { m_semRun
.Post(); }
950 // ask the thread to terminate
953 // go to sleep until Resume() is called
961 int GetPriority() const
963 void SetPriority(int prio
);
966 wxThreadState
GetState() const
968 void SetState(wxThreadState state
)
971 // Get the ID of this thread's underlying MP Services task.
972 MPTaskID
GetId() const
976 { m_cancelled
= true; }
978 bool WasCancelled() const
979 { return m_cancelled
; }
982 void SetExitCode(wxThread::ExitCode exitcode
)
983 { m_exitcode
= exitcode
; }
984 wxThread::ExitCode
GetExitCode() const
985 { return m_exitcode
; }
988 void SetReallyPaused(bool paused
)
989 { m_isPaused
= paused
; }
990 bool IsReallyPaused() const
991 { return m_isPaused
; }
993 // tell the thread that it is a detached one
996 wxCriticalSectionLocker
lock(m_csJoinFlag
);
998 m_shouldBeJoined
= false;
1003 // the thread we're associated with
1004 wxThread
* m_thread
;
1006 MPTaskID m_tid
; // thread id
1007 MPQueueID m_notifyQueueId
; // its notification queue
1009 wxThreadState m_state
; // see wxThreadState enum
1010 int m_prio
; // in wxWidgets units: from 0 to 100
1012 // this flag is set when the thread should terminate
1015 // this flag is set when the thread is blocking on m_semSuspend
1018 // the thread exit code - only used for joinable (!detached) threads and
1019 // is only valid after the thread termination
1020 wxThread::ExitCode m_exitcode
;
1022 // many threads may call Wait(), but only one of them should call
1023 // pthread_join(), so we have to keep track of this
1024 wxCriticalSection m_csJoinFlag
;
1025 bool m_shouldBeJoined
;
1028 // this semaphore is posted by Run() and the threads Entry() is not
1029 // called before it is done
1030 wxSemaphore m_semRun
;
1032 // this one is signaled when the thread should resume after having been
1034 wxSemaphore m_semSuspend
;
1037 OSStatus
wxThreadInternal::MacThreadStart(void *parameter
)
1039 wxThread
* thread
= (wxThread
*) parameter
;
1040 wxThreadInternal
*pthread
= thread
->m_internal
;
1042 // add to TLS so that This() will work
1043 verify_noerr( MPSetTaskStorageValue( gs_tlsForWXThread
, (long) thread
) ) ;
1045 // have to declare this before pthread_cleanup_push() which defines a
1049 // wait for the semaphore to be posted from Run()
1050 pthread
->m_semRun
.Wait();
1052 // test whether we should run the run at all - may be it was deleted
1053 // before it started to Run()?
1055 wxCriticalSectionLocker
lock(thread
->m_critsect
);
1057 dontRunAtAll
= pthread
->GetState() == STATE_NEW
&&
1058 pthread
->WasCancelled();
1061 if ( !dontRunAtAll
)
1063 pthread
->m_exitcode
= thread
->Entry();
1066 wxCriticalSectionLocker
lock(thread
->m_critsect
);
1067 pthread
->SetState( STATE_EXITED
);
1073 if ( pthread
->m_isDetached
)
1080 // on Mac for the running code,
1081 // the correct thread termination is to return
1083 // terminate the thread
1084 thread
->Exit( pthread
->m_exitcode
);
1086 return (OSStatus
) NULL
; // pthread->m_exitcode;
1090 bool wxThreadInternal::Create( wxThread
*thread
, unsigned int stackSize
)
1092 wxASSERT_MSG( m_state
== STATE_NEW
&& !m_tid
,
1093 wxT("Create()ing thread twice?") );
1095 OSStatus err
= noErr
;
1098 if ( m_notifyQueueId
== kInvalidID
)
1100 OSStatus err
= MPCreateQueue( &m_notifyQueueId
);
1103 wxLogSysError( wxT("Cant create the thread event queue") );
1109 m_state
= STATE_NEW
;
1112 MacThreadStart
, (void*)m_thread
, stackSize
,
1113 m_notifyQueueId
, &m_exitcode
, 0, 0, &m_tid
);
1117 wxLogSysError( wxT("Can't create thread") );
1122 if ( m_prio
!= WXTHREAD_DEFAULT_PRIORITY
)
1123 SetPriority( m_prio
);
1128 void wxThreadInternal::SetPriority( int priority
)
1134 // Mac priorities range from 1 to 10,000, with a default of 100.
1135 // wxWidgets priorities range from 0 to 100 with a default of 50.
1136 // We can map wxWidgets to Mac priorities easily by assuming
1137 // the former uses a logarithmic scale.
1138 const unsigned int macPriority
= (int)( exp( priority
/ 25.0 * log( 10.0)) + 0.5);
1140 MPSetTaskWeight( m_tid
, macPriority
);
1144 wxThreadError
wxThreadInternal::Run()
1146 wxCHECK_MSG( GetState() == STATE_NEW
, wxTHREAD_RUNNING
,
1147 wxT("thread may only be started once after Create()") );
1149 SetState( STATE_RUNNING
);
1151 // wake up threads waiting for our start
1154 return wxTHREAD_NO_ERROR
;
1157 void wxThreadInternal::Wait()
1159 wxCHECK_RET( !m_isDetached
, wxT("can't wait for a detached thread") );
1161 // if the thread we're waiting for is waiting for the GUI mutex, we will
1162 // deadlock so make sure we release it temporarily
1163 if ( wxThread::IsMain() )
1165 // give the thread we're waiting for chance to do the GUI call
1166 // it might be in, we don't do this conditionally as the to be waited on
1167 // thread might have to acquire the mutex later but before terminating
1168 if ( wxGuiOwnedByMainThread() )
1173 wxCriticalSectionLocker
lock(m_csJoinFlag
);
1175 if ( m_shouldBeJoined
)
1177 void *param1
, *param2
, *rc
;
1179 OSStatus err
= MPWaitOnQueue(
1187 wxLogSysError( wxT( "Cannot wait for thread termination."));
1191 // actually param1 would be the address of m_exitcode
1192 // but we don't need this here
1195 m_shouldBeJoined
= false;
1200 void wxThreadInternal::Pause()
1202 // the state is set from the thread which pauses us first, this function
1203 // is called later so the state should have been already set
1204 wxCHECK_RET( m_state
== STATE_PAUSED
,
1205 wxT("thread must first be paused with wxThread::Pause().") );
1207 // wait until the semaphore is Post()ed from Resume()
1208 m_semSuspend
.Wait();
1211 void wxThreadInternal::Resume()
1213 wxCHECK_RET( m_state
== STATE_PAUSED
,
1214 wxT("can't resume thread which is not suspended.") );
1216 // the thread might be not actually paused yet - if there were no call to
1217 // TestDestroy() since the last call to Pause() for example
1218 if ( IsReallyPaused() )
1221 m_semSuspend
.Post();
1224 SetReallyPaused( false );
1227 SetState( STATE_RUNNING
);
1233 wxThread
*wxThread::This()
1235 wxThread
* thr
= (wxThread
*) MPGetTaskStorageValue( gs_tlsForWXThread
) ;
1240 bool wxThread::IsMain()
1242 return GetCurrentId() == gs_idMainThread
|| gs_idMainThread
== kInvalidID
;
1249 void wxThread::Yield()
1251 #if TARGET_API_MAC_OSX
1252 CFRunLoopRunInMode( kCFRunLoopDefaultMode
, 0 , true ) ;
1258 void wxThread::Sleep( unsigned long milliseconds
)
1260 AbsoluteTime wakeup
= AddDurationToAbsolute( milliseconds
, UpTime() );
1261 MPDelayUntil( &wakeup
);
1264 int wxThread::GetCPUCount()
1266 return MPProcessors();
1269 unsigned long wxThread::GetCurrentId()
1271 return (unsigned long)MPCurrentTaskID();
1274 bool wxThread::SetConcurrency( size_t level
)
1276 // Cannot be set in MacOS.
1280 wxThread::wxThread( wxThreadKind kind
)
1282 g_numberOfThreads
++;
1283 m_internal
= new wxThreadInternal();
1285 m_isDetached
= (kind
== wxTHREAD_DETACHED
);
1288 wxThread::~wxThread()
1290 wxASSERT_MSG( g_numberOfThreads
>0 , wxT("More threads deleted than created.") ) ;
1292 g_numberOfThreads
--;
1297 // check that the thread either exited or couldn't be created
1298 if ( m_internal
->GetState() != STATE_EXITED
&&
1299 m_internal
->GetState() != STATE_NEW
)
1302 wxT("The thread %ld is being destroyed although it is still running! The application may crash."),
1309 wxDELETE( m_internal
) ;
1312 wxThreadError
wxThread::Create( unsigned int stackSize
)
1314 wxCriticalSectionLocker
lock(m_critsect
);
1317 m_internal
->Detach() ;
1319 if ( !m_internal
->Create(this, stackSize
) )
1321 m_internal
->SetState( STATE_EXITED
);
1323 return wxTHREAD_NO_RESOURCE
;
1326 return wxTHREAD_NO_ERROR
;
1329 wxThreadError
wxThread::Run()
1331 wxCriticalSectionLocker
lock(m_critsect
);
1333 wxCHECK_MSG( m_internal
->GetId(), wxTHREAD_MISC_ERROR
,
1334 wxT("must call wxThread::Create() first") );
1336 return m_internal
->Run();
1339 // -----------------------------------------------------------------------------
1341 // -----------------------------------------------------------------------------
1343 wxThreadError
wxThread::Pause()
1345 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
,
1346 _T("a thread can't pause itself") );
1348 wxCriticalSectionLocker
lock(m_critsect
);
1350 if ( m_internal
->GetState() != STATE_RUNNING
)
1352 wxLogDebug( wxT("Can't pause thread which is not running.") );
1354 return wxTHREAD_NOT_RUNNING
;
1357 // just set a flag, the thread will be really paused only during the next
1358 // call to TestDestroy()
1359 m_internal
->SetState( STATE_PAUSED
);
1361 return wxTHREAD_NO_ERROR
;
1364 wxThreadError
wxThread::Resume()
1366 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
,
1367 wxT("a thread can't resume itself") );
1369 wxCriticalSectionLocker
lock(m_critsect
);
1371 wxThreadState state
= m_internal
->GetState();
1376 m_internal
->Resume();
1377 return wxTHREAD_NO_ERROR
;
1380 return wxTHREAD_NO_ERROR
;
1383 wxLogDebug( wxT("Attempt to resume a thread which is not paused.") );
1385 return wxTHREAD_MISC_ERROR
;
1389 // -----------------------------------------------------------------------------
1391 // -----------------------------------------------------------------------------
1393 wxThread::ExitCode
wxThread::Wait()
1395 wxCHECK_MSG( This() != this, (ExitCode
)-1,
1396 wxT("a thread can't wait for itself") );
1398 wxCHECK_MSG( !m_isDetached
, (ExitCode
)-1,
1399 wxT("can't wait for detached thread") );
1403 return m_internal
->GetExitCode();
1406 wxThreadError
wxThread::Delete(ExitCode
*rc
)
1408 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
,
1409 wxT("a thread can't delete itself") );
1411 bool isDetached
= m_isDetached
;
1414 wxThreadState state
= m_internal
->GetState();
1416 // ask the thread to stop
1417 m_internal
->SetCancelFlag();
1424 // we need to wake up the thread so that PthreadStart() will
1425 // terminate - right now it's blocking on run semaphore in
1427 m_internal
->SignalRun();
1436 // resume the thread first
1437 m_internal
->Resume();
1444 // wait until the thread stops
1449 // return the exit code of the thread
1450 *rc
= m_internal
->GetExitCode();
1455 return wxTHREAD_NO_ERROR
;
1458 wxThreadError
wxThread::Kill()
1460 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
,
1461 wxT("a thread can't kill itself") );
1463 switch ( m_internal
->GetState() )
1467 return wxTHREAD_NOT_RUNNING
;
1470 // resume the thread first
1476 OSStatus err
= MPTerminateTask( m_internal
->GetId() , -1 ) ;
1479 wxLogError( wxT("Failed to terminate a thread.") );
1481 return wxTHREAD_MISC_ERROR
;
1490 // this should be retrieved by Wait actually
1491 m_internal
->SetExitCode( (void*)-1 );
1494 return wxTHREAD_NO_ERROR
;
1498 void wxThread::Exit( ExitCode status
)
1500 wxASSERT_MSG( This() == this,
1501 wxT("wxThread::Exit() can only be called in the context of the same thread") );
1503 // don't enter m_critsect before calling OnExit() because the user code
1504 // might deadlock if, for example, it signals a condition in OnExit() (a
1505 // common case) while the main thread calls any of functions entering
1506 // m_critsect on us (almost all of them do)
1509 MPTaskID threadid
= m_internal
->GetId();
1517 // update the status of the joinable thread
1518 wxCriticalSectionLocker
lock( m_critsect
);
1519 m_internal
->SetState( STATE_EXITED
);
1522 MPTerminateTask( threadid
, (long)status
);
1525 // also test whether we were paused
1526 bool wxThread::TestDestroy()
1528 wxASSERT_MSG( This() == this,
1529 wxT("wxThread::TestDestroy() can only be called in the context of the same thread") );
1533 if ( m_internal
->GetState() == STATE_PAUSED
)
1535 m_internal
->SetReallyPaused( true );
1537 // leave the crit section or the other threads will stop too if they attempt
1538 // to call any of (seemingly harmless) IsXXX() functions while we sleep
1541 m_internal
->Pause();
1545 // thread wasn't requested to pause, nothing to do
1549 return m_internal
->WasCancelled();
1552 // -----------------------------------------------------------------------------
1554 // -----------------------------------------------------------------------------
1556 void wxThread::SetPriority(unsigned int prio
)
1558 wxCHECK_RET( ((int)WXTHREAD_MIN_PRIORITY
<= (int)prio
) &&
1559 ((int)prio
<= (int)WXTHREAD_MAX_PRIORITY
),
1560 wxT("invalid thread priority") );
1562 wxCriticalSectionLocker
lock(m_critsect
);
1564 switch ( m_internal
->GetState() )
1569 // thread not yet started, priority will be set when it is
1570 m_internal
->SetPriority( prio
);
1575 wxFAIL_MSG( wxT("impossible to set thread priority in this state") );
1579 unsigned int wxThread::GetPriority() const
1581 wxCriticalSectionLocker
lock((wxCriticalSection
&)m_critsect
); // const_cast
1583 return m_internal
->GetPriority();
1586 unsigned long wxThread::GetId() const
1588 wxCriticalSectionLocker
lock((wxCriticalSection
&)m_critsect
); // const_cast
1590 return (unsigned long)m_internal
->GetId();
1593 // -----------------------------------------------------------------------------
1595 // -----------------------------------------------------------------------------
1597 bool wxThread::IsRunning() const
1599 wxCriticalSectionLocker
lock((wxCriticalSection
&)m_critsect
);
1601 return m_internal
->GetState() == STATE_RUNNING
;
1604 bool wxThread::IsAlive() const
1606 wxCriticalSectionLocker
lock((wxCriticalSection
&)m_critsect
);
1608 switch ( m_internal
->GetState() )
1619 bool wxThread::IsPaused() const
1621 wxCriticalSectionLocker
lock((wxCriticalSection
&)m_critsect
);
1623 return (m_internal
->GetState() == STATE_PAUSED
);
1626 // ----------------------------------------------------------------------------
1627 // Automatic initialization for thread module
1628 // ----------------------------------------------------------------------------
1630 class wxThreadModule
: public wxModule
1633 virtual bool OnInit();
1634 virtual void OnExit();
1637 DECLARE_DYNAMIC_CLASS(wxThreadModule
)
1640 IMPLEMENT_DYNAMIC_CLASS(wxThreadModule
, wxModule
)
1642 bool wxThreadModule::OnInit()
1644 bool hasThreadManager
= MPLibraryIsLoaded();
1646 if ( !hasThreadManager
)
1648 wxLogError( wxT("MP thread support is not available on this system" ) ) ;
1653 // main thread's This() is NULL
1654 verify_noerr( MPAllocateTaskStorageIndex( &gs_tlsForWXThread
) ) ;
1655 verify_noerr( MPSetTaskStorageValue( gs_tlsForWXThread
, 0 ) ) ;
1657 gs_idMainThread
= wxThread::GetCurrentId();
1658 gs_critsectWaitingForGui
= new wxCriticalSection();
1660 gs_critsectGui
= new wxCriticalSection();
1661 gs_critsectGui
->Enter();
1666 void wxThreadModule::OnExit()
1668 if ( gs_critsectGui
)
1670 if ( !wxGuiOwnedByMainThread() )
1672 gs_critsectGui
->Enter();
1673 gs_bGuiOwnedByMainThread
= true;
1676 gs_critsectGui
->Leave();
1677 delete gs_critsectGui
;
1678 gs_critsectGui
= NULL
;
1681 delete gs_critsectWaitingForGui
;
1682 gs_critsectWaitingForGui
= NULL
;
1685 // ----------------------------------------------------------------------------
1686 // GUI Serialization copied from MSW implementation
1687 // ----------------------------------------------------------------------------
1689 void WXDLLIMPEXP_BASE
wxMutexGuiEnter()
1691 // this would dead lock everything...
1692 wxASSERT_MSG( !wxThread::IsMain(),
1693 wxT("main thread doesn't want to block in wxMutexGuiEnter()!") );
1695 // the order in which we enter the critical sections here is crucial!!
1697 // set the flag telling to the main thread that we want to do some GUI
1699 wxCriticalSectionLocker
enter(*gs_critsectWaitingForGui
);
1701 gs_nWaitingForGui
++;
1704 wxWakeUpMainThread();
1706 // now we may block here because the main thread will soon let us in
1707 // (during the next iteration of OnIdle())
1708 gs_critsectGui
->Enter();
1711 void WXDLLIMPEXP_BASE
wxMutexGuiLeave()
1713 wxCriticalSectionLocker
enter(*gs_critsectWaitingForGui
);
1715 if ( wxThread::IsMain() )
1717 gs_bGuiOwnedByMainThread
= false;
1721 // decrement the number of threads waiting for GUI access now
1722 wxASSERT_MSG( gs_nWaitingForGui
> 0,
1723 wxT("calling wxMutexGuiLeave() without entering it first?") );
1725 gs_nWaitingForGui
--;
1727 wxWakeUpMainThread();
1730 gs_critsectGui
->Leave();
1733 void WXDLLIMPEXP_BASE
wxMutexGuiLeaveOrEnter()
1735 wxASSERT_MSG( wxThread::IsMain(),
1736 wxT("only main thread may call wxMutexGuiLeaveOrEnter()!") );
1738 if ( !gs_critsectWaitingForGui
)
1741 wxCriticalSectionLocker
enter(*gs_critsectWaitingForGui
);
1743 if ( gs_nWaitingForGui
== 0 )
1745 // no threads are waiting for GUI - so we may acquire the lock without
1746 // any danger (but only if we don't already have it)
1747 if ( !wxGuiOwnedByMainThread() )
1749 gs_critsectGui
->Enter();
1751 gs_bGuiOwnedByMainThread
= true;
1753 //else: already have it, nothing to do
1757 // some threads are waiting, release the GUI lock if we have it
1758 if ( wxGuiOwnedByMainThread() )
1760 //else: some other worker thread is doing GUI
1764 bool WXDLLIMPEXP_BASE
wxGuiOwnedByMainThread()
1766 return gs_bGuiOwnedByMainThread
;
1769 // wake up the main thread
1770 void WXDLLEXPORT
wxWakeUpMainThread()
1775 // ----------------------------------------------------------------------------
1776 // include common implementation code
1777 // ----------------------------------------------------------------------------
1779 #include "wx/thrimpl.cpp"
1781 #endif // wxUSE_THREADS