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 ///////////////////////////////////////////////////////////////////////////// 
  13 // ---------------------------------------------------------------------------- 
  15 // ---------------------------------------------------------------------------- 
  17 // For compilers that support precompilation, includes "wx.h". 
  18 #include "wx/wxprec.h" 
  20 #if defined(__BORLANDC__) 
  26 #include "wx/thread.h" 
  33 #include "wx/apptrait.h" 
  34 #include "wx/scopeguard.h" 
  36 #include "wx/msw/private.h" 
  37 #include "wx/msw/missing.h" 
  38 #include "wx/msw/seh.h" 
  40 #include "wx/except.h" 
  41 #include "wx/module.h" 
  43 // must have this symbol defined to get _beginthread/_endthread declarations 
  48 #if defined(__BORLANDC__) 
  50         // I can't set -tWM in the IDE (anyone?) so have to do this 
  54     #if !defined(__MFC_COMPAT__) 
  55         // Needed to know about _beginthreadex etc.. 
  56         #define __MFC_COMPAT__ 
  60 // define wxUSE_BEGIN_THREAD if the compiler has _beginthreadex() function 
  61 // which should be used instead of Win32 ::CreateThread() if possible 
  62 #if defined(__VISUALC__) || \ 
  63     (defined(__BORLANDC__) && (__BORLANDC__ >= 0x500)) || \ 
  64     (defined(__GNUG__) && defined(__MSVCRT__)) || \ 
  65     defined(__WATCOMC__) || defined(__MWERKS__) 
  68     #undef wxUSE_BEGIN_THREAD 
  69     #define wxUSE_BEGIN_THREAD 
  74 #ifdef wxUSE_BEGIN_THREAD 
  75     // this is where _beginthreadex() is declared 
  78     // the return type of the thread function entry point 
  79     typedef unsigned THREAD_RETVAL
; 
  81     // the calling convention of the thread function entry point 
  82     #define THREAD_CALLCONV __stdcall 
  84     // the settings for CreateThread() 
  85     typedef DWORD THREAD_RETVAL
; 
  86     #define THREAD_CALLCONV WINAPI 
  89 // ---------------------------------------------------------------------------- 
  91 // ---------------------------------------------------------------------------- 
  93 // the possible states of the thread ("=>" shows all possible transitions from 
  97     STATE_NEW
,          // didn't start execution yet (=> RUNNING) 
  98     STATE_RUNNING
,      // thread is running (=> PAUSED, CANCELED) 
  99     STATE_PAUSED
,       // thread is temporarily suspended (=> RUNNING) 
 100     STATE_CANCELED
,     // thread should terminate a.s.a.p. (=> EXITED) 
 101     STATE_EXITED        
// thread is terminating 
 104 // ---------------------------------------------------------------------------- 
 105 // this module globals 
 106 // ---------------------------------------------------------------------------- 
 108 // TLS index of the slot where we store the pointer to the current thread 
 109 static DWORD gs_tlsThisThread 
= 0xFFFFFFFF; 
 111 // id of the main thread - the one which can call GUI functions without first 
 112 // calling wxMutexGuiEnter() 
 113 static DWORD gs_idMainThread 
= 0; 
 115 // if it's false, some secondary thread is holding the GUI lock 
 116 static bool gs_bGuiOwnedByMainThread 
= true; 
 118 // critical section which controls access to all GUI functions: any secondary 
 119 // thread (i.e. except the main one) must enter this crit section before doing 
 121 static wxCriticalSection 
*gs_critsectGui 
= NULL
; 
 123 // critical section which protects gs_nWaitingForGui variable 
 124 static wxCriticalSection 
*gs_critsectWaitingForGui 
= NULL
; 
 126 // critical section which serializes WinThreadStart() and WaitForTerminate() 
 127 // (this is a potential bottleneck, we use a single crit sect for all threads 
 128 // in the system, but normally time spent inside it should be quite short) 
 129 static wxCriticalSection 
*gs_critsectThreadDelete 
= NULL
; 
 131 // number of threads waiting for GUI in wxMutexGuiEnter() 
 132 static size_t gs_nWaitingForGui 
= 0; 
 134 // are we waiting for a thread termination? 
 135 static bool gs_waitingForThread 
