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" 
  52 #ifdef HAVE_THR_SETCONCURRENCY 
  56 // we use wxFFile under Linux in GetCPUCount() 
  61     #include <sys/resource.h> 
  65     #define THR_ID(thr) ((long long)(thr)->GetId()) 
  67     #define THR_ID(thr) ((long)(thr)->GetId()) 
  72     // implement wxCriticalSection using mutexes 
  73 wxCriticalSection::wxCriticalSection( wxCriticalSectionType critSecType 
) 
  74        : m_mutex( critSecType 
== wxCRITSEC_DEFAULT 
? wxMUTEX_RECURSIVE 
: wxMUTEX_DEFAULT 
)  { } 
  75 wxCriticalSection::~wxCriticalSection() { } 
  77 void wxCriticalSection::Enter() { (void)m_mutex
.Lock(); } 
  78 void wxCriticalSection::Leave() { (void)m_mutex
.Unlock(); } 
  81 // ---------------------------------------------------------------------------- 
  83 // ---------------------------------------------------------------------------- 
  85 // the possible states of the thread and transitions from them 
  88     STATE_NEW
,          // didn't start execution yet (=> RUNNING) 
  89     STATE_RUNNING
,      // running (=> PAUSED or EXITED) 
  90     STATE_PAUSED
,       // suspended (=> RUNNING or EXITED) 
  91     STATE_EXITED        
// thread doesn't exist any more 
  94 // the exit value of a thread which has been cancelled 
  95 static const wxThread::ExitCode EXITCODE_CANCELLED 
= (wxThread::ExitCode
)-1; 
  97 // trace mask for wxThread operations 
  98 #define TRACE_THREADS   _T("thread") 
 100 // you can get additional debugging messages for the semaphore operations 
 101 #define TRACE_SEMA      _T("semaphore") 
 103 // ---------------------------------------------------------------------------- 
 105 // ---------------------------------------------------------------------------- 
 107 static void ScheduleThreadForDeletion(); 
 108 static void DeleteThread(wxThread 
*This
); 
 110 // ---------------------------------------------------------------------------- 
 112 // ---------------------------------------------------------------------------- 
 114 // an (non owning) array of pointers to threads 
 115 WX_DEFINE_ARRAY_PTR(wxThread 
*, wxArrayThread
); 
 117 // an entry for a thread we can wait for 
 119 // ----------------------------------------------------------------------------- 
 121 // ----------------------------------------------------------------------------- 
 123 // we keep the list of all threads created by the application to be able to 
 124 // terminate them on exit if there are some left - otherwise the process would 
 126 static wxArrayThread gs_allThreads
; 
 128 // a mutex to protect gs_allThreads 
 129 static wxMutex 
*gs_mutexAllThreads 
= NULL
; 
 131 // the id of the main thread 
 132 static pthread_t gs_tidMain 
= (pthread_t
)-1; 
 134 // the key for the pointer to the associated wxThread object 
 135 static pthread_key_t gs_keySelf
; 
 137 // the number of threads which are being deleted - the program won't exit 
 138 // until there are any left 
 139 static size_t gs_nThreadsBeingDeleted 
= 0; 
 141 // a mutex to protect gs_nThreadsBeingDeleted 
 142 static wxMutex 
*gs_mutexDeleteThread 
= (wxMutex 
*)NULL
; 
 144 // and a condition variable which will be signaled when all 
 145 // gs_nThreadsBeingDeleted will have been deleted 
 146 static wxCondition 
*gs_condAllDeleted 
= (wxCondition 
*)NULL
; 
 148 // this mutex must be acquired before any call to a GUI function 
 149 // (it's not inside #if wxUSE_GUI because this file is compiled as part 
 151 static wxMutex 
*gs_mutexGui 
= NULL
; 
 153 // when we wait for a thread to exit, we're blocking on a condition which the 
 154 // thread signals in its SignalExit() method -- but this condition can't be a 
 155 // member of the thread itself as a detached thread may delete itself at any 
 156 // moment and accessing the condition member of the thread after this would 
 157 // result in a disaster 
 159 // so instead we maintain a global list of the structs below for the threads 
 160 // we're interested in waiting on 
 162 // ============================================================================ 
 163 // wxMutex implementation 
 164 // ============================================================================ 
 166 // ---------------------------------------------------------------------------- 
 168 // ---------------------------------------------------------------------------- 
 170 // this is a simple wrapper around pthread_mutex_t which provides error 
 172 class wxMutexInternal
 
 175     wxMutexInternal(wxMutexType mutexType
); 
 179     wxMutexError 
Lock(unsigned long ms
); 
 180     wxMutexError 
TryLock(); 
 181     wxMutexError 
Unlock(); 
 183     bool IsOk() const { return m_isOk
; } 
 186     // convert the result of pthread_mutex_[timed]lock() call to wx return code 
 187     wxMutexError 
HandleLockResult(int err
); 
 190     pthread_mutex_t m_mutex
; 
 193     unsigned long m_owningThread
; 
 195     // wxConditionInternal uses our m_mutex 
 196     friend class wxConditionInternal
; 
 199 #if defined(HAVE_PTHREAD_MUTEXATTR_T) && \ 
 200         wxUSE_UNIX && !defined(HAVE_PTHREAD_MUTEXATTR_SETTYPE_DECL) 
 201 // on some systems pthread_mutexattr_settype() is not in the headers (but it is 
 202 // in the library, otherwise we wouldn't compile this code at all) 
 203 extern "C" int pthread_mutexattr_settype(pthread_mutexattr_t 
*, int); 
 206 wxMutexInternal::wxMutexInternal(wxMutexType mutexType
) 
 214         case wxMUTEX_RECURSIVE
: 
 215             // support recursive locks like Win32, i.e. a thread can lock a 
 216             // mutex which it had itself already locked 
 218             // unfortunately initialization of recursive mutexes is non 
 219             // portable, so try several methods 
 220 #ifdef HAVE_PTHREAD_MUTEXATTR_T 
 222                 pthread_mutexattr_t attr
; 
 223                 pthread_mutexattr_init(&attr
); 
 224                 pthread_mutexattr_settype(&attr
, PTHREAD_MUTEX_RECURSIVE
); 
 226                 err 
= pthread_mutex_init(&m_mutex
, &attr
); 
 228 #elif defined(HAVE_PTHREAD_RECURSIVE_MUTEX_INITIALIZER) 
 229             // we can use this only as initializer so we have to assign it 
 230             // first to a temp var - assigning directly to m_mutex wouldn't 
 233                 pthread_mutex_t mutex 
= PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
; 
 236 #else // no recursive mutexes 
 238 #endif // HAVE_PTHREAD_MUTEXATTR_T/... 
 242             wxFAIL_MSG( _T("unknown mutex type") ); 
 245         case wxMUTEX_DEFAULT
: 
 246             err 
= pthread_mutex_init(&m_mutex
, NULL
); 
 253         wxLogApiError( wxT("pthread_mutex_init()"), err
); 
 257 wxMutexInternal::~wxMutexInternal() 
 261         int err 
= pthread_mutex_destroy(&m_mutex
); 
 264             wxLogApiError( wxT("pthread_mutex_destroy()"), err
); 
 269 wxMutexError 
wxMutexInternal::Lock() 
 271     if ((m_type 
== wxMUTEX_DEFAULT
) && (m_owningThread 
!= 0)) 
 273         if (m_owningThread 
== wxThread::GetCurrentId()) 
 274            return wxMUTEX_DEAD_LOCK
; 
 277     return HandleLockResult(pthread_mutex_lock(&m_mutex
)); 
 280 wxMutexError 
wxMutexInternal::Lock(unsigned long ms
) 
 282 #ifdef HAVE_PTHREAD_MUTEX_TIMEDLOCK 
 283     static const long MSEC_IN_SEC   
= 1000; 
 284     static const long NSEC_IN_MSEC  
= 1000000; 
 285     static const long NSEC_IN_USEC  
= 1000; 
 286     static const long NSEC_IN_SEC   
= MSEC_IN_SEC 
* NSEC_IN_MSEC
; 
 288     time_t seconds 
= ms
/MSEC_IN_SEC
; 
 289     long nanoseconds 
= (ms 
% MSEC_IN_SEC
) * NSEC_IN_MSEC
; 
 290     timespec ts 
= { 0, 0 }; 
 292     // normally we should use clock_gettime(CLOCK_REALTIME) here but this 
 293     // function is in librt and we don't link with it currently, so use 
 294     // gettimeofday() instead -- if it turns out that this is really too 
 295     // imprecise, we should modify configure to check if clock_gettime() is 
 296     // available and whether it requires -lrt and use it instead 
 298     if ( clock_gettime(CLOCK_REALTIME
, &ts
) == 0 ) 
 303     if ( wxGetTimeOfDay(&tv
) != -1 ) 
 305         ts
.tv_sec 
= tv
.tv_sec
; 
 306         ts
.tv_nsec 
= tv
.tv_usec
*NSEC_IN_USEC
; 
 309     else // fall back on system timer 
 311         ts
.tv_sec 
= time(NULL
); 
 314     ts
.tv_sec 
+= seconds
; 
 315     ts
.tv_nsec 
+= nanoseconds
; 
 316     if ( ts
.tv_nsec 
> NSEC_IN_SEC 
) 
 319         ts
.tv_nsec 
-= NSEC_IN_SEC
; 
 322     return HandleLockResult(pthread_mutex_timedlock(&m_mutex
, &ts
)); 
 323 #else // !HAVE_PTHREAD_MUTEX_TIMEDLOCK 
 326     return wxMUTEX_MISC_ERROR
; 
 327 #endif // HAVE_PTHREAD_MUTEX_TIMEDLOCK/!HAVE_PTHREAD_MUTEX_TIMEDLOCK 
 330 wxMutexError 
wxMutexInternal::HandleLockResult(int err
) 
 332     // wxPrintf( "err %d\n", err ); 
 337             // only error checking mutexes return this value and so it's an 
 338             // unexpected situation -- hence use assert, not wxLogDebug 
 339             wxFAIL_MSG( _T("mutex deadlock prevented") ); 
 340             return wxMUTEX_DEAD_LOCK
; 
 343             wxLogDebug(_T("pthread_mutex_[timed]lock(): mutex not initialized")); 
 347             return wxMUTEX_TIMEOUT
; 
 350             if (m_type 
== wxMUTEX_DEFAULT
) 
 351                 m_owningThread 
= wxThread::GetCurrentId(); 
 352             return wxMUTEX_NO_ERROR
; 
 355             wxLogApiError(_T("pthread_mutex_[timed]lock()"), err
); 
 358     return wxMUTEX_MISC_ERROR
; 
 362 wxMutexError 
wxMutexInternal::TryLock() 
 364     int err 
= pthread_mutex_trylock(&m_mutex
); 
 368             // not an error: mutex is already locked, but we're prepared for 
 373             wxLogDebug(_T("pthread_mutex_trylock(): mutex not initialized.")); 
 377             if (m_type 
== wxMUTEX_DEFAULT
) 
 378                 m_owningThread 
= wxThread::GetCurrentId(); 
 379             return wxMUTEX_NO_ERROR
; 
 382             wxLogApiError(_T("pthread_mutex_trylock()"), err
); 
 385     return wxMUTEX_MISC_ERROR
; 
 388 wxMutexError 
wxMutexInternal::Unlock() 
 392     int err 
= pthread_mutex_unlock(&m_mutex
); 
 396             // we don't own the mutex 
 397             return wxMUTEX_UNLOCKED
; 
 400             wxLogDebug(_T("pthread_mutex_unlock(): mutex not initialized.")); 
 404             return wxMUTEX_NO_ERROR
; 
 407             wxLogApiError(_T("pthread_mutex_unlock()"), err
); 
 410     return wxMUTEX_MISC_ERROR
; 
 413 // =========================================================================== 
 414 // wxCondition implementation 
 415 // =========================================================================== 
 417 // --------------------------------------------------------------------------- 
 418 // wxConditionInternal 
 419 // --------------------------------------------------------------------------- 
 421 // this is a wrapper around pthread_cond_t associated with a wxMutex (and hence 
 422 // with a pthread_mutex_t) 
 423 class wxConditionInternal
 
 426     wxConditionInternal(wxMutex
& mutex
); 
 427     ~wxConditionInternal(); 
 429     bool IsOk() const { return m_isOk 
&& m_mutex
.IsOk(); } 
 432     wxCondError 
WaitTimeout(unsigned long milliseconds
); 
 434     wxCondError 
Signal(); 
 435     wxCondError 
Broadcast(); 
 438     // get the POSIX mutex associated with us 
 439     pthread_mutex_t 
*GetPMutex() const { return &m_mutex
.m_internal
->m_mutex
; } 
 442     pthread_cond_t m_cond
; 
 447 wxConditionInternal::wxConditionInternal(wxMutex
& mutex
) 
 450     int err 
