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__) 
  31 #include "wx/apptrait.h" 
  32 #include "wx/scopeguard.h" 
  34 #include "wx/msw/private.h" 
  35 #include "wx/msw/missing.h" 
  36 #include "wx/msw/seh.h" 
  38 #include "wx/except.h" 
  39 #include "wx/module.h" 
  40 #include "wx/thread.h" 
  42 // must have this symbol defined to get _beginthread/_endthread declarations 
  47 #if defined(__BORLANDC__) 
  49         // I can't set -tWM in the IDE (anyone?) so have to do this 
  53     #if !defined(__MFC_COMPAT__) 
  54         // Needed to know about _beginthreadex etc.. 
  55         #define __MFC_COMPAT__ 
  59 // define wxUSE_BEGIN_THREAD if the compiler has _beginthreadex() function 
  60 // which should be used instead of Win32 ::CreateThread() if possible 
  61 #if defined(__VISUALC__) || \ 
  62     (defined(__BORLANDC__) && (__BORLANDC__ >= 0x500)) || \ 
  63     (defined(__GNUG__) && defined(__MSVCRT__)) || \ 
  64     defined(__WATCOMC__) || defined(__MWERKS__) 
  67     #undef wxUSE_BEGIN_THREAD 
  68     #define wxUSE_BEGIN_THREAD 
  73 #ifdef wxUSE_BEGIN_THREAD 
  74     // this is where _beginthreadex() is declared 
  77     // the return type of the thread function entry point 
  78     typedef unsigned THREAD_RETVAL
; 
  80     // the calling convention of the thread function entry point 
  81     #define THREAD_CALLCONV __stdcall 
  83     // the settings for CreateThread() 
  84     typedef DWORD THREAD_RETVAL
; 
  85     #define THREAD_CALLCONV WINAPI 
  88 // ---------------------------------------------------------------------------- 
  90 // ---------------------------------------------------------------------------- 
  92 // the possible states of the thread ("=>" shows all possible transitions from 
  96     STATE_NEW
,          // didn't start execution yet (=> RUNNING) 
  97     STATE_RUNNING
,      // thread is running (=> PAUSED, CANCELED) 
  98     STATE_PAUSED
,       // thread is temporarily suspended (=> RUNNING) 
  99     STATE_CANCELED
,     // thread should terminate a.s.a.p. (=> EXITED) 
 100     STATE_EXITED        
// thread is terminating 
 103 // ---------------------------------------------------------------------------- 
 104 // this module globals 
 105 // ---------------------------------------------------------------------------- 
 107 // TLS index of the slot where we store the pointer to the current thread 
 108 static DWORD gs_tlsThisThread 
= 0xFFFFFFFF; 
 110 // id of the main thread - the one which can call GUI functions without first 
 111 // calling wxMutexGuiEnter() 
 112 static DWORD gs_idMainThread 
= 0; 
 114 // if it's false, some secondary thread is holding the GUI lock 
 115 static bool gs_bGuiOwnedByMainThread 
= true; 
 117 // critical section which controls access to all GUI functions: any secondary 
 118 // thread (i.e. except the main one) must enter this crit section before doing 
 120 static wxCriticalSection 
*gs_critsectGui 
= NULL
; 
 122 // critical section which protects gs_nWaitingForGui variable 
 123 static wxCriticalSection 
*gs_critsectWaitingForGui 
= NULL
; 
 125 // critical section which serializes WinThreadStart() and WaitForTerminate() 
 126 // (this is a potential bottleneck, we use a single crit sect for all threads 
 127 // in the system, but normally time spent inside it should be quite short) 
 128 static wxCriticalSection 
*gs_critsectThreadDelete 
= NULL
; 
 130 // number of threads waiting for GUI in wxMutexGuiEnter() 
 131 static size_t gs_nWaitingForGui 
= 0; 
 133 // are we waiting for a thread termination? 
 134 static bool gs_waitingForThread 
= false; 
 136 // ============================================================================ 
 137 // Windows implementation of thread and related classes 
 138 // ============================================================================ 
 140 // ---------------------------------------------------------------------------- 
 142 // ---------------------------------------------------------------------------- 
 144 wxCriticalSection::wxCriticalSection() 
 146     wxCOMPILE_TIME_ASSERT( sizeof(CRITICAL_SECTION
) <= sizeof(wxCritSectBuffer
), 
 147                            wxCriticalSectionBufferTooSmall 
); 
 149     ::InitializeCriticalSection((CRITICAL_SECTION 
*)m_buffer
); 
 152 wxCriticalSection::~wxCriticalSection() 
 154     ::DeleteCriticalSection((CRITICAL_SECTION 
*)m_buffer
); 
 157 void wxCriticalSection::Enter() 
 159     ::EnterCriticalSection((CRITICAL_SECTION 
*)m_buffer
); 
 162 void wxCriticalSection::Leave() 
 164     ::LeaveCriticalSection((CRITICAL_SECTION 
*)m_buffer
); 
 167 // ---------------------------------------------------------------------------- 
 169 // ---------------------------------------------------------------------------- 
 171 class wxMutexInternal
 
 174     wxMutexInternal(wxMutexType mutexType
); 
 177     bool IsOk() const { return m_mutex 
!= NULL
; } 
 179     wxMutexError 
