1 ///////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:     wxThread Implementation 
   4 // Author:      Original from Wolfram Gloger/Guilhem Lavaux 
   5 // Modified by: Vadim Zeitlin to make it work :-) 
   8 // Copyright:   (c) Wolfram Gloger (1996, 1997); Guilhem Lavaux (1998), 
   9 //                  Vadim Zeitlin (1999) 
  10 // Licence:     wxWindows licence 
  11 ///////////////////////////////////////////////////////////////////////////// 
  14     #pragma implementation "thread.h" 
  17 // ---------------------------------------------------------------------------- 
  19 // ---------------------------------------------------------------------------- 
  21 // For compilers that support precompilation, includes "wx.h". 
  22 #include "wx/wxprec.h" 
  24 #if defined(__BORLANDC__) 
  38 #include "wx/module.h" 
  39 #include "wx/thread.h" 
  41 // the possible states of the thread ("=>" shows all possible transitions from 
  45     STATE_NEW
,          // didn't start execution yet (=> RUNNING) 
  46     STATE_RUNNING
,      // thread is running (=> PAUSED, CANCELED) 
  47     STATE_PAUSED
,       // thread is temporarily suspended (=> RUNNING) 
  48     STATE_CANCELED
,     // thread should terminate a.s.a.p. (=> EXITED) 
  49     STATE_EXITED        
// thread is terminating 
  52 // ---------------------------------------------------------------------------- 
  54 // ---------------------------------------------------------------------------- 
  56 // if it's FALSE, some secondary thread is holding the GUI lock 
  57 static bool s_bGuiOwnedByMainThread 
= TRUE
; 
  59 // critical section which controls access to all GUI functions: any secondary 
  60 // thread (i.e. except the main one) must enter this crit section before doing 
  62 static wxCriticalSection 
*s_critsectGui 
= NULL
; 
  64 // critical section which protects s_nWaitingForGui variable 
  65 static wxCriticalSection 
*s_critsectWaitingForGui 
= NULL
; 
  67 // number of threads waiting for GUI in wxMutexGuiEnter() 
  68 static size_t s_nWaitingForGui 
= 0; 
  70 // are we waiting for a thread termination? 
  71 static bool s_waitingForThread 
= FALSE
; 
  73 // ============================================================================ 
  74 // Windows implementation of thread classes 
  75 // ============================================================================ 
  77 // ---------------------------------------------------------------------------- 
  78 // wxMutex implementation 
  79 // ---------------------------------------------------------------------------- 
  88     p_internal 
= new wxMutexInternal
; 
  89 //    p_internal->p_mutex = CreateMutex(NULL, FALSE, NULL); 
  90     if ( !p_internal
->p_mutex 
) 
  92         wxLogSysError(_("Can not create mutex.")); 
 101         wxLogDebug(wxT("Warning: freeing a locked mutex (%d locks)."), m_locked
); 
 102 //    CloseHandle(p_internal->p_mutex); 
 105 wxMutexError 
wxMutex::Lock() 
 110     ret = WaitForSingleObject(p_internal->p_mutex, INFINITE); 
 121             wxLogSysError(_("Couldn't acquire a mutex lock")); 
 122             return wxMUTEX_MISC_ERROR; 
 126             wxFAIL_MSG(wxT("impossible return value in wxMutex::Lock")); 
 130     return wxMUTEX_NO_ERROR
; 
 133 wxMutexError 
wxMutex::TryLock() 
 138     ret = WaitForSingleObject(p_internal->p_mutex, 0); 
 139     if (ret == WAIT_TIMEOUT || ret == WAIT_ABANDONED) 
 144     return wxMUTEX_NO_ERROR
; 
 147 wxMutexError 
wxMutex::Unlock() 
 152     BOOL ret = ReleaseMutex(p_internal->p_mutex); 
 155         wxLogSysError(_("Couldn't release a mutex")); 
 156         return wxMUTEX_MISC_ERROR; 
 159     return wxMUTEX_NO_ERROR
; 
 162 // ---------------------------------------------------------------------------- 
 163 // wxCondition implementation 
 164 // ---------------------------------------------------------------------------- 
 166 class wxConditionInternal
 
 173 wxCondition::wxCondition() 
 175     p_internal 