= pthread_cond_init(&m_cond
, NULL 
/* default attributes */); 
 456         wxLogApiError(_T("pthread_cond_init()"), err
); 
 460 wxConditionInternal::~wxConditionInternal() 
 464         int err 
= pthread_cond_destroy(&m_cond
); 
 467             wxLogApiError(_T("pthread_cond_destroy()"), err
); 
 472 wxCondError 
wxConditionInternal::Wait() 
 474     int err 
= pthread_cond_wait(&m_cond
, GetPMutex()); 
 477         wxLogApiError(_T("pthread_cond_wait()"), err
); 
 479         return wxCOND_MISC_ERROR
; 
 482     return wxCOND_NO_ERROR
; 
 485 wxCondError 
wxConditionInternal::WaitTimeout(unsigned long milliseconds
) 
 487     wxLongLong curtime 
= wxGetLocalTimeMillis(); 
 488     curtime 
+= milliseconds
; 
 489     wxLongLong temp 
= curtime 
/ 1000; 
 490     int sec 
= temp
.GetLo(); 
 492     temp 
= curtime 
- temp
; 
 493     int millis 
= temp
.GetLo(); 
 498     tspec
.tv_nsec 
= millis 
* 1000L * 1000L; 
 500     int err 
= pthread_cond_timedwait( &m_cond
, GetPMutex(), &tspec 
); 
 504             return wxCOND_TIMEOUT
; 
 507             return wxCOND_NO_ERROR
; 
 510             wxLogApiError(_T("pthread_cond_timedwait()"), err
); 
 513     return wxCOND_MISC_ERROR
; 
 516 wxCondError 
wxConditionInternal::Signal() 
 518     int err 
= pthread_cond_signal(&m_cond
); 
 521         wxLogApiError(_T("pthread_cond_signal()"), err
); 
 523         return wxCOND_MISC_ERROR
; 
 526     return wxCOND_NO_ERROR
; 
 529 wxCondError 
wxConditionInternal::Broadcast() 
 531     int err 
= pthread_cond_broadcast(&m_cond
); 
 534         wxLogApiError(_T("pthread_cond_broadcast()"), err
); 
 536         return wxCOND_MISC_ERROR
; 
 539     return wxCOND_NO_ERROR
; 
 542 // =========================================================================== 
 543 // wxSemaphore implementation 
 544 // =========================================================================== 
 546 // --------------------------------------------------------------------------- 
 547 // wxSemaphoreInternal 
 548 // --------------------------------------------------------------------------- 
 550 // we implement the semaphores using mutexes and conditions instead of using 
 551 // the sem_xxx() POSIX functions because they're not widely available and also 
 552 // because it's impossible to implement WaitTimeout() using them 
 553 class wxSemaphoreInternal
 
 556     wxSemaphoreInternal(int initialcount
, int maxcount
); 
 558     bool IsOk() const { return m_isOk
; } 
 561     wxSemaError 
TryWait(); 
 562     wxSemaError 
WaitTimeout(unsigned long milliseconds
); 
 576 wxSemaphoreInternal::wxSemaphoreInternal(int initialcount
, int maxcount
) 
 580     if ( (initialcount 
< 0 || maxcount 
< 0) || 
 581             ((maxcount 
> 0) && (initialcount 
> maxcount
)) ) 
 583         wxFAIL_MSG( _T("wxSemaphore: invalid initial or maximal count") ); 
 589         m_maxcount 
= (size_t)maxcount
; 
 590         m_count 
= (size_t)initialcount
; 
 593     m_isOk 
= m_mutex
.IsOk() && m_cond
.IsOk(); 
 596 wxSemaError 
wxSemaphoreInternal::Wait() 
 598     wxMutexLocker 
locker(m_mutex
); 
 600     while ( m_count 
== 0 ) 
 602         wxLogTrace(TRACE_SEMA
, 
 603                    _T("Thread %ld waiting for semaphore to become signalled"), 
 604                    wxThread::GetCurrentId()); 
 606         if ( m_cond
.Wait() != wxCOND_NO_ERROR 
) 
 607             return wxSEMA_MISC_ERROR
; 
 609         wxLogTrace(TRACE_SEMA
, 
 610                    _T("Thread %ld finished waiting for semaphore, count = %lu"), 
 611                    wxThread::GetCurrentId(), (unsigned long)m_count
); 
 616     return wxSEMA_NO_ERROR
; 
 619 wxSemaError 
wxSemaphoreInternal::TryWait() 
 621     wxMutexLocker 
locker(m_mutex
); 
 628     return wxSEMA_NO_ERROR
; 
 631 wxSemaError 
wxSemaphoreInternal::WaitTimeout(unsigned long milliseconds
) 
 633     wxMutexLocker 
locker(m_mutex
); 
 635     wxLongLong startTime 
= wxGetLocalTimeMillis(); 
 637     while ( m_count 
== 0 ) 
 639         wxLongLong elapsed 
= wxGetLocalTimeMillis() - startTime
; 
 640         long remainingTime 
= (long)milliseconds 
- (long)elapsed
.GetLo(); 
 641         if ( remainingTime 
<= 0 ) 
 644             return wxSEMA_TIMEOUT
; 
 647         switch ( m_cond
.WaitTimeout(remainingTime
) ) 
 650                 return wxSEMA_TIMEOUT
; 
 653                 return wxSEMA_MISC_ERROR
; 
 655             case wxCOND_NO_ERROR
: 
 662     return wxSEMA_NO_ERROR
; 
 665 wxSemaError 
wxSemaphoreInternal::Post() 
 667     wxMutexLocker 
locker(m_mutex
); 
 669     if ( m_maxcount 
> 0 && m_count 
== m_maxcount 
) 
 671         return wxSEMA_OVERFLOW
; 
 676     wxLogTrace(TRACE_SEMA
, 
 677                _T("Thread %ld about to signal semaphore, count = %lu"), 
 678                wxThread::GetCurrentId(), (unsigned long)m_count
); 
 680     return m_cond
.Signal() == wxCOND_NO_ERROR 
? wxSEMA_NO_ERROR
 
 684 // =========================================================================== 
 685 // wxThread implementation 
 686 // =========================================================================== 
 688 // the thread callback functions must have the C linkage 
 692 #ifdef wxHAVE_PTHREAD_CLEANUP 
 693     // thread exit function 
 694     void wxPthreadCleanup(void *ptr
); 
 695 #endif // wxHAVE_PTHREAD_CLEANUP 
 697 void *wxPthreadStart(void *ptr
); 
 701 // ---------------------------------------------------------------------------- 
 703 // ---------------------------------------------------------------------------- 
 705 class wxThreadInternal
 
 711     // thread entry function 
 712     static void *PthreadStart(wxThread 
*thread
); 
 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 
