1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/unix/threadpsx.cpp 
   3 // Purpose:     wxThread (Posix) Implementation 
   4 // Author:      Original from Wolfram Gloger/Guilhem Lavaux 
   5 // Modified by: K. S. Sreeram (2002): POSIXified wxCondition, added wxSemaphore 
   8 // Copyright:   (c) Wolfram Gloger (1996, 1997) 
   9 //                  Guilhem Lavaux (1998) 
  10 //                  Vadim Zeitlin (1999-2002) 
  11 //                  Robert Roebling (1999) 
  12 //                  K. S. Sreeram (2002) 
  13 // Licence:     wxWindows licence 
  14 ///////////////////////////////////////////////////////////////////////////// 
  16 // ============================================================================ 
  18 // ============================================================================ 
  20 // ---------------------------------------------------------------------------- 
  22 // ---------------------------------------------------------------------------- 
  24 // for compilers that support precompilation, includes "wx.h". 
  25 #include "wx/wxprec.h" 
  29 #include "wx/thread.h" 
  30 #include "wx/except.h" 
  34     #include "wx/dynarray.h" 
  39     #include "wx/stopwatch.h" 
  40     #include "wx/module.h" 
  48 #include <sys/time.h>           // needed for at least __QNX__ 
  53 #ifdef HAVE_THR_SETCONCURRENCY 
  57 #ifdef HAVE_ABI_FORCEDUNWIND 
  61 #ifdef HAVE_SETPRIORITY 
  62     #include <sys/resource.h>   // for setpriority() 
  65 // we use wxFFile under Linux in GetCPUCount() 
  70 #define THR_ID_CAST(id)  (reinterpret_cast<void*>(id)) 
  71 #define THR_ID(thr)      THR_ID_CAST((thr)->GetId()) 
  73 // ---------------------------------------------------------------------------- 
  75 // ---------------------------------------------------------------------------- 
  77 // the possible states of the thread and transitions from them 
  80     STATE_NEW
,          // didn't start execution yet (=> RUNNING) 
  81     STATE_RUNNING
,      // running (=> PAUSED or EXITED) 
  82     STATE_PAUSED
,       // suspended (=> RUNNING or EXITED) 
  83     STATE_EXITED        
// thread doesn't exist any more 
  86 // the exit value of a thread which has been cancelled 
  87 static const wxThread::ExitCode EXITCODE_CANCELLED 
= (wxThread::ExitCode
)-1; 
  89 // trace mask for wxThread operations 
  90 #define TRACE_THREADS   wxT("thread") 
  92 // you can get additional debugging messages for the semaphore operations 
  93 #define TRACE_SEMA      wxT("semaphore") 
  95 // ---------------------------------------------------------------------------- 
  97 // ---------------------------------------------------------------------------- 
  99 static void ScheduleThreadForDeletion(); 
 100 static void DeleteThread(wxThread 
*This
); 
 102 // ---------------------------------------------------------------------------- 
 104 // ---------------------------------------------------------------------------- 
 106 // an (non owning) array of pointers to threads 
 107 WX_DEFINE_ARRAY_PTR(wxThread 
*, wxArrayThread
); 
 109 // an entry for a thread we can wait for 
 111 // ----------------------------------------------------------------------------- 
 113 // ----------------------------------------------------------------------------- 
 115 // we keep the list of all threads created by the application to be able to 
 116 // terminate them on exit if there are some left - otherwise the process would 
 118 static wxArrayThread gs_allThreads
; 
 120 // a mutex to protect gs_allThreads 
 121 static wxMutex 
*gs_mutexAllThreads 
= NULL
; 
 123 // the id of the main thread 
 125 // we suppose that 0 is not a valid pthread_t value but in principle this might 
 126 // be false (e.g. if it's a selector-like value), wxThread::IsMain() would need 
 127 // to be updated in such case 
 128 wxThreadIdType 
wxThread::ms_idMainThread 
= 0; 
 130 // the key for the pointer to the associated wxThread object 
 131 static pthread_key_t gs_keySelf
; 
 133 // the number of threads which are being deleted - the program won't exit 
 134 // until there are any left 
 135 static size_t gs_nThreadsBeingDeleted 
= 0; 
 137 // a mutex to protect gs_nThreadsBeingDeleted 
 138 static wxMutex 
*gs_mutexDeleteThread 
= NULL
; 
 140 // and a condition variable which will be signaled when all 
 141 // gs_nThreadsBeingDeleted will have been deleted 
 142 static wxCondition 
*gs_condAllDeleted 
= NULL
; 
 145 // this mutex must be acquired before any call to a GUI function 
 146 // (it's not inside #if wxUSE_GUI because this file is compiled as part 
 148 static wxMutex 
*gs_mutexGui 
= NULL
; 
 151 // when we wait for a thread to exit, we're blocking on a condition which the 
 152 // thread signals in its SignalExit() method -- but this condition can't be a 
 153 // member of the thread itself as a detached thread may delete itself at any 
 154 // moment and accessing the condition member of the thread after this would 
 155 // result in a disaster 
 157 // so instead we maintain a global list of the structs below for the threads 
 158 // we're interested in waiting on 
 160 // ============================================================================ 
 161 // wxMutex implementation 
 162 // ============================================================================ 
 164 // ---------------------------------------------------------------------------- 
 166 // ---------------------------------------------------------------------------- 
 168 // this is a simple wrapper around pthread_mutex_t which provides error 
 170 class wxMutexInternal
 
 173     wxMutexInternal(wxMutexType mutexType
); 
 177     wxMutexError 
Lock(unsigned long ms
); 
 178     wxMutexError 
TryLock(); 
 179     wxMutexError 
Unlock(); 
 181     bool IsOk() const { return m_isOk
; } 
 184     // convert the result of pthread_mutex_[timed]lock() call to wx return code 
 185     wxMutexError 
HandleLockResult(int err
); 
 188     pthread_mutex_t m_mutex
; 
 191     unsigned long m_owningThread
; 
 193     // wxConditionInternal uses our m_mutex 
 194     friend class wxConditionInternal
; 
 197 #if defined(HAVE_PTHREAD_MUTEXATTR_T) && \ 
 198         wxUSE_UNIX && !defined(HAVE_PTHREAD_MUTEXATTR_SETTYPE_DECL) 
 199 // on some systems pthread_mutexattr_settype() is not in the headers (but it is 
 200 // in the library, otherwise we wouldn't compile this code at all) 
 201 extern "C" int pthread_mutexattr_settype(pthread_mutexattr_t 
*, int); 
 204 wxMutexInternal::wxMutexInternal(wxMutexType mutexType
) 
 212         case wxMUTEX_RECURSIVE
: 
 213             // support recursive locks like Win32, i.e. a thread can lock a 
 214             // mutex which it had itself already locked 
 216             // unfortunately initialization of recursive mutexes is non 
 217             // portable, so try several methods 
 218 #ifdef HAVE_PTHREAD_MUTEXATTR_T 
 220                 pthread_mutexattr_t attr
