1 ///////////////////////////////////////////////////////////////////////////// 
   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 // ---------------------------------------------------------------------------- 
  25     #pragma implementation "thread.h" 
  32 #include "wx/thread.h" 
  33 #include "wx/module.h" 
  37 #include "wx/dynarray.h" 
  49 #ifdef HAVE_THR_SETCONCURRENCY 
  53 // we use wxFFile under Linux in GetCPUCount() 
  58     #include <sys/resource.h> 
  61 // ---------------------------------------------------------------------------- 
  63 // ---------------------------------------------------------------------------- 
  65 // the possible states of the thread and transitions from them 
  68     STATE_NEW
,          // didn't start execution yet (=> RUNNING) 
  69     STATE_RUNNING
,      // running (=> PAUSED or EXITED) 
  70     STATE_PAUSED
,       // suspended (=> RUNNING or EXITED) 
  71     STATE_EXITED        
// thread doesn't exist any more 
  74 // the exit value of a thread which has been cancelled 
  75 static const wxThread::ExitCode EXITCODE_CANCELLED 
= (wxThread::ExitCode
)-1; 
  77 // trace mask for wxThread operations 
  78 #define TRACE_THREADS   _T("thread") 
  80 // you can get additional debugging messages for the semaphore operations 
  81 #define TRACE_SEMA      _T("semaphore") 
  83 // ---------------------------------------------------------------------------- 
  85 // ---------------------------------------------------------------------------- 
  87 static void ScheduleThreadForDeletion(); 
  88 static void DeleteThread(wxThread 
*This
); 
  90 // ---------------------------------------------------------------------------- 
  92 // ---------------------------------------------------------------------------- 
  94 // an (non owning) array of pointers to threads 
  95 WX_DEFINE_ARRAY(wxThread 
*, wxArrayThread
); 
  97 // an entry for a thread we can wait for 
  99 // ----------------------------------------------------------------------------- 
 101 // ----------------------------------------------------------------------------- 
 103 // we keep the list of all threads created by the application to be able to 
 104 // terminate them on exit if there are some left - otherwise the process would 
 106 static wxArrayThread gs_allThreads
; 
 108 // the id of the main thread 
 109 static pthread_t gs_tidMain
; 
 111 // the key for the pointer to the associated wxThread object 
 112 static pthread_key_t gs_keySelf
; 
 114 // the number of threads which are being deleted - the program won't exit 
 115 // until there are any left 
 116 static size_t gs_nThreadsBeingDeleted 
= 0; 
 118 // a mutex to protect gs_nThreadsBeingDeleted 
 119 static wxMutex 
*gs_mutexDeleteThread 
= (wxMutex 
*)NULL
; 
 121 // and a condition variable which will be signaled when all 
 122 // gs_nThreadsBeingDeleted will have been deleted 
 123 static wxCondition 
*gs_condAllDeleted 
= (wxCondition 
*)NULL
; 
 126     // this mutex must be acquired before any call to a GUI function 
 127     static wxMutex 
*gs_mutexGui
; 
 130 // when we wait for a thread to exit, we're blocking on a condition which the 
 131 // thread signals in its SignalExit() method -- but this condition can't be a 
 132 // member of the thread itself as a detached thread may delete itself at any 
 133 // moment and accessing the condition member of the thread after this would 
 134 // result in a disaster 
 136 // so instead we maintain a global list of the structs below for the threads 
 137 // we're interested in waiting on 
 139 // ============================================================================ 
 140 // wxMutex implementation 
 141 // ============================================================================ 
 143 // ---------------------------------------------------------------------------- 
 145 // ---------------------------------------------------------------------------- 
 147 // this is a simple wrapper around pthread_mutex_t which provides error 
 149 class wxMutexInternal
 
 152     wxMutexInternal(wxMutexType mutexType
); 
 156     wxMutexError 
TryLock(); 
 157     wxMutexError 
Unlock(); 
 159     bool IsOk() const { return m_isOk
; } 
 162     pthread_mutex_t m_mutex
; 
 165     // wxConditionInternal uses our m_mutex 
 166     friend class wxConditionInternal
; 
 169 wxMutexInternal::wxMutexInternal(wxMutexType mutexType
) 
 174         case wxMUTEX_RECURSIVE
: 
 175             // support recursive locks like Win32, i.e. a thread can lock a 
 176             // mutex which it had itself already locked 
 178             // unfortunately initialization of recursive mutexes is non 
 179             // portable, so try several methods 
 180 #ifdef HAVE_PTHREAD_MUTEXATTR_T 
 182                 pthread_mutexattr_t attr
; 
 183                 pthread_mutexattr_init(&attr
); 
 184                 pthread_mutexattr_settype(&attr
, PTHREAD_MUTEX_RECURSIVE
); 
 186                 err 
= pthread_mutex_init(&m_mutex
, &attr
); 
 188 #elif defined(HAVE_PTHREAD_RECURSIVE_MUTEX_INITIALIZER) 
 189             // we can use this only as initializer so we have to assign it 
 190             // first to a temp var - assigning directly to m_mutex wouldn't 
 193                 pthread_mutex_t mutex 
= PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
; 
 196 #else // no recursive mutexes 
 198 #endif // HAVE_PTHREAD_MUTEXATTR_T/... 
 202             wxFAIL_MSG( _T("unknown mutex type") ); 
 205         case wxMUTEX_DEFAULT
: 
 206             err 
= pthread_mutex_init(&m_mutex
, NULL
); 
 213         wxLogApiError( wxT("pthread_mutex_init()"), err
); 
 217 wxMutexInternal::~wxMutexInternal() 
 221         int err 
= pthread_mutex_destroy(&m_mutex
); 
 224             wxLogApiError( wxT("pthread_mutex_destroy()"), err
); 
 229 wxMutexError 
wxMutexInternal::Lock() 
 231     int err 
= pthread_mutex_lock(&m_mutex
); 
 235             // only error checking mutexes return this value and so it's an 
 236             // unexpected situation -- hence use assert, not wxLogDebug 
 237             wxFAIL_MSG( _T("mutex deadlock prevented") ); 
 238             return wxMUTEX_DEAD_LOCK