*stateNames
[] = 
 743         wxLogTrace(TRACE_THREADS
, _T("Thread %ld: %s => %s."), 
 744                    (long)GetId(), stateNames
[m_state
], stateNames
[state
]); 
 745 #endif // __WXDEBUG__ 
 750     pthread_t 
GetId() const { return m_threadId
; } 
 751     pthread_t 
*GetIdPtr() { return &m_threadId
; } 
 753     void SetCancelFlag() { m_cancelled 
= true; } 
 754     bool WasCancelled() const { return m_cancelled
; } 
 756     void SetExitCode(wxThread::ExitCode exitcode
) { m_exitcode 
= exitcode
; } 
 757     wxThread::ExitCode 
GetExitCode() const { return m_exitcode
; } 
 760     void SetReallyPaused(bool paused
) { m_isPaused 
= paused
; } 
 761     bool IsReallyPaused() const { return m_isPaused
; } 
 763         // tell the thread that it is a detached one 
 766         wxCriticalSectionLocker 
lock(m_csJoinFlag
); 
 768         m_shouldBeJoined 
= false; 
 772 #ifdef wxHAVE_PTHREAD_CLEANUP 
 773     // this is used by wxPthreadCleanup() only 
 774     static void Cleanup(wxThread 
*thread
); 
 775 #endif // wxHAVE_PTHREAD_CLEANUP 
 778     pthread_t     m_threadId
;   // id of the thread 
 779     wxThreadState m_state
;      // see wxThreadState enum 
 780     int           m_prio
;       // in wxWidgets units: from 0 to 100 
 782     // this flag is set when the thread should terminate 
 785     // this flag is set when the thread is blocking on m_semSuspend 
 788     // the thread exit code - only used for joinable (!detached) threads and 
 789     // is only valid after the thread termination 
 790     wxThread::ExitCode m_exitcode
; 
 792     // many threads may call Wait(), but only one of them should call 
 793     // pthread_join(), so we have to keep track of this 
 794     wxCriticalSection m_csJoinFlag
; 
 795     bool m_shouldBeJoined
; 
 798     // this semaphore is posted by Run() and the threads Entry() is not 
 799     // called before it is done 
 800     wxSemaphore m_semRun
; 
 802     // this one is signaled when the thread should resume after having been 
 804     wxSemaphore m_semSuspend
; 
 807 // ---------------------------------------------------------------------------- 
 808 // thread startup and exit functions 
 809 // ---------------------------------------------------------------------------- 
 811 void *wxPthreadStart(void *ptr
) 
 813     return wxThreadInternal::PthreadStart((wxThread 
*)ptr
); 
 816 void *wxThreadInternal::PthreadStart(wxThread 
*thread
) 
 818     wxThreadInternal 
*pthread 
= thread
->m_internal
; 
 820     wxLogTrace(TRACE_THREADS
, _T("Thread %ld started."), THR_ID(pthread
)); 
 822     // associate the thread pointer with the newly created thread so that 
 823     // wxThread::This() will work 
 824     int rc 
= pthread_setspecific(gs_keySelf
, thread
); 
 827         wxLogSysError(rc
, _("Cannot start thread: error writing TLS")); 
 832     // have to declare this before pthread_cleanup_push() which defines a 
 836 #ifdef wxHAVE_PTHREAD_CLEANUP 
 837     // install the cleanup handler which will be called if the thread is 
 839     pthread_cleanup_push(wxPthreadCleanup
, thread
); 
 840 #endif // wxHAVE_PTHREAD_CLEANUP 
 842     // wait for the semaphore to be posted from Run() 
 843     pthread
->m_semRun
.Wait(); 
 845     // test whether we should run the run at all - may be it was deleted 
 846     // before it started to Run()? 
 848         wxCriticalSectionLocker 
lock(thread
->m_critsect
); 
 850         dontRunAtAll 
= pthread
->GetState() == STATE_NEW 
&& 
 851                        pthread