= false; 
 137 // ============================================================================ 
 138 // Windows implementation of thread and related classes 
 139 // ============================================================================ 
 141 // ---------------------------------------------------------------------------- 
 143 // ---------------------------------------------------------------------------- 
 145 wxCriticalSection::wxCriticalSection() 
 147     wxCOMPILE_TIME_ASSERT( sizeof(CRITICAL_SECTION
) <= sizeof(wxCritSectBuffer
), 
 148                            wxCriticalSectionBufferTooSmall 
); 
 150     ::InitializeCriticalSection((CRITICAL_SECTION 
*)m_buffer
); 
 153 wxCriticalSection::~wxCriticalSection() 
 155     ::DeleteCriticalSection((CRITICAL_SECTION 
*)m_buffer
); 
 158 void wxCriticalSection::Enter() 
 160     ::EnterCriticalSection((CRITICAL_SECTION 
*)m_buffer
); 
 163 void wxCriticalSection::Leave() 
 165     ::LeaveCriticalSection((CRITICAL_SECTION 
*)m_buffer
); 
 168 // ---------------------------------------------------------------------------- 
 170 // ---------------------------------------------------------------------------- 
 172 class wxMutexInternal
 
 175     wxMutexInternal(wxMutexType mutexType
); 
 178     bool IsOk() const { return m_mutex 
!= NULL
; } 
 180     wxMutexError 
Lock() { return LockTimeout(INFINITE
); } 
 181     wxMutexError 
TryLock() { return LockTimeout(0); } 
 182     wxMutexError 
Unlock(); 
 185     wxMutexError 
LockTimeout(DWORD milliseconds
); 
 189     DECLARE_NO_COPY_CLASS(wxMutexInternal
) 
 192 // all mutexes are recursive under Win32 so we don't use mutexType 
 193 wxMutexInternal::wxMutexInternal(wxMutexType 
WXUNUSED(mutexType
)) 
 195     // create a nameless (hence intra process and always private) mutex 
 196     m_mutex 
= ::CreateMutex
 
 198                     NULL
,       // default secutiry attributes 
 199                     false,      // not initially locked 
 205         wxLogLastError(_T("CreateMutex()")); 
 209 wxMutexInternal::~wxMutexInternal() 
 213         if ( !::CloseHandle(m_mutex
) ) 
 215             wxLogLastError(_T("CloseHandle(mutex)")); 
 220 wxMutexError 
wxMutexInternal::LockTimeout(DWORD milliseconds
) 
 222     DWORD rc 
= ::WaitForSingleObject(m_mutex
, milliseconds
); 
 223     if ( rc 
== WAIT_ABANDONED 
) 
 225         // the previous caller died without releasing the mutex, but now we can 
 227         wxLogDebug(_T("WaitForSingleObject() returned WAIT_ABANDONED")); 
 229         // use 0 timeout, normally we should always get it 
 230         rc 
= ::WaitForSingleObject(m_mutex
, 0); 
 242         case WAIT_ABANDONED
:        // checked for above 
 244             wxFAIL_MSG(wxT("impossible return value in wxMutex::Lock")); 
 248             wxLogLastError(_T("WaitForSingleObject(mutex)")); 
 249             return wxMUTEX_MISC_ERROR
; 
 252     return wxMUTEX_NO_ERROR
; 
 255 wxMutexError 
wxMutexInternal::Unlock() 
 257     if ( !::ReleaseMutex(m_mutex
) ) 
 259         wxLogLastError(_T("ReleaseMutex()")); 
 261         return wxMUTEX_MISC_ERROR
; 
 264     return wxMUTEX_NO_ERROR
; 
 267 // -------------------------------------------------------------------------- 
 269 // -------------------------------------------------------------------------- 
 271 // a trivial wrapper around Win32 semaphore 
 272 class wxSemaphoreInternal
 
 275     wxSemaphoreInternal(int initialcount
, int maxcount
); 
 276     ~wxSemaphoreInternal(); 
 278     bool IsOk() const { return m_semaphore 
!= NULL
; } 
 280     wxSemaError 
Wait() { return WaitTimeout(INFINITE
); } 
 282     wxSemaError 
TryWait() 
 284         wxSemaError rc 
= WaitTimeout(0); 
 285         if ( rc 
== wxSEMA_TIMEOUT 
) 
 291     wxSemaError 
WaitTimeout(unsigned long milliseconds
); 
 298     DECLARE_NO_COPY_CLASS(wxSemaphoreInternal
) 
 301 wxSemaphoreInternal::wxSemaphoreInternal(int initialcount
, int maxcount
) 
 303 #if !defined(_WIN32_WCE) || (_WIN32_WCE >= 300) 
 306         // make it practically infinite 
 310     m_semaphore 
= ::CreateSemaphore
 
 312                         NULL
,           // default security attributes 
 320         wxLogLastError(_T("CreateSemaphore()")); 
 324 wxSemaphoreInternal::~wxSemaphoreInternal() 
 328         if ( !::CloseHandle(m_semaphore
) ) 
 330             wxLogLastError(_T("CloseHandle(semaphore)")); 
 335 wxSemaError 
wxSemaphoreInternal::WaitTimeout(unsigned long milliseconds
) 
 337     DWORD rc 
= ::WaitForSingleObject( m_semaphore
, milliseconds 
); 
 342            return wxSEMA_NO_ERROR
; 
 345            return wxSEMA_TIMEOUT
; 
 348             wxLogLastError(_T("WaitForSingleObject(semaphore)")); 
 351     return wxSEMA_MISC_ERROR