; 
 221                 pthread_mutexattr_init(&attr
); 
 222                 pthread_mutexattr_settype(&attr
, PTHREAD_MUTEX_RECURSIVE
); 
 224                 err 
= pthread_mutex_init(&m_mutex
, &attr
); 
 226 #elif defined(HAVE_PTHREAD_RECURSIVE_MUTEX_INITIALIZER) 
 227             // we can use this only as initializer so we have to assign it 
 228             // first to a temp var - assigning directly to m_mutex wouldn't 
 231                 pthread_mutex_t mutex 
= PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
; 
 234 #else // no recursive mutexes 
 236 #endif // HAVE_PTHREAD_MUTEXATTR_T/... 
 240             wxFAIL_MSG( wxT("unknown mutex type") ); 
 243         case wxMUTEX_DEFAULT
: 
 244             err 
= pthread_mutex_init(&m_mutex
, NULL
); 
 251         wxLogApiError( wxT("pthread_mutex_init()"), err
); 
 255 wxMutexInternal::~wxMutexInternal() 
 259         int err 
= pthread_mutex_destroy(&m_mutex
); 
 262             wxLogApiError( wxT("pthread_mutex_destroy()"), err
); 
 267 wxMutexError 
wxMutexInternal::Lock() 
 269     if ((m_type 
== wxMUTEX_DEFAULT
) && (m_owningThread 
!= 0)) 
 271         if (m_owningThread 
== wxThread::GetCurrentId()) 
 272            return wxMUTEX_DEAD_LOCK
; 
 275     return HandleLockResult(pthread_mutex_lock(&m_mutex
)); 
 278 wxMutexError 
wxMutexInternal::Lock(unsigned long ms
) 
 280 #ifdef HAVE_PTHREAD_MUTEX_TIMEDLOCK 
 281     static const long MSEC_IN_SEC   
= 1000; 
 282     static const long NSEC_IN_MSEC  
= 1000000; 
 283     static const long NSEC_IN_USEC  
= 1000; 
 284     static const long NSEC_IN_SEC   
= MSEC_IN_SEC 
* NSEC_IN_MSEC
; 
 286     time_t seconds 
= ms
/MSEC_IN_SEC
; 
 287     long nanoseconds 
= (ms 
% MSEC_IN_SEC
) * NSEC_IN_MSEC
; 
 288     timespec ts 
= { 0, 0 }; 
 290     // normally we should use clock_gettime(CLOCK_REALTIME) here but this 
 291     // function is in librt and we don't link with it currently, so use 
 292     // gettimeofday() instead -- if it turns out that this is really too 
 293     // imprecise, we should modify configure to check if clock_gettime() is 
 294     // available and whether it requires -lrt and use it instead 
 296     if ( clock_gettime(CLOCK_REALTIME
, &ts
) == 0 ) 
 301     if ( wxGetTimeOfDay(&tv
) != -1 ) 
 303         ts
.tv_sec 
= tv
.tv_sec
; 
 304         ts
.tv_nsec 
= tv
.tv_usec
*NSEC_IN_USEC
; 
 307     else // fall back on system timer 
 309         ts
.tv_sec 
= time(NULL
); 
 312     ts
.tv_sec 
+= seconds
; 
 313     ts
.tv_nsec 
+= nanoseconds
; 
 314     if ( ts
.tv_nsec 
> NSEC_IN_SEC 
) 
 317         ts
.tv_nsec 
-= NSEC_IN_SEC
; 
 320     return HandleLockResult(pthread_mutex_timedlock(&m_mutex
, &ts
)); 
 321 #else // !HAVE_PTHREAD_MUTEX_TIMEDLOCK 
 324     return wxMUTEX_MISC_ERROR
; 
 325 #endif // HAVE_PTHREAD_MUTEX_TIMEDLOCK/!HAVE_PTHREAD_MUTEX_TIMEDLOCK 
 328 wxMutexError 
wxMutexInternal::HandleLockResult(int err
) 
 330     // wxPrintf( "err %d\n", err ); 
 335             // only error checking mutexes return this value and so it's an 
 336             // unexpected situation -- hence use assert, not wxLogDebug 
 337             wxFAIL_MSG( wxT("mutex deadlock prevented") ); 
 338             return wxMUTEX_DEAD_LOCK
; 
 341             wxLogDebug(wxT("pthread_mutex_[timed]lock(): mutex not initialized")); 
 345             return wxMUTEX_TIMEOUT
; 
 348             if (m_type 
== wxMUTEX_DEFAULT
) 
 349                 m_owningThread 
= wxThread::GetCurrentId(); 
 350             return wxMUTEX_NO_ERROR
; 
 353             wxLogApiError(wxT("pthread_mutex_[timed]lock()"), err
); 
 356     return wxMUTEX_MISC_ERROR
; 
 360 wxMutexError 
wxMutexInternal::TryLock() 
 362     int err 
= pthread_mutex_trylock(&m_mutex
); 
 366             // not an error: mutex is already locked, but we're prepared for 
 371             wxLogDebug(wxT("pthread_mutex_trylock(): mutex not initialized.")); 
 375             if (m_type 
== wxMUTEX_DEFAULT
) 
 376                 m_owningThread 
= wxThread::GetCurrentId(); 
 377             return wxMUTEX_NO_ERROR
; 
 380             wxLogApiError(wxT("pthread_mutex_trylock()"), err
); 
 383     return wxMUTEX_MISC_ERROR
; 
 386 wxMutexError 
wxMutexInternal::Unlock() 
 390     int err 
= pthread_mutex_unlock(&m_mutex
); 
 394             // we don't own the mutex 
 395             return wxMUTEX_UNLOCKED
; 
 398             wxLogDebug(wxT("pthread_mutex_unlock(): mutex not initialized.")); 
 402             return wxMUTEX_NO_ERROR
; 
 405             wxLogApiError(wxT("pthread_mutex_unlock()"), err
); 
 408     return wxMUTEX_MISC_ERROR
; 
 411 // =========================================================================== 
 412 // wxCondition implementation 
 413 // =========================================================================== 
 415 // --------------------------------------------------------------------------- 
 416 // wxConditionInternal 
 417 // --------------------------------------------------------------------------- 
 419 // this is a wrapper around pthread_cond_t associated with a wxMutex (and hence 
 420 // with a pthread_mutex_t) 
 421 class wxConditionInternal
 
 424     wxConditionInternal(wxMutex
& mutex
); 
 425     ~wxConditionInternal(); 
 427     bool IsOk() const { return m_isOk 
&& m_mutex
.IsOk(); } 
 430     wxCondError 
WaitTimeout(unsigned long milliseconds
); 
 432     wxCondError 
Signal(); 
 433     wxCondError 
Broadcast(); 
 436     // get the POSIX mutex associated with us 
 437     pthread_mutex_t 