->WasCancelled(); 
 856         // call the main entry 
 857         wxLogTrace(TRACE_THREADS
, 
 858                    _T("Thread %ld about to enter its Entry()."), 
 863             pthread
->m_exitcode 
= thread
->Entry(); 
 865             wxLogTrace(TRACE_THREADS
, 
 866                        _T("Thread %ld Entry() returned %lu."), 
 867                        THR_ID(pthread
), wxPtrToUInt(pthread
->m_exitcode
)); 
 869         wxCATCH_ALL( wxTheApp
->OnUnhandledException(); ) 
 872             wxCriticalSectionLocker 
lock(thread
->m_critsect
); 
 874             // change the state of the thread to "exited" so that 
 875             // wxPthreadCleanup handler won't do anything from now (if it's 
 876             // called before we do pthread_cleanup_pop below) 
 877             pthread
->SetState(STATE_EXITED
); 
 881     // NB: pthread_cleanup_push/pop() are macros and pop contains the matching 
 882     //     '}' for the '{' in push, so they must be used in the same block! 
 883 #ifdef wxHAVE_PTHREAD_CLEANUP 
 885         // under Tru64 we get a warning from macro expansion 
 887         #pragma message disable(declbutnotref) 
 890     // remove the cleanup handler without executing it 
 891     pthread_cleanup_pop(FALSE
); 
 894         #pragma message restore 
 896 #endif // wxHAVE_PTHREAD_CLEANUP 
 900         // FIXME: deleting a possibly joinable thread here??? 
 903         return EXITCODE_CANCELLED
; 
 907         // terminate the thread 
 908         thread
->Exit(pthread
->m_exitcode
); 
 910         wxFAIL_MSG(wxT("wxThread::Exit() can't return.")); 
 916 #ifdef wxHAVE_PTHREAD_CLEANUP 
 918 // this handler is called when the thread is cancelled 
 919 extern "C" void wxPthreadCleanup(void *ptr
) 
 921     wxThreadInternal::Cleanup((wxThread 
*)ptr
); 
 924 void wxThreadInternal::Cleanup(wxThread 
*thread
) 
 926     if (pthread_getspecific(gs_keySelf
) == 0) return; 
 928         wxCriticalSectionLocker 
lock(thread
->m_critsect
); 
 929         if ( thread
->m_internal
->GetState() == STATE_EXITED 
) 
 931             // thread is already considered as finished. 
 936     // exit the thread gracefully 
 937     thread
->Exit(EXITCODE_CANCELLED
); 
 940 #endif // wxHAVE_PTHREAD_CLEANUP 
 942 // ---------------------------------------------------------------------------- 
 944 // ---------------------------------------------------------------------------- 
 946 wxThreadInternal::wxThreadInternal() 
 950     m_prio 
= WXTHREAD_DEFAULT_PRIORITY
; 
 954     // set to true only when the thread starts waiting on m_semSuspend 
 957     // defaults for joinable threads 
 958     m_shouldBeJoined 
= true; 
 959     m_isDetached 
= false; 
 962 wxThreadInternal::~wxThreadInternal() 
 966 wxThreadError 
wxThreadInternal::Run() 
 968     wxCHECK_MSG( GetState() == STATE_NEW
, wxTHREAD_RUNNING
, 
 969                  wxT("thread may only be started once after Create()") ); 
 971     SetState(STATE_RUNNING
); 
 973     // wake up threads waiting for our start 
 976     return wxTHREAD_NO_ERROR
; 
 979 void wxThreadInternal::Wait() 
 981     wxCHECK_RET( !m_isDetached
, _T("can't wait for a detached thread") ); 
 983     // if the thread we're waiting for is waiting for the GUI mutex, we will 
 984     // deadlock so make sure we release it temporarily 
 985     if ( wxThread::IsMain() ) 
 988     wxLogTrace(TRACE_THREADS
, 
 989                _T("Starting to wait for thread %ld to exit."), 
 992     // to avoid memory leaks we should call pthread_join(), but it must only be 
 993     // done once so use a critical section to serialize the code below 
 995         wxCriticalSectionLocker 
lock(m_csJoinFlag
); 
 997         if ( m_shouldBeJoined 
) 
 999             // FIXME shouldn't we set cancellation type to DISABLED here? If 
1000             //       we're cancelled inside pthread_join(), things will almost 
1001             //       certainly break - but if we disable the cancellation, we 
1003             if ( pthread_join(GetId(), &m_exitcode
) != 0 ) 
1005                 // this is a serious problem, so use wxLogError and not 
1006                 // wxLogDebug: it is possible to bring the system to its knees 
1007                 // by creating too many threads and not joining them quite 
1009                 wxLogError(_("Failed to join a thread, potential memory leak detected - please restart the program")); 
1012             m_shouldBeJoined 
= false; 
1016     // reacquire GUI mutex 
1017     if ( wxThread::IsMain() ) 
1021 void wxThreadInternal::Pause() 
1023     // the state is set from the thread which pauses us first, this function 
1024     // is called later so the state should have been already set 
1025     wxCHECK_RET( m_state 
== STATE_PAUSED
, 
1026                  wxT("thread must first be paused with wxThread::Pause().") ); 
1028    wxLogTrace(TRACE_THREADS
, 
1029               _T("Thread %ld goes to sleep."), THR_ID(this)); 
1031     // wait until the semaphore is Post()ed from Resume() 
1032     m_semSuspend
.Wait(); 
1035 void wxThreadInternal::Resume() 
1037     wxCHECK_RET( m_state 
== STATE_PAUSED
, 
1038                  wxT("can't resume thread which is not suspended.") ); 
1040     // the thread might be not actually paused yet - if there were no call to 
1041     // TestDestroy() since the last call to Pause() for example 
1042     if ( IsReallyPaused() ) 
1044        wxLogTrace(TRACE_THREADS
, 
1045                   _T("Waking up thread %ld"), THR_ID(this)); 
1048         m_semSuspend
.Post(); 
1051         SetReallyPaused(false); 
1055         wxLogTrace(TRACE_THREADS
, 
1056                    _T("Thread %ld is not yet really paused"), THR_ID(this)); 
1059     SetState(STATE_RUNNING
); 
1062 // ----------------------------------------------------------------------------- 
1063 // wxThread static functions 
1064 // ----------------------------------------------------------------------------- 
1066 wxThread 
*wxThread::This() 
1068     return (wxThread 
*)pthread_getspecific(gs_keySelf
); 
1071 bool wxThread::IsMain() 
1073     return (bool)pthread_equal(pthread_self(), gs_tidMain
) || gs_tidMain 
== (pthread_t
)-1; 
1076 void wxThread::Yield() 
1078 #ifdef HAVE_SCHED_YIELD 
1083 int wxThread::GetCPUCount() 
1085 #if defined(_SC_NPROCESSORS_ONLN) 
1086     // this works for Solaris and Linux 2.6 
1087     int rc 
= sysconf(_SC_NPROCESSORS_ONLN
); 
1092 #elif defined(__LINUX__) && wxUSE_FFILE 
1093     // read from proc (can't use wxTextFile here because it's a special file: 
1094     // it has 0 size but still can be read from) 
1097     wxFFile 
file(_T("/proc/cpuinfo")); 
1098     if ( file
.IsOpened() ) 
1100         // slurp the whole file 
1102         if ( file
.ReadAll(&s
) ) 
1104             // (ab)use Replace() to find the number of "processor: num" strings 
1105             size_t count 
= s
.Replace(_T("processor\t:"), _T("")); 
1111             wxLogDebug(_T("failed to parse /proc/cpuinfo")); 
1115             wxLogDebug(_T("failed to read /proc/cpuinfo")); 
1118 #endif // different ways to get number of CPUs 
1124 // VMS is a 64 bit system and threads have 64 bit pointers. 
1125 // FIXME: also needed for other systems???? 
1127 unsigned long long wxThread::GetCurrentId() 
1129     return (unsigned long long)pthread_self(); 
1134 unsigned long wxThread::GetCurrentId() 
1136     return (unsigned long)pthread_self(); 
1139 #endif // __VMS/!__VMS 
1142 bool wxThread::SetConcurrency(size_t level
) 
1144 #ifdef HAVE_THR_SETCONCURRENCY 
1145     int rc 
= thr_setconcurrency(level
); 
1148         wxLogSysError(rc
, _T("thr_setconcurrency() failed")); 
1152 #else // !HAVE_THR_SETCONCURRENCY 
1153     // ok only for the default value 
1155 #endif // HAVE_THR_SETCONCURRENCY/!HAVE_THR_SETCONCURRENCY 
1158 // ----------------------------------------------------------------------------- 
1160 // ----------------------------------------------------------------------------- 
1162 wxThread::wxThread(wxThreadKind kind
) 
1164     // add this thread to the global list of all threads 
1166         wxMutexLocker 
lock(*gs_mutexAllThreads
); 
1168         gs_allThreads
.Add(this); 
1171     m_internal 
= new wxThreadInternal(); 
1173     m_isDetached 
= kind 
== wxTHREAD_DETACHED
; 
1176 #ifdef HAVE_PTHREAD_ATTR_SETSTACKSIZE 
1177     #define WXUNUSED_STACKSIZE(identifier)  identifier 
1179     #define WXUNUSED_STACKSIZE(identifier)  WXUNUSED(identifier) 
1182 wxThreadError 
wxThread::Create(unsigned int WXUNUSED_STACKSIZE(stackSize
)) 
1184     if ( m_internal
->GetState() != STATE_NEW 
) 
1186         // don't recreate thread 
1187         return wxTHREAD_RUNNING
; 
1190     // set up the thread attribute: right now, we only set thread priority 
1191     pthread_attr_t attr
; 
1192     pthread_attr_init(&attr
); 
1194 #ifdef HAVE_PTHREAD_ATTR_SETSTACKSIZE 
1196       pthread_attr_setstacksize(&attr
, stackSize
); 
1199 #ifdef HAVE_THREAD_PRIORITY_FUNCTIONS 
1201     if ( pthread_attr_getschedpolicy(&attr
, &policy
) != 0 ) 
1203         wxLogError(_("Cannot retrieve thread scheduling policy.")); 
1207    /* the pthread.h contains too many spaces. This is a work-around */ 
1208 # undef sched_get_priority_max 
1209 #undef sched_get_priority_min 
1210 #define sched_get_priority_max(_pol_) \ 
1211      (_pol_ == SCHED_OTHER ? PRI_FG_MAX_NP : PRI_FIFO_MAX) 
1212 #define sched_get_priority_min(_pol_) \ 
1213      (_pol_ == SCHED_OTHER ? PRI_FG_MIN_NP : PRI_FIFO_MIN) 
1216     int max_prio 
= sched_get_priority_max(policy
), 
1217         min_prio 
= sched_get_priority_min(policy
), 
1218         prio 
= m_internal
->GetPriority(); 
1220     if ( min_prio 
== -1 || max_prio 
== -1 ) 
1222         wxLogError(_("Cannot get priority range for scheduling policy %d."), 
1225     else if ( max_prio 
== min_prio 
) 
1227         if ( prio 
!= WXTHREAD_DEFAULT_PRIORITY 
) 
1229             // notify the programmer that this doesn't work here 
1230             wxLogWarning(_("Thread priority setting is ignored.")); 
1232         //else: we have default priority, so don't complain 
1234         // anyhow, don't do anything because priority is just ignored 
1238         struct sched_param sp
; 
1239         if ( pthread_attr_getschedparam(&attr
, &sp
) != 0 ) 
1241             wxFAIL_MSG(_T("pthread_attr_getschedparam() failed")); 
1244         sp
.sched_priority 
= min_prio 
+ (prio
*(max_prio 
- min_prio
))/100; 
1246         if ( pthread_attr_setschedparam(&attr
, &sp
) != 0 ) 
1248             wxFAIL_MSG(_T("pthread_attr_setschedparam(priority) failed")); 
1251 #endif // HAVE_THREAD_PRIORITY_FUNCTIONS 
1253 #ifdef HAVE_PTHREAD_ATTR_SETSCOPE 
1254     // this will make the threads created by this process really concurrent 
1255     if ( pthread_attr_setscope(&attr
, PTHREAD_SCOPE_SYSTEM
) != 0 ) 
1257         wxFAIL_MSG(_T("pthread_attr_setscope(PTHREAD_SCOPE_SYSTEM) failed")); 
1259 #endif // HAVE_PTHREAD_ATTR_SETSCOPE 
1261     // VZ: assume that this one is always available (it's rather fundamental), 
1262     //     if this function is ever missing we should try to use 
1263     //     pthread_detach() instead (after thread creation) 
1266         if ( pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_DETACHED
) != 0 ) 
1268             wxFAIL_MSG(_T("pthread_attr_setdetachstate(DETACHED) failed")); 
1271         // never try to join detached threads 
1272         m_internal
->Detach(); 
1274     //else: threads are created joinable by default, it's ok 
1276     // create the new OS thread object 
1277     int rc 
= pthread_create
 
1279                 m_internal
->GetIdPtr(), 
1285     if ( pthread_attr_destroy(&attr
) != 0 ) 
1287         wxFAIL_MSG(_T("pthread_attr_destroy() failed")); 
1292         m_internal
->SetState(STATE_EXITED
); 
1294         return wxTHREAD_NO_RESOURCE
; 
1297     return wxTHREAD_NO_ERROR
; 
1300 wxThreadError 
wxThread::Run() 
1302     wxCriticalSectionLocker 
lock(m_critsect
); 
1304     wxCHECK_MSG( m_internal
->GetId(), wxTHREAD_MISC_ERROR
, 
1305                  wxT("must call wxThread::Create() first") ); 
1307     return m_internal
->Run(); 
1310 // ----------------------------------------------------------------------------- 
1312 // ----------------------------------------------------------------------------- 
1314 void wxThread::SetPriority(unsigned int prio
) 
1316     wxCHECK_RET( ((int)WXTHREAD_MIN_PRIORITY 
<= (int)prio
) && 
1317                  ((int)prio 
<= (int)WXTHREAD_MAX_PRIORITY
), 
1318                  wxT("invalid thread priority") ); 
1320     wxCriticalSectionLocker 
lock(m_critsect
); 
1322     switch ( m_internal
->GetState() ) 
1325             // thread not yet started, priority will be set when it is 
1326             m_internal
->SetPriority(prio
); 
1331 #ifdef HAVE_THREAD_PRIORITY_FUNCTIONS 
1332 #if defined(__LINUX__) 
1333             // On Linux, pthread_setschedparam with SCHED_OTHER does not allow 
1334             // a priority other than 0.  Instead, we use the BSD setpriority 
1335             // which alllows us to set a 'nice' value between 20 to -20.  Only 
1336             // super user can set a value less than zero (more negative yields 
1337             // higher priority).  setpriority set the static priority of a 
1338             // process, but this is OK since Linux is configured as a thread 
1341             // FIXME this is not true for 2.6!! 
1343             // map wx priorites WXTHREAD_MIN_PRIORITY..WXTHREAD_MAX_PRIORITY 
1344             // to Unix priorities 20..-20 
1345             if ( setpriority(PRIO_PROCESS
, 0, -(2*(int)prio
)/5 + 20) == -1 ) 
1347                 wxLogError(_("Failed to set thread priority %d."), prio
); 
1351                 struct sched_param sparam
; 
1352                 sparam
.sched_priority 
= prio
; 
1354                 if ( pthread_setschedparam(m_internal
->GetId(), 
1355                                            SCHED_OTHER
, &sparam
) != 0 ) 
1357                     wxLogError(_("Failed to set thread priority %d."), prio
); 
1361 #endif // HAVE_THREAD_PRIORITY_FUNCTIONS 
1366             wxFAIL_MSG(wxT("impossible to set thread priority in this state")); 
1370 unsigned int wxThread::GetPriority() const 
1372     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); 
1374     return m_internal
->GetPriority(); 
1377 wxThreadIdType 
wxThread::GetId() const 
1379     return (wxThreadIdType
) m_internal
->GetId(); 
1382 // ----------------------------------------------------------------------------- 
1384 // ----------------------------------------------------------------------------- 
1386 wxThreadError 
wxThread::Pause() 
1388     wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
, 
1389                  _T("a thread can't pause itself") ); 
1391     wxCriticalSectionLocker 
lock(m_critsect
); 
1393     if ( m_internal
->GetState() != STATE_RUNNING 
) 
1395         wxLogDebug(wxT("Can't pause thread which is not running.")); 
1397         return wxTHREAD_NOT_RUNNING
; 
1400     // just set a flag, the thread will be really paused only during the next 
1401     // call to TestDestroy() 
1402     m_internal
->SetState(STATE_PAUSED
); 
1404     return wxTHREAD_NO_ERROR
; 
1407 wxThreadError 
wxThread::Resume() 
1409     wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
, 
1410                  _T("a thread can't resume itself") ); 
1412     wxCriticalSectionLocker 
lock(m_critsect
); 
1414     wxThreadState state 
= m_internal
->GetState(); 
1419             wxLogTrace(TRACE_THREADS
, _T("Thread %ld suspended, resuming."), 
1422             m_internal
->Resume(); 
1424             return wxTHREAD_NO_ERROR
; 
1427             wxLogTrace(TRACE_THREADS
, _T("Thread %ld exited, won't resume."), 
1429             return wxTHREAD_NO_ERROR
; 
1432             wxLogDebug(_T("Attempt to resume a thread which is not paused.")); 
1434             return wxTHREAD_MISC_ERROR
; 
1438 // ----------------------------------------------------------------------------- 
1440 // ----------------------------------------------------------------------------- 
1442 wxThread::ExitCode 
wxThread::Wait() 
1444     wxCHECK_MSG( This() != this, (ExitCode
)-1, 
1445                  _T("a thread can't wait for itself") ); 
1447     wxCHECK_MSG( !m_isDetached
, (ExitCode
)-1, 
1448                  _T("can't wait for detached thread") ); 
1452     return m_internal
->GetExitCode(); 
1455 wxThreadError 
wxThread::Delete(ExitCode 
*rc
) 
1457     wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
, 
1458                  _T("a thread can't delete itself") ); 
1460     bool isDetached 
= m_isDetached
; 
1463     wxThreadState state 
= m_internal
->GetState(); 
1465     // ask the thread to stop 
1466     m_internal
->SetCancelFlag(); 
1473             // we need to wake up the thread so that PthreadStart() will 
1474             // terminate - right now it's blocking on run semaphore in 
1476             m_internal
->SignalRun(); 
1485             // resume the thread first 
1486             m_internal
->Resume(); 
1493                 // wait until the thread stops 
1498                     // return the exit code of the thread 
1499                     *rc 
= m_internal
->GetExitCode(); 
1502             //else: can't wait for detached threads 
1505     return wxTHREAD_NO_ERROR
; 
1508 wxThreadError 
wxThread::Kill() 
1510     wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
, 
1511                  _T("a thread can't kill itself") ); 
1513     switch ( m_internal
->GetState() ) 
1517             return wxTHREAD_NOT_RUNNING
; 
1520             // resume the thread first 
1526 #ifdef HAVE_PTHREAD_CANCEL 
1527             if ( pthread_cancel(m_internal
->GetId()) != 0 ) 
1528 #endif // HAVE_PTHREAD_CANCEL 
1530                 wxLogError(_("Failed to terminate a thread.")); 
1532                 return wxTHREAD_MISC_ERROR
; 
1535 #ifdef HAVE_PTHREAD_CANCEL 
1538                 // if we use cleanup function, this will be done from 
1539                 // wxPthreadCleanup() 
1540 #ifndef wxHAVE_PTHREAD_CLEANUP 
1541                 ScheduleThreadForDeletion(); 
1543                 // don't call OnExit() here, it can only be called in the 
1544                 // threads context and we're in the context of another thread 
1547 #endif // wxHAVE_PTHREAD_CLEANUP 
1551                 m_internal
->SetExitCode(EXITCODE_CANCELLED
); 
1554             return wxTHREAD_NO_ERROR
; 
1555 #endif // HAVE_PTHREAD_CANCEL 
1559 void wxThread::Exit(ExitCode status
) 
1561     wxASSERT_MSG( This() == this, 
1562                   _T("wxThread::Exit() can only be called in the context of the same thread") ); 
1566         // from the moment we call OnExit(), the main program may terminate at 
1567         // any moment, so mark this thread as being already in process of being 
1568         // deleted or wxThreadModule::OnExit() will try to delete it again 
1569         ScheduleThreadForDeletion(); 
1572     // don't enter m_critsect before calling OnExit() because the user code 
1573     // might deadlock if, for example, it signals a condition in OnExit() (a 
1574     // common case) while the main thread calls any of functions entering 
1575     // m_critsect on us (almost all of them do) 
1580     wxCATCH_ALL( wxTheApp
->OnUnhandledException(); ) 
1582     // delete C++ thread object if this is a detached thread - user is 
1583     // responsible for doing this for joinable ones 
1586         // FIXME I'm feeling bad about it - what if another thread function is 
1587         //       called (in another thread context) now? It will try to access 
1588         //       half destroyed object which will probably result in something 
1589         //       very bad - but we can't protect this by a crit section unless 
1590         //       we make it a global object, but this would mean that we can 
1591         //       only call one thread function at a time :-( 
1593         pthread_setspecific(gs_keySelf
, 0); 
1598         m_internal
->SetState(STATE_EXITED
); 
1602     // terminate the thread (pthread_exit() never returns) 
1603     pthread_exit(status
); 
1605     wxFAIL_MSG(_T("pthread_exit() failed")); 
1608 // also test whether we were paused 
1609 bool wxThread::TestDestroy() 
1611     wxASSERT_MSG( This() == this, 
1612                   _T("wxThread::TestDestroy() can only be called in the context of the same thread") ); 
1616     if ( m_internal
->GetState() == STATE_PAUSED 
) 
1618         m_internal
->SetReallyPaused(true); 
1620         // leave the crit section or the other threads will stop too if they 
1621         // try to call any of (seemingly harmless) IsXXX() functions while we 
1625         m_internal
->Pause(); 
1629         // thread wasn't requested to pause, nothing to do 
1633     return m_internal
->WasCancelled(); 
1636 wxThread::~wxThread() 
1641     // check that the thread either exited or couldn't be created 
1642     if ( m_internal
->GetState() != STATE_EXITED 
&& 
1643          m_internal
->GetState() != STATE_NEW 
) 
1645         wxLogDebug(_T("The thread %ld is being destroyed although it is still running! The application may crash."), 
1650 #endif // __WXDEBUG__ 
1654     // remove this thread from the global array 
1656         wxMutexLocker 
lock(*gs_mutexAllThreads
); 
1658         gs_allThreads
.Remove(this); 
1662 // ----------------------------------------------------------------------------- 
1664 // ----------------------------------------------------------------------------- 
1666 bool wxThread::IsRunning() const 
1668     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); 
1670     return m_internal
->GetState() == STATE_RUNNING
; 
1673 bool wxThread::IsAlive() const 
1675     wxCriticalSectionLocker 
lock((wxCriticalSection
&)m_critsect
); 
1677     switch ( m_internal
->GetState() ) 
1688 bool wxThread::IsPaused() const 
1690     wxCriticalSectionLocker 
lock((wxCriticalSection
&)m_critsect
); 
1692     return (m_internal
->GetState() == STATE_PAUSED
); 
1695 //-------------------------------------------------------------------- 
1697 //-------------------------------------------------------------------- 
1699 class wxThreadModule 
: public wxModule
 