Lock() { return LockTimeout(INFINITE
); } 
 180     wxMutexError 
TryLock() { return LockTimeout(0); } 
 181     wxMutexError 
Unlock(); 
 184     wxMutexError 
LockTimeout(DWORD milliseconds
); 
 188     DECLARE_NO_COPY_CLASS(wxMutexInternal
) 
 191 // all mutexes are recursive under Win32 so we don't use mutexType 
 192 wxMutexInternal::wxMutexInternal(wxMutexType 
WXUNUSED(mutexType
)) 
 194     // create a nameless (hence intra process and always private) mutex 
 195     m_mutex 
= ::CreateMutex
 
 197                     NULL
,       // default secutiry attributes 
 198                     false,      // not initially locked 
 204         wxLogLastError(_T("CreateMutex()")); 
 208 wxMutexInternal::~wxMutexInternal() 
 212         if ( !::CloseHandle(m_mutex
) ) 
 214             wxLogLastError(_T("CloseHandle(mutex)")); 
 219 wxMutexError 
wxMutexInternal::LockTimeout(DWORD milliseconds
) 
 221     DWORD rc 
= ::WaitForSingleObject(m_mutex
, milliseconds
); 
 222     if ( rc 
== WAIT_ABANDONED 
) 
 224         // the previous caller died without releasing the mutex, but now we can 
 226         wxLogDebug(_T("WaitForSingleObject() returned WAIT_ABANDONED")); 
 228         // use 0 timeout, normally we should always get it 
 229         rc 
= ::WaitForSingleObject(m_mutex
, 0); 
 241         case WAIT_ABANDONED
:        // checked for above 
 243             wxFAIL_MSG(wxT("impossible return value in wxMutex::Lock")); 
 247             wxLogLastError(_T("WaitForSingleObject(mutex)")); 
 248             return wxMUTEX_MISC_ERROR
; 
 251     return wxMUTEX_NO_ERROR
; 
 254 wxMutexError 
wxMutexInternal::Unlock() 
 256     if ( !::ReleaseMutex(m_mutex
) ) 
 258         wxLogLastError(_T("ReleaseMutex()")); 
 260         return wxMUTEX_MISC_ERROR
; 
 263     return wxMUTEX_NO_ERROR
; 
 266 // -------------------------------------------------------------------------- 
 268 // -------------------------------------------------------------------------- 
 270 // a trivial wrapper around Win32 semaphore 
 271 class wxSemaphoreInternal
 
 274     wxSemaphoreInternal(int initialcount
, int maxcount
); 
 275     ~wxSemaphoreInternal(); 
 277     bool IsOk() const { return m_semaphore 
!= NULL
; } 
 279     wxSemaError 
Wait() { return WaitTimeout(INFINITE
); } 
 281     wxSemaError 
TryWait() 
 283         wxSemaError rc 
= WaitTimeout(0); 
 284         if ( rc 
== wxSEMA_TIMEOUT 
) 
 290     wxSemaError 
WaitTimeout(unsigned long milliseconds
); 
 297     DECLARE_NO_COPY_CLASS(wxSemaphoreInternal
) 
 300 wxSemaphoreInternal::wxSemaphoreInternal(int initialcount
, int maxcount
) 
 302 #if !defined(_WIN32_WCE) || (_WIN32_WCE >= 300) 
 305         // make it practically infinite 
 309     m_semaphore 
= ::CreateSemaphore
 
 311                         NULL
,           // default security attributes 
 319         wxLogLastError(_T("CreateSemaphore()")); 
 323 wxSemaphoreInternal::~wxSemaphoreInternal() 
 327         if ( !::CloseHandle(m_semaphore
) ) 
 329             wxLogLastError(_T("CloseHandle(semaphore)")); 
 334 wxSemaError 
wxSemaphoreInternal::WaitTimeout(unsigned long milliseconds
) 
 336     DWORD rc 
= ::WaitForSingleObject( m_semaphore
, milliseconds 
); 
 341            return wxSEMA_NO_ERROR
; 
 344            return wxSEMA_TIMEOUT
; 
 347             wxLogLastError(_T("WaitForSingleObject(semaphore)")); 
 350     return wxSEMA_MISC_ERROR
; 
 353 wxSemaError 