; 
 354 wxSemaError 
wxSemaphoreInternal::Post() 
 356 #if !defined(_WIN32_WCE) || (_WIN32_WCE >= 300) 
 357     if ( !::ReleaseSemaphore(m_semaphore
, 1, NULL 
/* ptr to previous count */) ) 
 360         wxLogLastError(_T("ReleaseSemaphore")); 
 362         return wxSEMA_MISC_ERROR
; 
 365     return wxSEMA_NO_ERROR
; 
 368 // ---------------------------------------------------------------------------- 
 369 // wxThread implementation 
 370 // ---------------------------------------------------------------------------- 
 372 // wxThreadInternal class 
 373 // ---------------------- 
 375 class wxThreadInternal
 
 378     wxThreadInternal(wxThread 
*thread
) 
 383         m_priority 
= WXTHREAD_DEFAULT_PRIORITY
; 
 396             if ( !::CloseHandle(m_hThread
) ) 
 398                 wxLogLastError(wxT("CloseHandle(thread)")); 
 405     // create a new (suspended) thread (for the given thread object) 
 406     bool Create(wxThread 
*thread
, unsigned int stackSize
); 
 408     // wait for the thread to terminate, either by itself, or by asking it 
 409     // (politely, this is not Kill()!) to do it 
 410     wxThreadError 
WaitForTerminate(wxCriticalSection
& cs
, 
 411                                    wxThread::ExitCode 
*pRc
, 
 412                                    wxThread 
*threadToDelete 
= NULL
); 
 414     // kill the thread unconditionally 
 415     wxThreadError 
Kill(); 
 417     // suspend/resume/terminate 
 420     void Cancel() { m_state 
= STATE_CANCELED
; } 
 423     void SetState(wxThreadState state
) { m_state 
= state
; } 
 424     wxThreadState 
GetState() const { return m_state
; } 
 427     void SetPriority(unsigned int priority
); 
 428     unsigned int GetPriority() const { return m_priority
; } 
 430     // thread handle and id 
 431     HANDLE 
GetHandle() const { return m_hThread
; } 
 432     DWORD  
GetId() const { return m_tid
; } 
 434     // the thread function forwarding to DoThreadStart 
 435     static THREAD_RETVAL THREAD_CALLCONV 
WinThreadStart(void *thread
); 
 437     // really start the thread (if it's not already dead) 
 438     static THREAD_RETVAL 
DoThreadStart(wxThread 
*thread
); 
 440     // call OnExit() on the thread 
 441     static void DoThreadOnExit(wxThread 
*thread
); 
 446         if ( m_thread
->IsDetached() ) 
 447             ::InterlockedIncrement(&m_nRef
); 
 452         if ( m_thread
->IsDetached() && !::InterlockedDecrement(&m_nRef
) ) 
 457     // the thread we're associated with 
 460     HANDLE        m_hThread
;    // handle of the thread 
 461     wxThreadState m_state
;      // state, see wxThreadState enum 
 462     unsigned int  m_priority
;   // thread priority in "wx" units 
 463     DWORD         m_tid
;        // thread id 
 465     // number of threads which need this thread to remain alive, when the count 
 466     // reaches 0 we kill the owning wxThread -- and die ourselves with it 
 469     DECLARE_NO_COPY_CLASS(wxThreadInternal
) 
 472 // small class which keeps a thread alive during its lifetime 
 473 class wxThreadKeepAlive
 
 476     wxThreadKeepAlive(wxThreadInternal
& thrImpl
) : m_thrImpl(thrImpl
) 
 477         { m_thrImpl
.KeepAlive(); } 
 479         { m_thrImpl
.LetDie(); } 
 482     wxThreadInternal
& m_thrImpl
; 
 486 void wxThreadInternal::DoThreadOnExit(wxThread 
*thread
) 
 492     wxCATCH_ALL( wxTheApp
->OnUnhandledException(); ) 
 496 THREAD_RETVAL 
wxThreadInternal::DoThreadStart(wxThread 
*thread
) 
 498     wxON_BLOCK_EXIT1(DoThreadOnExit
, thread
); 
 500     THREAD_RETVAL rc 
= (THREAD_RETVAL
)-1; 
 504         // store the thread object in the TLS 
 505         if ( !::TlsSetValue(gs_tlsThisThread
, thread
) ) 
 507             wxLogSysError(_("Can not start thread: error writing TLS.")); 
 509             return (THREAD_RETVAL
)-1; 
 512         rc 
= (THREAD_RETVAL
)thread
->Entry(); 
 514     wxCATCH_ALL( wxTheApp
->OnUnhandledException(); ) 
 520 THREAD_RETVAL THREAD_CALLCONV 
wxThreadInternal::WinThreadStart(void *param
) 
 522     THREAD_RETVAL rc 
= (THREAD_RETVAL
)-1; 
 524     wxThread 