*GetPMutex() const { return &m_mutex
.m_internal
->m_mutex
; } 
 440     pthread_cond_t m_cond
; 
 445 wxConditionInternal::wxConditionInternal(wxMutex
& mutex
) 
 448     int err 
= pthread_cond_init(&m_cond
, NULL 
/* default attributes */); 
 454         wxLogApiError(wxT("pthread_cond_init()"), err
); 
 458 wxConditionInternal::~wxConditionInternal() 
 462         int err 
= pthread_cond_destroy(&m_cond
); 
 465             wxLogApiError(wxT("pthread_cond_destroy()"), err
); 
 470 wxCondError 
wxConditionInternal::Wait() 
 472     int err 
= pthread_cond_wait(&m_cond
, GetPMutex()); 
 475         wxLogApiError(wxT("pthread_cond_wait()"), err
); 
 477         return wxCOND_MISC_ERROR
; 
 480     return wxCOND_NO_ERROR
; 
 483 wxCondError 
wxConditionInternal::WaitTimeout(unsigned long milliseconds
) 
 485     wxLongLong curtime 
= wxGetUTCTimeMillis(); 
 486     curtime 
+= milliseconds
; 
 487     wxLongLong temp 
= curtime 
/ 1000; 
 488     int sec 
= temp
.GetLo(); 
 490     temp 
= curtime 
- temp
; 
 491     int millis 
= temp
.GetLo(); 
 496     tspec
.tv_nsec 
= millis 
* 1000L * 1000L; 
 498     int err 
= pthread_cond_timedwait( &m_cond
, GetPMutex(), &tspec 
); 
 502             return wxCOND_TIMEOUT
; 
 505             return wxCOND_NO_ERROR
; 
 508             wxLogApiError(wxT("pthread_cond_timedwait()"), err
); 
 511     return wxCOND_MISC_ERROR
; 
 514 wxCondError 
wxConditionInternal::Signal() 
 516     int err 
= pthread_cond_signal(&m_cond
); 
 519         wxLogApiError(wxT("pthread_cond_signal()"), err
); 
 521         return wxCOND_MISC_ERROR
; 
 524     return wxCOND_NO_ERROR
; 
 527 wxCondError 
wxConditionInternal::Broadcast() 
 529     int err 
= pthread_cond_broadcast(&m_cond
); 
 532         wxLogApiError(wxT("pthread_cond_broadcast()"), err
); 
 534         return wxCOND_MISC_ERROR
; 
 537     return wxCOND_NO_ERROR
; 
 540 // =========================================================================== 
 541 // wxSemaphore implementation 
 542 // =========================================================================== 
 544 // --------------------------------------------------------------------------- 
 545 // wxSemaphoreInternal 
 546 // --------------------------------------------------------------------------- 
 548 // we implement the semaphores using mutexes and conditions instead of using 
 549 // the sem_xxx() POSIX functions because they're not widely available and also 
 550 // because it's impossible to implement WaitTimeout() using them 
 551 class wxSemaphoreInternal
 
 554     wxSemaphoreInternal(int initialcount
, int maxcount
); 
 556     bool IsOk() const { return m_isOk
; } 
 559     wxSemaError 
TryWait(); 
 560     wxSemaError 
WaitTimeout(unsigned long milliseconds
); 
 574 wxSemaphoreInternal::wxSemaphoreInternal(int initialcount
, int maxcount
) 
 578     if ( (initialcount 
< 0 || maxcount 
< 0) || 
 579             ((maxcount 
> 0) && (initialcount 
> maxcount
)) ) 
 581         wxFAIL_MSG( wxT("wxSemaphore: invalid initial or maximal count") ); 
 587         m_maxcount 
= (size_t)maxcount
; 
 588         m_count 
= (size_t)initialcount
; 
 591     m_isOk 
= m_mutex
.IsOk() && m_cond
.IsOk(); 
 594 wxSemaError 
wxSemaphoreInternal::Wait() 
 596     wxMutexLocker 
locker(m_mutex
); 
 598     while ( m_count 
== 0 ) 
 600         wxLogTrace(TRACE_SEMA
, 
 601                    wxT("Thread %p waiting for semaphore to become signalled"), 
 602                    THR_ID_CAST(wxThread::GetCurrentId())); 
 604         if ( m_cond
.Wait() != wxCOND_NO_ERROR 
) 
 605             return wxSEMA_MISC_ERROR
; 
 607         wxLogTrace(TRACE_SEMA
, 
 608                    wxT("Thread %p finished waiting for semaphore, count = %lu"), 
 609                    THR_ID_CAST(wxThread::GetCurrentId()), (unsigned long)m_count
); 
 614     return wxSEMA_NO_ERROR
; 
 617 wxSemaError 
wxSemaphoreInternal::TryWait() 
 619     wxMutexLocker 
locker(m_mutex
); 
 626     return wxSEMA_NO_ERROR
; 
 629 wxSemaError 
wxSemaphoreInternal::WaitTimeout(unsigned long milliseconds
) 
 631     wxMutexLocker 
locker(m_mutex
); 
 633     wxLongLong startTime 
= wxGetLocalTimeMillis(); 
 635     while ( m_count 
== 0 ) 
 637         wxLongLong elapsed 
= wxGetLocalTimeMillis() - startTime
; 
 638         long remainingTime 
= (long)milliseconds 
- (long)elapsed
.GetLo(); 
 639         if ( remainingTime 
<= 0 ) 
 642             return wxSEMA_TIMEOUT
; 
 645         switch ( m_cond
.WaitTimeout(remainingTime
) ) 
 648                 return wxSEMA_TIMEOUT
; 
 651                 return wxSEMA_MISC_ERROR
; 
 653             case wxCOND_NO_ERROR
: 
 660     return wxSEMA_NO_ERROR
; 
 663 wxSemaError 
wxSemaphoreInternal::Post() 
 665     wxMutexLocker 
locker(m_mutex
); 
 667     if ( m_maxcount 
> 0 && m_count 
== m_maxcount 
) 
 669         return wxSEMA_OVERFLOW
; 
 674     wxLogTrace(TRACE_SEMA
, 
 675                wxT("Thread %p about to signal semaphore, count = %lu"), 
 676                THR_ID_CAST(wxThread::GetCurrentId()), (unsigned long)m_count
); 
 678     return m_cond
.Signal() == wxCOND_NO_ERROR 
? wxSEMA_NO_ERROR
 
 682 // =========================================================================== 
 683 // wxThread implementation 
 684 // =========================================================================== 
 686 // the thread callback functions must have the C linkage 
 690 #ifdef wxHAVE_PTHREAD_CLEANUP 
 691     // thread exit function 
 692     void wxPthreadCleanup(void *ptr
); 
 693 #endif // wxHAVE_PTHREAD_CLEANUP 
 695 void *wxPthreadStart(void *ptr
); 
 699 // ---------------------------------------------------------------------------- 
 701 // ---------------------------------------------------------------------------- 
 703 class wxThreadInternal
 
 709     // thread entry function 
 710     static void *PthreadStart(wxThread 
*thread
); 
 714     wxThreadError 