wxSemaphoreInternal::Post() 
 355 #if !defined(_WIN32_WCE) || (_WIN32_WCE >= 300) 
 356     if ( !::ReleaseSemaphore(m_semaphore
, 1, NULL 
/* ptr to previous count */) ) 
 359         wxLogLastError(_T("ReleaseSemaphore")); 
 361         return wxSEMA_MISC_ERROR
; 
 364     return wxSEMA_NO_ERROR
; 
 367 // ---------------------------------------------------------------------------- 
 368 // wxThread implementation 
 369 // ---------------------------------------------------------------------------- 
 371 // wxThreadInternal class 
 372 // ---------------------- 
 374 class wxThreadInternal
 
 377     wxThreadInternal(wxThread 
*thread
) 
 382         m_priority 
= WXTHREAD_DEFAULT_PRIORITY
; 
 395             if ( !::CloseHandle(m_hThread
) ) 
 397                 wxLogLastError(wxT("CloseHandle(thread)")); 
 404     // create a new (suspended) thread (for the given thread object) 
 405     bool Create(wxThread 
*thread
, unsigned int stackSize
); 
 407     // wait for the thread to terminate, either by itself, or by asking it 
 408     // (politely, this is not Kill()!) to do it 
 409     wxThreadError 
WaitForTerminate(wxCriticalSection
& cs
, 
 410                                    wxThread::ExitCode 
*pRc
, 
 411                                    wxThread 
*threadToDelete 
= NULL
); 
 413     // kill the thread unconditionally 
 414     wxThreadError 
Kill(); 
 416     // suspend/resume/terminate 
 419     void Cancel() { m_state 
= STATE_CANCELED
; } 
 422     void SetState(wxThreadState state
) { m_state 
= state
; } 
 423     wxThreadState 
GetState() const { return m_state
; } 
 426     void SetPriority(unsigned int priority
); 
 427     unsigned int GetPriority() const { return m_priority
; } 
 429     // thread handle and id 
 430     HANDLE 
GetHandle() const { return m_hThread
; } 
 431     DWORD  
GetId() const { return m_tid
; } 
 433     // the thread function forwarding to DoThreadStart 
 434     static THREAD_RETVAL THREAD_CALLCONV 
WinThreadStart(void *thread
); 
 436     // really start the thread (if it's not already dead) 
 437     static THREAD_RETVAL 
DoThreadStart(wxThread 
*thread
); 
 441         if ( m_thread
->IsDetached() ) 
 442             ::InterlockedIncrement(&m_nRef
); 
 447         if ( m_thread
->IsDetached() && !::InterlockedDecrement(&m_nRef
) ) 
 452     // the thread we're associated with 
 455     HANDLE        m_hThread
;    // handle of the thread 
 456     wxThreadState m_state
;      // state, see wxThreadState enum 
 457     unsigned int  m_priority
;   // thread priority in "wx" units 
 458     DWORD         m_tid
;        // thread id 
 460     // number of threads which need this thread to remain alive, when the count 
 461     // reaches 0 we kill the owning wxThread -- and die ourselves with it 
 464     DECLARE_NO_COPY_CLASS(wxThreadInternal
) 
 467 // small class which keeps a thread alive during its lifetime 
 468 class wxThreadKeepAlive
 
 471     wxThreadKeepAlive(wxThreadInternal
& thrImpl
) : m_thrImpl(thrImpl
) 
 472         { m_thrImpl
.KeepAlive(); } 
 474         { m_thrImpl
.LetDie(); } 
 477     wxThreadInternal
& m_thrImpl
; 
 480 THREAD_RETVAL 
wxThreadInternal::DoThreadStart(wxThread 
*thread
) 
 482     THREAD_RETVAL rc 
= (THREAD_RETVAL
)-1; 
 486         wxON_BLOCK_EXIT_OBJ0(*thread
, wxThread::OnExit
); 
 488         // store the thread object in the TLS 
 489         if ( !::TlsSetValue(gs_tlsThisThread
, thread
) ) 
 491             wxLogSysError(_("Can not start thread: error writing TLS.")); 
 493             return (THREAD_RETVAL
)-1; 
 496         rc 
= (THREAD_RETVAL
)thread
->Entry(); 
 498     wxCATCH_ALL( wxTheApp
->OnUnhandledException(); ) 
 503 THREAD_RETVAL THREAD_CALLCONV 
wxThreadInternal::WinThreadStart(void *param
) 
 505     THREAD_RETVAL rc 
= (THREAD_RETVAL
)-1; 
 507     wxThread 
* const thread 
= (wxThread 
*)param
; 
 509     // each thread has its own SEH translator so install our own a.s.a.p. 
 510     DisableAutomaticSETranslator(); 
 512     // first of all, check whether we hadn't been cancelled already and don't 
 513     // start the user code at all then 
 514     const bool hasExited 