* const thread 
= (wxThread 
*)param
; 
 526     // each thread has its own SEH translator so install our own a.s.a.p. 
 527     DisableAutomaticSETranslator(); 
 529     // first of all, check whether we hadn't been cancelled already and don't 
 530     // start the user code at all then 
 531     const bool hasExited 
= thread
->m_internal
->GetState() == STATE_EXITED
; 
 533     // run the thread function itself inside a SEH try/except block 
 537             DoThreadOnExit(thread
); 
 539             rc 
= DoThreadStart(thread
); 
 541     wxSEH_HANDLE((THREAD_RETVAL
)-1) 
 544     // save IsDetached because thread object can be deleted by joinable 
 545     // threads after state is changed to STATE_EXITED. 
 546     const bool isDetached 
= thread
->IsDetached(); 
 549         // enter m_critsect before changing the thread state 
 551         // NB: can't use wxCriticalSectionLocker here as we use SEH and it's 
 552         //     incompatible with C++ object dtors 
 553         thread
->m_critsect
.Enter(); 
 554         thread
->m_internal
->SetState(STATE_EXITED
); 
 555         thread
->m_critsect
.Leave(); 
 558     // the thread may delete itself now if it wants, we don't need it any more 
 560         thread
->m_internal
->LetDie(); 
 565 void wxThreadInternal::SetPriority(unsigned int priority
) 
 567     m_priority 
= priority
; 
 569     // translate wxWidgets priority to the Windows one 
 571     if (m_priority 
<= 20) 
 572         win_priority 
= THREAD_PRIORITY_LOWEST
; 
 573     else if (m_priority 
<= 40) 
 574         win_priority 
= THREAD_PRIORITY_BELOW_NORMAL
; 
 575     else if (m_priority 
<= 60) 
 576         win_priority 
= THREAD_PRIORITY_NORMAL
; 
 577     else if (m_priority 
<= 80) 
 578         win_priority 
= THREAD_PRIORITY_ABOVE_NORMAL
; 
 579     else if (m_priority 
<= 100) 
 580         win_priority 
= THREAD_PRIORITY_HIGHEST
; 
 583         wxFAIL_MSG(wxT("invalid value of thread priority parameter")); 
 584         win_priority 
= THREAD_PRIORITY_NORMAL
; 
 587     if ( !::SetThreadPriority(m_hThread
, win_priority
) ) 
 589         wxLogSysError(_("Can't set thread priority")); 
 593 bool wxThreadInternal::Create(wxThread 
*thread
, unsigned int stackSize
) 
 595     wxASSERT_MSG( m_state 
== STATE_NEW 
&& !m_hThread
, 
 596                     _T("Create()ing thread twice?") ); 
 598     // for compilers which have it, we should use C RTL function for thread 
 599     // creation instead of Win32 API one because otherwise we will have memory 
 600     // leaks if the thread uses C RTL (and most threads do) 
 601 #ifdef wxUSE_BEGIN_THREAD 
 603     // Watcom is reported to not like 0 stack size (which means "use default" 
 604     // for the other compilers and is also the default value for stackSize) 
 608 #endif // __WATCOMC__ 
 610     m_hThread 
= (HANDLE
)_beginthreadex
 
 612                           NULL
,                             // default security 
 614                           wxThreadInternal::WinThreadStart
, // entry point 
 617                           (unsigned int *)&m_tid
 
 619 #else // compiler doesn't have _beginthreadex 
 620     m_hThread 
= ::CreateThread
 
 622                     NULL
,                               // default security 
 623                     stackSize
,                          // stack size 
 624                     wxThreadInternal::WinThreadStart
,   // thread entry point 
 625                     (LPVOID
)thread
,                     // parameter 
 626                     CREATE_SUSPENDED
,                   // flags 
 627                     &m_tid                              
// [out] thread id 
 629 #endif // _beginthreadex/CreateThread 
 631     if ( m_hThread 
== NULL 
) 
 633         wxLogSysError(_("Can't create thread")); 
 638     if ( m_priority 
!= WXTHREAD_DEFAULT_PRIORITY 
) 
 640         SetPriority(m_priority
); 
 646 wxThreadError 
wxThreadInternal::Kill() 
 648     if ( !::TerminateThread(m_hThread
, (DWORD
)-1) ) 
 650         wxLogSysError(_("Couldn't terminate thread")); 
 652         return wxTHREAD_MISC_ERROR
; 
 657     return wxTHREAD_NO_ERROR
; 
 661 wxThreadInternal::WaitForTerminate(wxCriticalSection
& cs
, 
 662                                    wxThread::ExitCode 
*pRc
, 
 663                                    wxThread 
*threadToDelete
) 
 665     // prevent the thread C++ object from disappearing as long as we are using 
 667     wxThreadKeepAlive 