Create(wxThread 
*thread
, unsigned int stackSize
); 
 717         // unblock the thread allowing it to run 
 718     void SignalRun() { m_semRun
.Post(); } 
 719         // ask the thread to terminate 
 721         // go to sleep until Resume() is called 
 728     int GetPriority() const { return m_prio
; } 
 729     void SetPriority(int prio
) { m_prio 
= prio
; } 
 731     wxThreadState 
GetState() const { return m_state
; } 
 732     void SetState(wxThreadState state
) 
 735         static const wxChar 
*const stateNames
[] = 
 743         wxLogTrace(TRACE_THREADS
, wxT("Thread %p: %s => %s."), 
 744                    THR_ID(this), stateNames
[m_state
], stateNames
[state
]); 
 745 #endif // wxUSE_LOG_TRACE 
 750     pthread_t 
GetId() const { return m_threadId
; } 
 751     pthread_t 
*GetIdPtr() { return &m_threadId
; } 
 753     bool WasCreated() const { return m_created
; } 
 755     void SetCancelFlag() { m_cancelled 
= true; } 
 756     bool WasCancelled() const { return m_cancelled
; } 
 758     void SetExitCode(wxThread::ExitCode exitcode
) { m_exitcode 
= exitcode
; } 
 759     wxThread::ExitCode 
GetExitCode() const { return m_exitcode
; } 
 762     void SetReallyPaused(bool paused
) { m_isPaused 
= paused
; } 
 763     bool IsReallyPaused() const { return m_isPaused
; } 
 765         // tell the thread that it is a detached one 
 768         wxCriticalSectionLocker 
lock(m_csJoinFlag
); 
 770         m_shouldBeJoined 
= false; 
 774 #ifdef wxHAVE_PTHREAD_CLEANUP 
 775     // this is used by wxPthreadCleanup() only 
 776     static void Cleanup(wxThread 
*thread
); 
 777 #endif // wxHAVE_PTHREAD_CLEANUP 
 780     pthread_t     m_threadId
;   // id of the thread 
 781     wxThreadState m_state
;      // see wxThreadState enum 
 782     int           m_prio
;       // in wxWidgets units: from 0 to 100 
 784     // this flag is set when the thread was successfully created 
 787     // this flag is set when the thread should terminate 
 790     // this flag is set when the thread is blocking on m_semSuspend 
 793     // the thread exit code - only used for joinable (!detached) threads and 
 794     // is only valid after the thread termination 
 795     wxThread::ExitCode m_exitcode
; 
 797     // many threads may call Wait(), but only one of them should call 
 798     // pthread_join(), so we have to keep track of this 
 799     wxCriticalSection m_csJoinFlag
; 
 800     bool m_shouldBeJoined
; 
 803     // this semaphore is posted by Run() and the threads Entry() is not 
 804     // called before it is done 
 805     wxSemaphore m_semRun
; 
 807     // this one is signaled when the thread should resume after having been 
 809     wxSemaphore m_semSuspend
; 
 812 // ---------------------------------------------------------------------------- 
 813 // thread startup and exit functions 
 814 // ---------------------------------------------------------------------------- 
 816 void *wxPthreadStart(void *ptr
) 
 818     return wxThreadInternal::PthreadStart((wxThread 
*)ptr
); 
 821 void *wxThreadInternal::PthreadStart(wxThread 
*thread
) 
 823     wxThreadInternal 
*pthread 
= thread
->m_internal
; 
 825     wxLogTrace(TRACE_THREADS
, wxT("Thread %p started."), THR_ID(pthread
)); 
 827     // associate the thread pointer with the newly created thread so that 
 828     // wxThread::This() will work 
 829     int rc 
= pthread_setspecific(gs_keySelf
, thread
); 
 832         wxLogSysError(rc
, _("Cannot start thread: error writing TLS.")); 
 837     // have to declare this before pthread_cleanup_push() which defines a 
 841 #ifdef wxHAVE_PTHREAD_CLEANUP 
 842     // install the cleanup handler which will be called if the thread is 
 844     pthread_cleanup_push(wxPthreadCleanup
, thread
); 
 845 #endif // wxHAVE_PTHREAD_CLEANUP 
 847     // wait for the semaphore to be posted from Run() 
 848     pthread
->m_semRun
.Wait(); 
 850     // test whether we should run the run at all - may be it was deleted 
 851     // before it started to Run()? 
 853         wxCriticalSectionLocker 
lock(thread
->m_critsect
); 
 855         dontRunAtAll 
= pthread
->GetState() == STATE_NEW 
&& 
 856                        pthread