= thread
->m_internal
->GetState() == STATE_EXITED
; 
 520             rc 
= DoThreadStart(thread
); 
 522         wxSEH_HANDLE((THREAD_RETVAL
)-1) 
 525     // save IsDetached because thread object can be deleted by joinable 
 526     // threads after state is changed to STATE_EXITED. 
 527     const bool isDetached 
= thread
->IsDetached(); 
 530         // enter m_critsect before changing the thread state 
 532         // NB: can't use wxCriticalSectionLocker here as we use SEH and it's 
 533         //     incompatible with C++ object dtors 
 534         thread
->m_critsect
.Enter(); 
 535         thread
->m_internal
->SetState(STATE_EXITED
); 
 536         thread
->m_critsect
.Leave(); 
 539     // the thread may delete itself now if it wants, we don't need it any more 
 541         thread
->m_internal
->LetDie(); 
 546 void wxThreadInternal::SetPriority(unsigned int priority
) 
 548     m_priority 
= priority
; 
 550     // translate wxWidgets priority to the Windows one 
 552     if (m_priority 
<= 20) 
 553         win_priority 
= THREAD_PRIORITY_LOWEST
; 
 554     else if (m_priority 
<= 40) 
 555         win_priority 
= THREAD_PRIORITY_BELOW_NORMAL
; 
 556     else if (m_priority 
<= 60) 
 557         win_priority 
= THREAD_PRIORITY_NORMAL
; 
 558     else if (m_priority 
<= 80) 
 559         win_priority 
= THREAD_PRIORITY_ABOVE_NORMAL
; 
 560     else if (m_priority 
<= 100) 
 561         win_priority 
= THREAD_PRIORITY_HIGHEST
; 
 564         wxFAIL_MSG(wxT("invalid value of thread priority parameter")); 
 565         win_priority 
= THREAD_PRIORITY_NORMAL
; 
 568     if ( !::SetThreadPriority(m_hThread
, win_priority
) ) 
 570         wxLogSysError(_("Can't set thread priority")); 
 574 bool wxThreadInternal::Create(wxThread 
*thread
, unsigned int stackSize
) 
 576     wxASSERT_MSG( m_state 
== STATE_NEW 
&& !m_hThread
, 
 577                     _T("Create()ing thread twice?") ); 
 579     // for compilers which have it, we should use C RTL function for thread 
 580     // creation instead of Win32 API one because otherwise we will have memory 
 581     // leaks if the thread uses C RTL (and most threads do) 
 582 #ifdef wxUSE_BEGIN_THREAD 
 584     // Watcom is reported to not like 0 stack size (which means "use default" 
 585     // for the other compilers and is also the default value for stackSize) 
 589 #endif // __WATCOMC__ 
 591     m_hThread 
= (HANDLE
)_beginthreadex
 
 593                           NULL
,                             // default security 
 595                           wxThreadInternal::WinThreadStart
, // entry point 
 598                           (unsigned int *)&m_tid
 
 600 #else // compiler doesn't have _beginthreadex 
 601     m_hThread 
= ::CreateThread
 
 603                     NULL
,                               // default security 
 604                     stackSize
,                          // stack size 
 605                     wxThreadInternal::WinThreadStart
,   // thread entry point 
 606                     (LPVOID
)thread
,                     // parameter 
 607                     CREATE_SUSPENDED
,                   // flags 
 608                     &m_tid                              
// [out] thread id 
 610 #endif // _beginthreadex/CreateThread 
 612     if ( m_hThread 
== NULL 
) 
 614         wxLogSysError(_("Can't create thread")); 
 619     if ( m_priority 
!= WXTHREAD_DEFAULT_PRIORITY 
) 
 621         SetPriority(m_priority
); 
 627 wxThreadError 
wxThreadInternal::Kill() 
 629     if ( !::TerminateThread(m_hThread
, (DWORD
)-1) ) 
 631         wxLogSysError(_("Couldn't terminate thread")); 
 633         return wxTHREAD_MISC_ERROR
; 
 638     return wxTHREAD_NO_ERROR
; 
 642 wxThreadInternal::WaitForTerminate(wxCriticalSection
& cs
, 
 643                                    wxThread::ExitCode 
*pRc
, 
 644                                    wxThread 
*threadToDelete
) 
 646     // prevent the thread C++ object from disappearing as long as we are using 
 648     wxThreadKeepAlive 
keepAlive(*this); 
 651     // we may either wait passively for the thread to terminate (when called 
 652     // from Wait()) or ask it to terminate (when called from Delete()) 
 653     bool shouldDelete 
= threadToDelete 
!= NULL
; 
 655     wxThread::ExitCode rc 
= 0; 
 657     // we might need to resume the thread if it's currently stopped 
 658     bool shouldResume 