keepAlive(*this); 
 670     // we may either wait passively for the thread to terminate (when called 
 671     // from Wait()) or ask it to terminate (when called from Delete()) 
 672     bool shouldDelete 
= threadToDelete 
!= NULL
; 
 674     wxThread::ExitCode rc 
= 0; 
 676     // we might need to resume the thread if it's currently stopped 
 677     bool shouldResume 
= false; 
 679     // as Delete() (which calls us) is always safe to call we need to consider 
 680     // all possible states 
 682         wxCriticalSectionLocker 
lock(cs
); 
 684         if ( m_state 
== STATE_NEW 
) 
 688                 // WinThreadStart() will see it and terminate immediately, no 
 689                 // need to cancel the thread -- but we still need to resume it 
 691                 m_state 
= STATE_EXITED
; 
 693                 // we must call Resume() as the thread hasn't been initially 
 694                 // resumed yet (and as Resume() it knows about STATE_EXITED 
 695                 // special case, it won't touch it and WinThreadStart() will 
 696                 // just exit immediately) 
 698                 shouldDelete 
= false; 
 700             //else: shouldResume is correctly set to false here, wait until 
 701             //      someone else runs the thread and it finishes 
 703         else // running, paused, cancelled or even exited 
 705             shouldResume 
= m_state 
== STATE_PAUSED
; 
 709     // resume the thread if it is paused 
 713     // ask the thread to terminate 
 716         wxCriticalSectionLocker 
lock(cs
); 
 722     // now wait for thread to finish 
 723     if ( wxThread::IsMain() ) 
 725         // set flag for wxIsWaitingForThread() 
 726         gs_waitingForThread 
= true; 
 729     // we can't just wait for the thread to terminate because it might be 
 730     // calling some GUI functions and so it will never terminate before we 
 731     // process the Windows messages that result from these functions 
 732     // (note that even in console applications we might have to process 
 733     // messages if we use wxExecute() or timers or ...) 
 734     DWORD result 
wxDUMMY_INITIALIZE(0); 
 737         if ( wxThread::IsMain() ) 
 739             // give the thread we're waiting for chance to do the GUI call 
 741             if ( (gs_nWaitingForGui 
> 0) && wxGuiOwnedByMainThread() ) 
 747 #if !defined(QS_ALLPOSTMESSAGE) 
 748 #define QS_ALLPOSTMESSAGE 0 
 751         result 
= ::MsgWaitForMultipleObjects
 
 753                    1,              // number of objects to wait for 
 754                    &m_hThread
,     // the objects 
 755                    false,          // don't wait for all objects 
 756                    INFINITE
,       // no timeout 
 757                    QS_ALLINPUT
|QS_ALLPOSTMESSAGE   
// return as soon as there are any events 
 764                 wxLogSysError(_("Can not wait for thread termination")); 
 766                 return wxTHREAD_KILLED
; 
 769                 // thread we're waiting for terminated 
 772             case WAIT_OBJECT_0 
+ 1: 
 773                 // new message arrived, process it -- but only if we're the 
 774                 // main thread as we don't support processing messages in 
 777                 // NB: we still must include QS_ALLINPUT even when waiting 
 778                 //     in a secondary thread because if it had created some 
 779                 //     window somehow (possible not even using wxWidgets) 
 780                 //     the system might dead lock then 
 781                 if ( wxThread::IsMain() ) 
 783                     wxAppTraits 
*traits 
= wxTheApp 
? wxTheApp
->GetTraits() 
 786                     if ( traits 
&& !traits
->DoMessageFromThreadWait() ) 
 788                         // WM_QUIT received: kill the thread 
 791                         return wxTHREAD_KILLED
; 
 797                 wxFAIL_MSG(wxT("unexpected result of MsgWaitForMultipleObject")); 
 799     } while ( result 
!= WAIT_OBJECT_0 
); 
 801     if ( wxThread::IsMain() ) 
 803         gs_waitingForThread 
= false; 
 807     // although the thread might be already in the EXITED state it might not 
 808     // have terminated yet and so we are not sure that it has actually 
 809     // terminated if the "if" above hadn't been taken 
 812         if ( !::GetExitCodeThread(m_hThread
, (LPDWORD
)&rc
) ) 
 814             wxLogLastError(wxT("GetExitCodeThread")); 
 816             rc 
= (wxThread::ExitCode
)-1; 
 821         if ( (DWORD
)rc 
!= STILL_ACTIVE 
) 
 824         // give the other thread some time to terminate, otherwise we may be 
 832     // we don't need the thread handle any more in any case 
 836     return rc 
== (wxThread::ExitCode
)-1 ? wxTHREAD_MISC_ERROR
 
 840 bool wxThreadInternal::Suspend() 
 842     DWORD nSuspendCount 
= ::SuspendThread(m_hThread
); 
 843     if ( nSuspendCount 
== (DWORD
)-1 ) 
 845         wxLogSysError(_("Can not suspend thread %x"), m_hThread
); 
 850     m_state 