; 
 241             wxLogDebug(_T("pthread_mutex_lock(): mutex not initialized.")); 
 245             return wxMUTEX_NO_ERROR
; 
 248             wxLogApiError(_T("pthread_mutex_lock()"), err
); 
 251     return wxMUTEX_MISC_ERROR
; 
 254 wxMutexError 
wxMutexInternal::TryLock() 
 256     int err 
= pthread_mutex_trylock(&m_mutex
); 
 260             // not an error: mutex is already locked, but we're prepared for 
 265             wxLogDebug(_T("pthread_mutex_trylock(): mutex not initialized.")); 
 269             return wxMUTEX_NO_ERROR
; 
 272             wxLogApiError(_T("pthread_mutex_trylock()"), err
); 
 275     return wxMUTEX_MISC_ERROR
; 
 278 wxMutexError 
wxMutexInternal::Unlock() 
 280     int err 
= pthread_mutex_unlock(&m_mutex
); 
 284             // we don't own the mutex 
 285             return wxMUTEX_UNLOCKED
; 
 288             wxLogDebug(_T("pthread_mutex_unlock(): mutex not initialized.")); 
 292             return wxMUTEX_NO_ERROR
; 
 295             wxLogApiError(_T("pthread_mutex_unlock()"), err
); 
 298     return wxMUTEX_MISC_ERROR
; 
 301 // =========================================================================== 
 302 // wxCondition implementation 
 303 // =========================================================================== 
 305 // --------------------------------------------------------------------------- 
 306 // wxConditionInternal 
 307 // --------------------------------------------------------------------------- 
 309 // this is a wrapper around pthread_cond_t associated with a wxMutex (and hence 
 310 // with a pthread_mutex_t) 
 311 class wxConditionInternal
 
 314     wxConditionInternal(wxMutex
& mutex
); 
 315     ~wxConditionInternal(); 
 317     bool IsOk() const { return m_isOk 
&& m_mutex
.IsOk(); } 
 320     wxCondError 
WaitTimeout(unsigned long milliseconds
); 
 322     wxCondError 
Signal(); 
 323     wxCondError 
Broadcast(); 
 326     // get the POSIX mutex associated with us 
 327     pthread_mutex_t 
*GetPMutex() const { return &m_mutex
.m_internal
->m_mutex
; } 
 330     pthread_cond_t m_cond
; 
 335 wxConditionInternal::wxConditionInternal(wxMutex
& mutex
) 
 338     int err 
= pthread_cond_init(&m_cond
, NULL 
/* default attributes */); 
 344         wxLogApiError(_T("pthread_cond_init()"), err
); 
 348 wxConditionInternal::~wxConditionInternal() 
 352         int err 
= pthread_cond_destroy(&m_cond
); 
 355             wxLogApiError(_T("pthread_cond_destroy()"), err
); 
 360 wxCondError 
wxConditionInternal::Wait() 
 362     int err 
= pthread_cond_wait(&m_cond
, GetPMutex()); 
 365         wxLogApiError(_T("pthread_cond_wait()"), err
); 
 367         return wxCOND_MISC_ERROR
; 
 370     return wxCOND_NO_ERROR
; 
 373 wxCondError 
wxConditionInternal::WaitTimeout(unsigned long milliseconds
) 
 375     wxLongLong curtime 
= wxGetLocalTimeMillis(); 
 376     curtime 
+= milliseconds
; 
 377     wxLongLong temp 
= curtime 
/ 1000; 
 378     int sec 
= temp
.GetLo(); 
 380     temp 
= curtime 
- temp
; 
 381     int millis 
= temp
.GetLo(); 
 386     tspec
.tv_nsec 
= millis 
* 1000L * 1000L; 
 388     int err 
= pthread_cond_timedwait( &m_cond
, GetPMutex(), &tspec 
); 
 392             return wxCOND_TIMEOUT
; 
 395             return wxCOND_NO_ERROR
; 
 398             wxLogApiError(_T("pthread_cond_timedwait()"), err
); 
 401     return wxCOND_MISC_ERROR
; 
 404 wxCondError 
wxConditionInternal::Signal() 
 406     int err 
= pthread_cond_signal(&m_cond
); 
 409         wxLogApiError(_T("pthread_cond_signal()"), err
); 
 411         return wxCOND_MISC_ERROR
; 
 414     return wxCOND_NO_ERROR
; 
 417 wxCondError 
wxConditionInternal::Broadcast() 
 419     int err 
= pthread_cond_broadcast(&m_cond
); 
 422         wxLogApiError(_T("pthread_cond_broadcast()"), err
); 
 424         return wxCOND_MISC_ERROR
; 
 427     return wxCOND_NO_ERROR
; 
 430 // =========================================================================== 
 431 // wxSemaphore implementation 
 432 // =========================================================================== 
 434 // --------------------------------------------------------------------------- 
 435 // wxSemaphoreInternal 
 436 // --------------------------------------------------------------------------- 
 438 // we implement the semaphores using mutexes and conditions instead of using 
 439 // the sem_xxx() POSIX functions because they're not widely available and also 
 440 // because it's impossible to implement WaitTimeout() using them 
 441 class wxSemaphoreInternal
 
 444     wxSemaphoreInternal(int initialcount
, int maxcount
); 
 446     bool IsOk() const { return m_isOk
; } 
 449     wxSemaError 
TryWait(); 
 450     wxSemaError 
WaitTimeout(unsigned long milliseconds
); 
 464 wxSemaphoreInternal::wxSemaphoreInternal(int initialcount
, int maxcount
) 
 468     if ( (initialcount 
< 0 || maxcount 
< 0) || 
 469             ((maxcount 
> 0) && (initialcount 
> maxcount
)) ) 
 471         wxFAIL_MSG( _T("wxSemaphore: invalid initial or maximal count") ); 
 477         m_maxcount 
= (size_t)maxcount
; 
 478         m_count 