= new wxConditionInternal
; 
 176 //    p_internal->event = CreateEvent(NULL, FALSE, FALSE, NULL); 
 177     if ( !p_internal
->event 
) 
 179         wxLogSysError(_("Can not create event object.")); 
 182     p_internal
->waiters 
= 0; 
 185 wxCondition::~wxCondition() 
 187 //    CloseHandle(p_internal->event); 
 190 void wxCondition::Wait(wxMutex
& mutex
) 
 193     p_internal
->waiters
++; 
 194 //    WaitForSingleObject(p_internal->event, INFINITE); 
 195     p_internal
->waiters
--; 
 199 bool wxCondition::Wait(wxMutex
& mutex
, 
 206     p_internal
->waiters
++; 
 207  //   ret = WaitForSingleObject(p_internal->event, (sec*1000)+(nsec/1000000)); 
 208     p_internal
->waiters
--; 
 211     return TRUE
; // false for timeout 
 214 void wxCondition::Signal() 
 216 //    SetEvent(p_internal->event); 
 219 void wxCondition::Broadcast() 
 223     for (i
=0;i
<p_internal
->waiters
;i
++) 
 225 //        if ( SetEvent(p_internal->event) == 0 ) 
 227             wxLogSysError(_("Couldn't change the state of event object.")); 
 232 // ---------------------------------------------------------------------------- 
 233 // wxCriticalSection implementation 
 234 // ---------------------------------------------------------------------------- 
 236 class wxCriticalSectionInternal
 
 239     // init the critical section object 
 240     wxCriticalSectionInternal() 
 241         { /* ::InitializeCriticalSection(&m_data);*/ } 
 243     // implicit cast to the associated data 
 244     operator Handle 
*() { return &m_data
; } 
 246     // free the associated ressources 
 247     ~wxCriticalSectionInternal() 
 248         { /* ::DeleteCriticalSection(&m_data); */} 
 254 wxCriticalSection::wxCriticalSection() 
 256     m_critsect 
= new wxCriticalSectionInternal
; 
 259 wxCriticalSection::~wxCriticalSection() 
 264 void wxCriticalSection::Enter() 
 266 //    ::EnterCriticalSection(*m_critsect); 
 269 void wxCriticalSection::Leave() 
 271 //    ::LeaveCriticalSection(*m_critsect); 
 274 // ---------------------------------------------------------------------------- 
 275 // wxThread implementation 
 276 // ---------------------------------------------------------------------------- 
 278 // wxThreadInternal class 
 279 // ---------------------- 
 282 class wxThreadInternal 
 289         m_priority = WXTHREAD_DEFAULT_PRIORITY; 
 292     // create a new (suspended) thread (for the given thread object) 
 293     bool Create(wxThread *thread); 
 295     // suspend/resume/terminate 
 298     void Cancel() { m_state = STATE_CANCELED; } 
 301     void SetState(wxThreadState state) { m_state = state; } 
 302     wxThreadState GetState() const { return m_state; } 
 305     void SetPriority(unsigned int priority) { m_priority = priority; } 
 306     unsigned int GetPriority() const { return m_priority; } 
 308     // thread handle and id 
 309     HANDLE GetHandle() const { return m_hThread; } 
 310     DWORD  GetId() const { return m_tid; } 
 313     static DWORD WinThreadStart(wxThread *thread); 
 316     Handle        m_hThread;    // handle of the thread 
 317     wxThreadState m_state;      // state, see wxThreadState enum 
 318     unsigned int  m_priority;   // thread priority in "wx" units 
 319     ThreadId         m_tid;        // thread id 
 322 DWORD wxThreadInternal::WinThreadStart(wxThread *thread) 
 324     // store the thread object in the TLS 
 325     if ( !::TlsSetValue(s_tlsThisThread, thread) ) 
 327         wxLogSysError(_("Can not start thread: error writing TLS.")); 
 332     DWORD ret = (DWORD)thread->Entry(); 
 333     thread->p_internal->SetState(STATE_EXITED); 
 341 bool wxThreadInternal::Create(wxThread *thread) 
 343     m_hThread = ::CreateThread 
 345                     NULL,                               // default security 
 346                     0,                                  // default stack size 
 347                     (LPTHREAD_START_ROUTINE)            // thread entry point 
 348                     wxThreadInternal::WinThreadStart,   // 
 349                     (LPVOID)thread,                     // parameter 
 350                     CREATE_SUSPENDED,                   // flags 
 351                     &m_tid                              // [out] thread id 
 354     if ( m_hThread == NULL ) 
 356         wxLogSysError(_("Can't create thread")); 
 361     // translate wxWindows priority to the Windows one 
 363     if (m_priority <= 20) 
 364         win_priority = THREAD_PRIORITY_LOWEST; 
 365     else if (m_priority <= 40) 
 366         win_priority = THREAD_PRIORITY_BELOW_NORMAL; 
 367     else if (m_priority <= 60) 
 368         win_priority = THREAD_PRIORITY_NORMAL; 
 369     else if (m_priority <= 80) 
 370         win_priority = THREAD_PRIORITY_ABOVE_NORMAL; 
 371     else if (m_priority <= 100) 
 372         win_priority = THREAD_PRIORITY_HIGHEST; 
 375         wxFAIL_MSG(wxT("invalid value of thread priority parameter")); 
 376         win_priority = THREAD_PRIORITY_NORMAL; 
 379     if ( ::SetThreadPriority(m_hThread, win_priority) == 0 ) 
 381         wxLogSysError(_("Can't set thread priority")); 
 387 bool wxThreadInternal::Suspend() 
 389     DWORD nSuspendCount = ::SuspendThread(m_hThread); 
 390     if ( nSuspendCount == (DWORD)-1 ) 
 392         wxLogSysError(_("Can not suspend thread %x"), m_hThread); 
 397     m_state = STATE_PAUSED; 
 402 bool wxThreadInternal::Resume() 
 404     DWORD nSuspendCount = ::ResumeThread(m_hThread); 
 405     if ( nSuspendCount == (DWORD)-1 ) 
 407         wxLogSysError(_("Can not resume thread %x"), m_hThread); 
 412     m_state = STATE_RUNNING; 
 420 wxThread *wxThread::This() 
 422     wxThread *thread = (wxThread *)::TlsGetValue(s_tlsThisThread); 
 424     // be careful, 0 may be a valid return value as well 
 425     if ( !thread && (::GetLastError() != NO_ERROR) ) 
 427         wxLogSysError(_("Couldn't get the current thread pointer")); 
 435 bool wxThread::IsMain() 
 437     return ::GetCurrentThreadId() == s_idMainThread; 
 444 void wxThread::Yield() 
 446     // 0 argument to Sleep() is special 
 450 void wxThread::Sleep(unsigned long milliseconds) 
 452     ::Sleep(milliseconds); 
 455 // create/start thread 
 456 // ------------------- 
 458 wxThreadError wxThread::Create() 
 460     if ( !p_internal->Create(this) ) 
 461         return wxTHREAD_NO_RESOURCE; 
 463     return wxTHREAD_NO_ERROR; 
 466 wxThreadError wxThread::Run() 
 468     wxCriticalSectionLocker lock(m_critsect); 
 470     if ( p_internal->GetState() != STATE_NEW ) 
 472         // actually, it may be almost any state at all, not only STATE_RUNNING 
 473         return wxTHREAD_RUNNING; 
 479 // suspend/resume thread 
 480 // --------------------- 
 482 wxThreadError wxThread::Pause() 
 484     wxCriticalSectionLocker lock(m_critsect); 
 486     return p_internal->Suspend() ? wxTHREAD_NO_ERROR : wxTHREAD_MISC_ERROR; 
 489 wxThreadError wxThread::Resume() 
 491     wxCriticalSectionLocker lock(m_critsect); 
 493     return p_internal->Resume() ? wxTHREAD_NO_ERROR : wxTHREAD_MISC_ERROR; 
 499 wxThread::ExitCode wxThread::Delete() 
 503     // Delete() is always safe to call, so consider all possible states 
 511             // set flag for wxIsWaitingForThread() 
 512             s_waitingForThread = TRUE; 
 519             wxCriticalSectionLocker lock(m_critsect); 
 521             p_internal->Cancel(); 
 522             hThread = p_internal->GetHandle(); 
 525         // we can't just wait for the thread to terminate because it might be 
 526         // calling some GUI functions and so it will never terminate before we 
 527         // process the Windows messages that result from these functions 
 531             result = ::MsgWaitForMultipleObjects 
 533                        1,              // number of objects to wait for 
 534                        &hThread,       // the objects 
 535                        FALSE,          // don't wait for all objects 
 536                        INFINITE,       // no timeout 
 537                        QS_ALLEVENTS    // return as soon as there are any events 
 544                     wxLogSysError(_("Can not wait for thread termination")); 
 549                     // thread we're waiting for terminated 
 552                 case WAIT_OBJECT_0 + 1: 
 553                     // new message arrived, process it 
 554                     if ( !wxTheApp->DoMessage() ) 
 556                         // WM_QUIT received: kill the thread 
 564                         // give the thread we're waiting for chance to exit 
 565                         // from the GUI call it might have been in 
 566                         if ( (s_nWaitingForGui > 0) && wxGuiOwnedByMainThread() ) 
 575                     wxFAIL_MSG(wxT("unexpected result of MsgWaitForMultipleObject")); 
 577         } while ( result != WAIT_OBJECT_0 ); 
 581             s_waitingForThread = FALSE; 
 586         if ( !::GetExitCodeThread(hThread, (LPDWORD)&rc) ) 
 588             wxLogLastError("GetExitCodeThread"); 
 593         wxASSERT_MSG( (LPVOID)rc != (LPVOID)STILL_ACTIVE, 
 594                       wxT("thread must be already terminated.") ); 
 596         ::CloseHandle(hThread); 
 602 wxThreadError wxThread::Kill() 
 605         return wxTHREAD_NOT_RUNNING; 
 607     if ( !::TerminateThread(p_internal->GetHandle(), (DWORD)-1) ) 
 609         wxLogSysError(_("Couldn't terminate thread")); 
 611         return wxTHREAD_MISC_ERROR; 
 616     return wxTHREAD_NO_ERROR; 
 619 void wxThread::Exit(void *status) 
 623     ::ExitThread((DWORD)status); 
 625     wxFAIL_MSG(wxT("Couldn't return from ExitThread()!")); 
 628 void wxThread::SetPriority(unsigned int prio) 
 630     wxCriticalSectionLocker lock(m_critsect); 
 632     p_internal->SetPriority(prio); 
 635 unsigned int wxThread::GetPriority() const 
 637     wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect); 
 639     return p_internal->GetPriority(); 
 642 unsigned long wxThread::GetID() const 
 644     wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect); 
 646     return (unsigned long)p_internal->GetId(); 
 649 bool wxThread::IsRunning() const 
 651     wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect); 
 653     return p_internal->GetState() == STATE_RUNNING; 
 656 bool wxThread::IsAlive() const 
 658     wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect); 
 660     return (p_internal->GetState() == STATE_RUNNING) || 
 661            (p_internal->GetState() == STATE_PAUSED); 
 664 bool wxThread::IsPaused() const 
 666     wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect); 
 668     return (p_internal->GetState() == STATE_PAUSED); 
 671 bool wxThread::TestDestroy() 
 673     wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect); 
 675     return p_internal->GetState() == STATE_CANCELED; 
 680     p_internal = new wxThreadInternal(); 
 683 wxThread::~wxThread() 
 688 // ---------------------------------------------------------------------------- 
 689 // Automatic initialization for thread module 
 690 // ---------------------------------------------------------------------------- 
 692 class wxThreadModule : public wxModule 
 695     virtual bool OnInit(); 
 696     virtual void OnExit(); 
 699     DECLARE_DYNAMIC_CLASS(wxThreadModule) 
 702 IMPLEMENT_DYNAMIC_CLASS(wxThreadModule, wxModule) 
 704 bool wxThreadModule::OnInit() 
 706     // allocate TLS index for storing the pointer to the current thread 
 707     s_tlsThisThread = ::TlsAlloc(); 
 708     if ( s_tlsThisThread == 0xFFFFFFFF ) 
 710         // in normal circumstances it will only happen if all other 
 711         // TLS_MINIMUM_AVAILABLE (>= 64) indices are already taken - in other 
 712         // words, this should never happen 
 713         wxLogSysError(_("Thread module initialization failed: " 
 714                         "impossible to allocate index in thread " 
 720     // main thread doesn't have associated wxThread object, so store 0 in the 
 722     if ( !::TlsSetValue(s_tlsThisThread, (LPVOID)0) ) 
 724         ::TlsFree(s_tlsThisThread); 
 725         s_tlsThisThread = 0xFFFFFFFF; 
 727         wxLogSysError(_("Thread module initialization failed: " 
 728                         "can not store value in thread local storage")); 
 733     s_critsectWaitingForGui = new wxCriticalSection(); 
 735     s_critsectGui = new wxCriticalSection(); 
 736     s_critsectGui->Enter(); 
 738     // no error return for GetCurrentThreadId() 
 739     s_idMainThread = ::GetCurrentThreadId(); 
 744 void wxThreadModule::OnExit() 
 746     if ( !::TlsFree(s_tlsThisThread) ) 
 748         wxLogLastError("TlsFree failed."); 
 753         s_critsectGui->Leave(); 
 754         delete s_critsectGui; 
 755         s_critsectGui = NULL; 
 758     wxDELETE(s_critsectWaitingForGui); 
 761 // ---------------------------------------------------------------------------- 
 762 // under Windows, these functions are implemented usign a critical section and 
 763 // not a mutex, so the names are a bit confusing 
 764 // ---------------------------------------------------------------------------- 
 766 void WXDLLEXPORT wxMutexGuiEnter() 
 768     // this would dead lock everything... 
 769     wxASSERT_MSG( !wxThread::IsMain(), 
 770                   wxT("main thread doesn't want to block in wxMutexGuiEnter()!") ); 
 772     // the order in which we enter the critical sections here is crucial!! 
 774     // set the flag telling to the main thread that we want to do some GUI 
 776         wxCriticalSectionLocker enter(*s_critsectWaitingForGui); 
 781     wxWakeUpMainThread(); 
 783     // now we may block here because the main thread will soon let us in 
 784     // (during the next iteration of OnIdle()) 
 785     s_critsectGui->Enter(); 
 788 void WXDLLEXPORT wxMutexGuiLeave() 
 790     wxCriticalSectionLocker enter(*s_critsectWaitingForGui); 
 792     if ( wxThread::IsMain() ) 
 794         s_bGuiOwnedByMainThread = FALSE; 
 798         // decrement the number of waiters now 
 799         wxASSERT_MSG( s_nWaitingForGui > 0, 
 800                       wxT("calling wxMutexGuiLeave() without entering it first?") ); 
 804         wxWakeUpMainThread(); 
 807     s_critsectGui->Leave(); 
 810 void WXDLLEXPORT wxMutexGuiLeaveOrEnter() 
 812     wxASSERT_MSG( wxThread::IsMain(), 
 813                   wxT("only main thread may call wxMutexGuiLeaveOrEnter()!") ); 
 815     wxCriticalSectionLocker enter(*s_critsectWaitingForGui); 
 817     if ( s_nWaitingForGui == 0 ) 
 819         // no threads are waiting for GUI - so we may acquire the lock without 
 820         // any danger (but only if we don't already have it) 
 821         if ( !wxGuiOwnedByMainThread() ) 
 823             s_critsectGui->Enter(); 
 825             s_bGuiOwnedByMainThread = TRUE; 
 827         //else: already have it, nothing to do 
 831         // some threads are waiting, release the GUI lock if we have it 
 832         if ( wxGuiOwnedByMainThread() ) 
 836         //else: some other worker thread is doing GUI 
 840 bool WXDLLEXPORT wxGuiOwnedByMainThread() 
 842     return s_bGuiOwnedByMainThread; 
 845 // wake up the main thread if it's in ::GetMessage() 
 846 void WXDLLEXPORT wxWakeUpMainThread() 
 848     // sending any message would do - hopefully WM_NULL is harmless enough 
 849     if ( !::PostThreadMessage(s_idMainThread, WM_NULL, 0, 0) ) 
 851         // should never happen 
 852         wxLogLastError("PostThreadMessage(WM_NULL)"); 
 856 bool WXDLLEXPORT wxIsWaitingForThread() 
 858     return s_waitingForThread; 
 862 #endif // wxUSE_THREADS