= STATE_PAUSED
; 
 855 bool wxThreadInternal::Resume() 
 857     DWORD nSuspendCount 
= ::ResumeThread(m_hThread
); 
 858     if ( nSuspendCount 
== (DWORD
)-1 ) 
 860         wxLogSysError(_("Can not resume thread %x"), m_hThread
); 
 865     // don't change the state from STATE_EXITED because it's special and means 
 866     // we are going to terminate without running any user code - if we did it, 
 867     // the code in WaitForTerminate() wouldn't work 
 868     if ( m_state 
!= STATE_EXITED 
) 
 870         m_state 
= STATE_RUNNING
; 
 879 wxThread 
*wxThread::This() 
 881     wxThread 
*thread 
= (wxThread 
*)::TlsGetValue(gs_tlsThisThread
); 
 883     // be careful, 0 may be a valid return value as well 
 884     if ( !thread 
&& (::GetLastError() != NO_ERROR
) ) 
 886         wxLogSysError(_("Couldn't get the current thread pointer")); 
 894 bool wxThread::IsMain() 
 896     return ::GetCurrentThreadId() == gs_idMainThread 
|| gs_idMainThread 
== 0; 
 899 void wxThread::Yield() 
 901     // 0 argument to Sleep() is special and means to just give away the rest of 
 906 void wxThread::Sleep(unsigned long milliseconds
) 
 908     ::Sleep(milliseconds
); 
 911 int wxThread::GetCPUCount() 
 916     return si
.dwNumberOfProcessors
; 
 919 unsigned long wxThread::GetCurrentId() 
 921     return (unsigned long)::GetCurrentThreadId(); 
 924 bool wxThread::SetConcurrency(size_t WXUNUSED_IN_WINCE(level
)) 
 929     wxASSERT_MSG( IsMain(), _T("should only be called from the main thread") ); 
 931     // ok only for the default one 
 935     // get system affinity mask first 
 936     HANDLE hProcess 
= ::GetCurrentProcess(); 
 937     DWORD_PTR dwProcMask
, dwSysMask
; 
 938     if ( ::GetProcessAffinityMask(hProcess
, &dwProcMask
, &dwSysMask
) == 0 ) 
 940         wxLogLastError(_T("GetProcessAffinityMask")); 
 945     // how many CPUs have we got? 
 946     if ( dwSysMask 
== 1 ) 
 948         // don't bother with all this complicated stuff - on a single 
 949         // processor system it doesn't make much sense anyhow 
 953     // calculate the process mask: it's a bit vector with one bit per 
 954     // processor; we want to schedule the process to run on first level 
 959         if ( dwSysMask 
& bit 
) 
 961             // ok, we can set this bit 
 964             // another process added 
 976     // could we set all bits? 
 979         wxLogDebug(_T("bad level %u in wxThread::SetConcurrency()"), level
); 
 984     // set it: we can't link to SetProcessAffinityMask() because it doesn't 
 985     // exist in Win9x, use RT binding instead 
 987     typedef BOOL (*SETPROCESSAFFINITYMASK
)(HANDLE
, DWORD
); 
 989     // can use static var because we're always in the main thread here 
 990     static SETPROCESSAFFINITYMASK pfnSetProcessAffinityMask 
= NULL
; 
 992     if ( !pfnSetProcessAffinityMask 
) 
 994         HMODULE hModKernel 
= ::LoadLibrary(_T("kernel32")); 
 997             pfnSetProcessAffinityMask 
