1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/msw/thread.cpp 
   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-2002) 
  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__) 
  34 #include "wx/msw/private.h" 
  35 #include "wx/msw/missing.h" 
  37 #include "wx/module.h" 
  38 #include "wx/thread.h" 
  40 // must have this symbol defined to get _beginthread/_endthread declarations 
  45 #if defined(__BORLANDC__) 
  47         // I can't set -tWM in the IDE (anyone?) so have to do this 
  51     #if !defined(__MFC_COMPAT__) 
  52         // Needed to know about _beginthreadex etc.. 
  53         #define __MFC_COMPAT__ 
  57 // define wxUSE_BEGIN_THREAD if the compiler has _beginthreadex() function 
  58 // which should be used instead of Win32 ::CreateThread() if possible 
  59 #if defined(__VISUALC__) || \ 
  60     (defined(__BORLANDC__) && (__BORLANDC__ >= 0x500)) || \ 
  61     (defined(__GNUG__) && defined(__MSVCRT__)) || \ 
  62     defined(__WATCOMC__) || defined(__MWERKS__) 
  64     #undef wxUSE_BEGIN_THREAD 
  65     #define wxUSE_BEGIN_THREAD 
  68 #ifdef wxUSE_BEGIN_THREAD 
  69     // this is where _beginthreadex() is declared 
  72     // the return type of the thread function entry point 
  73     typedef unsigned THREAD_RETVAL
; 
  75     // the calling convention of the thread function entry point 
  76     #define THREAD_CALLCONV __stdcall 
  78     // the settings for CreateThread() 
  79     typedef DWORD THREAD_RETVAL
; 
  80     #define THREAD_CALLCONV WINAPI 
  83 // ---------------------------------------------------------------------------- 
  85 // ---------------------------------------------------------------------------- 
  87 // the possible states of the thread ("=>" shows all possible transitions from 
  91     STATE_NEW
,          // didn't start execution yet (=> RUNNING) 
  92     STATE_RUNNING
,      // thread is running (=> PAUSED, CANCELED) 
  93     STATE_PAUSED
,       // thread is temporarily suspended (=> RUNNING) 
  94     STATE_CANCELED
,     // thread should terminate a.s.a.p. (=> EXITED) 
  95     STATE_EXITED        
// thread is terminating 
  98 // ---------------------------------------------------------------------------- 
  99 // this module globals 
 100 // ---------------------------------------------------------------------------- 
 102 // TLS index of the slot where we store the pointer to the current thread 
 103 static DWORD gs_tlsThisThread 
= 0xFFFFFFFF; 
 105 // id of the main thread - the one which can call GUI functions without first 
 106 // calling wxMutexGuiEnter() 
 107 static DWORD gs_idMainThread 
= 0; 
 109 // if it's FALSE, some secondary thread is holding the GUI lock 
 110 static bool gs_bGuiOwnedByMainThread 
= TRUE
; 
 112 // critical section which controls access to all GUI functions: any secondary 
 113 // thread (i.e. except the main one) must enter this crit section before doing 
 115 static wxCriticalSection 
*gs_critsectGui 
= NULL
; 
 117 // critical section which protects gs_nWaitingForGui variable 
 118 static wxCriticalSection 
*gs_critsectWaitingForGui 
= NULL
; 
 120 // number of threads waiting for GUI in wxMutexGuiEnter() 
 121 static size_t gs_nWaitingForGui 
= 0; 
 123 // are we waiting for a thread termination? 
 124 static bool gs_waitingForThread 
= FALSE
; 
 126 // ============================================================================ 
 127 // Windows implementation of thread and related classes 
 128 // ============================================================================ 
 130 // ---------------------------------------------------------------------------- 
 132 // ---------------------------------------------------------------------------- 
 134 wxCriticalSection::wxCriticalSection() 
 136     wxCOMPILE_TIME_ASSERT( sizeof(CRITICAL_SECTION
) <= sizeof(wxCritSectBuffer
), 
 137                            wxCriticalSectionBufferTooSmall 
); 
 139     ::InitializeCriticalSection((CRITICAL_SECTION 
*)m_buffer
); 
 142 wxCriticalSection::~wxCriticalSection() 
 144     ::DeleteCriticalSection((CRITICAL_SECTION 
*)m_buffer
); 
 147 void wxCriticalSection::Enter() 
 149     ::EnterCriticalSection((CRITICAL_SECTION 
*)m_buffer
); 
 152 void wxCriticalSection::Leave() 
 154     ::LeaveCriticalSection((CRITICAL_SECTION 
*)m_buffer
); 
 157 // ---------------------------------------------------------------------------- 
 159 // ---------------------------------------------------------------------------- 
 161 class wxMutexInternal
 
 164     wxMutexInternal(wxMutexType mutexType
); 
 167     bool IsOk() const { return m_mutex 
!= NULL
; } 
 169     wxMutexError 