= (size_t)initialcount
; 
 481     m_isOk 
= m_mutex
.IsOk() && m_cond
.IsOk(); 
 484 wxSemaError 
wxSemaphoreInternal::Wait() 
 486     wxMutexLocker 
locker(m_mutex
); 
 488     while ( m_count 
== 0 ) 
 490         wxLogTrace(TRACE_SEMA
, 
 491                    "Thread %ld waiting for semaphore to become signalled", 
 492                    wxThread::GetCurrentId()); 
 494         if ( m_cond
.Wait() != wxCOND_NO_ERROR 
) 
 495             return wxSEMA_MISC_ERROR
; 
 497         wxLogTrace(TRACE_SEMA
, 
 498                    "Thread %ld finished waiting for semaphore, count = %lu", 
 499                    wxThread::GetCurrentId(), (unsigned long)m_count
); 
 504     return wxSEMA_NO_ERROR
; 
 507 wxSemaError 
wxSemaphoreInternal::TryWait() 
 509     wxMutexLocker 
locker(m_mutex
); 
 516     return wxSEMA_NO_ERROR
; 
 519 wxSemaError 
wxSemaphoreInternal::WaitTimeout(unsigned long milliseconds
) 
 521     wxMutexLocker 
locker(m_mutex
); 
 523     wxLongLong startTime 
= wxGetLocalTimeMillis(); 
 525     while ( m_count 
== 0 ) 
 527         wxLongLong elapsed 
= wxGetLocalTimeMillis() - startTime
; 
 528         long remainingTime 
= (long)milliseconds 
- (long)elapsed
.GetLo(); 
 529         if ( remainingTime 
<= 0 ) 
 532             return wxSEMA_TIMEOUT
; 
 535         if ( m_cond
.WaitTimeout(remainingTime
) != wxCOND_NO_ERROR 
) 
 536             return wxSEMA_MISC_ERROR
; 
 541     return wxSEMA_NO_ERROR
; 
 544 wxSemaError 
wxSemaphoreInternal::Post() 
 546     wxMutexLocker 
locker(m_mutex
); 
 548     if ( m_maxcount 
> 0 && m_count 
== m_maxcount 
) 
 550         return wxSEMA_OVERFLOW
; 
 555     wxLogTrace(TRACE_SEMA
, 
 556                "Thread %ld about to signal semaphore, count = %lu", 
 557                wxThread::GetCurrentId(), (unsigned long)m_count
); 
 559     return m_cond
.Signal() == wxCOND_NO_ERROR 
? wxSEMA_NO_ERROR
 
 563 // =========================================================================== 
 564 // wxThread implementation 
 565 // =========================================================================== 
 567 // the thread callback functions must have the C linkage 
 571 #if HAVE_THREAD_CLEANUP_FUNCTIONS 
 572     // thread exit function 
 573     void wxPthreadCleanup(void *ptr
); 
 574 #endif // HAVE_THREAD_CLEANUP_FUNCTIONS 
 576 void *wxPthreadStart(void *ptr
); 
 580 // ---------------------------------------------------------------------------- 
 582 // ---------------------------------------------------------------------------- 
 584 class wxThreadInternal
 
 590     // thread entry function 
 591     static void *PthreadStart(wxThread 
*thread
); 
 596         // unblock the thread allowing it to run 
 597     void SignalRun() { m_semRun
.Post(); } 
 598         // ask the thread to terminate 
 600         // go to sleep until Resume() is called 
 607     int GetPriority() const { return m_prio
; } 
 608     void SetPriority(int prio
) { m_prio 
= prio
; } 
 610     wxThreadState 
GetState() const { return m_state
; } 
 611     void SetState(wxThreadState state
) 
 614         static const wxChar 
*stateNames
[] = 
 622         wxLogTrace(TRACE_THREADS
, _T("Thread %ld: %s => %s."), 
 623                    (long)GetId(), stateNames
[m_state
], stateNames
[state
]); 
 624 #endif // __WXDEBUG__ 
 629     pthread_t 
GetId() const { return m_threadId
; } 
 630     pthread_t 
*GetIdPtr() { return &m_threadId
; } 
 632     void SetCancelFlag() { m_cancelled 
= TRUE
; } 
 633     bool WasCancelled() const { return m_cancelled
; } 
 635     void SetExitCode(wxThread::ExitCode exitcode
) { m_exitcode 
= exitcode
; } 
 636     wxThread::ExitCode 
GetExitCode() const { return m_exitcode
; } 
 639     void SetReallyPaused(bool paused
) { m_isPaused 
= paused
; } 
 640     bool IsReallyPaused() const { return m_isPaused
; } 
 642         // tell the thread that it is a detached one 
 645         wxCriticalSectionLocker 
lock(m_csJoinFlag
); 
 647         m_shouldBeJoined 
= FALSE
; 
 651 #if HAVE_THREAD_CLEANUP_FUNCTIONS 
 652     // this is used by wxPthreadCleanup() only 
 653     static void Cleanup(wxThread 
*thread
); 
 654 #endif // HAVE_THREAD_CLEANUP_FUNCTIONS 
 657     pthread_t     m_threadId
;   // id of the thread 
 658     wxThreadState m_state
;      // see wxThreadState enum 
 659     int           m_prio
;       // in wxWindows units: from 0 to 100 
 661     // this flag is set when the thread should terminate 
 664     // this flag is set when the thread is blocking on m_semSuspend 
 667     // the thread exit code - only used for joinable (!detached) threads and 
 668     // is only valid after the thread termination 
 669     wxThread::ExitCode m_exitcode
; 
 671     // many threads may call Wait(), but only one of them should call 
 672     // pthread_join(), so we have to keep track of this 
 673     wxCriticalSection m_csJoinFlag
; 
 674     bool m_shouldBeJoined
; 
 677     // this semaphore is posted by Run() and the threads Entry() is not 
 678     // called before it is done 
 679     wxSemaphore m_semRun
; 
 681     // this one is signaled when the thread should resume after having been 
 683     wxSemaphore m_semSuspend