= false; 
 660     // as Delete() (which calls us) is always safe to call we need to consider 
 661     // all possible states 
 663         wxCriticalSectionLocker 
lock(cs
); 
 665         if ( m_state 
== STATE_NEW 
) 
 669                 // WinThreadStart() will see it and terminate immediately, no 
 670                 // need to cancel the thread -- but we still need to resume it 
 672                 m_state 
= STATE_EXITED
; 
 674                 // we must call Resume() as the thread hasn't been initially 
 675                 // resumed yet (and as Resume() it knows about STATE_EXITED 
 676                 // special case, it won't touch it and WinThreadStart() will 
 677                 // just exit immediately) 
 679                 shouldDelete 
= false; 
 681             //else: shouldResume is correctly set to false here, wait until 
 682             //      someone else runs the thread and it finishes 
 684         else // running, paused, cancelled or even exited 
 686             shouldResume 
= m_state 
== STATE_PAUSED
; 
 690     // resume the thread if it is paused 
 694     // ask the thread to terminate 
 697         wxCriticalSectionLocker 
lock(cs
); 
 703     // now wait for thread to finish 
 704     if ( wxThread::IsMain() ) 
 706         // set flag for wxIsWaitingForThread() 
 707         gs_waitingForThread 
= true; 
 710     // we can't just wait for the thread to terminate because it might be 
 711     // calling some GUI functions and so it will never terminate before we 
 712     // process the Windows messages that result from these functions 
 713     // (note that even in console applications we might have to process 
 714     // messages if we use wxExecute() or timers or ...) 
 715     DWORD result 
wxDUMMY_INITIALIZE(0); 
 718         if ( wxThread::IsMain() ) 
 720             // give the thread we're waiting for chance to do the GUI call 
 722             if ( (gs_nWaitingForGui 
> 0) && wxGuiOwnedByMainThread() ) 
 728 #if !defined(QS_ALLPOSTMESSAGE) 
 729 #define QS_ALLPOSTMESSAGE 0 
 732         result 
= ::MsgWaitForMultipleObjects
 
 734                    1,              // number of objects to wait for 
 735                    &m_hThread
,     // the objects 
 736                    false,          // don't wait for all objects 
 737                    INFINITE
,       // no timeout 
 738                    QS_ALLINPUT
|QS_ALLPOSTMESSAGE   
// return as soon as there are any events 
 745                 wxLogSysError(_("Can not wait for thread termination")); 
 747                 return wxTHREAD_KILLED
; 
 750                 // thread we're waiting for terminated 
 753             case WAIT_OBJECT_0 
+ 1: 
 754                 // new message arrived, process it -- but only if we're the 
 755                 // main thread as we don't support processing messages in 
 758                 // NB: we still must include QS_ALLINPUT even when waiting 
 759                 //     in a secondary thread because if it had created some 
 760                 //     window somehow (possible not even using wxWidgets) 
 761                 //     the system might dead lock then 
 762                 if ( wxThread::IsMain() ) 
 764                     wxAppTraits 
*traits 
= wxTheApp 
? wxTheApp
->GetTraits() 
 767                     if ( traits 
&& !traits
->DoMessageFromThreadWait() ) 
 769                         // WM_QUIT received: kill the thread 
 772                         return wxTHREAD_KILLED
; 
 778                 wxFAIL_MSG(wxT("unexpected result of MsgWaitForMultipleObject")); 
 780     } while ( result 
!= WAIT_OBJECT_0 
); 
 782     if ( wxThread::IsMain() ) 
 784         gs_waitingForThread 
= false; 
 788     // although the thread might be already in the EXITED state it might not 
 789     // have terminated yet and so we are not sure that it has actually 
 790     // terminated if the "if" above hadn't been taken 
 793         if ( !::GetExitCodeThread(m_hThread
, (LPDWORD
)&rc
) ) 
 795             wxLogLastError(wxT("GetExitCodeThread")); 
 797             rc 
= (wxThread::ExitCode
)-1; 
 802         if ( (DWORD
)rc 
!= STILL_ACTIVE 
) 
 805         // give the other thread some time to terminate, otherwise we may be 
 813     // we don't need the thread handle any more in any case 
 817     return rc 
== (wxThread::ExitCode
)-1 ? wxTHREAD_MISC_ERROR
 
 821 bool wxThreadInternal::Suspend() 
 823     DWORD nSuspendCount 
= ::SuspendThread(m_hThread
); 
 824     if ( nSuspendCount 
== (DWORD
)-1 ) 
 826         wxLogSysError(_("Can not suspend thread %x"), m_hThread
); 
 831     m_state 
= STATE_PAUSED
; 
 836 bool wxThreadInternal::Resume() 
 838     DWORD nSuspendCount 