Lock() { return LockTimeout(INFINITE
); } 
 170     wxMutexError 
TryLock() { return LockTimeout(0); } 
 171     wxMutexError 
Unlock(); 
 174     wxMutexError 
LockTimeout(DWORD milliseconds
); 
 179 // all mutexes are recursive under Win32 so we don't use mutexType 
 180 wxMutexInternal::wxMutexInternal(wxMutexType 
WXUNUSED(mutexType
)) 
 182     // create a nameless (hence intra process and always private) mutex 
 183     m_mutex 
= ::CreateMutex
 
 185                     NULL
,       // default secutiry attributes 
 186                     FALSE
,      // not initially locked 
 192         wxLogLastError(_T("CreateMutex()")); 
 196 wxMutexInternal::~wxMutexInternal() 
 200         if ( !::CloseHandle(m_mutex
) ) 
 202             wxLogLastError(_T("CloseHandle(mutex)")); 
 207 wxMutexError 
wxMutexInternal::LockTimeout(DWORD milliseconds
) 
 209     DWORD rc 
= ::WaitForSingleObject(m_mutex
, milliseconds
); 
 210     if ( rc 
== WAIT_ABANDONED 
) 
 212         // the previous caller died without releasing the mutex, but now we can 
 214         wxLogDebug(_T("WaitForSingleObject() returned WAIT_ABANDONED")); 
 216         // use 0 timeout, normally we should always get it 
 217         rc 
= ::WaitForSingleObject(m_mutex
, 0); 
 229         case WAIT_ABANDONED
:        // checked for above 
 231             wxFAIL_MSG(wxT("impossible return value in wxMutex::Lock")); 
 235             wxLogLastError(_T("WaitForSingleObject(mutex)")); 
 236             return wxMUTEX_MISC_ERROR
; 
 239     return wxMUTEX_NO_ERROR
; 
 242 wxMutexError 
wxMutexInternal::Unlock() 
 244     if ( !::ReleaseMutex(m_mutex
) ) 
 246         wxLogLastError(_("ReleaseMutex()")); 
 248         return wxMUTEX_MISC_ERROR
; 
 251     return wxMUTEX_NO_ERROR
; 
 254 // -------------------------------------------------------------------------- 
 256 // -------------------------------------------------------------------------- 
 258 // a trivial wrapper around Win32 semaphore 
 259 class wxSemaphoreInternal
 
 262     wxSemaphoreInternal(int initialcount
, int maxcount
); 
 263     ~wxSemaphoreInternal(); 
 265     bool IsOk() const { return m_semaphore 
!= NULL
; } 
 267     wxSemaError 
Wait() { return WaitTimeout(INFINITE
); } 
 268     wxSemaError 
TryWait() { return WaitTimeout(0); } 
 269     wxSemaError 
WaitTimeout(unsigned long milliseconds
); 
 277 wxSemaphoreInternal::wxSemaphoreInternal(int initialcount
, int maxcount
) 
 281         // make it practically infinite 
 285     m_semaphore 
= ::CreateSemaphore
 
 287                         NULL
,           // default security attributes 
 295         wxLogLastError(_T("CreateSemaphore()")); 
 299 wxSemaphoreInternal::~wxSemaphoreInternal() 
 303         if ( !::CloseHandle(m_semaphore
) ) 
 305             wxLogLastError(_T("CloseHandle(semaphore)")); 
 310 wxSemaError 
wxSemaphoreInternal::WaitTimeout(unsigned long milliseconds
) 
 312     DWORD rc 
= ::WaitForSingleObject( m_semaphore
, milliseconds 
); 
 317            return wxSEMA_NO_ERROR
; 
 323             wxLogLastError(_T("WaitForSingleObject(semaphore)")); 
 326     return wxSEMA_MISC_ERROR
; 
 329 wxSemaError 
wxSemaphoreInternal::Post() 
 331     if ( !::ReleaseSemaphore(m_semaphore
, 1, NULL 
/* ptr to previous count */) ) 
 333         wxLogLastError(_T("ReleaseSemaphore")); 
 335         return wxSEMA_MISC_ERROR
; 
 338     return wxSEMA_NO_ERROR
; 
 341 // -------------------------------------------------------------------------- 
 343 // -------------------------------------------------------------------------- 
 345 // Win32 doesn't have explicit support for the POSIX condition variables and 
 346 // the Win32 events have quite different semantics, so we reimplement the 
 347 // conditions from scratch using the mutexes and semaphores 
 348 class wxConditionInternal
 
 351     wxConditionInternal(wxMutex
& mutex
); 
 353     bool IsOk() const { return m_mutex
.IsOk() && m_semaphore
.IsOk(); } 
 356     wxCondError 