; 
 686 // ---------------------------------------------------------------------------- 
 687 // thread startup and exit functions 
 688 // ---------------------------------------------------------------------------- 
 690 void *wxPthreadStart(void *ptr
) 
 692     return wxThreadInternal::PthreadStart((wxThread 
*)ptr
); 
 695 void *wxThreadInternal::PthreadStart(wxThread 
*thread
) 
 697     wxThreadInternal 
*pthread 
= thread
->m_internal
; 
 700    wxLogTrace(TRACE_THREADS
, _T("Thread %ld started."), (long long)pthread
->GetId()); 
 702    wxLogTrace(TRACE_THREADS
, _T("Thread %ld started."), (long)pthread
->GetId()); 
 705     // associate the thread pointer with the newly created thread so that 
 706     // wxThread::This() will work 
 707     int rc 
= pthread_setspecific(gs_keySelf
, thread
); 
 710         wxLogSysError(rc
, _("Cannot start thread: error writing TLS")); 
 715     // have to declare this before pthread_cleanup_push() which defines a 
 719 #if HAVE_THREAD_CLEANUP_FUNCTIONS 
 720     // install the cleanup handler which will be called if the thread is 
 722     pthread_cleanup_push(wxPthreadCleanup
, thread
); 
 723 #endif // HAVE_THREAD_CLEANUP_FUNCTIONS 
 725     // wait for the semaphore to be posted from Run() 
 726     pthread
->m_semRun
.Wait(); 
 728     // test whether we should run the run at all - may be it was deleted 
 729     // before it started to Run()? 
 731         wxCriticalSectionLocker 
lock(thread
->m_critsect
); 
 733         dontRunAtAll 
= pthread
->GetState() == STATE_NEW 
&& 
 734                        pthread
->WasCancelled(); 
 739         // call the main entry 
 740         wxLogTrace(TRACE_THREADS
, _T("Thread %ld about to enter its Entry()."), 
 742                    (long long)pthread
->GetId()); 
 744                    (long)pthread
->GetId()); 
 747         pthread
->m_exitcode 
= thread
->Entry(); 
 749         wxLogTrace(TRACE_THREADS
, _T("Thread %ld Entry() returned %lu."), 
 751                    (long long)pthread
->GetId(), (unsigned long)pthread
->m_exitcode
); 
 753                    (long)pthread
->GetId(), (unsigned long)pthread
->m_exitcode
); 
 757             wxCriticalSectionLocker 
lock(thread
->m_critsect
); 
 759             // change the state of the thread to "exited" so that 
 760             // wxPthreadCleanup handler won't do anything from now (if it's 
 761             // called before we do pthread_cleanup_pop below) 
 762             pthread
->SetState(STATE_EXITED
); 
 766     // NB: at least under Linux, pthread_cleanup_push/pop are macros and pop 
 767     //     contains the matching '}' for the '{' in push, so they must be used 
 768     //     in the same block! 
 769 #if HAVE_THREAD_CLEANUP_FUNCTIONS 
 770     // remove the cleanup handler without executing it 
 771     pthread_cleanup_pop(FALSE
); 
 772 #endif // HAVE_THREAD_CLEANUP_FUNCTIONS 
 776         // FIXME: deleting a possibly joinable thread here??? 
 779         return EXITCODE_CANCELLED
; 
 783         // terminate the thread 
 784         thread
->Exit(pthread
->m_exitcode
); 
 786         wxFAIL_MSG(wxT("wxThread::Exit() can't return.")); 
 792 #if HAVE_THREAD_CLEANUP_FUNCTIONS 
 794 // this handler is called when the thread is cancelled 
 795 extern "C" void wxPthreadCleanup(void *ptr
) 
 797     wxThreadInternal::Cleanup((wxThread 
*)ptr
); 
 800 void wxThreadInternal::Cleanup(wxThread 
*thread
) 
 803         wxCriticalSectionLocker 
lock(thread
->m_critsect
); 
 804         if ( thread
->m_internal
->GetState() == STATE_EXITED 
) 
 806             // thread is already considered as finished. 
 811     // exit the thread gracefully 
 812     thread
->Exit(EXITCODE_CANCELLED
); 
 815 #endif // HAVE_THREAD_CLEANUP_FUNCTIONS 
 817 // ---------------------------------------------------------------------------- 
 819 // ---------------------------------------------------------------------------- 
 821 wxThreadInternal::wxThreadInternal() 
 825     m_prio 
= WXTHREAD_DEFAULT_PRIORITY
; 
 829     // set to TRUE only when the thread starts waiting on m_semSuspend 
 832     // defaults for joinable threads 
 833     m_shouldBeJoined 
= TRUE
; 
 834     m_isDetached 
= FALSE
; 
 837 wxThreadInternal::~wxThreadInternal() 
 841 wxThreadError 
wxThreadInternal::Run() 
 843     wxCHECK_MSG( GetState() == STATE_NEW
, wxTHREAD_RUNNING
, 
 844                  wxT("thread may only be started once after Create()") ); 
 846     SetState(STATE_RUNNING
); 
 848     // wake up threads waiting for our start 
 851     return wxTHREAD_NO_ERROR
; 
 854 void wxThreadInternal::Wait() 
 856     wxCHECK_RET( !m_isDetached
, _T("can't wait for a detached thread") ); 
 858     // if the thread we're waiting for is waiting for the GUI mutex, we will 
 859     // deadlock so make sure we release it temporarily 
 860     if ( wxThread::IsMain() ) 
 863     wxLogTrace(TRACE_THREADS
, 
 865                _T("Starting to wait for thread %ld to exit."), (long long)GetId()); 
 867                _T("Starting to wait for thread %ld to exit."), (long)GetId()); 
 870     // to avoid memory leaks we should call pthread_join(), but it must only be 
 871     // done once so use a critical section to serialize the code below 
 873         wxCriticalSectionLocker 