= ::ResumeThread(m_hThread
); 
 839     if ( nSuspendCount 
== (DWORD
)-1 ) 
 841         wxLogSysError(_("Can not resume thread %x"), m_hThread
); 
 846     // don't change the state from STATE_EXITED because it's special and means 
 847     // we are going to terminate without running any user code - if we did it, 
 848     // the code in WaitForTerminate() wouldn't work 
 849     if ( m_state 
!= STATE_EXITED 
) 
 851         m_state 
= STATE_RUNNING
; 
 860 wxThread 
*wxThread::This() 
 862     wxThread 
*thread 
= (wxThread 
*)::TlsGetValue(gs_tlsThisThread
); 
 864     // be careful, 0 may be a valid return value as well 
 865     if ( !thread 
&& (::GetLastError() != NO_ERROR
) ) 
 867         wxLogSysError(_("Couldn't get the current thread pointer")); 
 875 bool wxThread::IsMain() 
 877     return ::GetCurrentThreadId() == gs_idMainThread 
|| gs_idMainThread 
== 0; 
 880 void wxThread::Yield() 
 882     // 0 argument to Sleep() is special and means to just give away the rest of 
 887 void wxThread::Sleep(unsigned long milliseconds
) 
 889     ::Sleep(milliseconds
); 
 892 int wxThread::GetCPUCount() 
 897     return si
.dwNumberOfProcessors
; 
 900 unsigned long wxThread::GetCurrentId() 
 902     return (unsigned long)::GetCurrentThreadId(); 
 905 bool wxThread::SetConcurrency(size_t WXUNUSED_IN_WINCE(level
)) 
 910     wxASSERT_MSG( IsMain(), _T("should only be called from the main thread") ); 
 912     // ok only for the default one 
 916     // get system affinity mask first 
 917     HANDLE hProcess 
= ::GetCurrentProcess(); 
 918     DWORD_PTR dwProcMask
, dwSysMask
; 
 919     if ( ::GetProcessAffinityMask(hProcess
, &dwProcMask
, &dwSysMask
) == 0 ) 
 921         wxLogLastError(_T("GetProcessAffinityMask")); 
 926     // how many CPUs have we got? 
 927     if ( dwSysMask 
== 1 ) 
 929         // don't bother with all this complicated stuff - on a single 
 930         // processor system it doesn't make much sense anyhow 
 934     // calculate the process mask: it's a bit vector with one bit per 
 935     // processor; we want to schedule the process to run on first level 
 940         if ( dwSysMask 
& bit 
) 
 942             // ok, we can set this bit 
 945             // another process added 
 957     // could we set all bits? 
 960         wxLogDebug(_T("bad level %u in wxThread::SetConcurrency()"), level
); 
 965     // set it: we can't link to SetProcessAffinityMask() because it doesn't 
 966     // exist in Win9x, use RT binding instead 
 968     typedef BOOL (*SETPROCESSAFFINITYMASK
)(HANDLE
, DWORD
); 
 970     // can use static var because we're always in the main thread here 
 971     static SETPROCESSAFFINITYMASK pfnSetProcessAffinityMask 
= NULL
; 
 973     if ( !pfnSetProcessAffinityMask 
) 
 975         HMODULE hModKernel 
= ::LoadLibrary(_T("kernel32")); 
 978             pfnSetProcessAffinityMask 
= (SETPROCESSAFFINITYMASK
) 
 979                 ::GetProcAddress(hModKernel
, "SetProcessAffinityMask"); 
 982         // we've discovered a MT version of Win9x! 
 983         wxASSERT_MSG( pfnSetProcessAffinityMask
, 
 984                       _T("this system has several CPUs but no SetProcessAffinityMask function?") ); 
 987     if ( !pfnSetProcessAffinityMask 
) 
 989         // msg given above - do it only once 
 993     if ( pfnSetProcessAffinityMask(hProcess
, dwProcMask
) == 0 ) 
 995         wxLogLastError(_T("SetProcessAffinityMask")); 