WaitTimeout(unsigned long milliseconds
); 
 358     wxCondError 
Signal(); 
 359     wxCondError 
Broadcast(); 
 362     // the number of threads currently waiting for this condition 
 365     // the critical section protecting m_numWaiters 
 366     wxCriticalSection m_csWaiters
; 
 369     wxSemaphore m_semaphore
; 
 372 wxConditionInternal::wxConditionInternal(wxMutex
& mutex
) 
 375     // another thread can't access it until we return from ctor, so no need to 
 376     // protect access to m_numWaiters here 
 380 wxCondError 
wxConditionInternal::Wait() 
 382     // increment the number of waiters 
 383     ::InterlockedIncrement(&m_numWaiters
); 
 387     // a potential race condition can occur here 
 389     // after a thread increments nwaiters, and unlocks the mutex and before the 
 390     // semaphore.Wait() is called, if another thread can cause a signal to be 
 393     // this race condition is handled by using a semaphore and incrementing the 
 394     // semaphore only if 'nwaiters' is greater that zero since the semaphore, 
 395     // can 'remember' signals the race condition will not occur 
 397     // wait ( if necessary ) and decrement semaphore 
 398     wxSemaError err 
= m_semaphore
.Wait(); 
 401     return err 
== wxSEMA_NO_ERROR 
? wxCOND_NO_ERROR 
: wxCOND_MISC_ERROR
; 
 404 wxCondError 
wxConditionInternal::WaitTimeout(unsigned long milliseconds
) 
 406     ::InterlockedIncrement(&m_numWaiters
); 
 410     // a race condition can occur at this point in the code 
 412     // please see the comments in Wait(), for details 
 414     wxSemaError err 
= m_semaphore
.WaitTimeout(milliseconds
); 
 416     if ( err 
== wxSEMA_BUSY 
) 
 418         // another potential race condition exists here it is caused when a 
 419         // 'waiting' thread timesout, and returns from WaitForSingleObject, but 
 420         // has not yet decremented 'nwaiters'. 
 422         // at this point if another thread calls signal() then the semaphore 
 423         // will be incremented, but the waiting thread will miss it. 
 425         // to handle this particular case, the waiting thread calls 
 426         // WaitForSingleObject again with a timeout of 0, after locking 
 427         // 'nwaiters_mutex'. this call does not block because of the zero 
 428         // timeout, but will allow the waiting thread to catch the missed 
 430         wxCriticalSectionLocker 
lock(m_csWaiters
); 
 432         err 
= m_semaphore
.WaitTimeout(0); 
 434         if ( err 
!= wxSEMA_NO_ERROR 
) 
 442     return err 
== wxSEMA_NO_ERROR 
? wxCOND_NO_ERROR 
: wxCOND_MISC_ERROR
; 
 445 wxCondError 
wxConditionInternal::Signal() 
 447     wxCriticalSectionLocker 
lock(m_csWaiters
); 
 449     if ( m_numWaiters 
> 0 ) 
 451         // increment the semaphore by 1 
 452         if ( m_semaphore
.Post() != wxSEMA_NO_ERROR 
) 
 453             return wxCOND_MISC_ERROR
; 
 458     return wxCOND_NO_ERROR
; 
 461 wxCondError 
wxConditionInternal::Broadcast() 
 463     wxCriticalSectionLocker 
lock(m_csWaiters
); 
 465     while ( m_numWaiters 
> 0 ) 
 467         if ( m_semaphore
.Post() != wxSEMA_NO_ERROR 
) 
 468             return wxCOND_MISC_ERROR
; 
 473     return wxCOND_NO_ERROR
; 
 476 // ---------------------------------------------------------------------------- 
 477 // wxThread implementation 
 478 // ---------------------------------------------------------------------------- 
 480 // wxThreadInternal class 
 481 // ---------------------- 
 483 class wxThreadInternal
 
 490         m_priority 
= WXTHREAD_DEFAULT_PRIORITY
; 
 502             if ( !::CloseHandle(m_hThread
) ) 
 504                 wxLogLastError(wxT("CloseHandle(thread)")); 
 511     // create a new (suspended) thread (for the given thread object) 
 512     bool Create(wxThread 
*thread
, unsigned int stackSize
); 
 514     // suspend/resume/terminate 
 517     void Cancel() { m_state 
= STATE_CANCELED
; } 
 520     void SetState(wxThreadState state
) { m_state 
= state
; } 
 521     wxThreadState 
GetState() const { return m_state
; } 
 524     void SetPriority(unsigned int priority
); 
 525     unsigned int GetPriority() const { return m_priority
; } 
 527     // thread handle and id 
 528     HANDLE 