->WasCancelled(); 
 861         // call the main entry 
 862         wxLogTrace(TRACE_THREADS
, 
 863                    wxT("Thread %p about to enter its Entry()."), 
 868             pthread
->m_exitcode 
= thread
->Entry(); 
 870             wxLogTrace(TRACE_THREADS
, 
 871                        wxT("Thread %p Entry() returned %lu."), 
 872                        THR_ID(pthread
), wxPtrToUInt(pthread
->m_exitcode
)); 
 874 #ifdef HAVE_ABI_FORCEDUNWIND 
 875         // When using common C++ ABI under Linux we must always rethrow this 
 876         // special exception used to unwind the stack when the thread was 
 877         // cancelled, otherwise the thread library would simply terminate the 
 878         // program, see http://udrepper.livejournal.com/21541.html 
 879         catch ( abi::__forced_unwind
& ) 
 881             wxCriticalSectionLocker 
lock(thread
->m_critsect
); 
 882             pthread
->SetState(STATE_EXITED
); 
 885 #endif // HAVE_ABI_FORCEDUNWIND 
 886         wxCATCH_ALL( wxTheApp
->OnUnhandledException(); ) 
 889             wxCriticalSectionLocker 
lock(thread
->m_critsect
); 
 891             // change the state of the thread to "exited" so that 
 892             // wxPthreadCleanup handler won't do anything from now (if it's 
 893             // called before we do pthread_cleanup_pop below) 
 894             pthread
->SetState(STATE_EXITED
); 
 898     // NB: pthread_cleanup_push/pop() are macros and pop contains the matching 
 899     //     '}' for the '{' in push, so they must be used in the same block! 
 900 #ifdef wxHAVE_PTHREAD_CLEANUP 
 902         // under Tru64 we get a warning from macro expansion 
 904         #pragma message disable(declbutnotref) 
 907     // remove the cleanup handler without executing it 
 908     pthread_cleanup_pop(FALSE
); 
 911         #pragma message restore 
 913 #endif // wxHAVE_PTHREAD_CLEANUP 
 917         // FIXME: deleting a possibly joinable thread here??? 
 920         return EXITCODE_CANCELLED
; 
 924         // terminate the thread 
 925         thread
->Exit(pthread
->m_exitcode
); 
 927         wxFAIL_MSG(wxT("wxThread::Exit() can't return.")); 
 933 #ifdef wxHAVE_PTHREAD_CLEANUP 
 935 // this handler is called when the thread is cancelled 
 936 extern "C" void wxPthreadCleanup(void *ptr
) 
 938     wxThreadInternal::Cleanup((wxThread 
*)ptr
); 
 941 void wxThreadInternal::Cleanup(wxThread 
*thread
) 
 943     if (pthread_getspecific(gs_keySelf
) == 0) return; 
 945         wxCriticalSectionLocker 
lock(thread
->m_critsect
); 
 946         if ( thread
->m_internal
->GetState() == STATE_EXITED 
) 
 948             // thread is already considered as finished. 
 953     // exit the thread gracefully 
 954     thread
->Exit(EXITCODE_CANCELLED
); 
 957 #endif // wxHAVE_PTHREAD_CLEANUP 
 959 // ---------------------------------------------------------------------------- 
 961 // ---------------------------------------------------------------------------- 
 963 wxThreadInternal::wxThreadInternal() 
 968     m_prio 
= wxPRIORITY_DEFAULT
; 
 972     // set to true only when the thread starts waiting on m_semSuspend 
 975     // defaults for joinable threads 
 976     m_shouldBeJoined 
= true; 
 977     m_isDetached 
= false; 
 980 wxThreadInternal::~wxThreadInternal() 
 984 #ifdef HAVE_PTHREAD_ATTR_SETSTACKSIZE 
 985     #define WXUNUSED_STACKSIZE(identifier)  identifier 
 987     #define WXUNUSED_STACKSIZE(identifier)  WXUNUSED(identifier) 
 990 wxThreadError 
wxThreadInternal::Create(wxThread 
*thread
, 
 991                                        unsigned int WXUNUSED_STACKSIZE(stackSize
)) 
 993     if ( GetState() != STATE_NEW 
) 
 995         // don't recreate thread 
 996         return wxTHREAD_RUNNING
; 
 999     // set up the thread attribute: right now, we only set thread priority 
1000     pthread_attr_t attr
; 
1001     pthread_attr_init(&attr
); 
1003 #ifdef HAVE_PTHREAD_ATTR_SETSTACKSIZE 
1005       pthread_attr_setstacksize(&attr
, stackSize
); 
1008 #ifdef HAVE_THREAD_PRIORITY_FUNCTIONS 
1010     if ( pthread_attr_getschedpolicy(&attr
, &policy
) != 0 ) 
1012         wxLogError(_("Cannot retrieve thread scheduling policy.")); 
1016    /* the pthread.h contains too many spaces. This is a work-around */ 
1017 # undef sched_get_priority_max 
1018 #undef sched_get_priority_min 
1019 #define sched_get_priority_max(_pol_) \ 
1020      (_pol_ == SCHED_OTHER ? PRI_FG_MAX_NP : PRI_FIFO_MAX) 
1021 #define sched_get_priority_min(_pol_) \ 
1022      (_pol_ == SCHED_OTHER ? PRI_FG_MIN_NP : PRI_FIFO_MIN) 
1025     int max_prio 
= sched_get_priority_max(policy
), 
1026         min_prio 
= sched_get_priority_min(policy
), 
1027         prio 
= GetPriority(); 
1029     if ( min_prio 
== -1 || max_prio 
== -1 ) 
1031         wxLogError(_("Cannot get priority range for scheduling policy %d."), 
1034     else if ( max_prio 
== min_prio 
) 
1036         if ( prio 
!= wxPRIORITY_DEFAULT 
) 
1038             // notify the programmer that this doesn't work here 
1039             wxLogWarning(_("Thread priority setting is ignored.")); 
1041         //else: we have default priority, so don't complain 
1043         // anyhow, don't do anything because priority is just ignored 
1047         struct sched_param sp
; 
1048         if ( pthread_attr_getschedparam(&attr
, &sp
) != 0 ) 
1050             wxFAIL_MSG(wxT("pthread_attr_getschedparam() failed")); 
1053         sp
.sched_priority 
= min_prio 
+ (prio
*(max_prio 
- min_prio
))/100; 
1055         if ( pthread_attr_setschedparam(&attr
, &sp
) != 0 ) 
1057             wxFAIL_MSG(wxT("pthread_attr_setschedparam(priority) failed")); 
1060 #endif // HAVE_THREAD_PRIORITY_FUNCTIONS 
1062 #ifdef HAVE_PTHREAD_ATTR_SETSCOPE 
1063     // this will make the threads created by this process really concurrent 
1064     if ( pthread_attr_setscope(&attr
, PTHREAD_SCOPE_SYSTEM
) != 0 ) 
1066         wxFAIL_MSG(wxT("pthread_attr_setscope(PTHREAD_SCOPE_SYSTEM) failed")); 
1068 #endif // HAVE_PTHREAD_ATTR_SETSCOPE 
1070     // VZ: assume that this one is always available (it's rather fundamental), 
1071     //     if this function is ever missing we should try to use 
1072     //     pthread_detach() instead (after thread creation) 
1073     if ( thread
->IsDetached() ) 
1075         if ( pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_DETACHED
) != 0 ) 
1077             wxFAIL_MSG(wxT("pthread_attr_setdetachstate(DETACHED) failed")); 
1080         // never try to join detached threads 
1083     //else: threads are created joinable by default, it's ok 
1085     // create the new OS thread object 
1086     int rc 
= pthread_create
 
1094     if ( pthread_attr_destroy(&attr
) != 0 ) 
1096         wxFAIL_MSG(wxT("pthread_attr_destroy() failed")); 
1101         SetState(STATE_EXITED
); 
1103         return wxTHREAD_NO_RESOURCE
; 
1107     return wxTHREAD_NO_ERROR
; 
1110 wxThreadError 
wxThreadInternal::Run() 
1112     wxCHECK_MSG( GetState() == STATE_NEW
, wxTHREAD_RUNNING
, 
1113                  wxT("thread may only be started once after Create()") ); 
1115     SetState(STATE_RUNNING
); 
1117     // wake up threads waiting for our start 
1120     return wxTHREAD_NO_ERROR
; 
1123 void wxThreadInternal::Wait() 
1125     wxCHECK_RET( !m_isDetached
, wxT("can't wait for a detached thread") ); 
1127     // if the thread we're waiting for is waiting for the GUI mutex, we will 
1128     // deadlock so make sure we release it temporarily 
1129     if ( wxThread::IsMain() ) 
1132         // give the thread we're waiting for chance to do the GUI call 
1133         // it might be in, we don't do this conditionally as the to be waited on 
1134         // thread might have to acquire the mutex later but before terminating 
1135         if ( wxGuiOwnedByMainThread() ) 
1142     wxLogTrace(TRACE_THREADS
, 
1143                wxT("Starting to wait for thread %p to exit."), 
1146     // to avoid memory leaks we should call pthread_join(), but it must only be 
1147     // done once so use a critical section to serialize the code below 
1149         wxCriticalSectionLocker 
lock(m_csJoinFlag
); 
1151         if ( m_shouldBeJoined 
) 
1153             // FIXME shouldn't we set cancellation type to DISABLED here? If 
1154             //       we're cancelled inside pthread_join(), things will almost 
1155             //       certainly break - but if we disable the cancellation, we 
1157             if ( pthread_join(GetId(), &m_exitcode
) != 0 ) 
1159                 // this is a serious problem, so use wxLogError and not 
1160                 // wxLogDebug: it is possible to bring the system to its knees 
1161                 // by creating too many threads and not joining them quite 
1163                 wxLogError(_("Failed to join a thread, potential memory leak detected - please restart the program")); 
1166             m_shouldBeJoined 
= false; 
1171     // reacquire GUI mutex 
1172     if ( wxThread::IsMain() ) 
1177 void wxThreadInternal::Pause() 
1179     // the state is set from the thread which pauses us first, this function 
1180     // is called later so the state should have been already set 
1181     wxCHECK_RET( m_state 
== STATE_PAUSED
, 
1182                  wxT("thread must first be paused with wxThread::Pause().") ); 
1184    wxLogTrace(TRACE_THREADS
, 
1185               wxT("Thread %p goes to sleep."), THR_ID(this)); 
1187     // wait until the semaphore is Post()ed from Resume() 
1188     m_semSuspend
.Wait(); 
1191 void wxThreadInternal::Resume() 
1193     wxCHECK_RET( m_state 
== STATE_PAUSED
, 
1194                  wxT("can't resume thread which is not suspended.") ); 
1196     // the thread might be not actually paused yet - if there were no call to 
1197     // TestDestroy() since the last call to Pause() for example 
1198     if ( IsReallyPaused() ) 
1200        wxLogTrace(TRACE_THREADS
, 
1201                   wxT("Waking up thread %p"), THR_ID(this)); 
1204         m_semSuspend
.Post(); 
1207         SetReallyPaused(false); 
1211         wxLogTrace(TRACE_THREADS
, 
1212                    wxT("Thread %p is not yet really paused"), THR_ID(this)); 
1215     SetState(STATE_RUNNING
); 
1218 // ----------------------------------------------------------------------------- 
1219 // wxThread static functions 
1220 // ----------------------------------------------------------------------------- 
1222 wxThread 
*wxThread::This() 
1224     return (wxThread 
*)pthread_getspecific(gs_keySelf
); 
1227 void wxThread::Yield() 
1229 #ifdef HAVE_SCHED_YIELD 
1234 int wxThread::GetCPUCount() 
1236 #if defined(_SC_NPROCESSORS_ONLN) 
1237     // this works for Solaris and Linux 2.6 
1238     int rc 
= sysconf(_SC_NPROCESSORS_ONLN
); 
1243 #elif defined(__LINUX__) && wxUSE_FFILE 
1244     // read from proc (can't use wxTextFile here because it's a special file: 
1245     // it has 0 size but still can be read from) 
1248     wxFFile 
file(wxT("/proc/cpuinfo")); 
1249     if ( file
.IsOpened() ) 
1251         // slurp the whole file 
1253         if ( file
.ReadAll(&s
) ) 
1255             // (ab)use Replace() to find the number of "processor: num" strings 
1256             size_t count 
= s
.Replace(wxT("processor\t:"), wxT("")); 
1262             wxLogDebug(wxT("failed to parse /proc/cpuinfo")); 
1266             wxLogDebug(wxT("failed to read /proc/cpuinfo")); 
1269 #endif // different ways to get number of CPUs 
1275 wxThreadIdType 
wxThread::GetCurrentId() 
1277     return (wxThreadIdType
)pthread_self(); 
1281 bool wxThread::SetConcurrency(size_t level
) 
1283 #ifdef HAVE_PTHREAD_SET_CONCURRENCY 
1284     int rc 
= pthread_setconcurrency( level 
); 
1285 #elif defined(HAVE_THR_SETCONCURRENCY) 
1286     int rc 
= thr_setconcurrency(level
); 
1287 #else // !HAVE_THR_SETCONCURRENCY 
1288     // ok only for the default value 
1289     int rc 
= level 
== 0 ? 0 : -1; 
1290 #endif // HAVE_THR_SETCONCURRENCY/!HAVE_THR_SETCONCURRENCY 
1294         wxLogSysError(rc
, _("Failed to set thread concurrency level to %lu"), 
1295                       static_cast<unsigned long>(level
)); 
1302 // ----------------------------------------------------------------------------- 
1304 // ----------------------------------------------------------------------------- 
1306 wxThread::wxThread(wxThreadKind kind
) 
1308     // add this thread to the global list of all threads 
1310         wxMutexLocker 
lock(*gs_mutexAllThreads
); 
1312         gs_allThreads
.Add(this); 
1315     m_internal 
= new wxThreadInternal(); 
1317     m_isDetached 
= kind 
== wxTHREAD_DETACHED
; 
1320 wxThreadError 
wxThread::Create(unsigned int stackSize
) 
1322     wxCriticalSectionLocker 
lock(m_critsect
); 
1324     return m_internal
->Create(this, stackSize
); 
1327 wxThreadError 
wxThread::Run() 
1329     wxCriticalSectionLocker 
lock(m_critsect
); 
1331     // Create the thread if it wasn't created yet with an explicit 
1333     if ( !m_internal
->WasCreated() ) 
1335         wxThreadError rv 
= m_internal
->Create(this, 0); 
1336         if ( rv 
!= wxTHREAD_NO_ERROR 
) 
1340     return m_internal
->Run(); 
1343 // ----------------------------------------------------------------------------- 
1345 // ----------------------------------------------------------------------------- 
1347 void wxThread::SetPriority(unsigned int prio
) 
1349     wxCHECK_RET( wxPRIORITY_MIN 
<= prio 
&& prio 
<= wxPRIORITY_MAX
, 
1350                  wxT("invalid thread priority") ); 
1352     wxCriticalSectionLocker 
lock(m_critsect
); 
1354     switch ( m_internal
->GetState() ) 
1357             // thread not yet started, priority will be set when it is 
1358             m_internal
->SetPriority(prio
); 
1363 #ifdef HAVE_THREAD_PRIORITY_FUNCTIONS 
1364 #if defined(__LINUX__) 
1365             // On Linux, pthread_setschedparam with SCHED_OTHER does not allow 
1366             // a priority other than 0.  Instead, we use the BSD setpriority 
1367             // which alllows us to set a 'nice' value between 20 to -20.  Only 
1368             // super user can set a value less than zero (more negative yields 
1369             // higher priority).  setpriority set the static priority of a 
1370             // process, but this is OK since Linux is configured as a thread 
1373             // FIXME this is not true for 2.6!! 
1375             // map wx priorites 0..100 to Unix priorities 20..-20 
1376             if ( setpriority(PRIO_PROCESS
, 0, -(2*(int)prio
)/5 + 20) == -1 ) 
1378                 wxLogError(_("Failed to set thread priority %d."), prio
); 
1382                 struct sched_param sparam
; 
1383                 sparam
.sched_priority 
= prio
; 
1385                 if ( pthread_setschedparam(m_internal
->GetId(), 
1386                                            SCHED_OTHER
, &sparam
) != 0 ) 
1388                     wxLogError(_("Failed to set thread priority %d."), prio
); 
1392 #endif // HAVE_THREAD_PRIORITY_FUNCTIONS 
1397             wxFAIL_MSG(wxT("impossible to set thread priority in this state")); 
1401 unsigned int wxThread::GetPriority() const 
1403     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); 
1405     return m_internal
->GetPriority(); 
1408 wxThreadIdType 
wxThread::GetId() const 
1410     return (wxThreadIdType
) m_internal
->GetId(); 
1413 // ----------------------------------------------------------------------------- 
1415 // ----------------------------------------------------------------------------- 
1417 wxThreadError 
wxThread::Pause() 
1419     wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
, 
1420                  wxT("a thread can't pause itself") ); 
1422     wxCriticalSectionLocker 
lock(m_critsect
); 
1424     if ( m_internal
->GetState() != STATE_RUNNING 
) 
1426         wxLogDebug(wxT("Can't pause thread which is not running.")); 
1428         return wxTHREAD_NOT_RUNNING
; 
1431     // just set a flag, the thread will be really paused only during the next 
1432     // call to TestDestroy() 
1433     m_internal
->SetState(STATE_PAUSED
); 
1435     return wxTHREAD_NO_ERROR
; 
1438 wxThreadError 
wxThread::Resume() 
1440     wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
, 
1441                  wxT("a thread can't resume itself") ); 
1443     wxCriticalSectionLocker 
lock(m_critsect
); 
1445     wxThreadState state 
= m_internal
->GetState(); 
1450             wxLogTrace(TRACE_THREADS
, wxT("Thread %p suspended, resuming."), 
1453             m_internal
->Resume(); 
1455             return wxTHREAD_NO_ERROR
; 
1458             wxLogTrace(TRACE_THREADS
, wxT("Thread %p exited, won't resume."), 
1460             return wxTHREAD_NO_ERROR
; 
1463             wxLogDebug(wxT("Attempt to resume a thread which is not paused.")); 
1465             return wxTHREAD_MISC_ERROR
; 
1469 // ----------------------------------------------------------------------------- 
1471 // ----------------------------------------------------------------------------- 
1473 wxThread::ExitCode 
wxThread::Wait(wxThreadWait 
WXUNUSED(waitMode
)) 
1475     wxCHECK_MSG( This() != this, (ExitCode
)-1, 
1476                  wxT("a thread can't wait for itself") ); 
1478     wxCHECK_MSG( !m_isDetached
, (ExitCode
)-1, 
1479                  wxT("can't wait for detached thread") ); 
1483     return m_internal
->GetExitCode(); 
1486 wxThreadError 
wxThread::Delete(ExitCode 
*rc
, wxThreadWait 
WXUNUSED(waitMode
)) 
1488     wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
, 
1489                  wxT("a thread can't delete itself") ); 
1491     bool isDetached 
= m_isDetached
; 
1494     wxThreadState state 
= m_internal
->GetState(); 
1496     // ask the thread to stop 
1497     m_internal
->SetCancelFlag(); 
1506             // we need to wake up the thread so that PthreadStart() will 
1507             // terminate - right now it's blocking on run semaphore in 
1509             m_internal
->SignalRun(); 
1518             // resume the thread first 
1519             m_internal
->Resume(); 
1526                 // wait until the thread stops 
1531                     // return the exit code of the thread 
1532                     *rc 
= m_internal
->GetExitCode(); 
1535             //else: can't wait for detached threads 
1538     if (state 
== STATE_NEW
) 
1539         return wxTHREAD_MISC_ERROR
; 
1540             // for coherency with the MSW implementation, signal the user that 
1541             // Delete() was called on a thread which didn't start to run yet. 
1543     return wxTHREAD_NO_ERROR
; 
1546 wxThreadError 
wxThread::Kill() 
1548     wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
, 
1549                  wxT("a thread can't kill itself") ); 
1553     switch ( m_internal
->GetState() ) 
1557             return wxTHREAD_NOT_RUNNING
; 
1560             // resume the thread first 
1566 #ifdef HAVE_PTHREAD_CANCEL 
1567             if ( pthread_cancel(m_internal
->GetId()) != 0 ) 
1568 #endif // HAVE_PTHREAD_CANCEL 
1570                 wxLogError(_("Failed to terminate a thread.")); 
1572                 return wxTHREAD_MISC_ERROR
; 
1575 #ifdef HAVE_PTHREAD_CANCEL 
1578                 // if we use cleanup function, this will be done from 
1579                 // wxPthreadCleanup() 
1580 #ifndef wxHAVE_PTHREAD_CLEANUP 
1581                 ScheduleThreadForDeletion(); 
1583                 // don't call OnExit() here, it can only be called in the 
1584                 // threads context and we're in the context of another thread 
1587 #endif // wxHAVE_PTHREAD_CLEANUP 
1591                 m_internal
->SetExitCode(EXITCODE_CANCELLED
); 
1594             return wxTHREAD_NO_ERROR
; 
1595 #endif // HAVE_PTHREAD_CANCEL 
1599 void wxThread::Exit(ExitCode status
) 
1601     wxASSERT_MSG( This() == this, 
1602                   wxT("wxThread::Exit() can only be called in the context of the same thread") ); 
1606         // from the moment we call OnExit(), the main program may terminate at 
1607         // any moment, so mark this thread as being already in process of being 
1608         // deleted or wxThreadModule::OnExit() will try to delete it again 
1609         ScheduleThreadForDeletion(); 
1612     // don't enter m_critsect before calling OnExit() because the user code 
1613     // might deadlock if, for example, it signals a condition in OnExit() (a 
1614     // common case) while the main thread calls any of functions entering 
1615     // m_critsect on us (almost all of them do) 
1620     wxCATCH_ALL( wxTheApp
->OnUnhandledException(); ) 
1622     // delete C++ thread object if this is a detached thread - user is 
1623     // responsible for doing this for joinable ones 
1626         // FIXME I'm feeling bad about it - what if another thread function is 
1627         //       called (in another thread context) now? It will try to access 
1628         //       half destroyed object which will probably result in something 
1629         //       very bad - but we can't protect this by a crit section unless 
1630         //       we make it a global object, but this would mean that we can 
1631         //       only call one thread function at a time :-( 
1633         pthread_setspecific(gs_keySelf
, 0); 
1638         m_internal
->SetState(STATE_EXITED
); 
1642     // terminate the thread (pthread_exit() never returns) 
1643     pthread_exit(status
); 
1645     wxFAIL_MSG(wxT("pthread_exit() failed")); 
1648 // also test whether we were paused 
1649 bool wxThread::TestDestroy() 
1651     wxASSERT_MSG( This() == this, 
1652                   wxT("wxThread::TestDestroy() can only be called in the context of the same thread") ); 
1656     if ( m_internal
->GetState() == STATE_PAUSED 
) 
1658         m_internal
->SetReallyPaused(true); 
1660         // leave the crit section or the other threads will stop too if they 
1661         // try to call any of (seemingly harmless) IsXXX() functions while we 
1665         m_internal
->Pause(); 
1669         // thread wasn't requested to pause, nothing to do 
1673     return m_internal
->WasCancelled(); 
1676 wxThread::~wxThread() 
1680     // check that the thread either exited or couldn't be created 
1681     if ( m_internal
->GetState() != STATE_EXITED 
&& 
1682          m_internal
->GetState() != STATE_NEW 
) 
1684         wxLogDebug(wxT("The thread %p is being destroyed although it is still running! The application may crash."), 
1692     // remove this thread from the global array 
1694         wxMutexLocker 
lock(*gs_mutexAllThreads
); 
1696         gs_allThreads
.Remove(this); 
1700 // ----------------------------------------------------------------------------- 
1702 // ----------------------------------------------------------------------------- 
1704 bool wxThread::IsRunning() const 
1706     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); 
1708     return m_internal
->GetState() == STATE_RUNNING
; 
1711 bool wxThread::IsAlive() const 
1713     wxCriticalSectionLocker 
lock((wxCriticalSection
&)m_critsect
); 
1715     switch ( m_internal
->GetState() ) 
1726 bool wxThread::IsPaused() const 
1728     wxCriticalSectionLocker 
lock((wxCriticalSection
&)m_critsect
); 
1730     return (m_internal
->GetState() == STATE_PAUSED
); 
1733 //-------------------------------------------------------------------- 
1735 //-------------------------------------------------------------------- 
1738 void wxOSXThreadModuleOnInit(); 
1739 void wxOSXThreadModuleOnExit(); 
1742 class wxThreadModule 
: public wxModule
 