1001 #endif // __WXWINCE__/!__WXWINCE__ 
1007 wxThread::wxThread(wxThreadKind kind
) 
1009     m_internal 
= new wxThreadInternal(this); 
1011     m_isDetached 
= kind 
== wxTHREAD_DETACHED
; 
1014 wxThread::~wxThread() 
1019 // create/start thread 
1020 // ------------------- 
1022 wxThreadError 
wxThread::Create(unsigned int stackSize
) 
1024     wxCriticalSectionLocker 
lock(m_critsect
); 
1026     if ( !m_internal
->Create(this, stackSize
) ) 
1027         return wxTHREAD_NO_RESOURCE
; 
1029     return wxTHREAD_NO_ERROR
; 
1032 wxThreadError 
wxThread::Run() 
1034     wxCriticalSectionLocker 
lock(m_critsect
); 
1036     if ( m_internal
->GetState() != STATE_NEW 
) 
1038         // actually, it may be almost any state at all, not only STATE_RUNNING 
1039         return wxTHREAD_RUNNING
; 
1042     // the thread has just been created and is still suspended - let it run 
1046 // suspend/resume thread 
1047 // --------------------- 
1049 wxThreadError 
wxThread::Pause() 
1051     wxCriticalSectionLocker 
lock(m_critsect
); 
1053     return m_internal
->Suspend() ? wxTHREAD_NO_ERROR 
: wxTHREAD_MISC_ERROR
; 
1056 wxThreadError 
wxThread::Resume() 
1058     wxCriticalSectionLocker 
lock(m_critsect
); 
1060     return m_internal
->Resume() ? wxTHREAD_NO_ERROR 
: wxTHREAD_MISC_ERROR
; 
1066 wxThread::ExitCode 
wxThread::Wait() 
1068     // although under Windows we can wait for any thread, it's an error to 
1069     // wait for a detached one in wxWin API 
1070     wxCHECK_MSG( !IsDetached(), (ExitCode
)-1, 
1071                  _T("wxThread::Wait(): can't wait for detached thread") ); 
1073     ExitCode rc 
= (ExitCode
)-1; 
1075     (void)m_internal
->WaitForTerminate(m_critsect
, &rc
); 
1080 wxThreadError 
wxThread::Delete(ExitCode 
*pRc
) 
1082     return m_internal
->WaitForTerminate(m_critsect
, pRc
, this); 
1085 wxThreadError 
wxThread::Kill() 
1088         return wxTHREAD_NOT_RUNNING
; 
1090     wxThreadError rc 
= m_internal
->Kill(); 
1098         // update the status of the joinable thread 
1099         wxCriticalSectionLocker 
lock(m_critsect
); 
1100         m_internal
->SetState(STATE_EXITED
); 
1106 void wxThread::Exit(ExitCode status
) 
1116         // update the status of the joinable thread 
1117         wxCriticalSectionLocker 
lock(m_critsect
); 
1118         m_internal
->SetState(STATE_EXITED
); 
1121 #ifdef wxUSE_BEGIN_THREAD 
1122     _endthreadex((unsigned)status
); 
1124     ::ExitThread((DWORD
)status
); 
1125 #endif // VC++/!VC++ 
1127     wxFAIL_MSG(wxT("Couldn't return from ExitThread()!")); 
1133 void wxThread::SetPriority(unsigned int prio
) 
1135     wxCriticalSectionLocker 
lock(m_critsect
); 
1137     m_internal
->SetPriority(prio
); 
1140 unsigned int wxThread::GetPriority() const 
1142     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); // const_cast 
1144     return m_internal
->GetPriority(); 
1147 unsigned long wxThread::GetId() const 
1149     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); // const_cast 
1151     return (unsigned long)m_internal
->GetId(); 
1154 bool wxThread::IsRunning() const 
1156     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); // const_cast 
1158     return m_internal
->GetState() == STATE_RUNNING
; 
1161 bool wxThread::IsAlive() const 
1163     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); // const_cast 
1165     return (m_internal
->GetState() == STATE_RUNNING
) || 
1166            (m_internal
->GetState() == STATE_PAUSED
); 
1169 bool wxThread::IsPaused() const 
1171     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); // const_cast 
1173     return m_internal
->GetState() == STATE_PAUSED
; 
1176 bool wxThread::TestDestroy() 
1178     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); // const_cast 
1180     return m_internal
->GetState() == STATE_CANCELED
; 
1183 // ---------------------------------------------------------------------------- 
1184 // Automatic initialization for thread module 
1185 // ---------------------------------------------------------------------------- 
1187 class wxThreadModule 
: public wxModule
 