GetHandle() const { return m_hThread
; } 
 529     DWORD  
GetId() const { return m_tid
; } 
 532     static THREAD_RETVAL THREAD_CALLCONV 
WinThreadStart(void *thread
); 
 535     HANDLE        m_hThread
;    // handle of the thread 
 536     wxThreadState m_state
;      // state, see wxThreadState enum 
 537     unsigned int  m_priority
;   // thread priority in "wx" units 
 538     DWORD         m_tid
;        // thread id 
 541 THREAD_RETVAL THREAD_CALLCONV 
wxThreadInternal::WinThreadStart(void *param
) 
 546     // first of all, check whether we hadn't been cancelled already and don't 
 547     // start the user code at all then 
 548     wxThread 
*thread 
= (wxThread 
*)param
; 
 549     if ( thread
->m_internal
->GetState() == STATE_EXITED 
) 
 551         rc 
= (THREAD_RETVAL
)-1; 
 554     else // do run thread 
 556         // store the thread object in the TLS 
 557         if ( !::TlsSetValue(gs_tlsThisThread
, thread
) ) 
 559             wxLogSysError(_("Can not start thread: error writing TLS.")); 
 564         rc 
= (THREAD_RETVAL
)thread
->Entry(); 
 566         // enter m_critsect before changing the thread state 
 567         thread
->m_critsect
.Enter(); 
 568         wasCancelled 
= thread
->m_internal
->GetState() == STATE_CANCELED
; 
 569         thread
->m_internal
->SetState(STATE_EXITED
); 
 570         thread
->m_critsect
.Leave(); 
 575     // if the thread was cancelled (from Delete()), then its handle is still 
 577     if ( thread
->IsDetached() && !wasCancelled 
) 
 582     //else: the joinable threads handle will be closed when Wait() is done 
 587 void wxThreadInternal::SetPriority(unsigned int priority
) 
 589     m_priority 
= priority
; 
 591     // translate wxWindows priority to the Windows one 
 593     if (m_priority 
<= 20) 
 594         win_priority 
= THREAD_PRIORITY_LOWEST
; 
 595     else if (m_priority 
<= 40) 
 596         win_priority 
= THREAD_PRIORITY_BELOW_NORMAL
; 
 597     else if (m_priority 
<= 60) 
 598         win_priority 
= THREAD_PRIORITY_NORMAL
; 
 599     else if (m_priority 
<= 80) 
 600         win_priority 
= THREAD_PRIORITY_ABOVE_NORMAL
; 
 601     else if (m_priority 
<= 100) 
 602         win_priority 
= THREAD_PRIORITY_HIGHEST
; 
 605         wxFAIL_MSG(wxT("invalid value of thread priority parameter")); 
 606         win_priority 
= THREAD_PRIORITY_NORMAL
; 
 609     if ( !::SetThreadPriority(m_hThread
, win_priority
) ) 
 611         wxLogSysError(_("Can't set thread priority")); 
 615 bool wxThreadInternal::Create(wxThread 
*thread
, unsigned int stackSize
) 
 617     // for compilers which have it, we should use C RTL function for thread 
 618     // creation instead of Win32 API one because otherwise we will have memory 
 619     // leaks if the thread uses C RTL (and most threads do) 
 620 #ifdef wxUSE_BEGIN_THREAD 
 622     // Watcom is reported to not like 0 stack size (which means "use default" 
 623     // for the other compilers and is also the default value for stackSize) 
 627 #endif // __WATCOMC__ 
 629     m_hThread 
= (HANDLE
)_beginthreadex
 
 631                           NULL
,                             // default security 
 633                           wxThreadInternal::WinThreadStart
, // entry point 
 636                           (unsigned int *)&m_tid
 
 638 #else // compiler doesn't have _beginthreadex 
 639     m_hThread 
= ::CreateThread
 
 641                     NULL
,                               // default security 
 642                     stackSize
,                          // stack size 
 643                     wxThreadInternal::WinThreadStart
,   // thread entry point 
 644                     (LPVOID
)thread
,                     // parameter 
 645                     CREATE_SUSPENDED
,                   // flags 
 646                     &m_tid                              
// [out] thread id 
 648 #endif // _beginthreadex/CreateThread 
 650     if ( m_hThread 
== NULL 
) 
 652         wxLogSysError(_("Can't create thread")); 
 657     if ( m_priority 
!= WXTHREAD_DEFAULT_PRIORITY 
) 
 659         SetPriority(m_priority
); 
 665 bool wxThreadInternal::Suspend() 
 667     DWORD nSuspendCount 