lock(m_csJoinFlag
); 
 875         if ( m_shouldBeJoined 
) 
 877             // FIXME shouldn't we set cancellation type to DISABLED here? If 
 878             //       we're cancelled inside pthread_join(), things will almost 
 879             //       certainly break - but if we disable the cancellation, we 
 881             if ( pthread_join(GetId(), &m_exitcode
) != 0 ) 
 883                 // this is a serious problem, so use wxLogError and not 
 884                 // wxLogDebug: it is possible to bring the system to its knees 
 885                 // by creating too many threads and not joining them quite 
 887                 wxLogError(_("Failed to join a thread, potential memory leak " 
 888                              "detected - please restart the program")); 
 891             m_shouldBeJoined 
= FALSE
; 
 895     // reacquire GUI mutex 
 896     if ( wxThread::IsMain() ) 
 900 void wxThreadInternal::Pause() 
 902     // the state is set from the thread which pauses us first, this function 
 903     // is called later so the state should have been already set 
 904     wxCHECK_RET( m_state 
== STATE_PAUSED
, 
 905                  wxT("thread must first be paused with wxThread::Pause().") ); 
 908    wxLogTrace(TRACE_THREADS
, _T("Thread %ld goes to sleep."), (long long)GetId()); 
 910    wxLogTrace(TRACE_THREADS
, _T("Thread %ld goes to sleep."), (long)GetId()); 
 913     // wait until the semaphore is Post()ed from Resume() 
 917 void wxThreadInternal::Resume() 
 919     wxCHECK_RET( m_state 
== STATE_PAUSED
, 
 920                  wxT("can't resume thread which is not suspended.") ); 
 922     // the thread might be not actually paused yet - if there were no call to 
 923     // TestDestroy() since the last call to Pause() for example 
 924     if ( IsReallyPaused() ) 
 927        wxLogTrace(TRACE_THREADS
, _T("Waking up thread %ld"), (long long)GetId()); 
 929        wxLogTrace(TRACE_THREADS
, _T("Waking up thread %ld"), (long)GetId()); 
 936         SetReallyPaused(FALSE
); 
 940         wxLogTrace(TRACE_THREADS
, _T("Thread %ld is not yet really paused"), 
 948     SetState(STATE_RUNNING
); 
 951 // ----------------------------------------------------------------------------- 
 952 // wxThread static functions 
 953 // ----------------------------------------------------------------------------- 
 955 wxThread 
*wxThread::This() 
 957     return (wxThread 
*)pthread_getspecific(gs_keySelf
); 
 960 bool wxThread::IsMain() 
 962     return (bool)pthread_equal(pthread_self(), gs_tidMain
); 
 965 void wxThread::Yield() 
 967 #ifdef HAVE_SCHED_YIELD 
 972 void wxThread::Sleep(unsigned long milliseconds
) 
 974     wxUsleep(milliseconds
); 
 977 int wxThread::GetCPUCount() 
 979 #if defined(__LINUX__) && wxUSE_FFILE 
 980     // read from proc (can't use wxTextFile here because it's a special file: 
 981     // it has 0 size but still can be read from) 
 984     wxFFile 
file(_T("/proc/cpuinfo")); 
 985     if ( file
.IsOpened() ) 
 987         // slurp the whole file 
 989         if ( file
.ReadAll(&s
) ) 
 991             // (ab)use Replace() to find the number of "processor" strings 
 992             size_t count 
= s
.Replace(_T("processor"), _T("")); 
 998             wxLogDebug(_T("failed to parse /proc/cpuinfo")); 
1002             wxLogDebug(_T("failed to read /proc/cpuinfo")); 
1005 #elif defined(_SC_NPROCESSORS_ONLN) 
1006     // this works for Solaris 
1007     int rc 
= sysconf(_SC_NPROCESSORS_ONLN
); 
1012 #endif // different ways to get number of CPUs 
1019   // VMS is a 64 bit system and threads have 64 bit pointers. 
1020   // ??? also needed for other systems???? 
1021 unsigned long long wxThread::GetCurrentId() 
1023     return (unsigned long long)pthread_self(); 
1025 unsigned long wxThread::GetCurrentId() 
1027     return (unsigned long)pthread_self(); 
1031 bool wxThread::SetConcurrency(size_t level
) 
1033 #ifdef HAVE_THR_SETCONCURRENCY 
1034     int rc 
= thr_setconcurrency(level
); 
1037         wxLogSysError(rc
, _T("thr_setconcurrency() failed")); 
1041 #else // !HAVE_THR_SETCONCURRENCY 
1042     // ok only for the default value 
1044 #endif // HAVE_THR_SETCONCURRENCY/!HAVE_THR_SETCONCURRENCY 
1047 // ----------------------------------------------------------------------------- 
1049 // ----------------------------------------------------------------------------- 
1051 wxThread::wxThread(wxThreadKind kind
) 
1053     // add this thread to the global list of all threads 
1054     gs_allThreads
.Add(this); 
1056     m_internal 
= new wxThreadInternal(); 
1058     m_isDetached 
= kind 
== wxTHREAD_DETACHED
; 
1061 wxThreadError 
wxThread::Create(unsigned int WXUNUSED(stackSize
)) 
1063     if ( m_internal
->GetState() != STATE_NEW 
) 
1065         // don't recreate thread 
1066         return wxTHREAD_RUNNING
; 
1069     // set up the thread attribute: right now, we only set thread priority 
1070     pthread_attr_t attr
; 
1071     pthread_attr_init(&attr
); 
1073 #ifdef HAVE_THREAD_PRIORITY_FUNCTIONS 
1075     if ( pthread_attr_getschedpolicy(&attr
, &policy
) != 0 ) 
1077         wxLogError(_("Cannot retrieve thread scheduling policy.")); 
1081    /* the pthread.h contains too many spaces. This is a work-around */ 
1082 # undef sched_get_priority_max 
1083 #undef sched_get_priority_min 
1084 #define sched_get_priority_max(_pol_) \ 
1085      (_pol_ == SCHED_OTHER ? PRI_FG_MAX_NP : PRI_FIFO_MAX) 
1086 #define sched_get_priority_min(_pol_) \ 
1087      (_pol_ == SCHED_OTHER ? PRI_FG_MIN_NP : PRI_FIFO_MIN) 
1090     int max_prio 
= sched_get_priority_max(policy
), 
1091         min_prio 
= sched_get_priority_min(policy
), 
1092         prio 
= m_internal
->GetPriority(); 
1094     if ( min_prio 
== -1 || max_prio 
== -1 ) 
1096         wxLogError(_("Cannot get priority range for scheduling policy %d."), 
1099     else if ( max_prio 
== min_prio 
) 
1101         if ( prio 
!= WXTHREAD_DEFAULT_PRIORITY 
) 
1103             // notify the programmer that this doesn't work here 
1104             wxLogWarning(_("Thread priority setting is ignored.")); 
1106         //else: we have default priority, so don't complain 
1108         // anyhow, don't do anything because priority is just ignored 
1112         struct sched_param sp
; 
1113         if ( pthread_attr_getschedparam(&attr
, &sp
) != 0 ) 
1115             wxFAIL_MSG(_T("pthread_attr_getschedparam() failed")); 
1118         sp
.sched_priority 
= min_prio 
+ (prio
*(max_prio 
- min_prio
))/100; 
1120         if ( pthread_attr_setschedparam(&attr
, &sp
) != 0 ) 
1122             wxFAIL_MSG(_T("pthread_attr_setschedparam(priority) failed")); 
1125 #endif // HAVE_THREAD_PRIORITY_FUNCTIONS 
1127 #ifdef HAVE_PTHREAD_ATTR_SETSCOPE 
1128     // this will make the threads created by this process really concurrent 
1129     if ( pthread_attr_setscope(&attr
, PTHREAD_SCOPE_SYSTEM
) != 0 ) 
1131         wxFAIL_MSG(_T("pthread_attr_setscope(PTHREAD_SCOPE_SYSTEM) failed")); 
1133 #endif // HAVE_PTHREAD_ATTR_SETSCOPE 
1135     // VZ: assume that this one is always available (it's rather fundamental), 
1136     //     if this function is ever missing we should try to use 
1137     //     pthread_detach() instead (after thread creation) 
1140         if ( pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_DETACHED
) != 0 ) 
1142             wxFAIL_MSG(_T("pthread_attr_setdetachstate(DETACHED) failed")); 
1145         // never try to join detached threads 
1146         m_internal
->Detach(); 
1148     //else: threads are created joinable by default, it's ok 
1150     // create the new OS thread object 
1151     int rc 
= pthread_create
 
1153                 m_internal
->GetIdPtr(), 
1159     if ( pthread_attr_destroy(&attr
) != 0 ) 
1161         wxFAIL_MSG(_T("pthread_attr_destroy() failed")); 
1166         m_internal
->SetState(STATE_EXITED
); 
1168         return wxTHREAD_NO_RESOURCE
; 
1171     return wxTHREAD_NO_ERROR
; 
1174 wxThreadError 
wxThread::Run() 
1176     wxCriticalSectionLocker 
lock(m_critsect
); 
1178     wxCHECK_MSG( m_internal
->GetId(), wxTHREAD_MISC_ERROR
, 
1179                  wxT("must call wxThread::Create() first") ); 
1181     return m_internal
->Run(); 
1184 // ----------------------------------------------------------------------------- 
1186 // ----------------------------------------------------------------------------- 
1188 void wxThread::SetPriority(unsigned int prio
) 
1190     wxCHECK_RET( ((int)WXTHREAD_MIN_PRIORITY 
<= (int)prio
) && 
1191                  ((int)prio 
<= (int)WXTHREAD_MAX_PRIORITY
), 
1192                  wxT("invalid thread priority") ); 
1194     wxCriticalSectionLocker 
lock(m_critsect
); 
1196     switch ( m_internal
->GetState() ) 
1199             // thread not yet started, priority will be set when it is 
1200             m_internal
->SetPriority(prio
); 
1205 #ifdef HAVE_THREAD_PRIORITY_FUNCTIONS 
1206 #if defined(__LINUX__) 
1207 // On Linux, pthread_setschedparam with SCHED_OTHER does not allow 
1208 // a priority other than 0.  Instead, we use the BSD setpriority 
1209 // which alllows us to set a 'nice' value between 20 to -20.  Only 
1210 // super user can set a value less than zero (more negative yields 
1211 // higher priority).  setpriority set the static priority of a process, 
1212 // but this is OK since Linux is configured as a thread per process. 
1218                 // Map Wx priorites (WXTHREAD_MIN_PRIORITY - 
1219                 // WXTHREAD_MAX_PRIORITY) into BSD priorities (20 - -20). 
1220                 // Do calculation of values instead of hard coding them 
1221                 // to make maintenance easier. 
1223                 pSpan 
= ((float)(WXTHREAD_MAX_PRIORITY 
- WXTHREAD_MIN_PRIORITY
)) / 2.0; 
1225                 // prio starts as ...................  // value =>  (0) >=  p  <=  (n) 
1227                 fPrio 
= ((float)prio
) -  pSpan
;        // value =>  (-n) >=  p  <=  (+n) 
1229                 fPrio 
= 0.0 - fPrio
;                   // value =>  (+n) <=  p  >=  (-n) 
1231                 fPrio 
= fPrio 
* (20. / pSpan
) + .5;    // value =>  (20) <=  p  >=  (-20) 
1235                 // Clamp prio from 20 - -20; 
1236                 iPrio 
= (iPrio 
> 20)  ?  20 : iPrio
; 
1237                 iPrio 
= (iPrio 
< -20) ? -20 : iPrio
; 
1239                 if (setpriority(PRIO_PROCESS
, 0, iPrio
) == -1) 
1241                     wxLogError(_("Failed to set thread priority %d."), prio
); 
1246                 struct sched_param sparam
; 
1247                 sparam
.sched_priority 
= prio
; 
1249                 if ( pthread_setschedparam(m_internal
->GetId(), 
1250                                            SCHED_OTHER
, &sparam
) != 0 ) 
1252                     wxLogError(_("Failed to set thread priority %d."), prio
); 
1256 #endif // HAVE_THREAD_PRIORITY_FUNCTIONS 
1261             wxFAIL_MSG(wxT("impossible to set thread priority in this state")); 
1265 unsigned int wxThread::GetPriority() const 
1267     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); 
1269     return m_internal
->GetPriority(); 
1272 wxThreadIdType 
wxThread::GetId() const 
1274     return (wxThreadIdType
) m_internal
->GetId(); 
1277 // ----------------------------------------------------------------------------- 
1279 // ----------------------------------------------------------------------------- 
1281 wxThreadError 
wxThread::Pause() 
1283     wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
, 
1284                  _T("a thread can't pause itself") ); 
1286     wxCriticalSectionLocker 
lock(m_critsect
); 
1288     if ( m_internal
->GetState() != STATE_RUNNING 
) 
1290         wxLogDebug(wxT("Can't pause thread which is not running.")); 
1292         return wxTHREAD_NOT_RUNNING
; 
1295     // just set a flag, the thread will be really paused only during the next 
1296     // call to TestDestroy() 
1297     m_internal
->SetState(STATE_PAUSED
); 
1299     return wxTHREAD_NO_ERROR
; 
1302 wxThreadError 
wxThread::Resume() 
1304     wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
, 
1305                  _T("a thread can't resume itself") ); 
1307     wxCriticalSectionLocker 
lock(m_critsect
); 
1309     wxThreadState state 
= m_internal
->GetState(); 
1314             wxLogTrace(TRACE_THREADS
, _T("Thread %ld suspended, resuming."), 
1317             m_internal
->Resume(); 
1319             return wxTHREAD_NO_ERROR
; 
1322             wxLogTrace(TRACE_THREADS
, _T("Thread %ld exited, won't resume."), 
1324             return wxTHREAD_NO_ERROR
; 
1327             wxLogDebug(_T("Attempt to resume a thread which is not paused.")); 
1329             return wxTHREAD_MISC_ERROR
; 
1333 // ----------------------------------------------------------------------------- 
1335 // ----------------------------------------------------------------------------- 
1337 wxThread::ExitCode 
wxThread::Wait() 
1339     wxCHECK_MSG( This() != this, (ExitCode
)-1, 
1340                  _T("a thread can't wait for itself") ); 
1342     wxCHECK_MSG( !m_isDetached
, (ExitCode
)-1, 
1343                  _T("can't wait for detached thread") ); 
1347     return m_internal
->GetExitCode(); 
1350 wxThreadError 
wxThread::Delete(ExitCode 
*rc
) 
1352     wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
, 
1353                  _T("a thread can't delete itself") ); 
1355     bool isDetached 
= m_isDetached
; 
1358     wxThreadState state 
= m_internal
->GetState(); 
1360     // ask the thread to stop 
1361     m_internal
->SetCancelFlag(); 
1368             // we need to wake up the thread so that PthreadStart() will 
1369             // terminate - right now it's blocking on run semaphore in 
1371             m_internal
->SignalRun(); 
1380             // resume the thread first 
1381             m_internal
->Resume(); 
1388                 // wait until the thread stops 
1393                     // return the exit code of the thread 
1394                     *rc 
= m_internal
->GetExitCode(); 
1397             //else: can't wait for detached threads 
1400     return wxTHREAD_NO_ERROR
; 
1403 wxThreadError 
wxThread::Kill() 
1405     wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
, 
1406                  _T("a thread can't kill itself") ); 
1408     switch ( m_internal
->GetState() ) 
1412             return wxTHREAD_NOT_RUNNING
; 
1415             // resume the thread first 
1421 #ifdef HAVE_PTHREAD_CANCEL 
1422             if ( pthread_cancel(m_internal
->GetId()) != 0 ) 
1425                 wxLogError(_("Failed to terminate a thread.")); 
1427                 return wxTHREAD_MISC_ERROR
; 
1432                 // if we use cleanup function, this will be done from 
1433                 // wxPthreadCleanup() 
1434 #if !HAVE_THREAD_CLEANUP_FUNCTIONS 
1435                 ScheduleThreadForDeletion(); 
1437                 // don't call OnExit() here, it can only be called in the 
1438                 // threads context and we're in the context of another thread 
1441 #endif // HAVE_THREAD_CLEANUP_FUNCTIONS 
1445                 m_internal
->SetExitCode(EXITCODE_CANCELLED
); 
1448             return wxTHREAD_NO_ERROR
; 
1452 void wxThread::Exit(ExitCode status
) 
1454     wxASSERT_MSG( This() == this, 
1455                   _T("wxThread::Exit() can only be called in the " 
1456                      "context of the same thread") ); 
1460         // from the moment we call OnExit(), the main program may terminate at 
1461         // any moment, so mark this thread as being already in process of being 
1462         // deleted or wxThreadModule::OnExit() will try to delete it again 
1463         ScheduleThreadForDeletion(); 
1466     // don't enter m_critsect before calling OnExit() because the user code 
1467     // might deadlock if, for example, it signals a condition in OnExit() (a 
1468     // common case) while the main thread calls any of functions entering 
1469     // m_critsect on us (almost all of them do) 
1472     // delete C++ thread object if this is a detached thread - user is 
1473     // responsible for doing this for joinable ones 
1476         // FIXME I'm feeling bad about it - what if another thread function is 
1477         //       called (in another thread context) now? It will try to access 
1478         //       half destroyed object which will probably result in something 
1479         //       very bad - but we can't protect this by a crit section unless 
1480         //       we make it a global object, but this would mean that we can 
1481         //       only call one thread function at a time :-( 
1485     // terminate the thread (pthread_exit() never returns) 
1486     pthread_exit(status
); 
1488     wxFAIL_MSG(_T("pthread_exit() failed")); 
1491 // also test whether we were paused 
1492 bool wxThread::TestDestroy() 
1494     wxASSERT_MSG( This() == this, 
1495                   _T("wxThread::TestDestroy() can only be called in the " 
1496                      "context of the same thread") ); 
1500     if ( m_internal
->GetState() == STATE_PAUSED 
) 
1502         m_internal
->SetReallyPaused(TRUE
); 
1504         // leave the crit section or the other threads will stop too if they 
1505         // try to call any of (seemingly harmless) IsXXX() functions while we 
1509         m_internal
->Pause(); 
1513         // thread wasn't requested to pause, nothing to do 
1517     return m_internal
->WasCancelled(); 
1520 wxThread::~wxThread() 
1525     // check that the thread either exited or couldn't be created 
1526     if ( m_internal
->GetState() != STATE_EXITED 
&& 
1527          m_internal
->GetState() != STATE_NEW 
) 
1529         wxLogDebug(_T("The thread %ld is being destroyed although it is still " 
1530                       "running! The application may crash."), GetId()); 
1534 #endif // __WXDEBUG__ 
1538     // remove this thread from the global array 
1539     gs_allThreads
.Remove(this); 
1542 // ----------------------------------------------------------------------------- 
1544 // ----------------------------------------------------------------------------- 
1546 bool wxThread::IsRunning() const 
1548     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); 
1550     return m_internal
->GetState() == STATE_RUNNING
; 
1553 bool wxThread::IsAlive() const 
1555     wxCriticalSectionLocker 
lock((wxCriticalSection
&)m_critsect
); 
1557     switch ( m_internal
->GetState() ) 
1568 bool wxThread::IsPaused() const 
1570     wxCriticalSectionLocker 
lock((wxCriticalSection
&)m_critsect
); 
1572     return (m_internal
->GetState() == STATE_PAUSED
); 
1575 //-------------------------------------------------------------------- 
1577 //-------------------------------------------------------------------- 
1579 class wxThreadModule 
: public wxModule
 