1702     virtual bool OnInit(); 
1703     virtual void OnExit(); 
1706     DECLARE_DYNAMIC_CLASS(wxThreadModule
) 
1709 IMPLEMENT_DYNAMIC_CLASS(wxThreadModule
, wxModule
) 
1711 bool wxThreadModule::OnInit() 
1713     int rc 
= pthread_key_create(&gs_keySelf
, NULL 
/* dtor function */); 
1716         wxLogSysError(rc
, _("Thread module initialization failed: failed to create thread key")); 
1721     gs_tidMain 
= pthread_self(); 
1723     gs_mutexAllThreads 
= new wxMutex(); 
1725     gs_mutexGui 
= new wxMutex(); 
1726     gs_mutexGui
->Lock(); 
1728     gs_mutexDeleteThread 
= new wxMutex(); 
1729     gs_condAllDeleted 
= new wxCondition(*gs_mutexDeleteThread
); 
1734 void wxThreadModule::OnExit() 
1736     wxASSERT_MSG( wxThread::IsMain(), wxT("only main thread can be here") ); 
1738     // are there any threads left which are being deleted right now? 
1739     size_t nThreadsBeingDeleted
; 
1742         wxMutexLocker 
lock( *gs_mutexDeleteThread 
); 
1743         nThreadsBeingDeleted 
= gs_nThreadsBeingDeleted
; 
1745         if ( nThreadsBeingDeleted 
> 0 ) 
1747             wxLogTrace(TRACE_THREADS
, 
1748                        _T("Waiting for %lu threads to disappear"), 
1749                        (unsigned long)nThreadsBeingDeleted
); 
1751             // have to wait until all of them disappear 
1752             gs_condAllDeleted
->Wait(); 
1759         wxMutexLocker 
lock(*gs_mutexAllThreads
); 
1761         // terminate any threads left 
1762         count 
= gs_allThreads
.GetCount(); 
1765             wxLogDebug(wxT("%lu threads were not terminated by the application."), 
1766                        (unsigned long)count
); 
1768     } // unlock mutex before deleting the threads as they lock it in their dtor 
1770     for ( size_t n 
= 0u; n 
< count
; n
++ ) 
1772         // Delete calls the destructor which removes the current entry. We 
1773         // should only delete the first one each time. 
1774         gs_allThreads
[0]->Delete(); 
1777     delete gs_mutexAllThreads
; 
1779     // destroy GUI mutex 
1780     gs_mutexGui
->Unlock(); 
1783     // and free TLD slot 
1784     (void)pthread_key_delete(gs_keySelf
); 
1786     delete gs_condAllDeleted
; 
1787     delete gs_mutexDeleteThread
; 
1790 // ---------------------------------------------------------------------------- 
1792 // ---------------------------------------------------------------------------- 
1794 static void ScheduleThreadForDeletion() 
1796     wxMutexLocker 
lock( *gs_mutexDeleteThread 
); 
1798     gs_nThreadsBeingDeleted
++; 
1800     wxLogTrace(TRACE_THREADS
, _T("%lu thread%s waiting to be deleted"), 
1801                (unsigned long)gs_nThreadsBeingDeleted
, 
1802                gs_nThreadsBeingDeleted 
== 1 ? _T("") : _T("s")); 
1805 static void DeleteThread(wxThread 
*This
) 
1807     // gs_mutexDeleteThread should be unlocked before signalling the condition 
1808     // or wxThreadModule::OnExit() would deadlock 
1809     wxMutexLocker 
locker( *gs_mutexDeleteThread 
); 
1811     wxLogTrace(TRACE_THREADS
, _T("Thread %ld auto deletes."), This
->GetId()); 
1815     wxCHECK_RET( gs_nThreadsBeingDeleted 
> 0, 
1816                  _T("no threads scheduled for deletion, yet we delete one?") ); 
1818     wxLogTrace(TRACE_THREADS
, _T("%lu scheduled for deletion threads left."), 
1819                (unsigned long)gs_nThreadsBeingDeleted 
- 1); 
1821     if ( !--gs_nThreadsBeingDeleted 
) 
1823         // no more threads left, signal it 
1824         gs_condAllDeleted
->Signal(); 
1828 void wxMutexGuiEnterImpl() 
1830     gs_mutexGui
->Lock(); 
1833 void wxMutexGuiLeaveImpl() 
1835     gs_mutexGui
->Unlock(); 
1838 // ---------------------------------------------------------------------------- 
1839 // include common implementation code 
1840 // ---------------------------------------------------------------------------- 
1842 #include "wx/thrimpl.cpp" 
1844 #endif // wxUSE_THREADS