1190     virtual bool OnInit(); 
1191     virtual void OnExit(); 
1194     DECLARE_DYNAMIC_CLASS(wxThreadModule
) 
1197 IMPLEMENT_DYNAMIC_CLASS(wxThreadModule
, wxModule
) 
1199 bool wxThreadModule::OnInit() 
1201     // allocate TLS index for storing the pointer to the current thread 
1202     gs_tlsThisThread 
= ::TlsAlloc(); 
1203     if ( gs_tlsThisThread 
== 0xFFFFFFFF ) 
1205         // in normal circumstances it will only happen if all other 
1206         // TLS_MINIMUM_AVAILABLE (>= 64) indices are already taken - in other 
1207         // words, this should never happen 
1208         wxLogSysError(_("Thread module initialization failed: impossible to allocate index in thread local storage")); 
1213     // main thread doesn't have associated wxThread object, so store 0 in the 
1215     if ( !::TlsSetValue(gs_tlsThisThread
, (LPVOID
)0) ) 
1217         ::TlsFree(gs_tlsThisThread
); 
1218         gs_tlsThisThread 
= 0xFFFFFFFF; 
1220         wxLogSysError(_("Thread module initialization failed: can not store value in thread local storage")); 
1225     gs_critsectWaitingForGui 
= new wxCriticalSection(); 
1227     gs_critsectGui 
= new wxCriticalSection(); 
1228     gs_critsectGui
->Enter(); 
1230     gs_critsectThreadDelete 
= new wxCriticalSection
; 
1232     // no error return for GetCurrentThreadId() 
1233     gs_idMainThread 
= ::GetCurrentThreadId(); 
1238 void wxThreadModule::OnExit() 
1240     if ( !::TlsFree(gs_tlsThisThread
) ) 
1242         wxLogLastError(wxT("TlsFree failed.")); 
1245     delete gs_critsectThreadDelete
; 
1246     gs_critsectThreadDelete 
= NULL
; 
1248     if ( gs_critsectGui 
) 
1250         gs_critsectGui
->Leave(); 
1251         delete gs_critsectGui
; 
1252         gs_critsectGui 
= NULL
; 
1255     delete gs_critsectWaitingForGui
; 
1256     gs_critsectWaitingForGui 
= NULL
; 
1259 // ---------------------------------------------------------------------------- 
1260 // under Windows, these functions are implemented using a critical section and 
1261 // not a mutex, so the names are a bit confusing 
1262 // ---------------------------------------------------------------------------- 
1264 void WXDLLIMPEXP_BASE 
wxMutexGuiEnter() 
1266     // this would dead lock everything... 
1267     wxASSERT_MSG( !wxThread::IsMain(), 
1268                   wxT("main thread doesn't want to block in wxMutexGuiEnter()!") ); 
1270     // the order in which we enter the critical sections here is crucial!! 
1272     // set the flag telling to the main thread that we want to do some GUI 
1274         wxCriticalSectionLocker 
enter(*gs_critsectWaitingForGui
); 
1276         gs_nWaitingForGui
++; 
1279     wxWakeUpMainThread(); 
1281     // now we may block here because the main thread will soon let us in 
1282     // (during the next iteration of OnIdle()) 
1283     gs_critsectGui
->Enter(); 
1286 void WXDLLIMPEXP_BASE 
wxMutexGuiLeave() 
1288     wxCriticalSectionLocker 
enter(*gs_critsectWaitingForGui
); 
1290     if ( wxThread::IsMain() ) 
1292         gs_bGuiOwnedByMainThread 
= false; 
1296         // decrement the number of threads waiting for GUI access now 
1297         wxASSERT_MSG( gs_nWaitingForGui 
> 0, 
1298                       wxT("calling wxMutexGuiLeave() without entering it first?") ); 
1300         gs_nWaitingForGui
--; 
1302         wxWakeUpMainThread(); 
1305     gs_critsectGui
->Leave(); 
1308 void WXDLLIMPEXP_BASE 
wxMutexGuiLeaveOrEnter() 
1310     wxASSERT_MSG( wxThread::IsMain(), 
1311                   wxT("only main thread may call wxMutexGuiLeaveOrEnter()!") ); 
1313     wxCriticalSectionLocker 
enter(*gs_critsectWaitingForGui
); 
1315     if ( gs_nWaitingForGui 
== 0 ) 
1317         // no threads are waiting for GUI - so we may acquire the lock without 
1318         // any danger (but only if we don't already have it) 
1319         if ( !wxGuiOwnedByMainThread() ) 
1321             gs_critsectGui
->Enter(); 
1323             gs_bGuiOwnedByMainThread 
= true; 
1325         //else: already have it, nothing to do 
1329         // some threads are waiting, release the GUI lock if we have it 
1330         if ( wxGuiOwnedByMainThread() ) 
1334         //else: some other worker thread is doing GUI 
1338 bool WXDLLIMPEXP_BASE 
wxGuiOwnedByMainThread() 
1340     return gs_bGuiOwnedByMainThread
; 
1343 // wake up the main thread if it's in ::GetMessage() 
1344 void WXDLLIMPEXP_BASE 
wxWakeUpMainThread() 
1346     // sending any message would do - hopefully WM_NULL is harmless enough 
1347     if ( !::PostThreadMessage(gs_idMainThread
, WM_NULL
, 0, 0) ) 
1349         // should never happen 
1350         wxLogLastError(wxT("PostThreadMessage(WM_NULL)")); 
1354 bool WXDLLIMPEXP_BASE 
wxIsWaitingForThread() 
1356     return gs_waitingForThread
; 
1359 // ---------------------------------------------------------------------------- 
1360 // include common implementation code 
1361 // ---------------------------------------------------------------------------- 
1363 #include "wx/thrimpl.cpp" 
1365 #endif // wxUSE_THREADS