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"
28 #include <CoreServices/CoreServices.h>
29 #include "wx/mac/uma.h"
31 // the possible states of the thread:
32 // ("=>" shows all possible transitions from this state)
35 STATE_NEW
, // didn't start execution yet (=> RUNNING)
36 STATE_RUNNING
, // thread is running (=> PAUSED, CANCELED)
37 STATE_PAUSED
, // thread is temporarily suspended (=> RUNNING)
38 STATE_CANCELED
, // thread should terminate a.s.a.p. (=> EXITED)
39 STATE_EXITED
// thread is terminating
42 // ----------------------------------------------------------------------------
44 // ----------------------------------------------------------------------------
46 // the task ID of the main thread
47 static wxThreadIdType gs_idMainThread
= kInvalidID
;
49 // this is the Per-Task Storage for the pointer to the appropriate wxThread
50 TaskStorageIndex gs_tlsForWXThread
= 0;
52 // if it's false, some secondary thread is holding the GUI lock
53 static bool gs_bGuiOwnedByMainThread
= true;
55 // critical section which controls access to all GUI functions: any secondary
56 // thread (i.e. except the main one) must enter this crit section before doing
58 static wxCriticalSection
*gs_critsectGui
= NULL
;
60 // critical section which protects gs_nWaitingForGui variable
61 static wxCriticalSection
*gs_critsectWaitingForGui
= NULL
;
63 // number of threads waiting for GUI in wxMutexGuiEnter()
64 static size_t gs_nWaitingForGui
= 0;
66 // overall number of threads, needed for determining
67 // the sleep value of the main event loop
68 size_t g_numberOfThreads
= 0;
72 MPCriticalRegionID gs_guiCritical
= kInvalidID
;
75 // ============================================================================
76 // MacOS implementation of thread classes
77 // ============================================================================
82 The implementation is very close to the phtreads implementation, the reason for
83 using MPServices is the fact that these are also available under OS 9. Thus allowing
84 for one common API for all current builds.
86 As soon as wxThreads are on a 64 bit address space, the TLS must be extended
87 to use two indices one for each 32 bit part as the MP implementation is limited
90 I have three implementations for mutexes :
91 version A based on a binary semaphore, problem - not reentrant, version B based
92 on a critical region, allows for reentrancy, performance implications not
93 yet tested, and third a plain pthreads implementation
95 The same for condition internal, one implementation by Aj Lavin and the other one
96 copied from the thrimpl.cpp which I assume has been more broadly tested, I've just
97 replaced the interlock increment with the appropriate PPC calls
100 // ----------------------------------------------------------------------------
102 // ----------------------------------------------------------------------------
104 wxCriticalSection::wxCriticalSection()
106 MPCreateCriticalRegion( (MPCriticalRegionID
*) &m_critRegion
);
109 wxCriticalSection::~wxCriticalSection()
111 MPDeleteCriticalRegion( (MPCriticalRegionID
) m_critRegion
);
114 void wxCriticalSection::Enter()
116 MPEnterCriticalRegion( (MPCriticalRegionID
) m_critRegion
, kDurationForever
);
119 void wxCriticalSection::Leave()
121 MPExitCriticalRegion( (MPCriticalRegionID
) m_critRegion
);
124 // ----------------------------------------------------------------------------
125 // wxMutex implementation
126 // ----------------------------------------------------------------------------
128 #define wxUSE_MAC_SEMAPHORE_MUTEX 0
129 #define wxUSE_MAC_CRITICAL_REGION_MUTEX 1
130 #define wxUSE_MAC_PTHREADS_MUTEX 0
132 #if wxUSE_MAC_PTHREADS_MUTEX
137 class wxMutexInternal
140 wxMutexInternal( wxMutexType mutexType
);
144 wxMutexError
TryLock();
145 wxMutexError
Unlock();
151 pthread_mutex_t m_mutex
;
154 // wxConditionInternal uses our m_mutex
155 friend class wxConditionInternal
;
158 #ifdef HAVE_PTHREAD_MUTEXATTR_T
159 // on some systems pthread_mutexattr_settype() is not in the headers (but it is
160 // in the library, otherwise we wouldn't compile this code at all)
161 extern "C" int pthread_mutexattr_settype( pthread_mutexattr_t
*, int );
164 wxMutexInternal::wxMutexInternal( wxMutexType mutexType
)
169 case wxMUTEX_RECURSIVE
:
170 // support recursive locks like Win32, i.e. a thread can lock a
171 // mutex which it had itself already locked
173 // unfortunately initialization of recursive mutexes is non
174 // portable, so try several methods
175 #ifdef HAVE_PTHREAD_MUTEXATTR_T
177 pthread_mutexattr_t attr
;
178 pthread_mutexattr_init( &attr
);
179 pthread_mutexattr_settype( &attr
, PTHREAD_MUTEX_RECURSIVE
);
181 err
= pthread_mutex_init( &m_mutex
, &attr
);
183 #elif defined(HAVE_PTHREAD_RECURSIVE_MUTEX_INITIALIZER)
184 // we can use this only as initializer so we have to assign it
185 // first to a temp var - assigning directly to m_mutex wouldn't
188 pthread_mutex_t mutex
= PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
;
191 #else // no recursive mutexes
193 #endif // HAVE_PTHREAD_MUTEXATTR_T/...
197 wxFAIL_MSG( wxT("unknown mutex type") );
200 case wxMUTEX_DEFAULT
:
201 err
= pthread_mutex_init( &m_mutex
, NULL
);
208 wxLogApiError( wxT("pthread_mutex_init()"), err
);
212 wxMutexInternal::~wxMutexInternal()
216 int err
= pthread_mutex_destroy( &m_mutex
);
219 wxLogApiError( wxT("pthread_mutex_destroy()"), err
);
224 wxMutexError
wxMutexInternal::Lock()
226 int err
= pthread_mutex_lock( &m_mutex
);
230 // only error checking mutexes return this value and so it's an
231 // unexpected situation -- hence use assert, not wxLogDebug
232 wxFAIL_MSG( wxT("mutex deadlock prevented") );
233 return wxMUTEX_DEAD_LOCK
;
236 wxLogDebug( wxT("pthread_mutex_lock(): mutex not initialized.") );
240 return wxMUTEX_NO_ERROR
;
243 wxLogApiError( wxT("pthread_mutex_lock()"), err
);
246 return wxMUTEX_MISC_ERROR
;
249 wxMutexError
wxMutexInternal::TryLock()
251 int err
= pthread_mutex_trylock( &m_mutex
);
255 // not an error: mutex is already locked, but we're prepared for this case
259 wxLogDebug( wxT("pthread_mutex_trylock(): mutex not initialized.") );
263 return wxMUTEX_NO_ERROR
;
266 wxLogApiError( wxT("pthread_mutex_trylock()"), err
);
269 return wxMUTEX_MISC_ERROR
;
272 wxMutexError
wxMutexInternal::Unlock()
274 int err
= pthread_mutex_unlock( &m_mutex
);
278 // we don't own the mutex
279 return wxMUTEX_UNLOCKED
;
282 wxLogDebug( wxT("pthread_mutex_unlock(): mutex not initialized.") );
286 return wxMUTEX_NO_ERROR
;
289 wxLogApiError( wxT("pthread_mutex_unlock()"), err
);
292 return wxMUTEX_MISC_ERROR
;
297 #if wxUSE_MAC_SEMAPHORE_MUTEX
299 class wxMutexInternal
302 wxMutexInternal( wxMutexType mutexType
);
303 virtual ~wxMutexInternal();
309 wxMutexError
TryLock();
310 wxMutexError
Unlock();
313 MPSemaphoreID m_semaphore
;
317 wxMutexInternal::wxMutexInternal(wxMutexType mutexType
)
320 m_semaphore
= kInvalidID
;
321 OSStatus err
= noErr
;
325 case wxMUTEX_DEFAULT
:
326 verify_noerr( MPCreateBinarySemaphore( &m_semaphore
) );
327 m_isOk
= ( m_semaphore
!= kInvalidID
);
330 case wxMUTEX_RECURSIVE
:
331 wxFAIL_MSG( wxT("Recursive Mutex not supported yet") );
335 wxFAIL_MSG( wxT("Unknown mutex type") );
340 wxMutexInternal::~wxMutexInternal()
342 if ( m_semaphore
!= kInvalidID
)
343 MPDeleteSemaphore( m_semaphore
);
348 wxMutexError
wxMutexInternal::Lock()
350 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") );
351 OSStatus err
= MPWaitOnSemaphore( m_semaphore
, kDurationForever
);
354 wxLogSysError( wxT("Could not lock mutex") );
356 return wxMUTEX_MISC_ERROR
;
359 return wxMUTEX_NO_ERROR
;
362 wxMutexError
wxMutexInternal::TryLock()
364 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") );
365 OSStatus err
= MPWaitOnSemaphore( m_semaphore
, kDurationImmediate
);
368 if (err
== kMPTimeoutErr
)
371 wxLogSysError( wxT("Could not try lock mutex") );
373 return wxMUTEX_MISC_ERROR
;
376 return wxMUTEX_NO_ERROR
;
379 wxMutexError
wxMutexInternal::Unlock()
381 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") );
382 OSStatus err
= MPSignalSemaphore( m_semaphore
);
387 wxLogSysError( wxT("Could not unlock mutex") );
388 return wxMUTEX_MISC_ERROR
;
391 return wxMUTEX_NO_ERROR
;
396 #if wxUSE_MAC_CRITICAL_REGION_MUTEX
398 class wxMutexInternal
401 wxMutexInternal( wxMutexType mutexType
);
402 virtual ~wxMutexInternal();
404 bool IsOk() const { return m_isOk
; }
406 wxMutexError
Lock() { return Lock(kDurationForever
); }
407 wxMutexError
Lock(unsigned long ms
);
408 wxMutexError
TryLock();
409 wxMutexError
Unlock();
412 MPCriticalRegionID m_critRegion
;
416 wxMutexInternal::wxMutexInternal( wxMutexType
WXUNUSED(mutexType
) )
419 m_critRegion
= kInvalidID
;
421 verify_noerr( MPCreateCriticalRegion( &m_critRegion
) );
422 m_isOk
= ( m_critRegion
!= kInvalidID
);
425 wxFAIL_MSG( wxT("Error when creating mutex") );
429 wxMutexInternal::~wxMutexInternal()
431 if ( m_critRegion
!= kInvalidID
)
432 MPDeleteCriticalRegion( m_critRegion
);
437 wxMutexError
wxMutexInternal::Lock(unsigned long ms
)
439 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") );
441 OSStatus err
= MPEnterCriticalRegion( m_critRegion
, ms
);
448 wxASSERT_MSG( ms
!= kDurationForever
, wxT("unexpected timeout") );
449 return wxMUTEX_TIMEOUT
;
452 wxLogSysError(wxT("Could not lock mutex"));
453 return wxMUTEX_MISC_ERROR
;
456 return wxMUTEX_NO_ERROR
;
459 wxMutexError
wxMutexInternal::TryLock()
461 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") ) ;
463 OSStatus err
= MPEnterCriticalRegion( m_critRegion
, kDurationImmediate
);
466 if ( err
== kMPTimeoutErr
)
469 wxLogSysError( wxT("Could not try lock mutex") );
470 return wxMUTEX_MISC_ERROR
;
473 return wxMUTEX_NO_ERROR
;
476 wxMutexError
wxMutexInternal::Unlock()
478 wxCHECK_MSG( m_isOk
, wxMUTEX_MISC_ERROR
, wxT("Invalid Mutex") ) ;
480 OSStatus err
= MPExitCriticalRegion( m_critRegion
);
485 wxLogSysError( wxT("Could not unlock mutex") );
487 return wxMUTEX_MISC_ERROR
;
490 return wxMUTEX_NO_ERROR
;
495 // --------------------------------------------------------------------------
497 // --------------------------------------------------------------------------
499 class wxSemaphoreInternal
502 wxSemaphoreInternal( int initialcount
, int maxcount
);
503 virtual ~wxSemaphoreInternal();
509 wxSemaError
WaitTimeout( unsigned long milliseconds
);
512 { return WaitTimeout( kDurationForever
); }
514 wxSemaError
TryWait()
516 wxSemaError err
= WaitTimeout( kDurationImmediate
);
517 if (err
== wxSEMA_TIMEOUT
)
524 MPSemaphoreID m_semaphore
;
528 wxSemaphoreInternal::wxSemaphoreInternal( int initialcount
, int maxcount
)
531 m_semaphore
= kInvalidID
;
533 // make it practically infinite
536 verify_noerr( MPCreateSemaphore( maxcount
, initialcount
, &m_semaphore
) );
537 m_isOk
= ( m_semaphore
!= kInvalidID
);
541 wxFAIL_MSG( wxT("Error when creating semaphore") );
545 wxSemaphoreInternal::~wxSemaphoreInternal()
547 if (m_semaphore
!= kInvalidID
)
548 MPDeleteSemaphore( m_semaphore
);
553 wxSemaError
wxSemaphoreInternal::WaitTimeout( unsigned long milliseconds
)
555 OSStatus err
= MPWaitOnSemaphore( m_semaphore
, milliseconds
);
558 if (err
== kMPTimeoutErr
)
559 return wxSEMA_TIMEOUT
;
561 return wxSEMA_MISC_ERROR
;
564 return wxSEMA_NO_ERROR
;
567 wxSemaError
wxSemaphoreInternal::Post()
569 OSStatus err
= MPSignalSemaphore( m_semaphore
);
572 return wxSEMA_MISC_ERROR
;
574 return wxSEMA_NO_ERROR
;
577 // ----------------------------------------------------------------------------
578 // wxCondition implementation
579 // ----------------------------------------------------------------------------
583 class wxConditionInternal
586 wxConditionInternal( wxMutex
& mutex
)
597 virtual ~wxConditionInternal() {}
600 { return m_mutex
.IsOk(); }
603 { return WaitTimeout( kDurationForever
); }
605 wxCondError
WaitTimeout( unsigned long msectimeout
);
608 { return DoSignal( false); }
610 wxCondError
Broadcast()
611 { return DoSignal( true ); }
614 wxCondError
DoSignal( bool signalAll
);
617 wxSemaphoreInternal m_semaphore
; // Signals the waiting threads.
618 wxSemaphoreInternal m_gate
;
619 wxCriticalSection m_varSection
;
620 size_t m_waiters
; // Number of threads waiting for a signal.
621 size_t m_signals
; // Number of signals to send.
622 size_t m_canceled
; // Number of canceled waiters in m_waiters.
625 wxCondError
wxConditionInternal::WaitTimeout( unsigned long msectimeout
)
629 if ( ++ m_waiters
== INT_MAX
)
631 m_varSection
.Enter();
633 m_waiters
-= m_canceled
;
634 m_signals
-= m_canceled
;
637 m_varSection
.Leave();
643 wxSemaError err
= m_semaphore
.WaitTimeout( msectimeout
);
644 wxASSERT( err
== wxSEMA_NO_ERROR
|| err
== wxSEMA_TIMEOUT
);
646 m_varSection
.Enter();
648 if ( err
!= wxSEMA_NO_ERROR
)
650 if ( m_signals
> m_canceled
)
652 // A signal is being sent after we timed out.
653 if ( m_waiters
== m_signals
)
655 // There are no excess waiters to catch the signal, so
656 // we must throw it away.
657 wxSemaError err2
= m_semaphore
.Wait();
658 if ( err2
!= wxSEMA_NO_ERROR
)
660 wxLogSysError( wx("Error while waiting on semaphore") );
663 wxASSERT( err2
== wxSEMA_NO_ERROR
);
666 if ( --m_signals
== m_canceled
)
668 // This was the last signal. open the gate.
669 wxASSERT( m_waiters
== m_canceled
);
675 // There are excess waiters to catch the signal, leave it be.
681 // No signals is being sent:
682 // the gate may be open or closed, so we can't touch m_waiters.
689 // We caught a signal.
690 wxASSERT( m_signals
> m_canceled
);
694 if ( --m_signals
== m_canceled
)
696 // This was the last signal. open the gate.
697 wxASSERT( m_waiters
== m_canceled
);
703 m_varSection
.Leave();
707 return err
== wxSEMA_TIMEOUT
? wxCOND_TIMEOUT
: wxCOND_MISC_ERROR
;
709 return wxCOND_NO_ERROR
;
713 wxCondError
wxConditionInternal::DoSignal( bool signalAll
)
716 m_varSection
.Enter();
718 wxASSERT( m_signals
== m_canceled
);
720 if ( m_waiters
== m_canceled
)
722 m_varSection
.Leave();
724 return wxCOND_NO_ERROR
;
729 m_waiters
-= m_canceled
;
734 m_signals
= signalAll
? m_waiters
: 1;
735 size_t n
= m_signals
;
737 m_varSection
.Leave();
739 // Let the waiters inherit the gate lock.
743 wxSemaError err
= m_semaphore
.Post();
744 wxASSERT( err
== wxSEMA_NO_ERROR
);
748 return wxCOND_NO_ERROR
;
752 class wxConditionInternal
755 wxConditionInternal( wxMutex
& mutex
);
758 { return m_mutex
.IsOk() && m_semaphore
.IsOk(); }
761 wxCondError
WaitTimeout( unsigned long milliseconds
);
763 wxCondError
Signal();
764 wxCondError
Broadcast();
767 // the number of threads currently waiting for this condition
770 // the critical section protecting m_numWaiters
771 wxCriticalSection m_csWaiters
;
774 wxSemaphore m_semaphore
;
776 DECLARE_NO_COPY_CLASS(wxConditionInternal
)
779 wxConditionInternal::wxConditionInternal( wxMutex
& mutex
)
782 // another thread can't access it until we return from ctor, so no need to
783 // protect access to m_numWaiters here
787 wxCondError
wxConditionInternal::Wait()
789 // increment the number of waiters
790 IncrementAtomic( &m_numWaiters
);
794 // a potential race condition can occur here
796 // after a thread increments nwaiters, and unlocks the mutex and before the
797 // semaphore.Wait() is called, if another thread can cause a signal to be
800 // this race condition is handled by using a semaphore and incrementing the
801 // semaphore only if 'nwaiters' is greater that zero since the semaphore,
802 // can 'remember' signals the race condition will not occur
804 // wait ( if necessary ) and decrement semaphore
805 wxSemaError err
= m_semaphore
.Wait();
808 return err
== wxSEMA_NO_ERROR
? wxCOND_NO_ERROR
: wxCOND_MISC_ERROR
;
811 wxCondError
wxConditionInternal::WaitTimeout( unsigned long milliseconds
)
813 IncrementAtomic( &m_numWaiters
);
817 // a race condition can occur at this point in the code
819 // please see the comments in Wait(), for details
821 wxSemaError err
= m_semaphore
.WaitTimeout(milliseconds
);
823 if ( err
== wxSEMA_TIMEOUT
)
825 // another potential race condition exists here it is caused when a
826 // 'waiting' thread timesout, and returns from WaitForSingleObject, but
827 // has not yet decremented 'nwaiters'.
829 // at this point if another thread calls signal() then the semaphore
830 // will be incremented, but the waiting thread will miss it.
832 // to handle this particular case, the waiting thread calls
833 // WaitForSingleObject again with a timeout of 0, after locking
834 // 'nwaiters_mutex'. this call does not block because of the zero
835 // timeout, but will allow the waiting thread to catch the missed
837 wxCriticalSectionLocker
lock(m_csWaiters
);
839 err
= m_semaphore
.WaitTimeout(0);
841 if ( err
!= wxSEMA_NO_ERROR
)
849 return err
== wxSEMA_NO_ERROR
? wxCOND_NO_ERROR
: wxCOND_MISC_ERROR
;
852 wxCondError
wxConditionInternal::Signal()
854 wxCriticalSectionLocker
lock(m_csWaiters
);
856 if ( m_numWaiters
> 0 )
858 // increment the semaphore by 1
859 if ( m_semaphore
.Post() != wxSEMA_NO_ERROR
)
860 return wxCOND_MISC_ERROR
;
865 return wxCOND_NO_ERROR
;
868 wxCondError
wxConditionInternal::Broadcast()
870 wxCriticalSectionLocker
lock(m_csWaiters
);
872 while ( m_numWaiters
> 0 )
874 if ( m_semaphore
.Post() != wxSEMA_NO_ERROR
)
875 return wxCOND_MISC_ERROR
;
880 return wxCOND_NO_ERROR
;
884 // ----------------------------------------------------------------------------
885 // wxCriticalSection implementation
886 // ----------------------------------------------------------------------------
888 // XXX currently implemented as mutex in headers. Change to critical section.
890 // ----------------------------------------------------------------------------
891 // wxThread implementation
892 // ----------------------------------------------------------------------------
894 // wxThreadInternal class
895 // ----------------------
897 class wxThreadInternal
904 m_prio
= WXTHREAD_DEFAULT_PRIORITY
;
905 m_notifyQueueId
= kInvalidID
;
907 m_cancelled
= false ;
909 // set to true only when the thread starts waiting on m_semSuspend
912 // defaults for joinable threads
913 m_shouldBeJoined
= true;
914 m_isDetached
= false;
917 virtual ~wxThreadInternal()
919 if ( m_notifyQueueId
)
921 MPDeleteQueue( m_notifyQueueId
);
922 m_notifyQueueId
= kInvalidID
;
927 static OSStatus
MacThreadStart(void* arg
);
929 // create a new (suspended) thread (for the given thread object)
930 bool Create(wxThread
*thread
, unsigned int stackSize
);
937 // unblock the thread allowing it to run
938 void SignalRun() { m_semRun
.Post(); }
940 // ask the thread to terminate
943 // go to sleep until Resume() is called
951 int GetPriority() const
953 void SetPriority(int prio
);
956 wxThreadState
GetState() const
958 void SetState(wxThreadState state
)
961 // Get the ID of this thread's underlying MP Services task.
962 MPTaskID
GetId() const
966 { m_cancelled
= true; }
968 bool WasCancelled() const
969 { return m_cancelled
; }
972 void SetExitCode(wxThread::ExitCode exitcode
)
973 { m_exitcode
= exitcode
; }
974 wxThread::ExitCode
GetExitCode() const
975 { return m_exitcode
; }
978 void SetReallyPaused(bool paused
)
979 { m_isPaused
= paused
; }
980 bool IsReallyPaused() const
981 { return m_isPaused
; }
983 // tell the thread that it is a detached one
986 wxCriticalSectionLocker
lock(m_csJoinFlag
);
988 m_shouldBeJoined
= false;
993 // the thread we're associated with
996 MPTaskID m_tid
; // thread id
997 MPQueueID m_notifyQueueId
; // its notification queue
999 wxThreadState m_state
; // see wxThreadState enum
1000 int m_prio
; // in wxWidgets units: from 0 to 100
1002 // this flag is set when the thread should terminate
1005 // this flag is set when the thread is blocking on m_semSuspend
1008 // the thread exit code - only used for joinable (!detached) threads and
1009 // is only valid after the thread termination
1010 wxThread::ExitCode m_exitcode
;
1012 // many threads may call Wait(), but only one of them should call
1013 // pthread_join(), so we have to keep track of this
1014 wxCriticalSection m_csJoinFlag
;
1015 bool m_shouldBeJoined
;
1018 // this semaphore is posted by Run() and the threads Entry() is not
1019 // called before it is done
1020 wxSemaphore m_semRun
;
1022 // this one is signaled when the thread should resume after having been
1024 wxSemaphore m_semSuspend
;
1027 OSStatus
wxThreadInternal::MacThreadStart(void *parameter
)
1029 wxThread
* thread
= (wxThread
*) parameter
;
1030 wxThreadInternal
*pthread
= thread
->m_internal
;
1032 // add to TLS so that This() will work
1033 verify_noerr( MPSetTaskStorageValue( gs_tlsForWXThread
, (TaskStorageValue
) thread
) ) ;
1035 // have to declare this before pthread_cleanup_push() which defines a
1039 // wait for the semaphore to be posted from Run()
1040 pthread
->m_semRun
.Wait();
1042 // test whether we should run the run at all - may be it was deleted
1043 // before it started to Run()?
1045 wxCriticalSectionLocker
lock(thread
->m_critsect
);
1047 dontRunAtAll
= pthread
->GetState() == STATE_NEW
&&
1048 pthread
->WasCancelled();
1051 if ( !dontRunAtAll
)
1053 pthread
->m_exitcode
= thread
->Entry();
1056 wxCriticalSectionLocker
lock(thread
->m_critsect
);
1057 pthread
->SetState( STATE_EXITED
);
1063 if ( pthread
->m_isDetached
)
1070 // on Mac for the running code,
1071 // the correct thread termination is to return
1073 // terminate the thread
1074 thread
->Exit( pthread
->m_exitcode
);
1076 return (OSStatus
) NULL
; // pthread->m_exitcode;
1080 bool wxThreadInternal::Create( wxThread
*thread
, unsigned int stackSize
)
1082 wxASSERT_MSG( m_state
== STATE_NEW
&& !m_tid
,
1083 wxT("Create()ing thread twice?") );
1085 OSStatus err
= noErr
;
1088 if ( m_notifyQueueId
== kInvalidID
)
1090 OSStatus err
= MPCreateQueue( &m_notifyQueueId
);
1093 wxLogSysError( wxT("Cant create the thread event queue") );
1099 m_state
= STATE_NEW
;
1102 MacThreadStart
, (void*)m_thread
, stackSize
,
1103 m_notifyQueueId
, &m_exitcode
, 0, 0, &m_tid
);
1107 wxLogSysError( wxT("Can't create thread") );
1112 if ( m_prio
!= WXTHREAD_DEFAULT_PRIORITY
)
1113 SetPriority( m_prio
);
1118 void wxThreadInternal::SetPriority( int priority
)
1124 // Mac priorities range from 1 to 10,000, with a default of 100.
1125 // wxWidgets priorities range from 0 to 100 with a default of 50.
1126 // We can map wxWidgets to Mac priorities easily by assuming
1127 // the former uses a logarithmic scale.
1128 const unsigned int macPriority
= (int)( exp( priority
/ 25.0 * log( 10.0)) + 0.5);
1130 MPSetTaskWeight( m_tid
, macPriority
);
1134 wxThreadError
wxThreadInternal::Run()
1136 wxCHECK_MSG( GetState() == STATE_NEW
, wxTHREAD_RUNNING
,
1137 wxT("thread may only be started once after Create()") );
1139 SetState( STATE_RUNNING
);
1141 // wake up threads waiting for our start
1144 return wxTHREAD_NO_ERROR
;
1147 void wxThreadInternal::Wait()
1149 wxCHECK_RET( !m_isDetached
, wxT("can't wait for a detached thread") );
1151 // if the thread we're waiting for is waiting for the GUI mutex, we will
1152 // deadlock so make sure we release it temporarily
1153 if ( wxThread::IsMain() )
1155 // give the thread we're waiting for chance to do the GUI call
1156 // it might be in, we don't do this conditionally as the to be waited on
1157 // thread might have to acquire the mutex later but before terminating
1158 if ( wxGuiOwnedByMainThread() )
1163 wxCriticalSectionLocker
lock(m_csJoinFlag
);
1165 if ( m_shouldBeJoined
)
1167 void *param1
, *param2
, *rc
;
1169 OSStatus err
= MPWaitOnQueue(
1177 wxLogSysError( wxT( "Cannot wait for thread termination."));
1181 // actually param1 would be the address of m_exitcode
1182 // but we don't need this here
1185 m_shouldBeJoined
= false;
1190 void wxThreadInternal::Pause()
1192 // the state is set from the thread which pauses us first, this function
1193 // is called later so the state should have been already set
1194 wxCHECK_RET( m_state
== STATE_PAUSED
,
1195 wxT("thread must first be paused with wxThread::Pause().") );
1197 // wait until the semaphore is Post()ed from Resume()
1198 m_semSuspend
.Wait();
1201 void wxThreadInternal::Resume()
1203 wxCHECK_RET( m_state
== STATE_PAUSED
,
1204 wxT("can't resume thread which is not suspended.") );
1206 // the thread might be not actually paused yet - if there were no call to
1207 // TestDestroy() since the last call to Pause() for example
1208 if ( IsReallyPaused() )
1211 m_semSuspend
.Post();
1214 SetReallyPaused( false );
1217 SetState( STATE_RUNNING
);
1223 wxThread
*wxThread::This()
1225 wxThread
* thr
= (wxThread
*) MPGetTaskStorageValue( gs_tlsForWXThread
) ;
1230 bool wxThread::IsMain()
1232 return GetCurrentId() == gs_idMainThread
|| gs_idMainThread
== kInvalidID
;
1239 void wxThread::Yield()
1241 CFRunLoopRunInMode( kCFRunLoopDefaultMode
, 0 , true ) ;
1246 void wxThread::Sleep( unsigned long milliseconds
)
1248 AbsoluteTime wakeup
= AddDurationToAbsolute( milliseconds
, UpTime() );
1249 MPDelayUntil( &wakeup
);
1252 int wxThread::GetCPUCount()
1254 return MPProcessors();
1257 unsigned long wxThread::GetCurrentId()
1259 return (unsigned long)MPCurrentTaskID();
1262 bool wxThread::SetConcurrency( size_t WXUNUSED(level
) )
1264 // Cannot be set in MacOS.
1268 wxThread::wxThread( wxThreadKind kind
)
1270 g_numberOfThreads
++;
1271 m_internal
= new wxThreadInternal();
1273 m_isDetached
= (kind
== wxTHREAD_DETACHED
);
1276 wxThread::~wxThread()
1278 wxASSERT_MSG( g_numberOfThreads
>0 , wxT("More threads deleted than created.") ) ;
1280 g_numberOfThreads
--;
1285 // check that the thread either exited or couldn't be created
1286 if ( m_internal
->GetState() != STATE_EXITED
&&
1287 m_internal
->GetState() != STATE_NEW
)
1290 wxT("The thread %ld is being destroyed although it is still running! The application may crash."),
1297 wxDELETE( m_internal
) ;
1300 wxThreadError
wxThread::Create( unsigned int stackSize
)
1302 wxCriticalSectionLocker
lock(m_critsect
);
1305 m_internal
->Detach() ;
1307 if ( !m_internal
->Create(this, stackSize
) )
1309 m_internal
->SetState( STATE_EXITED
);
1311 return wxTHREAD_NO_RESOURCE
;
1314 return wxTHREAD_NO_ERROR
;
1317 wxThreadError
wxThread::Run()
1319 wxCriticalSectionLocker
lock(m_critsect
);
1321 wxCHECK_MSG( m_internal
->GetId(), wxTHREAD_MISC_ERROR
,
1322 wxT("must call wxThread::Create() first") );
1324 return m_internal
->Run();
1327 // -----------------------------------------------------------------------------
1329 // -----------------------------------------------------------------------------
1331 wxThreadError
wxThread::Pause()
1333 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
,
1334 _T("a thread can't pause itself") );
1336 wxCriticalSectionLocker
lock(m_critsect
);
1338 if ( m_internal
->GetState() != STATE_RUNNING
)
1340 wxLogDebug( wxT("Can't pause thread which is not running.") );
1342 return wxTHREAD_NOT_RUNNING
;
1345 // just set a flag, the thread will be really paused only during the next
1346 // call to TestDestroy()
1347 m_internal
->SetState( STATE_PAUSED
);
1349 return wxTHREAD_NO_ERROR
;
1352 wxThreadError
wxThread::Resume()
1354 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
,
1355 wxT("a thread can't resume itself") );
1357 wxCriticalSectionLocker
lock(m_critsect
);
1359 wxThreadState state
= m_internal
->GetState();
1364 m_internal
->Resume();
1365 return wxTHREAD_NO_ERROR
;
1368 return wxTHREAD_NO_ERROR
;
1371 wxLogDebug( wxT("Attempt to resume a thread which is not paused.") );
1373 return wxTHREAD_MISC_ERROR
;
1377 // -----------------------------------------------------------------------------
1379 // -----------------------------------------------------------------------------
1381 wxThread::ExitCode
wxThread::Wait()
1383 wxCHECK_MSG( This() != this, (ExitCode
)-1,
1384 wxT("a thread can't wait for itself") );
1386 wxCHECK_MSG( !m_isDetached
, (ExitCode
)-1,
1387 wxT("can't wait for detached thread") );
1391 return m_internal
->GetExitCode();
1394 wxThreadError
wxThread::Delete(ExitCode
*rc
)
1396 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
,
1397 wxT("a thread can't delete itself") );
1399 bool isDetached
= m_isDetached
;
1402 wxThreadState state
= m_internal
->GetState();
1404 // ask the thread to stop
1405 m_internal
->SetCancelFlag();
1412 // we need to wake up the thread so that PthreadStart() will
1413 // terminate - right now it's blocking on run semaphore in
1415 m_internal
->SignalRun();
1424 // resume the thread first
1425 m_internal
->Resume();
1432 // wait until the thread stops
1437 // return the exit code of the thread
1438 *rc
= m_internal
->GetExitCode();
1443 return wxTHREAD_NO_ERROR
;
1446 wxThreadError
wxThread::Kill()
1448 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
,
1449 wxT("a thread can't kill itself") );
1451 switch ( m_internal
->GetState() )
1455 return wxTHREAD_NOT_RUNNING
;
1458 // resume the thread first
1464 OSStatus err
= MPTerminateTask( m_internal
->GetId() , -1 ) ;
1467 wxLogError( wxT("Failed to terminate a thread.") );
1469 return wxTHREAD_MISC_ERROR
;
1478 // this should be retrieved by Wait actually
1479 m_internal
->SetExitCode( (void*)-1 );
1482 return wxTHREAD_NO_ERROR
;
1486 void wxThread::Exit( ExitCode status
)
1488 wxASSERT_MSG( This() == this,
1489 wxT("wxThread::Exit() can only be called in the context of the same thread") );
1491 // don't enter m_critsect before calling OnExit() because the user code
1492 // might deadlock if, for example, it signals a condition in OnExit() (a
1493 // common case) while the main thread calls any of functions entering
1494 // m_critsect on us (almost all of them do)
1497 MPTaskID threadid
= m_internal
->GetId();
1505 // update the status of the joinable thread
1506 wxCriticalSectionLocker
lock( m_critsect
);
1507 m_internal
->SetState( STATE_EXITED
);
1510 MPTerminateTask( threadid
, (long)status
);
1513 // also test whether we were paused
1514 bool wxThread::TestDestroy()
1516 wxASSERT_MSG( This() == this,
1517 wxT("wxThread::TestDestroy() can only be called in the context of the same thread") );
1521 if ( m_internal
->GetState() == STATE_PAUSED
)
1523 m_internal
->SetReallyPaused( true );
1525 // leave the crit section or the other threads will stop too if they attempt
1526 // to call any of (seemingly harmless) IsXXX() functions while we sleep
1529 m_internal
->Pause();
1533 // thread wasn't requested to pause, nothing to do
1537 return m_internal
->WasCancelled();
1540 // -----------------------------------------------------------------------------
1542 // -----------------------------------------------------------------------------
1544 void wxThread::SetPriority(unsigned int prio
)
1546 wxCHECK_RET( ((int)WXTHREAD_MIN_PRIORITY
<= (int)prio
) &&
1547 ((int)prio
<= (int)WXTHREAD_MAX_PRIORITY
),
1548 wxT("invalid thread priority") );
1550 wxCriticalSectionLocker
lock(m_critsect
);
1552 switch ( m_internal
->GetState() )
1557 // thread not yet started, priority will be set when it is
1558 m_internal
->SetPriority( prio
);
1563 wxFAIL_MSG( wxT("impossible to set thread priority in this state") );
1567 unsigned int wxThread::GetPriority() const
1569 wxCriticalSectionLocker
lock((wxCriticalSection
&)m_critsect
); // const_cast
1571 return m_internal
->GetPriority();
1574 unsigned long wxThread::GetId() const
1576 wxCriticalSectionLocker
lock((wxCriticalSection
&)m_critsect
); // const_cast
1578 return (unsigned long)m_internal
->GetId();
1581 // -----------------------------------------------------------------------------
1583 // -----------------------------------------------------------------------------
1585 bool wxThread::IsRunning() const
1587 wxCriticalSectionLocker
lock((wxCriticalSection
&)m_critsect
);
1589 return m_internal
->GetState() == STATE_RUNNING
;
1592 bool wxThread::IsAlive() const
1594 wxCriticalSectionLocker
lock((wxCriticalSection
&)m_critsect
);
1596 switch ( m_internal
->GetState() )
1607 bool wxThread::IsPaused() const
1609 wxCriticalSectionLocker
lock((wxCriticalSection
&)m_critsect
);
1611 return (m_internal
->GetState() == STATE_PAUSED
);
1614 // ----------------------------------------------------------------------------
1615 // Automatic initialization for thread module
1616 // ----------------------------------------------------------------------------
1618 class wxThreadModule
: public wxModule
1621 virtual bool OnInit();
1622 virtual void OnExit();
1625 DECLARE_DYNAMIC_CLASS(wxThreadModule
)
1628 IMPLEMENT_DYNAMIC_CLASS(wxThreadModule
, wxModule
)
1630 bool wxThreadModule::OnInit()
1632 bool hasThreadManager
=
1634 true ; // TODO VERIFY IN NEXT BUILD
1636 MPLibraryIsLoaded();
1639 if ( !hasThreadManager
)
1641 wxLogError( wxT("MP thread support is not available on this system" ) ) ;
1646 // main thread's This() is NULL
1647 verify_noerr( MPAllocateTaskStorageIndex( &gs_tlsForWXThread
) ) ;
1648 verify_noerr( MPSetTaskStorageValue( gs_tlsForWXThread
, 0 ) ) ;
1650 gs_idMainThread
= wxThread::GetCurrentId();
1651 gs_critsectWaitingForGui
= new wxCriticalSection();
1653 gs_critsectGui
= new wxCriticalSection();
1654 gs_critsectGui
->Enter();
1659 void wxThreadModule::OnExit()
1661 if ( gs_critsectGui
)
1663 if ( !wxGuiOwnedByMainThread() )
1665 gs_critsectGui
->Enter();
1666 gs_bGuiOwnedByMainThread
= true;
1669 gs_critsectGui
->Leave();
1670 delete gs_critsectGui
;
1671 gs_critsectGui
= NULL
;
1674 delete gs_critsectWaitingForGui
;
1675 gs_critsectWaitingForGui
= NULL
;
1678 // ----------------------------------------------------------------------------
1679 // GUI Serialization copied from MSW implementation
1680 // ----------------------------------------------------------------------------
1682 void WXDLLIMPEXP_BASE
wxMutexGuiEnter()
1684 // this would dead lock everything...
1685 wxASSERT_MSG( !wxThread::IsMain(),
1686 wxT("main thread doesn't want to block in wxMutexGuiEnter()!") );
1688 // the order in which we enter the critical sections here is crucial!!
1690 // set the flag telling to the main thread that we want to do some GUI
1692 wxCriticalSectionLocker
enter(*gs_critsectWaitingForGui
);
1694 gs_nWaitingForGui
++;
1697 wxWakeUpMainThread();
1699 // now we may block here because the main thread will soon let us in
1700 // (during the next iteration of OnIdle())
1701 gs_critsectGui
->Enter();
1704 void WXDLLIMPEXP_BASE
wxMutexGuiLeave()
1706 wxCriticalSectionLocker
enter(*gs_critsectWaitingForGui
);
1708 if ( wxThread::IsMain() )
1710 gs_bGuiOwnedByMainThread
= false;
1714 // decrement the number of threads waiting for GUI access now
1715 wxASSERT_MSG( gs_nWaitingForGui
> 0,
1716 wxT("calling wxMutexGuiLeave() without entering it first?") );
1718 gs_nWaitingForGui
--;
1720 wxWakeUpMainThread();
1723 gs_critsectGui
->Leave();
1726 void WXDLLIMPEXP_BASE
wxMutexGuiLeaveOrEnter()
1728 wxASSERT_MSG( wxThread::IsMain(),
1729 wxT("only main thread may call wxMutexGuiLeaveOrEnter()!") );
1731 if ( !gs_critsectWaitingForGui
)
1734 wxCriticalSectionLocker
enter(*gs_critsectWaitingForGui
);
1736 if ( gs_nWaitingForGui
== 0 )
1738 // no threads are waiting for GUI - so we may acquire the lock without
1739 // any danger (but only if we don't already have it)
1740 if ( !wxGuiOwnedByMainThread() )
1742 gs_critsectGui
->Enter();
1744 gs_bGuiOwnedByMainThread
= true;
1746 //else: already have it, nothing to do
1750 // some threads are waiting, release the GUI lock if we have it
1751 if ( wxGuiOwnedByMainThread() )
1753 //else: some other worker thread is doing GUI
1757 bool WXDLLIMPEXP_BASE
wxGuiOwnedByMainThread()
1759 return gs_bGuiOwnedByMainThread
;
1762 // wake up the main thread
1763 void WXDLLEXPORT
wxWakeUpMainThread()
1768 // ----------------------------------------------------------------------------
1769 // include common implementation code
1770 // ----------------------------------------------------------------------------
1772 #include "wx/thrimpl.cpp"
1774 #endif // wxUSE_THREADS