1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/mac/carbon/thread.cpp
3 // Purpose: wxThread Implementation
4 // Author: Original from Wolfram Gloger/Guilhem Lavaux/Vadim Zeitlin
5 // Modified by: Aj Lavin, Stefan Csomor
8 // Copyright: (c) Wolfram Gloger (1996, 1997); Guilhem Lavaux (1998),
9 // Vadim Zeitlin (1999), Stefan Csomor (2000)
10 // Licence: wxWindows licence
11 /////////////////////////////////////////////////////////////////////////////
13 #include "wx/wxprec.h"
15 #if defined(__BORLANDC__)
21 #include "wx/module.h"
26 #include "wx/thread.h"
30 #include <CoreServices/CoreServices.h>
32 #include <DriverServices.h>
33 #include <Multiprocessing.h>
36 #include "wx/mac/uma.h"
39 // the possible states of the thread:
40 // ("=>" shows all possible transitions from this state)
43 STATE_NEW
, // didn't start execution yet (=> RUNNING)
44 STATE_RUNNING
, // thread is running (=> PAUSED, CANCELED)
45 STATE_PAUSED
, // thread is temporarily suspended (=> RUNNING)
46 STATE_CANCELED
, // thread should terminate a.s.a.p. (=> EXITED)
47 STATE_EXITED
// thread is terminating
50 // ----------------------------------------------------------------------------
52 // ----------------------------------------------------------------------------
54 // the task ID of the main thread
55 static wxThreadIdType gs_idMainThread
= kInvalidID
;
57 // this is the Per-Task Storage for the pointer to the appropriate wxThread
58 TaskStorageIndex gs_tlsForWXThread
= 0;
60 // if it's false, some secondary thread is holding the GUI lock
61 static bool gs_bGuiOwnedByMainThread
= true;
63 // critical section which controls access to all GUI functions: any secondary
64 // thread (i.e. except the main one) must enter this crit section before doing
66 static wxCriticalSection
*gs_critsectGui
= NULL
;
68 // critical section which protects gs_nWaitingForGui variable
69 static wxCriticalSection
*gs_critsectWaitingForGui
= NULL
;
71 // number of threads waiting for GUI in wxMutexGuiEnter()
72 static size_t gs_nWaitingForGui
= 0;
74 // overall number of threads, needed for determining
75 // the sleep value of the main event loop
76 size_t g_numberOfThreads
= 0;
80 MPCriticalRegionID gs_guiCritical
= kInvalidID
;
83 // ============================================================================
84 // MacOS implementation of thread classes
85 // ============================================================================
90 The implementation is very close to the phtreads implementation, the reason for
91 using MPServices is the fact that these are also available under OS 9. Thus allowing
92 for one common API for all current builds.
94 As soon as wxThreads are on a 64 bit address space, the TLS must be extended
95 to use two indices one for each 32 bit part as the MP implementation is limited
98 I have three implementations for mutexes :
99 version A based on a binary semaphore, problem - not reentrant, version B based
100 on a critical region, allows for reentrancy, performance implications not
101 yet tested, and third a plain pthreads implementation
103 The same for condition internal, one implementation by Aj Lavin and the other one
104 copied from the thrimpl.cpp which I assume has been more broadly tested, I've just
105 replaced the interlock increment with the appropriate PPC calls
108 // ----------------------------------------------------------------------------
110 // ----------------------------------------------------------------------------
112 wxCriticalSection::wxCriticalSection()
114 MPCreateCriticalRegion( (MPCriticalRegionID
*) &m_critRegion
);
117 wxCriticalSection::~wxCriticalSection()
119 MPDeleteCriticalRegion( (MPCriticalRegionID
) m_critRegion
);
122 void wxCriticalSection::Enter()
124 MPEnterCriticalRegion( (MPCriticalRegionID
) m_critRegion
, kDurationForever
);
127 void wxCriticalSection::Leave()
129 MPExitCriticalRegion( (MPCriticalRegionID
) m_critRegion
);
132 // ----------------------------------------------------------------------------
133 // wxMutex implementation
134 // ----------------------------------------------------------------------------
136 #define wxUSE_MAC_SEMAPHORE_MUTEX 0
137 #define wxUSE_MAC_CRITICAL_REGION_MUTEX 1
138 #define wxUSE_MAC_PTHREADS_MUTEX 0
140 #if wxUSE_MAC_PTHREADS_MUTEX
145 class wxMutexInternal
148 wxMutexInternal( wxMutexType mutexType
);
152 wxMutexError
TryLock();
153 wxMutexError
Unlock();
159 pthread_mutex_t m_mutex
;
162 // wxConditionInternal uses our m_mutex
163 friend class wxConditionInternal
;
166 #ifdef HAVE_PTHREAD_MUTEXATTR_T
167 // on some systems pthread_mutexattr_settype() is not in the headers (but it is
168 // in the library, otherwise we wouldn't compile this code at all)
169 extern "C" int pthread_mutexattr_settype( pthread_mutexattr_t
*, int );
172 wxMutexInternal::wxMutexInternal( wxMutexType mutexType
)
177 case wxMUTEX_RECURSIVE
:
178 // support recursive locks like Win32, i.e. a thread can lock a
179 // mutex which it had itself already locked
181 // unfortunately initialization of recursive mutexes is non
182 // portable, so try several methods
183 #ifdef HAVE_PTHREAD_MUTEXATTR_T
185 pthread_mutexattr_t attr
;
186 pthread_mutexattr_init( &attr
);
187 pthread_mutexattr_settype( &attr
, PTHREAD_MUTEX_RECURSIVE
);
189 err
= pthread_mutex_init( &m_mutex
, &attr
);
191 #elif defined(HAVE_PTHREAD_RECURSIVE_MUTEX_INITIALIZER)
192 // we can use this only as initializer so we have to assign it
193 // first to a temp var - assigning directly to m_mutex wouldn't
196 pthread_mutex_t mutex
= PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
;
199 #else // no recursive mutexes
201 #endif // HAVE_PTHREAD_MUTEXATTR_T/...
205 wxFAIL_MSG( wxT("unknown mutex type") );
208 case wxMUTEX_DEFAULT
:
209 err
= pthread_mutex_init( &m_mutex
, NULL
);
216 wxLogApiError( wxT("pthread_mutex_init()"), err
);
220 wxMutexInternal::~wxMutexInternal()
224 int err
= pthread_mutex_destroy( &m_mutex
);
227 wxLogApiError( wxT("pthread_mutex_destroy()"), err
);
232 wxMutexError
wxMutexInternal::Lock()
234 int err
= pthread_mutex_lock( &m_mutex
);
238 // only error checking mutexes return this value and so it's an
239 // unexpected situation -- hence use assert, not wxLogDebug
240 wxFAIL_MSG( wxT("mutex deadlock prevented") );
241 return wxMUTEX_DEAD_LOCK
;
244 wxLogDebug( wxT("pthread_mutex_lock(): mutex not initialized.") );
248 return wxMUTEX_NO_ERROR
;
251 wxLogApiError( wxT("pthread_mutex_lock()"), err
);
254 return wxMUTEX_MISC_ERROR
;
257 wxMutexError
wxMutexInternal::TryLock()
259 int err
= pthread_mutex_trylock( &m_mutex
);
263 // not an error: mutex is already locked, but we're prepared for this case
267 wxLogDebug( wxT("pthread_mutex_trylock(): mutex not initialized.") );
271 return wxMUTEX_NO_ERROR
;
274 wxLogApiError( wxT("pthread_mutex_trylock()"), err
);
277 return wxMUTEX_MISC_ERROR
;
280 wxMutexError
wxMutexInternal::Unlock()
282 int err
= pthread_mutex_unlock( &m_mutex
);
286 // we don't own the mutex
287 return wxMUTEX_UNLOCKED
;
290 wxLogDebug( wxT("pthread_mutex_unlock(): mutex not initialized.") );
294 return wxMUTEX_NO_ERROR
;
297 wxLogApiError( wxT("pthread_mutex_unlock()"), err
);
300 return wxMUTEX_MISC_ERROR
;
305 #if wxUSE_MAC_SEMAPHORE_MUTEX
307 class wxMutexInternal
310 wxMutexInternal( wxMutexType mutexType
);
311 virtual ~wxMutexInternal();
317 wxMutexError
TryLock();
318 wxMutexError
Unlock();
321 MPSemaphoreID m_semaphore
;
325 wxMutexInternal::wxMutexInternal(wxMutexType mutexType
)
328 m_semaphore
= kInvalidID
;
329 OSStatus err
= noErr
;
333 case wxMUTEX_DEFAULT
:
334 verify_noerr( MPCreateBinarySemaphore( &m_semaphore
) );
335 m_isOk
= ( m_semaphore
!= kInvalidID
);
338 case wxMUTEX_RECURSIVE
:
339 wxFAIL_MSG( wxT("Recursive Mutex not supported yet") );
343 wxFAIL_MSG( wxT("Unknown mutex type") );
348 wxMutexInternal::~wxMutexInternal()
350 if ( m_semaphore
!= kInvalidID
)
351 MPDeleteSemaphore( m_semaphore
);
356 wxMutexError
wxMutexInternal::Lock()
358 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") );
359 OSStatus err
= MPWaitOnSemaphore( m_semaphore
, kDurationForever
);
362 wxLogSysError( wxT("Could not lock mutex") );
364 return wxMUTEX_MISC_ERROR
;
367 return wxMUTEX_NO_ERROR
;
370 wxMutexError
wxMutexInternal::TryLock()
372 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") );
373 OSStatus err
= MPWaitOnSemaphore( m_semaphore
, kDurationImmediate
);
376 if (err
== kMPTimeoutErr
)
379 wxLogSysError( wxT("Could not try lock mutex") );
381 return wxMUTEX_MISC_ERROR
;
384 return wxMUTEX_NO_ERROR
;
387 wxMutexError
wxMutexInternal::Unlock()
389 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") );
390 OSStatus err
= MPSignalSemaphore( m_semaphore
);
395 wxLogSysError( wxT("Could not unlock mutex") );
396 return wxMUTEX_MISC_ERROR
;
399 return wxMUTEX_NO_ERROR
;
404 #if wxUSE_MAC_CRITICAL_REGION_MUTEX
406 class wxMutexInternal
409 wxMutexInternal( wxMutexType mutexType
);
410 virtual ~wxMutexInternal();
412 bool IsOk() const { return m_isOk
; }
414 wxMutexError
Lock() { return Lock(kDurationForever
); }
415 wxMutexError
Lock(unsigned long ms
);
416 wxMutexError
TryLock();
417 wxMutexError
Unlock();
420 MPCriticalRegionID m_critRegion
;
424 wxMutexInternal::wxMutexInternal( wxMutexType
WXUNUSED(mutexType
) )
427 m_critRegion
= kInvalidID
;
429 verify_noerr( MPCreateCriticalRegion( &m_critRegion
) );
430 m_isOk
= ( m_critRegion
!= kInvalidID
);
433 wxFAIL_MSG( wxT("Error when creating mutex") );
437 wxMutexInternal::~wxMutexInternal()
439 if ( m_critRegion
!= kInvalidID
)
440 MPDeleteCriticalRegion( m_critRegion
);
445 wxMutexError
wxMutexInternal::Lock(unsigned long ms
)
447 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") );
449 OSStatus err
= MPEnterCriticalRegion( m_critRegion
, ms
);
456 wxASSERT_MSG( ms
!= kDurationForever
, wxT("unexpected timeout") );
457 return wxMUTEX_TIMEOUT
;
460 wxLogSysError(wxT("Could not lock mutex"));
461 return wxMUTEX_MISC_ERROR
;
464 return wxMUTEX_NO_ERROR
;
467 wxMutexError
wxMutexInternal::TryLock()
469 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") ) ;
471 OSStatus err
= MPEnterCriticalRegion( m_critRegion
, kDurationImmediate
);
474 if ( err
== kMPTimeoutErr
)
477 wxLogSysError( wxT("Could not try lock mutex") );
478 return wxMUTEX_MISC_ERROR
;
481 return wxMUTEX_NO_ERROR
;
484 wxMutexError
wxMutexInternal::Unlock()
486 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") ) ;
488 OSStatus err
= MPExitCriticalRegion( m_critRegion
);
493 wxLogSysError( wxT("Could not unlock mutex") );
495 return wxMUTEX_MISC_ERROR
;
498 return wxMUTEX_NO_ERROR
;
503 // --------------------------------------------------------------------------
505 // --------------------------------------------------------------------------
507 class wxSemaphoreInternal
510 wxSemaphoreInternal( int initialcount
, int maxcount
);
511 virtual ~wxSemaphoreInternal();
517 wxSemaError
WaitTimeout( unsigned long milliseconds
);
520 { return WaitTimeout( kDurationForever
); }
522 wxSemaError
TryWait()
524 wxSemaError err
= WaitTimeout( kDurationImmediate
);
525 if (err
== wxSEMA_TIMEOUT
)
532 MPSemaphoreID m_semaphore
;
536 wxSemaphoreInternal::wxSemaphoreInternal( int initialcount
, int maxcount
)
539 m_semaphore
= kInvalidID
;
541 // make it practically infinite
544 verify_noerr( MPCreateSemaphore( maxcount
, initialcount
, &m_semaphore
) );
545 m_isOk
= ( m_semaphore
!= kInvalidID
);
549 wxFAIL_MSG( wxT("Error when creating semaphore") );
553 wxSemaphoreInternal::~wxSemaphoreInternal()
555 if (m_semaphore
!= kInvalidID
)
556 MPDeleteSemaphore( m_semaphore
);
561 wxSemaError
wxSemaphoreInternal::WaitTimeout( unsigned long milliseconds
)
563 OSStatus err
= MPWaitOnSemaphore( m_semaphore
, milliseconds
);
566 if (err
== kMPTimeoutErr
)
567 return wxSEMA_TIMEOUT
;
569 return wxSEMA_MISC_ERROR
;
572 return wxSEMA_NO_ERROR
;
575 wxSemaError
wxSemaphoreInternal::Post()
577 OSStatus err
= MPSignalSemaphore( m_semaphore
);
580 return wxSEMA_MISC_ERROR
;
582 return wxSEMA_NO_ERROR
;
585 // ----------------------------------------------------------------------------
586 // wxCondition implementation
587 // ----------------------------------------------------------------------------
591 class wxConditionInternal
594 wxConditionInternal( wxMutex
& mutex
)
605 virtual ~wxConditionInternal() {}
608 { return m_mutex
.IsOk(); }
611 { return WaitTimeout( kDurationForever
); }
613 wxCondError
WaitTimeout( unsigned long msectimeout
);
616 { return DoSignal( false); }
618 wxCondError
Broadcast()
619 { return DoSignal( true ); }
622 wxCondError
DoSignal( bool signalAll
);
625 wxSemaphoreInternal m_semaphore
; // Signals the waiting threads.
626 wxSemaphoreInternal m_gate
;
627 wxCriticalSection m_varSection
;
628 size_t m_waiters
; // Number of threads waiting for a signal.
629 size_t m_signals
; // Number of signals to send.
630 size_t m_canceled
; // Number of canceled waiters in m_waiters.
633 wxCondError
wxConditionInternal::WaitTimeout( unsigned long msectimeout
)
637 if ( ++ m_waiters
== INT_MAX
)
639 m_varSection
.Enter();
641 m_waiters
-= m_canceled
;
642 m_signals
-= m_canceled
;
645 m_varSection
.Leave();
651 wxSemaError err
= m_semaphore
.WaitTimeout( msectimeout
);
652 wxASSERT( err
== wxSEMA_NO_ERROR
|| err
== wxSEMA_TIMEOUT
);
654 m_varSection
.Enter();
656 if ( err
!= wxSEMA_NO_ERROR
)
658 if ( m_signals
> m_canceled
)
660 // A signal is being sent after we timed out.
661 if ( m_waiters
== m_signals
)
663 // There are no excess waiters to catch the signal, so
664 // we must throw it away.
665 wxSemaError err2
= m_semaphore
.Wait();
666 if ( err2
!= wxSEMA_NO_ERROR
)
668 wxLogSysError( wx("Error while waiting on semaphore") );
671 wxASSERT( err2
== wxSEMA_NO_ERROR
);
674 if ( --m_signals
== m_canceled
)
676 // This was the last signal. open the gate.
677 wxASSERT( m_waiters
== m_canceled
);
683 // There are excess waiters to catch the signal, leave it be.
689 // No signals is being sent:
690 // the gate may be open or closed, so we can't touch m_waiters.
697 // We caught a signal.
698 wxASSERT( m_signals
> m_canceled
);
702 if ( --m_signals
== m_canceled
)
704 // This was the last signal. open the gate.
705 wxASSERT( m_waiters
== m_canceled
);
711 m_varSection
.Leave();
715 return err
== wxSEMA_TIMEOUT
? wxCOND_TIMEOUT
: wxCOND_MISC_ERROR
;
717 return wxCOND_NO_ERROR
;
721 wxCondError
wxConditionInternal::DoSignal( bool signalAll
)
724 m_varSection
.Enter();
726 wxASSERT( m_signals
== m_canceled
);
728 if ( m_waiters
== m_canceled
)
730 m_varSection
.Leave();
732 return wxCOND_NO_ERROR
;
737 m_waiters
-= m_canceled
;
742 m_signals
= signalAll
? m_waiters
: 1;
743 size_t n
= m_signals
;
745 m_varSection
.Leave();
747 // Let the waiters inherit the gate lock.
751 wxSemaError err
= m_semaphore
.Post();
752 wxASSERT( err
== wxSEMA_NO_ERROR
);
756 return wxCOND_NO_ERROR
;
760 class wxConditionInternal
763 wxConditionInternal( wxMutex
& mutex
);
766 { return m_mutex
.IsOk() && m_semaphore
.IsOk(); }
769 wxCondError
WaitTimeout( unsigned long milliseconds
);
771 wxCondError
Signal();
772 wxCondError
Broadcast();
775 // the number of threads currently waiting for this condition
778 // the critical section protecting m_numWaiters
779 wxCriticalSection m_csWaiters
;
782 wxSemaphore m_semaphore
;
784 DECLARE_NO_COPY_CLASS(wxConditionInternal
)
787 wxConditionInternal::wxConditionInternal( wxMutex
& mutex
)
790 // another thread can't access it until we return from ctor, so no need to
791 // protect access to m_numWaiters here
795 wxCondError
wxConditionInternal::Wait()
797 // increment the number of waiters
798 IncrementAtomic( &m_numWaiters
);
802 // a potential race condition can occur here
804 // after a thread increments nwaiters, and unlocks the mutex and before the
805 // semaphore.Wait() is called, if another thread can cause a signal to be
808 // this race condition is handled by using a semaphore and incrementing the
809 // semaphore only if 'nwaiters' is greater that zero since the semaphore,
810 // can 'remember' signals the race condition will not occur
812 // wait ( if necessary ) and decrement semaphore
813 wxSemaError err
= m_semaphore
.Wait();
816 return err
== wxSEMA_NO_ERROR
? wxCOND_NO_ERROR
: wxCOND_MISC_ERROR
;
819 wxCondError
wxConditionInternal::WaitTimeout( unsigned long milliseconds
)
821 IncrementAtomic( &m_numWaiters
);
825 // a race condition can occur at this point in the code
827 // please see the comments in Wait(), for details
829 wxSemaError err
= m_semaphore
.WaitTimeout(milliseconds
);
831 if ( err
== wxSEMA_TIMEOUT
)
833 // another potential race condition exists here it is caused when a
834 // 'waiting' thread timesout, and returns from WaitForSingleObject, but
835 // has not yet decremented 'nwaiters'.
837 // at this point if another thread calls signal() then the semaphore
838 // will be incremented, but the waiting thread will miss it.
840 // to handle this particular case, the waiting thread calls
841 // WaitForSingleObject again with a timeout of 0, after locking
842 // 'nwaiters_mutex'. this call does not block because of the zero
843 // timeout, but will allow the waiting thread to catch the missed
845 wxCriticalSectionLocker
lock(m_csWaiters
);
847 err
= m_semaphore
.WaitTimeout(0);
849 if ( err
!= wxSEMA_NO_ERROR
)
857 return err
== wxSEMA_NO_ERROR
? wxCOND_NO_ERROR
: wxCOND_MISC_ERROR
;
860 wxCondError
wxConditionInternal::Signal()
862 wxCriticalSectionLocker
lock(m_csWaiters
);
864 if ( m_numWaiters
> 0 )
866 // increment the semaphore by 1
867 if ( m_semaphore
.Post() != wxSEMA_NO_ERROR
)
868 return wxCOND_MISC_ERROR
;
873 return wxCOND_NO_ERROR
;
876 wxCondError
wxConditionInternal::Broadcast()
878 wxCriticalSectionLocker
lock(m_csWaiters
);
880 while ( m_numWaiters
> 0 )
882 if ( m_semaphore
.Post() != wxSEMA_NO_ERROR
)
883 return wxCOND_MISC_ERROR
;
888 return wxCOND_NO_ERROR
;
892 // ----------------------------------------------------------------------------
893 // wxCriticalSection implementation
894 // ----------------------------------------------------------------------------
896 // XXX currently implemented as mutex in headers. Change to critical section.
898 // ----------------------------------------------------------------------------
899 // wxThread implementation
900 // ----------------------------------------------------------------------------
902 // wxThreadInternal class
903 // ----------------------
905 class wxThreadInternal
912 m_prio
= WXTHREAD_DEFAULT_PRIORITY
;
913 m_notifyQueueId
= kInvalidID
;
915 m_cancelled
= false ;
917 // set to true only when the thread starts waiting on m_semSuspend
920 // defaults for joinable threads
921 m_shouldBeJoined
= true;
922 m_isDetached
= false;
925 virtual ~wxThreadInternal()
927 if ( m_notifyQueueId
)
929 MPDeleteQueue( m_notifyQueueId
);
930 m_notifyQueueId
= kInvalidID
;
935 static OSStatus
MacThreadStart(void* arg
);
937 // create a new (suspended) thread (for the given thread object)
938 bool Create(wxThread
*thread
, unsigned int stackSize
);
945 // unblock the thread allowing it to run
946 void SignalRun() { m_semRun
.Post(); }
948 // ask the thread to terminate
951 // go to sleep until Resume() is called
959 int GetPriority() const
961 void SetPriority(int prio
);
964 wxThreadState
GetState() const
966 void SetState(wxThreadState state
)
969 // Get the ID of this thread's underlying MP Services task.
970 MPTaskID
GetId() const
974 { m_cancelled
= true; }
976 bool WasCancelled() const
977 { return m_cancelled
; }
980 void SetExitCode(wxThread::ExitCode exitcode
)
981 { m_exitcode
= exitcode
; }
982 wxThread::ExitCode
GetExitCode() const
983 { return m_exitcode
; }
986 void SetReallyPaused(bool paused
)
987 { m_isPaused
= paused
; }
988 bool IsReallyPaused() const
989 { return m_isPaused
; }
991 // tell the thread that it is a detached one
994 wxCriticalSectionLocker
lock(m_csJoinFlag
);
996 m_shouldBeJoined
= false;
1001 // the thread we're associated with
1002 wxThread
* m_thread
;
1004 MPTaskID m_tid
; // thread id
1005 MPQueueID m_notifyQueueId
; // its notification queue
1007 wxThreadState m_state
; // see wxThreadState enum
1008 int m_prio
; // in wxWidgets units: from 0 to 100
1010 // this flag is set when the thread should terminate
1013 // this flag is set when the thread is blocking on m_semSuspend
1016 // the thread exit code - only used for joinable (!detached) threads and
1017 // is only valid after the thread termination
1018 wxThread::ExitCode m_exitcode
;
1020 // many threads may call Wait(), but only one of them should call
1021 // pthread_join(), so we have to keep track of this
1022 wxCriticalSection m_csJoinFlag
;
1023 bool m_shouldBeJoined
;
1026 // this semaphore is posted by Run() and the threads Entry() is not
1027 // called before it is done
1028 wxSemaphore m_semRun
;
1030 // this one is signaled when the thread should resume after having been
1032 wxSemaphore m_semSuspend
;
1035 OSStatus
wxThreadInternal::MacThreadStart(void *parameter
)
1037 wxThread
* thread
= (wxThread
*) parameter
;
1038 wxThreadInternal
*pthread
= thread
->m_internal
;
1040 // add to TLS so that This() will work
1041 verify_noerr( MPSetTaskStorageValue( gs_tlsForWXThread
, (TaskStorageValue
) thread
) ) ;
1043 // have to declare this before pthread_cleanup_push() which defines a
1047 // wait for the semaphore to be posted from Run()
1048 pthread
->m_semRun
.Wait();
1050 // test whether we should run the run at all - may be it was deleted
1051 // before it started to Run()?
1053 wxCriticalSectionLocker
lock(thread
->m_critsect
);
1055 dontRunAtAll
= pthread
->GetState() == STATE_NEW
&&
1056 pthread
->WasCancelled();
1059 if ( !dontRunAtAll
)
1061 pthread
->m_exitcode
= thread
->Entry();
1064 wxCriticalSectionLocker
lock(thread
->m_critsect
);
1065 pthread
->SetState( STATE_EXITED
);
1071 if ( pthread
->m_isDetached
)
1078 // on Mac for the running code,
1079 // the correct thread termination is to return
1081 // terminate the thread
1082 thread
->Exit( pthread
->m_exitcode
);
1084 return (OSStatus
) NULL
; // pthread->m_exitcode;
1088 bool wxThreadInternal::Create( wxThread
*thread
, unsigned int stackSize
)
1090 wxASSERT_MSG( m_state
== STATE_NEW
&& !m_tid
,
1091 wxT("Create()ing thread twice?") );
1093 OSStatus err
= noErr
;
1096 if ( m_notifyQueueId
== kInvalidID
)
1098 OSStatus err
= MPCreateQueue( &m_notifyQueueId
);
1101 wxLogSysError( wxT("Cant create the thread event queue") );
1107 m_state
= STATE_NEW
;
1110 MacThreadStart
, (void*)m_thread
, stackSize
,
1111 m_notifyQueueId
, &m_exitcode
, 0, 0, &m_tid
);
1115 wxLogSysError( wxT("Can't create thread") );
1120 if ( m_prio
!= WXTHREAD_DEFAULT_PRIORITY
)
1121 SetPriority( m_prio
);
1126 void wxThreadInternal::SetPriority( int priority
)
1132 // Mac priorities range from 1 to 10,000, with a default of 100.
1133 // wxWidgets priorities range from 0 to 100 with a default of 50.
1134 // We can map wxWidgets to Mac priorities easily by assuming
1135 // the former uses a logarithmic scale.
1136 const unsigned int macPriority
= (int)( exp( priority
/ 25.0 * log( 10.0)) + 0.5);
1138 MPSetTaskWeight( m_tid
, macPriority
);
1142 wxThreadError
wxThreadInternal::Run()
1144 wxCHECK_MSG( GetState() == STATE_NEW
, wxTHREAD_RUNNING
,
1145 wxT("thread may only be started once after Create()") );
1147 SetState( STATE_RUNNING
);
1149 // wake up threads waiting for our start
1152 return wxTHREAD_NO_ERROR
;
1155 void wxThreadInternal::Wait()
1157 wxCHECK_RET( !m_isDetached
, wxT("can't wait for a detached thread") );
1159 // if the thread we're waiting for is waiting for the GUI mutex, we will
1160 // deadlock so make sure we release it temporarily
1161 if ( wxThread::IsMain() )
1163 // give the thread we're waiting for chance to do the GUI call
1164 // it might be in, we don't do this conditionally as the to be waited on
1165 // thread might have to acquire the mutex later but before terminating
1166 if ( wxGuiOwnedByMainThread() )
1171 wxCriticalSectionLocker
lock(m_csJoinFlag
);
1173 if ( m_shouldBeJoined
)
1175 void *param1
, *param2
, *rc
;
1177 OSStatus err
= MPWaitOnQueue(
1185 wxLogSysError( wxT( "Cannot wait for thread termination."));
1189 // actually param1 would be the address of m_exitcode
1190 // but we don't need this here
1193 m_shouldBeJoined
= false;
1198 void wxThreadInternal::Pause()
1200 // the state is set from the thread which pauses us first, this function
1201 // is called later so the state should have been already set
1202 wxCHECK_RET( m_state
== STATE_PAUSED
,
1203 wxT("thread must first be paused with wxThread::Pause().") );
1205 // wait until the semaphore is Post()ed from Resume()
1206 m_semSuspend
.Wait();
1209 void wxThreadInternal::Resume()
1211 wxCHECK_RET( m_state
== STATE_PAUSED
,
1212 wxT("can't resume thread which is not suspended.") );
1214 // the thread might be not actually paused yet - if there were no call to
1215 // TestDestroy() since the last call to Pause() for example
1216 if ( IsReallyPaused() )
1219 m_semSuspend
.Post();
1222 SetReallyPaused( false );
1225 SetState( STATE_RUNNING
);
1231 wxThread
*wxThread::This()
1233 wxThread
* thr
= (wxThread
*) MPGetTaskStorageValue( gs_tlsForWXThread
) ;
1238 bool wxThread::IsMain()
1240 return GetCurrentId() == gs_idMainThread
|| gs_idMainThread
== kInvalidID
;
1247 void wxThread::Yield()
1249 CFRunLoopRunInMode( kCFRunLoopDefaultMode
, 0 , true ) ;
1254 void wxThread::Sleep( unsigned long milliseconds
)
1256 AbsoluteTime wakeup
= AddDurationToAbsolute( milliseconds
, UpTime() );
1257 MPDelayUntil( &wakeup
);
1260 int wxThread::GetCPUCount()
1262 return MPProcessors();
1265 unsigned long wxThread::GetCurrentId()
1267 return (unsigned long)MPCurrentTaskID();
1270 bool wxThread::SetConcurrency( size_t WXUNUSED(level
) )
1272 // Cannot be set in MacOS.
1276 wxThread::wxThread( wxThreadKind kind
)
1278 g_numberOfThreads
++;
1279 m_internal
= new wxThreadInternal();
1281 m_isDetached
= (kind
== wxTHREAD_DETACHED
);
1284 wxThread::~wxThread()
1286 wxASSERT_MSG( g_numberOfThreads
>0 , wxT("More threads deleted than created.") ) ;
1288 g_numberOfThreads
--;
1293 // check that the thread either exited or couldn't be created
1294 if ( m_internal
->GetState() != STATE_EXITED
&&
1295 m_internal
->GetState() != STATE_NEW
)
1298 wxT("The thread %ld is being destroyed although it is still running! The application may crash."),
1305 wxDELETE( m_internal
) ;
1308 wxThreadError
wxThread::Create( unsigned int stackSize
)
1310 wxCriticalSectionLocker
lock(m_critsect
);
1313 m_internal
->Detach() ;
1315 if ( !m_internal
->Create(this, stackSize
) )
1317 m_internal
->SetState( STATE_EXITED
);
1319 return wxTHREAD_NO_RESOURCE
;
1322 return wxTHREAD_NO_ERROR
;
1325 wxThreadError
wxThread::Run()
1327 wxCriticalSectionLocker
lock(m_critsect
);
1329 wxCHECK_MSG( m_internal
->GetId(), wxTHREAD_MISC_ERROR
,
1330 wxT("must call wxThread::Create() first") );
1332 return m_internal
->Run();
1335 // -----------------------------------------------------------------------------
1337 // -----------------------------------------------------------------------------
1339 wxThreadError
wxThread::Pause()
1341 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
,
1342 _T("a thread can't pause itself") );
1344 wxCriticalSectionLocker
lock(m_critsect
);
1346 if ( m_internal
->GetState() != STATE_RUNNING
)
1348 wxLogDebug( wxT("Can't pause thread which is not running.") );
1350 return wxTHREAD_NOT_RUNNING
;
1353 // just set a flag, the thread will be really paused only during the next
1354 // call to TestDestroy()
1355 m_internal
->SetState( STATE_PAUSED
);
1357 return wxTHREAD_NO_ERROR
;
1360 wxThreadError
wxThread::Resume()
1362 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
,
1363 wxT("a thread can't resume itself") );
1365 wxCriticalSectionLocker
lock(m_critsect
);
1367 wxThreadState state
= m_internal
->GetState();
1372 m_internal
->Resume();
1373 return wxTHREAD_NO_ERROR
;
1376 return wxTHREAD_NO_ERROR
;
1379 wxLogDebug( wxT("Attempt to resume a thread which is not paused.") );
1381 return wxTHREAD_MISC_ERROR
;
1385 // -----------------------------------------------------------------------------
1387 // -----------------------------------------------------------------------------
1389 wxThread::ExitCode
wxThread::Wait()
1391 wxCHECK_MSG( This() != this, (ExitCode
)-1,
1392 wxT("a thread can't wait for itself") );
1394 wxCHECK_MSG( !m_isDetached
, (ExitCode
)-1,
1395 wxT("can't wait for detached thread") );
1399 return m_internal
->GetExitCode();
1402 wxThreadError
wxThread::Delete(ExitCode
*rc
)
1404 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
,
1405 wxT("a thread can't delete itself") );
1407 bool isDetached
= m_isDetached
;
1410 wxThreadState state
= m_internal
->GetState();
1412 // ask the thread to stop
1413 m_internal
->SetCancelFlag();
1420 // we need to wake up the thread so that PthreadStart() will
1421 // terminate - right now it's blocking on run semaphore in
1423 m_internal
->SignalRun();
1432 // resume the thread first
1433 m_internal
->Resume();
1440 // wait until the thread stops
1445 // return the exit code of the thread
1446 *rc
= m_internal
->GetExitCode();
1451 return wxTHREAD_NO_ERROR
;
1454 wxThreadError
wxThread::Kill()
1456 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
,
1457 wxT("a thread can't kill itself") );
1459 switch ( m_internal
->GetState() )
1463 return wxTHREAD_NOT_RUNNING
;
1466 // resume the thread first
1472 OSStatus err
= MPTerminateTask( m_internal
->GetId() , -1 ) ;
1475 wxLogError( wxT("Failed to terminate a thread.") );
1477 return wxTHREAD_MISC_ERROR
;
1486 // this should be retrieved by Wait actually
1487 m_internal
->SetExitCode( (void*)-1 );
1490 return wxTHREAD_NO_ERROR
;
1494 void wxThread::Exit( ExitCode status
)
1496 wxASSERT_MSG( This() == this,
1497 wxT("wxThread::Exit() can only be called in the context of the same thread") );
1499 // don't enter m_critsect before calling OnExit() because the user code
1500 // might deadlock if, for example, it signals a condition in OnExit() (a
1501 // common case) while the main thread calls any of functions entering
1502 // m_critsect on us (almost all of them do)
1505 MPTaskID threadid
= m_internal
->GetId();
1513 // update the status of the joinable thread
1514 wxCriticalSectionLocker
lock( m_critsect
);
1515 m_internal
->SetState( STATE_EXITED
);
1518 MPTerminateTask( threadid
, (long)status
);
1521 // also test whether we were paused
1522 bool wxThread::TestDestroy()
1524 wxASSERT_MSG( This() == this,
1525 wxT("wxThread::TestDestroy() can only be called in the context of the same thread") );
1529 if ( m_internal
->GetState() == STATE_PAUSED
)
1531 m_internal
->SetReallyPaused( true );
1533 // leave the crit section or the other threads will stop too if they attempt
1534 // to call any of (seemingly harmless) IsXXX() functions while we sleep
1537 m_internal
->Pause();
1541 // thread wasn't requested to pause, nothing to do
1545 return m_internal
->WasCancelled();
1548 // -----------------------------------------------------------------------------
1550 // -----------------------------------------------------------------------------
1552 void wxThread::SetPriority(unsigned int prio
)
1554 wxCHECK_RET( ((int)WXTHREAD_MIN_PRIORITY
<= (int)prio
) &&
1555 ((int)prio
<= (int)WXTHREAD_MAX_PRIORITY
),
1556 wxT("invalid thread priority") );
1558 wxCriticalSectionLocker
lock(m_critsect
);
1560 switch ( m_internal
->GetState() )
1565 // thread not yet started, priority will be set when it is
1566 m_internal
->SetPriority( prio
);
1571 wxFAIL_MSG( wxT("impossible to set thread priority in this state") );
1575 unsigned int wxThread::GetPriority() const
1577 wxCriticalSectionLocker
lock((wxCriticalSection
&)m_critsect
); // const_cast
1579 return m_internal
->GetPriority();
1582 unsigned long wxThread::GetId() const
1584 wxCriticalSectionLocker
lock((wxCriticalSection
&)m_critsect
); // const_cast
1586 return (unsigned long)m_internal
->GetId();
1589 // -----------------------------------------------------------------------------
1591 // -----------------------------------------------------------------------------
1593 bool wxThread::IsRunning() const
1595 wxCriticalSectionLocker
lock((wxCriticalSection
&)m_critsect
);
1597 return m_internal
->GetState() == STATE_RUNNING
;
1600 bool wxThread::IsAlive() const
1602 wxCriticalSectionLocker
lock((wxCriticalSection
&)m_critsect
);
1604 switch ( m_internal
->GetState() )
1615 bool wxThread::IsPaused() const
1617 wxCriticalSectionLocker
lock((wxCriticalSection
&)m_critsect
);
1619 return (m_internal
->GetState() == STATE_PAUSED
);
1622 // ----------------------------------------------------------------------------
1623 // Automatic initialization for thread module
1624 // ----------------------------------------------------------------------------
1626 class wxThreadModule
: public wxModule
1629 virtual bool OnInit();
1630 virtual void OnExit();
1633 DECLARE_DYNAMIC_CLASS(wxThreadModule
)
1636 IMPLEMENT_DYNAMIC_CLASS(wxThreadModule
, wxModule
)
1638 bool wxThreadModule::OnInit()
1640 bool hasThreadManager
=
1642 true ; // TODO VERIFY IN NEXT BUILD
1644 MPLibraryIsLoaded();
1647 if ( !hasThreadManager
)
1649 wxLogError( wxT("MP thread support is not available on this system" ) ) ;
1654 // main thread's This() is NULL
1655 verify_noerr( MPAllocateTaskStorageIndex( &gs_tlsForWXThread
) ) ;
1656 verify_noerr( MPSetTaskStorageValue( gs_tlsForWXThread
, 0 ) ) ;
1658 gs_idMainThread
= wxThread::GetCurrentId();
1659 gs_critsectWaitingForGui
= new wxCriticalSection();
1661 gs_critsectGui
= new wxCriticalSection();
1662 gs_critsectGui
->Enter();
1667 void wxThreadModule::OnExit()
1669 if ( gs_critsectGui
)
1671 if ( !wxGuiOwnedByMainThread() )
1673 gs_critsectGui
->Enter();
1674 gs_bGuiOwnedByMainThread
= true;
1677 gs_critsectGui
->Leave();
1678 delete gs_critsectGui
;
1679 gs_critsectGui
= NULL
;
1682 delete gs_critsectWaitingForGui
;
1683 gs_critsectWaitingForGui
= NULL
;
1686 // ----------------------------------------------------------------------------
1687 // GUI Serialization copied from MSW implementation
1688 // ----------------------------------------------------------------------------
1690 void WXDLLIMPEXP_BASE
wxMutexGuiEnter()
1692 // this would dead lock everything...
1693 wxASSERT_MSG( !wxThread::IsMain(),
1694 wxT("main thread doesn't want to block in wxMutexGuiEnter()!") );
1696 // the order in which we enter the critical sections here is crucial!!
1698 // set the flag telling to the main thread that we want to do some GUI
1700 wxCriticalSectionLocker
enter(*gs_critsectWaitingForGui
);
1702 gs_nWaitingForGui
++;
1705 wxWakeUpMainThread();
1707 // now we may block here because the main thread will soon let us in
1708 // (during the next iteration of OnIdle())
1709 gs_critsectGui
->Enter();
1712 void WXDLLIMPEXP_BASE
wxMutexGuiLeave()
1714 wxCriticalSectionLocker
enter(*gs_critsectWaitingForGui
);
1716 if ( wxThread::IsMain() )
1718 gs_bGuiOwnedByMainThread
= false;
1722 // decrement the number of threads waiting for GUI access now
1723 wxASSERT_MSG( gs_nWaitingForGui
> 0,
1724 wxT("calling wxMutexGuiLeave() without entering it first?") );
1726 gs_nWaitingForGui
--;
1728 wxWakeUpMainThread();
1731 gs_critsectGui
->Leave();
1734 void WXDLLIMPEXP_BASE
wxMutexGuiLeaveOrEnter()
1736 wxASSERT_MSG( wxThread::IsMain(),
1737 wxT("only main thread may call wxMutexGuiLeaveOrEnter()!") );
1739 if ( !gs_critsectWaitingForGui
)
1742 wxCriticalSectionLocker
enter(*gs_critsectWaitingForGui
);
1744 if ( gs_nWaitingForGui
== 0 )
1746 // no threads are waiting for GUI - so we may acquire the lock without
1747 // any danger (but only if we don't already have it)
1748 if ( !wxGuiOwnedByMainThread() )
1750 gs_critsectGui
->Enter();
1752 gs_bGuiOwnedByMainThread
= true;
1754 //else: already have it, nothing to do
1758 // some threads are waiting, release the GUI lock if we have it
1759 if ( wxGuiOwnedByMainThread() )
1761 //else: some other worker thread is doing GUI
1765 bool WXDLLIMPEXP_BASE
wxGuiOwnedByMainThread()
1767 return gs_bGuiOwnedByMainThread
;
1770 // wake up the main thread
1771 void WXDLLEXPORT
wxWakeUpMainThread()
1776 // ----------------------------------------------------------------------------
1777 // include common implementation code
1778 // ----------------------------------------------------------------------------
1780 #include "wx/thrimpl.cpp"
1782 #endif // wxUSE_THREADS