= ::SuspendThread(m_hThread
); 
 668     if ( nSuspendCount 
== (DWORD
)-1 ) 
 670         wxLogSysError(_("Can not suspend thread %x"), m_hThread
); 
 675     m_state 
= STATE_PAUSED
; 
 680 bool wxThreadInternal::Resume() 
 682     DWORD nSuspendCount 
= ::ResumeThread(m_hThread
); 
 683     if ( nSuspendCount 
== (DWORD
)-1 ) 
 685         wxLogSysError(_("Can not resume thread %x"), m_hThread
); 
 690     // don't change the state from STATE_EXITED because it's special and means 
 691     // we are going to terminate without running any user code - if we did it, 
 692     // the codei n Delete() wouldn't work 
 693     if ( m_state 
!= STATE_EXITED 
) 
 695         m_state 
= STATE_RUNNING
; 
 704 wxThread 
*wxThread::This() 
 706     wxThread 
*thread 
= (wxThread 
*)::TlsGetValue(gs_tlsThisThread
); 
 708     // be careful, 0 may be a valid return value as well 
 709     if ( !thread 
&& (::GetLastError() != NO_ERROR
) ) 
 711         wxLogSysError(_("Couldn't get the current thread pointer")); 
 719 bool wxThread::IsMain() 
 721     return ::GetCurrentThreadId() == gs_idMainThread
; 
 728 void wxThread::Yield() 
 730     // 0 argument to Sleep() is special and means to just give away the rest of 
 735 void wxThread::Sleep(unsigned long milliseconds
) 
 737     ::Sleep(milliseconds
); 
 740 int wxThread::GetCPUCount() 
 745     return si
.dwNumberOfProcessors
; 
 748 unsigned long wxThread::GetCurrentId() 
 750     return (unsigned long)::GetCurrentThreadId(); 
 753 bool wxThread::SetConcurrency(size_t level
) 
 755     wxASSERT_MSG( IsMain(), _T("should only be called from the main thread") ); 
 757     // ok only for the default one 
 761     // get system affinity mask first 
 762     HANDLE hProcess 
= ::GetCurrentProcess(); 
 763     DWORD dwProcMask
, dwSysMask
; 
 764     if ( ::GetProcessAffinityMask(hProcess
, &dwProcMask
, &dwSysMask
) == 0 ) 
 766         wxLogLastError(_T("GetProcessAffinityMask")); 
 771     // how many CPUs have we got? 
 772     if ( dwSysMask 
== 1 ) 
 774         // don't bother with all this complicated stuff - on a single 
 775         // processor system it doesn't make much sense anyhow 
 779     // calculate the process mask: it's a bit vector with one bit per 
 780     // processor; we want to schedule the process to run on first level 
 785         if ( dwSysMask 
& bit 
) 
 787             // ok, we can set this bit 
 790             // another process added 
 802     // could we set all bits? 
 805         wxLogDebug(_T("bad level %u in wxThread::SetConcurrency()"), level
); 
 810     // set it: we can't link to SetProcessAffinityMask() because it doesn't 
 811     // exist in Win9x, use RT binding instead 
 813     typedef BOOL (*SETPROCESSAFFINITYMASK
)(HANDLE
, DWORD
); 
 815     // can use static var because we're always in the main thread here 
 816     static SETPROCESSAFFINITYMASK pfnSetProcessAffinityMask 
= NULL
; 
 818     if ( !pfnSetProcessAffinityMask 
) 
 820         HMODULE hModKernel 
= ::LoadLibrary(_T("kernel32")); 
 823             pfnSetProcessAffinityMask 
= (SETPROCESSAFFINITYMASK
) 
 824                 ::GetProcAddress(hModKernel
, "SetProcessAffinityMask"); 
 827         // we've discovered a MT version of Win9x! 
 828         wxASSERT_MSG( pfnSetProcessAffinityMask
, 
 829                       _T("this system has several CPUs but no SetProcessAffinityMask function?") ); 
 832     if ( !pfnSetProcessAffinityMask 
) 
 834         // msg given above - do it only once 
 838     if ( pfnSetProcessAffinityMask(hProcess
, dwProcMask
) == 0 ) 
 840         wxLogLastError(_T("SetProcessAffinityMask")); 
 851 wxThread::wxThread(wxThreadKind kind
) 
 853     m_internal 
= new wxThreadInternal(); 
 855     m_isDetached 
= kind 
== wxTHREAD_DETACHED
; 
 858 wxThread::~wxThread() 
 863 // create/start thread 
 864 // ------------------- 
 866 wxThreadError 
wxThread::Create(unsigned int stackSize
) 
 868     wxCriticalSectionLocker 
lock(m_critsect
); 
 870     if ( !m_internal
->Create(this, stackSize
) ) 
 871         return wxTHREAD_NO_RESOURCE