1745     virtual bool OnInit(); 
1746     virtual void OnExit(); 
1749     DECLARE_DYNAMIC_CLASS(wxThreadModule
) 
1752 IMPLEMENT_DYNAMIC_CLASS(wxThreadModule
, wxModule
) 
1754 bool wxThreadModule::OnInit() 
1756     int rc 
= pthread_key_create(&gs_keySelf
, NULL 
/* dtor function */); 
1759         wxLogSysError(rc
, _("Thread module initialization failed: failed to create thread key")); 
1764     wxThread::ms_idMainThread 
= wxThread::GetCurrentId(); 
1766     gs_mutexAllThreads 
= new wxMutex(); 
1769     wxOSXThreadModuleOnInit(); 
1771     gs_mutexGui 
= new wxMutex(); 
1772     gs_mutexGui
->Lock(); 
1775     gs_mutexDeleteThread 
= new wxMutex(); 
1776     gs_condAllDeleted 
= new wxCondition(*gs_mutexDeleteThread
); 
1781 void wxThreadModule::OnExit() 
1783     wxASSERT_MSG( wxThread::IsMain(), wxT("only main thread can be here") ); 
1785     // are there any threads left which are being deleted right now? 
1786     size_t nThreadsBeingDeleted
; 
1789         wxMutexLocker 
lock( *gs_mutexDeleteThread 
); 
1790         nThreadsBeingDeleted 
= gs_nThreadsBeingDeleted
; 
1792         if ( nThreadsBeingDeleted 
> 0 ) 
1794             wxLogTrace(TRACE_THREADS
, 
1795                        wxT("Waiting for %lu threads to disappear"), 
1796                        (unsigned long)nThreadsBeingDeleted
); 
1798             // have to wait until all of them disappear 
1799             gs_condAllDeleted
->Wait(); 
1806         wxMutexLocker 
lock(*gs_mutexAllThreads
); 
1808         // terminate any threads left 
1809         count 
= gs_allThreads
.GetCount(); 
1812             wxLogDebug(wxT("%lu threads were not terminated by the application."), 
1813                        (unsigned long)count
); 
1815     } // unlock mutex before deleting the threads as they lock it in their dtor 
1817     for ( size_t n 
= 0u; n 
< count
; n
++ ) 
1819         // Delete calls the destructor which removes the current entry. We 
1820         // should only delete the first one each time. 
1821         gs_allThreads
[0]->Delete(); 
1824     delete gs_mutexAllThreads
; 
1827     wxOSXThreadModuleOnExit(); 
1829     // destroy GUI mutex 
1830     gs_mutexGui
->Unlock(); 
1834     // and free TLD slot 
1835     (void)pthread_key_delete(gs_keySelf
); 
1837     delete gs_condAllDeleted
; 
1838     delete gs_mutexDeleteThread
; 
1841 // ---------------------------------------------------------------------------- 
1843 // ---------------------------------------------------------------------------- 
1845 static void ScheduleThreadForDeletion() 
1847     wxMutexLocker 
lock( *gs_mutexDeleteThread 
); 
1849     gs_nThreadsBeingDeleted
++; 
1851     wxLogTrace(TRACE_THREADS
, wxT("%lu thread%s waiting to be deleted"), 
1852                (unsigned long)gs_nThreadsBeingDeleted
, 
1853                gs_nThreadsBeingDeleted 
== 1 ? wxT("") : wxT("s")); 
1856 static void DeleteThread(wxThread 
*This
) 
1858     wxLogTrace(TRACE_THREADS
, wxT("Thread %p auto deletes."), THR_ID(This
)); 
1862     // only lock gs_mutexDeleteThread after deleting the thread to avoid 
1863     // calling out into user code with it locked as this may result in 
1864     // deadlocks if the thread dtor deletes another thread (see #11501) 
1865     wxMutexLocker 
locker( *gs_mutexDeleteThread 
); 
1867     wxCHECK_RET( gs_nThreadsBeingDeleted 
> 0, 
1868                  wxT("no threads scheduled for deletion, yet we delete one?") ); 
1870     wxLogTrace(TRACE_THREADS
, wxT("%lu threads remain scheduled for deletion."), 
1871                (unsigned long)gs_nThreadsBeingDeleted 
- 1); 
1873     if ( !--gs_nThreadsBeingDeleted 
) 
1875         // no more threads left, signal it 
1876         gs_condAllDeleted
->Signal(); 
1882 void wxMutexGuiEnterImpl() 
1884     gs_mutexGui
->Lock(); 
1887 void wxMutexGuiLeaveImpl() 
1889     gs_mutexGui
->Unlock(); 
1894 // ---------------------------------------------------------------------------- 
1895 // include common implementation code 
1896 // ---------------------------------------------------------------------------- 
1898 #include "wx/thrimpl.cpp" 
1900 #endif // wxUSE_THREADS