= (SETPROCESSAFFINITYMASK
) 
 998                 ::GetProcAddress(hModKernel
, "SetProcessAffinityMask"); 
1001         // we've discovered a MT version of Win9x! 
1002         wxASSERT_MSG( pfnSetProcessAffinityMask
, 
1003                       _T("this system has several CPUs but no SetProcessAffinityMask function?") ); 
1006     if ( !pfnSetProcessAffinityMask 
) 
1008         // msg given above - do it only once 
1012     if ( pfnSetProcessAffinityMask(hProcess
, dwProcMask
) == 0 ) 
1014         wxLogLastError(_T("SetProcessAffinityMask")); 
1020 #endif // __WXWINCE__/!__WXWINCE__ 
1026 wxThread::wxThread(wxThreadKind kind
) 
1028     m_internal 
= new wxThreadInternal(this); 
1030     m_isDetached 
= kind 
== wxTHREAD_DETACHED
; 
1033 wxThread::~wxThread() 
1038 // create/start thread 
1039 // ------------------- 
1041 wxThreadError 
wxThread::Create(unsigned int stackSize
) 
1043     wxCriticalSectionLocker 
lock(m_critsect
); 
1045     if ( !m_internal
->Create(this, stackSize
) ) 
1046         return wxTHREAD_NO_RESOURCE
; 
1048     return wxTHREAD_NO_ERROR
; 
1051 wxThreadError 
wxThread::Run() 
1053     wxCriticalSectionLocker 
lock(m_critsect
); 
1055     if ( m_internal
->GetState() != STATE_NEW 
) 
1057         // actually, it may be almost any state at all, not only STATE_RUNNING 
1058         return wxTHREAD_RUNNING
; 
1061     // the thread has just been created and is still suspended - let it run 
1065 // suspend/resume thread 
1066 // --------------------- 
1068 wxThreadError 
wxThread::Pause() 
1070     wxCriticalSectionLocker 
lock(m_critsect
); 
1072     return m_internal
->Suspend() ? wxTHREAD_NO_ERROR 
: wxTHREAD_MISC_ERROR
; 
1075 wxThreadError 
wxThread::Resume() 
1077     wxCriticalSectionLocker 
lock(m_critsect
); 
1079     return m_internal
->Resume() ? wxTHREAD_NO_ERROR 
: wxTHREAD_MISC_ERROR
; 
1085 wxThread::ExitCode 
wxThread::Wait() 
1087     // although under Windows we can wait for any thread, it's an error to 
1088     // wait for a detached one in wxWin API 
1089     wxCHECK_MSG( !IsDetached(), (ExitCode
)-1, 
1090                  _T("wxThread::Wait(): can't wait for detached thread") ); 
1092     ExitCode rc 
= (ExitCode
)-1; 
1094     (void)m_internal
->WaitForTerminate(m_critsect
, &rc
); 
1099 wxThreadError 
wxThread::Delete(ExitCode 
*pRc
) 
1101     return m_internal
->WaitForTerminate(m_critsect
, pRc
, this); 
1104 wxThreadError 
wxThread::Kill() 
1107         return wxTHREAD_NOT_RUNNING
; 
1109     wxThreadError rc 
= m_internal
->Kill(); 
1117         // update the status of the joinable thread 
1118         wxCriticalSectionLocker 
lock(m_critsect
); 
1119         m_internal
->SetState(STATE_EXITED
); 
1125 void wxThread::Exit(ExitCode status
) 
1135         // update the status of the joinable thread 
1136         wxCriticalSectionLocker 
lock(m_critsect
); 
1137         m_internal
->SetState(STATE_EXITED
); 
1140 #ifdef wxUSE_BEGIN_THREAD 
1141     _endthreadex((unsigned)status
); 
1143     ::ExitThread((DWORD
)status
); 
1144 #endif // VC++/!VC++ 
1146     wxFAIL_MSG(wxT("Couldn't return from ExitThread()!")); 
1152 void wxThread::SetPriority(unsigned int prio
) 
1154     wxCriticalSectionLocker 
lock(m_critsect
); 
1156     m_internal
->SetPriority(prio
); 
1159 unsigned int wxThread::GetPriority() const 
1161     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); // const_cast 
1163     return m_internal
->GetPriority(); 
1166 unsigned long wxThread::GetId() const 
1168     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); // const_cast 
1170     return (unsigned long)m_internal
->GetId(); 
1173 bool wxThread::IsRunning() const 
1175     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); // const_cast 
1177     return m_internal
->GetState() == STATE_RUNNING
; 
1180 bool wxThread::IsAlive() const 
1182     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); // const_cast 
1184     return (m_internal
->GetState() == STATE_RUNNING
) || 
1185            (m_internal
->GetState() == STATE_PAUSED
); 
1188 bool wxThread::IsPaused() const 
1190     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); // const_cast 
1192     return m_internal
->GetState() == STATE_PAUSED
; 
1195 bool wxThread::TestDestroy() 
1197     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); // const_cast 
1199     return m_internal
->GetState() == STATE_CANCELED
; 
1202 // ---------------------------------------------------------------------------- 
1203 // Automatic initialization for thread module 
1204 // ---------------------------------------------------------------------------- 
1206 class wxThreadModule 
: public wxModule
 