; 
 873     return wxTHREAD_NO_ERROR
; 
 876 wxThreadError 
wxThread::Run() 
 878     wxCriticalSectionLocker 
lock(m_critsect
); 
 880     if ( m_internal
->GetState() != STATE_NEW 
) 
 882         // actually, it may be almost any state at all, not only STATE_RUNNING 
 883         return wxTHREAD_RUNNING
; 
 886     // the thread has just been created and is still suspended - let it run 
 890 // suspend/resume thread 
 891 // --------------------- 
 893 wxThreadError 
wxThread::Pause() 
 895     wxCriticalSectionLocker 
lock(m_critsect
); 
 897     return m_internal
->Suspend() ? wxTHREAD_NO_ERROR 
: wxTHREAD_MISC_ERROR
; 
 900 wxThreadError 
wxThread::Resume() 
 902     wxCriticalSectionLocker 
lock(m_critsect
); 
 904     return m_internal
->Resume() ? wxTHREAD_NO_ERROR 
: wxTHREAD_MISC_ERROR
; 
 910 wxThread::ExitCode 
wxThread::Wait() 
 912     // although under Windows we can wait for any thread, it's an error to 
 913     // wait for a detached one in wxWin API 
 914     wxCHECK_MSG( !IsDetached(), (ExitCode
)-1, 
 915                  _T("can't wait for detached thread") ); 
 917     ExitCode rc 
= (ExitCode
)-1; 
 926 wxThreadError 
wxThread::Delete(ExitCode 
*pRc
) 
 930     // Delete() is always safe to call, so consider all possible states 
 932     // we might need to resume the thread, but we might also not need to cancel 
 933     // it if it doesn't run yet 
 934     bool shouldResume 
= FALSE
, 
 938     // check if the thread already started to run 
 940         wxCriticalSectionLocker 
lock(m_critsect
); 
 942         if ( m_internal
->GetState() == STATE_NEW 
) 
 944             // WinThreadStart() will see it and terminate immediately, no need 
 945             // to cancel the thread - but we still need to resume it to let it 
 947             m_internal
->SetState(STATE_EXITED
); 
 949             Resume();   // it knows about STATE_EXITED special case 
 951             shouldCancel 
= FALSE
; 
 954             // shouldResume is correctly set to FALSE here 
 958             shouldResume 
= IsPaused(); 
 962     // resume the thread if it is paused 
 966     HANDLE hThread 
= m_internal
->GetHandle(); 
 968         // Check if thread is really still running.  There is a 
 969         // race condition in WinThreadStart between the time the 
 970         // m_internal->m_state is set to STATE_EXITED and the win32 
 971         // thread actually exits.  It can be flagged as STATE_EXITED 
 972         // and then we don't wait for it to exit.  This will cause 
 973         // GetExitCodeThread to return STILL_ACTIVE. 
 978                         if ( ::GetExitCodeThread(hThread
, (LPDWORD
)&rc
) ) 
 980                                 if ((DWORD
)rc 
== STILL_ACTIVE
) 
 990     // does it still run? 
 995             // set flag for wxIsWaitingForThread() 
 996             gs_waitingForThread 
= TRUE
; 
 999         // ask the thread to terminate 
1002             wxCriticalSectionLocker 
lock(m_critsect
); 
1004             m_internal
->Cancel(); 
1008         // we can't just wait for the thread to terminate because it might be 
1009         // calling some GUI functions and so it will never terminate before we 
1010         // process the Windows messages that result from these functions 
1011         DWORD result 
= 0;       // suppress warnings from broken compilers 
1016                 // give the thread we're waiting for chance to do the GUI call 
1018                 if ( (gs_nWaitingForGui 
> 0) && wxGuiOwnedByMainThread() ) 
1024             result 
= ::MsgWaitForMultipleObjects
 