1582     virtual bool OnInit(); 
1583     virtual void OnExit(); 
1586     DECLARE_DYNAMIC_CLASS(wxThreadModule
) 
1589 IMPLEMENT_DYNAMIC_CLASS(wxThreadModule
, wxModule
) 
1591 bool wxThreadModule::OnInit() 
1593     int rc 
= pthread_key_create(&gs_keySelf
, NULL 
/* dtor function */); 
1596         wxLogSysError(rc
, _("Thread module initialization failed: " 
1597                             "failed to create thread key")); 
1602     gs_tidMain 
= pthread_self(); 
1605     gs_mutexGui 
= new wxMutex(); 
1607     gs_mutexGui
->Lock(); 
1610     gs_mutexDeleteThread 
= new wxMutex(); 
1611     gs_condAllDeleted 
= new wxCondition( *gs_mutexDeleteThread 
); 
1616 void wxThreadModule::OnExit() 
1618     wxASSERT_MSG( wxThread::IsMain(), wxT("only main thread can be here") ); 
1620     // are there any threads left which are being deleted right now? 
1621     size_t nThreadsBeingDeleted
; 
1624         wxMutexLocker 
lock( *gs_mutexDeleteThread 
); 
1625         nThreadsBeingDeleted 
= gs_nThreadsBeingDeleted
; 
1627         if ( nThreadsBeingDeleted 
> 0 ) 
1629             wxLogTrace(TRACE_THREADS
, 
1630                        _T("Waiting for %lu threads to disappear"), 
1631                        (unsigned long)nThreadsBeingDeleted
); 
1633             // have to wait until all of them disappear 
1634             gs_condAllDeleted
->Wait(); 
1638     // terminate any threads left 
1639     size_t count 
= gs_allThreads
.GetCount(); 
1642         wxLogDebug(wxT("%lu threads were not terminated by the application."), 
1643                    (unsigned long)count
); 
1646     for ( size_t n 
= 0u; n 
< count
; n
++ ) 
1648         // Delete calls the destructor which removes the current entry. We 
1649         // should only delete the first one each time. 
1650         gs_allThreads
[0]->Delete(); 
1654     // destroy GUI mutex 
1655     gs_mutexGui
->Unlock(); 
1660     // and free TLD slot 
1661     (void)pthread_key_delete(gs_keySelf
); 
1663     delete gs_condAllDeleted
; 
1664     delete gs_mutexDeleteThread
; 
1667 // ---------------------------------------------------------------------------- 
1669 // ---------------------------------------------------------------------------- 
1671 static void ScheduleThreadForDeletion() 
1673     wxMutexLocker 
lock( *gs_mutexDeleteThread 
); 
1675     gs_nThreadsBeingDeleted
++; 
1677     wxLogTrace(TRACE_THREADS
, _T("%lu thread%s waiting to be deleted"), 
1678                (unsigned long)gs_nThreadsBeingDeleted
, 
1679                gs_nThreadsBeingDeleted 
== 1 ? "" : "s"); 
1682 static void DeleteThread(wxThread 
*This
) 
1684     // gs_mutexDeleteThread should be unlocked before signalling the condition 
1685     // or wxThreadModule::OnExit() would deadlock 
1686     wxMutexLocker 
locker( *gs_mutexDeleteThread 
); 
1688     wxLogTrace(TRACE_THREADS
, _T("Thread %ld auto deletes."), This
->GetId()); 
1692     wxCHECK_RET( gs_nThreadsBeingDeleted 
> 0, 
1693                  _T("no threads scheduled for deletion, yet we delete one?") ); 
1695     wxLogTrace(TRACE_THREADS
, _T("%lu scheduled for deletion threads left."), 
1696                (unsigned long)gs_nThreadsBeingDeleted 
- 1); 
1698     if ( !--gs_nThreadsBeingDeleted 
) 
1700         // no more threads left, signal it 
1701         gs_condAllDeleted
->Signal(); 
1705 void wxMutexGuiEnter() 
1708     gs_mutexGui
->Lock(); 
1712 void wxMutexGuiLeave() 
1715     gs_mutexGui
->Unlock(); 
1719 // ---------------------------------------------------------------------------- 
1720 // include common implementation code 
1721 // ---------------------------------------------------------------------------- 
1723 #include "wx/thrimpl.cpp" 
1725 #endif // wxUSE_THREADS