1209     virtual bool OnInit(); 
1210     virtual void OnExit(); 
1213     DECLARE_DYNAMIC_CLASS(wxThreadModule
) 
1216 IMPLEMENT_DYNAMIC_CLASS(wxThreadModule
, wxModule
) 
1218 bool wxThreadModule::OnInit() 
1220     // allocate TLS index for storing the pointer to the current thread 
1221     gs_tlsThisThread 
= ::TlsAlloc(); 
1222     if ( gs_tlsThisThread 
== 0xFFFFFFFF ) 
1224         // in normal circumstances it will only happen if all other 
1225         // TLS_MINIMUM_AVAILABLE (>= 64) indices are already taken - in other 
1226         // words, this should never happen 
1227         wxLogSysError(_("Thread module initialization failed: impossible to allocate index in thread local storage")); 
1232     // main thread doesn't have associated wxThread object, so store 0 in the 
1234     if ( !::TlsSetValue(gs_tlsThisThread
, (LPVOID
)0) ) 
1236         ::TlsFree(gs_tlsThisThread
); 
1237         gs_tlsThisThread 
= 0xFFFFFFFF; 
1239         wxLogSysError(_("Thread module initialization failed: can not store value in thread local storage")); 
1244     gs_critsectWaitingForGui 
= new wxCriticalSection(); 
1246     gs_critsectGui 
= new wxCriticalSection(); 
1247     gs_critsectGui
->Enter(); 
1249     gs_critsectThreadDelete 
= new wxCriticalSection
; 
1251     // no error return for GetCurrentThreadId() 
1252     gs_idMainThread 
= ::GetCurrentThreadId(); 
1257 void wxThreadModule::OnExit() 
1259     if ( !::TlsFree(gs_tlsThisThread
) ) 
1261         wxLogLastError(wxT("TlsFree failed.")); 
1264     delete gs_critsectThreadDelete
; 
1265     gs_critsectThreadDelete 
= NULL
; 
1267     if ( gs_critsectGui 
) 
1269         gs_critsectGui
->Leave(); 
1270         delete gs_critsectGui
; 
1271         gs_critsectGui 
= NULL
; 
1274     delete gs_critsectWaitingForGui
; 
1275     gs_critsectWaitingForGui 
= NULL
; 
1278 // ---------------------------------------------------------------------------- 
1279 // under Windows, these functions are implemented using a critical section and 
1280 // not a mutex, so the names are a bit confusing 
1281 // ---------------------------------------------------------------------------- 
1283 void WXDLLIMPEXP_BASE 
wxMutexGuiEnter() 
1285     // this would dead lock everything... 
1286     wxASSERT_MSG( !wxThread::IsMain(), 
1287                   wxT("main thread doesn't want to block in wxMutexGuiEnter()!") ); 
1289     // the order in which we enter the critical sections here is crucial!! 
1291     // set the flag telling to the main thread that we want to do some GUI 
1293         wxCriticalSectionLocker 
enter(*gs_critsectWaitingForGui
); 
1295         gs_nWaitingForGui
++; 
1298     wxWakeUpMainThread(); 
1300     // now we may block here because the main thread will soon let us in 
1301     // (during the next iteration of OnIdle()) 
1302     gs_critsectGui
->Enter(); 
1305 void WXDLLIMPEXP_BASE 
wxMutexGuiLeave() 
1307     wxCriticalSectionLocker 
enter(*gs_critsectWaitingForGui
); 
1309     if ( wxThread::IsMain() ) 
1311         gs_bGuiOwnedByMainThread 
= false; 
1315         // decrement the number of threads waiting for GUI access now 
1316         wxASSERT_MSG( gs_nWaitingForGui 
> 0, 
1317                       wxT("calling wxMutexGuiLeave() without entering it first?") ); 
1319         gs_nWaitingForGui
--; 
1321         wxWakeUpMainThread(); 
1324     gs_critsectGui
->Leave(); 
1327 void WXDLLIMPEXP_BASE 
wxMutexGuiLeaveOrEnter() 
1329     wxASSERT_MSG( wxThread::IsMain(), 
1330                   wxT("only main thread may call wxMutexGuiLeaveOrEnter()!") ); 
1332     wxCriticalSectionLocker 
enter(*gs_critsectWaitingForGui
); 
1334     if ( gs_nWaitingForGui 
== 0 ) 
1336         // no threads are waiting for GUI - so we may acquire the lock without 
1337         // any danger (but only if we don't already have it) 
1338         if ( !wxGuiOwnedByMainThread() ) 
1340             gs_critsectGui
->Enter(); 
1342             gs_bGuiOwnedByMainThread 
= true; 
1344         //else: already have it, nothing to do 
1348         // some threads are waiting, release the GUI lock if we have it 
1349         if ( wxGuiOwnedByMainThread() ) 
1353         //else: some other worker thread is doing GUI 
1357 bool WXDLLIMPEXP_BASE 
wxGuiOwnedByMainThread() 
1359     return gs_bGuiOwnedByMainThread
; 
1362 // wake up the main thread if it's in ::GetMessage() 
1363 void WXDLLIMPEXP_BASE 
wxWakeUpMainThread() 
1365     // sending any message would do - hopefully WM_NULL is harmless enough 
1366     if ( !::PostThreadMessage(gs_idMainThread
, WM_NULL
, 0, 0) ) 
1368         // should never happen 
1369         wxLogLastError(wxT("PostThreadMessage(WM_NULL)")); 
1373 bool WXDLLIMPEXP_BASE 
wxIsWaitingForThread() 
1375     return gs_waitingForThread
; 
1378 // ---------------------------------------------------------------------------- 
1379 // include common implementation code 
1380 // ---------------------------------------------------------------------------- 
1382 #include "wx/thrimpl.cpp" 
1384 #endif // wxUSE_THREADS