1026                        1,              // number of objects to wait for 
1027                        &hThread
,       // the objects 
1028                        FALSE
,          // don't wait for all objects 
1029                        INFINITE
,       // no timeout 
1030                        QS_ALLINPUT 
|   // return as soon as there are any events 
1038                     wxLogSysError(_("Can not wait for thread termination")); 
1040                     return wxTHREAD_KILLED
; 
1043                     // thread we're waiting for terminated 
1046                 case WAIT_OBJECT_0 
+ 1: 
1049                         // Check if a new message has really arrived. 
1050                         // MsgWaitForMultipleObjects can indicate that a message 
1051                         // is ready for processing, but this message may be sucked 
1052                         // up by GetMessage and then GetMessage will hang and not 
1053                         // allow us to process the actual thread exit event. 
1054                         if (::PeekMessage(&peekMsg
, (HWND
) NULL
, 0, 0, PM_NOREMOVE
)) 
1056                             // new message arrived, process it 
1057                             if ( !wxTheApp
->DoMessage() ) 
1059                                 // WM_QUIT received: kill the thread 
1062                                 return wxTHREAD_KILLED
; 
1069                     wxFAIL_MSG(wxT("unexpected result of MsgWaitForMultipleObject")); 
1071         } while ( result 
!= WAIT_OBJECT_0 
); 
1073         // simply wait for the thread to terminate 
1075         // OTOH, even console apps create windows (in wxExecute, for WinSock 
1076         // &c), so may be use MsgWaitForMultipleObject() too here? 
1077         if ( WaitForSingleObject(hThread
, INFINITE
) != WAIT_OBJECT_0 
) 
1079             wxFAIL_MSG(wxT("unexpected result of WaitForSingleObject")); 
1081 #endif // wxUSE_GUI/!wxUSE_GUI 
1085             gs_waitingForThread 
= FALSE
; 
1089     // although the thread might be already in the EXITED state it might not 
1090     // have terminated yet and so we are not sure that it has actually 
1091     // terminated if the "if" above hadn't been taken 
1094         if ( !::GetExitCodeThread(hThread
, (LPDWORD
)&rc
) ) 
1096             wxLogLastError(wxT("GetExitCodeThread")); 
1100     } while ( (DWORD
)rc 
== STILL_ACTIVE 
); 
1104         // if the thread exits normally, this is done in WinThreadStart, but in 
1105         // this case it would have been too early because 
1106         // MsgWaitForMultipleObject() would fail if the thread handle was 
1107         // closed while we were waiting on it, so we must do it here 
1114     return rc 
== (ExitCode
)-1 ? wxTHREAD_MISC_ERROR 
: wxTHREAD_NO_ERROR
; 
1117 wxThreadError 
wxThread::Kill() 
1120         return wxTHREAD_NOT_RUNNING
; 
1122     if ( !::TerminateThread(m_internal
->GetHandle(), (DWORD
)-1) ) 
1124         wxLogSysError(_("Couldn't terminate thread")); 
1126         return wxTHREAD_MISC_ERROR
; 
1136     return wxTHREAD_NO_ERROR
; 
1139 void wxThread::Exit(ExitCode status
) 
1148 #ifdef wxUSE_BEGIN_THREAD 
1149     _endthreadex((unsigned)status
); 
1151     ::ExitThread((DWORD
)status
); 
1152 #endif // VC++/!VC++ 
1154     wxFAIL_MSG(wxT("Couldn't return from ExitThread()!")); 
1160 void wxThread::SetPriority(unsigned int prio
) 
1162     wxCriticalSectionLocker 
lock(m_critsect
); 
1164     m_internal
->SetPriority(prio
); 
1167 unsigned int wxThread::GetPriority() const 
1169     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); // const_cast 
1171     return m_internal
->GetPriority(); 
1174 unsigned long wxThread::GetId() const 
1176     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); // const_cast 
1178     return (unsigned long)m_internal
->GetId(); 
1181 bool wxThread::IsRunning() const 
1183     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); // const_cast 
1185     return m_internal
->GetState() == STATE_RUNNING
; 
1188 bool wxThread::IsAlive() const 
1190     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); // const_cast 
1192     return (m_internal
->GetState() == STATE_RUNNING
) || 
1193            (m_internal
->GetState() == STATE_PAUSED
); 
1196 bool wxThread::IsPaused() const 
1198     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); // const_cast 
1200     return m_internal
->GetState() == STATE_PAUSED
; 
1203 bool wxThread::TestDestroy() 
1205     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); // const_cast 
1207     return m_internal
->GetState() == STATE_CANCELED
; 
1210 // ---------------------------------------------------------------------------- 
1211 // Automatic initialization for thread module 
1212 // ---------------------------------------------------------------------------- 
1214 class wxThreadModule 
: public wxModule
 
1217     virtual bool OnInit(); 
1218     virtual void OnExit(); 
1221     DECLARE_DYNAMIC_CLASS(wxThreadModule
) 
1224 IMPLEMENT_DYNAMIC_CLASS(wxThreadModule
, wxModule
) 
1226 bool wxThreadModule::OnInit() 
1228     // allocate TLS index for storing the pointer to the current thread 
1229     gs_tlsThisThread 
= ::TlsAlloc(); 
1230     if ( gs_tlsThisThread 
== 0xFFFFFFFF ) 
1232         // in normal circumstances it will only happen if all other 
1233         // TLS_MINIMUM_AVAILABLE (>= 64) indices are already taken - in other 
1234         // words, this should never happen 
1235         wxLogSysError(_("Thread module initialization failed: impossible to allocate index in thread local storage")); 
1240     // main thread doesn't have associated wxThread object, so store 0 in the 
1242     if ( !::TlsSetValue(gs_tlsThisThread
, (LPVOID
)0) ) 
1244         ::TlsFree(gs_tlsThisThread
); 
1245         gs_tlsThisThread 
= 0xFFFFFFFF; 
1247         wxLogSysError(_("Thread module initialization failed: can not store value in thread local storage")); 
1252     gs_critsectWaitingForGui 
= new wxCriticalSection(); 
1254     gs_critsectGui 
= new wxCriticalSection(); 
1255     gs_critsectGui
->Enter(); 
1257     // no error return for GetCurrentThreadId() 
1258     gs_idMainThread 
= ::GetCurrentThreadId(); 
1263 void wxThreadModule::OnExit() 
1265     if ( !::TlsFree(gs_tlsThisThread
) ) 
1267         wxLogLastError(wxT("TlsFree failed.")); 
1270     if ( gs_critsectGui 
) 
1272         gs_critsectGui
->Leave(); 
1273         delete gs_critsectGui
; 
1274         gs_critsectGui 
= NULL
; 
1277     delete gs_critsectWaitingForGui
; 
1278     gs_critsectWaitingForGui 
= NULL
; 
1281 // ---------------------------------------------------------------------------- 
1282 // under Windows, these functions are implemented using a critical section and 
1283 // not a mutex, so the names are a bit confusing 
1284 // ---------------------------------------------------------------------------- 
1286 void WXDLLEXPORT 
wxMutexGuiEnter() 
1288     // this would dead lock everything... 
1289     wxASSERT_MSG( !wxThread::IsMain(), 
1290                   wxT("main thread doesn't want to block in wxMutexGuiEnter()!") ); 
1292     // the order in which we enter the critical sections here is crucial!! 
1294     // set the flag telling to the main thread that we want to do some GUI 
1296         wxCriticalSectionLocker 
enter(*gs_critsectWaitingForGui
); 
1298         gs_nWaitingForGui
++; 
1301     wxWakeUpMainThread(); 
1303     // now we may block here because the main thread will soon let us in 
1304     // (during the next iteration of OnIdle()) 
1305     gs_critsectGui
->Enter(); 
1308 void WXDLLEXPORT 
wxMutexGuiLeave() 
1310     wxCriticalSectionLocker 
enter(*gs_critsectWaitingForGui
); 
1312     if ( wxThread::IsMain() ) 
1314         gs_bGuiOwnedByMainThread 
= FALSE
; 
1318         // decrement the number of threads waiting for GUI access now 
1319         wxASSERT_MSG( gs_nWaitingForGui 
> 0, 
1320                       wxT("calling wxMutexGuiLeave() without entering it first?") ); 
1322         gs_nWaitingForGui
--; 
1324         wxWakeUpMainThread(); 
1327     gs_critsectGui
->Leave(); 
1330 void WXDLLEXPORT 
wxMutexGuiLeaveOrEnter() 
1332     wxASSERT_MSG( wxThread::IsMain(), 
1333                   wxT("only main thread may call wxMutexGuiLeaveOrEnter()!") ); 
1335     wxCriticalSectionLocker 
enter(*gs_critsectWaitingForGui
); 
1337     if ( gs_nWaitingForGui 
== 0 ) 
1339         // no threads are waiting for GUI - so we may acquire the lock without 
1340         // any danger (but only if we don't already have it) 
1341         if ( !wxGuiOwnedByMainThread() ) 
1343             gs_critsectGui
->Enter(); 
1345             gs_bGuiOwnedByMainThread 
= TRUE
; 
1347         //else: already have it, nothing to do 
1351         // some threads are waiting, release the GUI lock if we have it 
1352         if ( wxGuiOwnedByMainThread() ) 
1356         //else: some other worker thread is doing GUI 
1360 bool WXDLLEXPORT 
wxGuiOwnedByMainThread() 
1362     return gs_bGuiOwnedByMainThread
; 
1365 // wake up the main thread if it's in ::GetMessage() 
1366 void WXDLLEXPORT 
wxWakeUpMainThread() 
1368     // sending any message would do - hopefully WM_NULL is harmless enough 
1369     if ( !::PostThreadMessage(gs_idMainThread
, WM_NULL
, 0, 0) ) 
1371         // should never happen 
1372         wxLogLastError(wxT("PostThreadMessage(WM_NULL)")); 
1376 bool WXDLLEXPORT 
wxIsWaitingForThread() 
1378     return gs_waitingForThread
; 
1381 // ---------------------------------------------------------------------------- 
1382 // include common implementation code 
1383 // ---------------------------------------------------------------------------- 
1385 #include "wx/thrimpl.cpp" 
1387 #endif // wxUSE_THREADS