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 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) 
  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__) 
  35 #include "wx/apptrait.h" 
  37 #include "wx/msw/private.h" 
  38 #include "wx/msw/missing.h" 
  40 #include "wx/module.h" 
  41 #include "wx/thread.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
; } 
 435     static THREAD_RETVAL THREAD_CALLCONV 
WinThreadStart(void *thread
); 
 439         if ( m_thread
->IsDetached() ) 
 440             ::InterlockedIncrement(&m_nRef
); 
 445         if ( m_thread
->IsDetached() && !::InterlockedDecrement(&m_nRef
) ) 
 450     // the thread we're associated with 
 453     HANDLE        m_hThread
;    // handle of the thread 
 454     wxThreadState m_state
;      // state, see wxThreadState enum 
 455     unsigned int  m_priority
;   // thread priority in "wx" units 
 456     DWORD         m_tid
;        // thread id 
 458     // number of threads which need this thread to remain alive, when the count 
 459     // reaches 0 we kill the owning wxThread -- and die ourselves with it 
 462     DECLARE_NO_COPY_CLASS(wxThreadInternal
) 
 465 // small class which keeps a thread alive during its lifetime 
 466 class wxThreadKeepAlive
 
 469     wxThreadKeepAlive(wxThreadInternal
& thrImpl
) : m_thrImpl(thrImpl
) 
 470         { m_thrImpl
.KeepAlive(); } 
 472         { m_thrImpl
.LetDie(); } 
 475     wxThreadInternal
& m_thrImpl
; 
 479 THREAD_RETVAL THREAD_CALLCONV 
wxThreadInternal::WinThreadStart(void *param
) 
 483     wxThread 
* const thread 
= (wxThread 
*)param
; 
 485     // first of all, check whether we hadn't been cancelled already and don't 
 486     // start the user code at all then 
 487     bool isExited 
= (thread
->m_internal
->GetState() == STATE_EXITED
); 
 491         rc 
= (THREAD_RETVAL
)-1; 
 493     else // do run thread 
 495         // store the thread object in the TLS 
 496         if ( !::TlsSetValue(gs_tlsThisThread
, thread
) ) 
 498             wxLogSysError(_("Can not start thread: error writing TLS.")); 
 503         rc 
= (THREAD_RETVAL
)thread
->Entry(); 
 508     // save IsDetached because thread object can be deleted by joinable 
 509     // threads after state is changed to STATE_EXITED. 
 510     bool isDetached 
= thread
->IsDetached(); 
 514         // enter m_critsect before changing the thread state 
 515         wxCriticalSectionLocker 
lock(thread
->m_critsect
); 
 516         thread
->m_internal
->SetState(STATE_EXITED
); 
 519     // the thread may delete itself now if it wants, we don't need it any more 
 520     if (isDetached
) thread
->m_internal
->LetDie(); 
 525 void wxThreadInternal::SetPriority(unsigned int priority
) 
 527     m_priority 
= priority
; 
 529     // translate wxWindows priority to the Windows one 
 531     if (m_priority 
<= 20) 
 532         win_priority 
= THREAD_PRIORITY_LOWEST
; 
 533     else if (m_priority 
<= 40) 
 534         win_priority 
= THREAD_PRIORITY_BELOW_NORMAL
; 
 535     else if (m_priority 
<= 60) 
 536         win_priority 
= THREAD_PRIORITY_NORMAL
; 
 537     else if (m_priority 
<= 80) 
 538         win_priority 
= THREAD_PRIORITY_ABOVE_NORMAL
; 
 539     else if (m_priority 
<= 100) 
 540         win_priority 
= THREAD_PRIORITY_HIGHEST
; 
 543         wxFAIL_MSG(wxT("invalid value of thread priority parameter")); 
 544         win_priority 
= THREAD_PRIORITY_NORMAL
; 
 547     if ( !::SetThreadPriority(m_hThread
, win_priority
) ) 
 549         wxLogSysError(_("Can't set thread priority")); 
 553 bool wxThreadInternal::Create(wxThread 
*thread
, unsigned int stackSize
) 
 555     wxASSERT_MSG( m_state 
== STATE_NEW 
&& !m_hThread
, 
 556                     _T("Create()ing thread twice?") ); 
 558     // for compilers which have it, we should use C RTL function for thread 
 559     // creation instead of Win32 API one because otherwise we will have memory 
 560     // leaks if the thread uses C RTL (and most threads do) 
 561 #ifdef wxUSE_BEGIN_THREAD 
 563     // Watcom is reported to not like 0 stack size (which means "use default" 
 564     // for the other compilers and is also the default value for stackSize) 
 568 #endif // __WATCOMC__ 
 570     m_hThread 
= (HANDLE
)_beginthreadex
 
 572                           NULL
,                             // default security 
 574                           wxThreadInternal::WinThreadStart
, // entry point 
 577                           (unsigned int *)&m_tid
 
 579 #else // compiler doesn't have _beginthreadex 
 580     m_hThread 
= ::CreateThread
 
 582                     NULL
,                               // default security 
 583                     stackSize
,                          // stack size 
 584                     wxThreadInternal::WinThreadStart
,   // thread entry point 
 585                     (LPVOID
)thread
,                     // parameter 
 586                     CREATE_SUSPENDED
,                   // flags 
 587                     &m_tid                              
// [out] thread id 
 589 #endif // _beginthreadex/CreateThread 
 591     if ( m_hThread 
== NULL 
) 
 593         wxLogSysError(_("Can't create thread")); 
 598     if ( m_priority 
!= WXTHREAD_DEFAULT_PRIORITY 
) 
 600         SetPriority(m_priority
); 
 606 wxThreadError 
wxThreadInternal::Kill() 
 608     if ( !::TerminateThread(m_hThread
, (DWORD
)-1) ) 
 610         wxLogSysError(_("Couldn't terminate thread")); 
 612         return wxTHREAD_MISC_ERROR
; 
 617     return wxTHREAD_NO_ERROR
; 
 621 wxThreadInternal::WaitForTerminate(wxCriticalSection
& cs
, 
 622                                    wxThread::ExitCode 
*pRc
, 
 623                                    wxThread 
*threadToDelete
) 
 625     // prevent the thread C++ object from disappearing as long as we are using 
 627     wxThreadKeepAlive 
keepAlive(*this); 
 630     // we may either wait passively for the thread to terminate (when called 
 631     // from Wait()) or ask it to terminate (when called from Delete()) 
 632     bool shouldDelete 
= threadToDelete 
!= NULL
; 
 634     wxThread::ExitCode rc 
= 0; 
 636     // Delete() is always safe to call, so consider all possible states 
 638     // we might need to resume the thread, but we might also not need to cancel 
 639     // it if it doesn't run yet 
 640     bool shouldResume 
= false, 
 643     // check if the thread already started to run 
 645         wxCriticalSectionLocker 
lock(cs
); 
 647         if ( m_state 
== STATE_NEW 
) 
 651                 // WinThreadStart() will see it and terminate immediately, no 
 652                 // need to cancel the thread -- but we still need to resume it 
 654                 m_state 
= STATE_EXITED
; 
 656                 Resume();   // it knows about STATE_EXITED special case 
 658                 shouldDelete 
= false; 
 663             // shouldResume is correctly set to false here 
 665         else if ( m_state 
== STATE_EXITED 
) 
 667             return wxTHREAD_NOT_RUNNING
; 
 669         else // running (but maybe paused or cancelled) 
 671             shouldResume 
= m_state 
== STATE_PAUSED
; 
 675     // resume the thread if it is paused 
 679     // is it still running? 
 680     if ( isRunning 
|| m_state 
== STATE_RUNNING 
) 
 682         if ( wxThread::IsMain() ) 
 684             // set flag for wxIsWaitingForThread() 
 685             gs_waitingForThread 
= true; 
 688         // ask the thread to terminate 
 691             wxCriticalSectionLocker 
lock(cs
); 
 696         // we can't just wait for the thread to terminate because it might be 
 697         // calling some GUI functions and so it will never terminate before we 
 698         // process the Windows messages that result from these functions 
 699         // (note that even in console applications we might have to process 
 700         // messages if we use wxExecute() or timers or ...) 
 701         DWORD result 
wxDUMMY_INITIALIZE(0); 
 704             if ( wxThread::IsMain() ) 
 706                 // give the thread we're waiting for chance to do the GUI call 
 708                 if ( (gs_nWaitingForGui 
> 0) && wxGuiOwnedByMainThread() ) 
 714             result 
= ::MsgWaitForMultipleObjects
 
 716                        1,              // number of objects to wait for 
 717                        &m_hThread
,     // the objects 
 718                        false,          // don't wait for all objects 
 719                        INFINITE
,       // no timeout 
 720                        QS_ALLINPUT 
|   // return as soon as there are any events 
 728                     wxLogSysError(_("Can not wait for thread termination")); 
 730                     return wxTHREAD_KILLED
; 
 733                     // thread we're waiting for terminated 
 736                 case WAIT_OBJECT_0 
+ 1: 
 737                     // new message arrived, process it -- but only if we're the 
 738                     // main thread as we don't support processing messages in 
 741                     // NB: we still must include QS_ALLINPUT even when waiting 
 742                     //     in a secondary thread because if it had created some 
 743                     //     window somehow (possible not even using wxWindows) 
 744                     //     the system might dead lock then 
 745                     if ( wxThread::IsMain() ) 
 747                         // it looks that sometimes WAIT_OBJECT_0 + 1 is 
 748                         // returned but there are no messages in the thread 
 749                         // queue -- prevent DoMessageFromThreadWait() from 
 750                         // blocking inside ::GetMessage() forever in this case 
 751                         ::PostMessage(NULL
, WM_NULL
, 0, 0); 
 753                         wxAppTraits 
*traits 
= wxTheApp 
? wxTheApp
->GetTraits() 
 756                         if ( traits 
&& !traits
->DoMessageFromThreadWait() ) 
 758                             // WM_QUIT received: kill the thread 
 761                             return wxTHREAD_KILLED
; 
 767                     wxFAIL_MSG(wxT("unexpected result of MsgWaitForMultipleObject")); 
 769         } while ( result 
!= WAIT_OBJECT_0 
); 
 771         if ( wxThread::IsMain() ) 
 773             gs_waitingForThread 
= false; 
 777     // although the thread might be already in the EXITED state it might not 
 778     // have terminated yet and so we are not sure that it has actually 
 779     // terminated if the "if" above hadn't been taken 
 782         if ( !::GetExitCodeThread(m_hThread
, (LPDWORD
)&rc
) ) 
 784             wxLogLastError(wxT("GetExitCodeThread")); 
 786             rc 
= (wxThread::ExitCode
)-1; 
 791         if ( (DWORD
)rc 
!= STILL_ACTIVE 
) 
 794         // give the other thread some time to terminate, otherwise we may be 
 802     // we don't need the thread handle any more in any case 
 806     return rc 
== (wxThread::ExitCode
)-1 ? wxTHREAD_MISC_ERROR
 
 810 bool wxThreadInternal::Suspend() 
 812     DWORD nSuspendCount 
= ::SuspendThread(m_hThread
); 
 813     if ( nSuspendCount 
== (DWORD
)-1 ) 
 815         wxLogSysError(_("Can not suspend thread %x"), m_hThread
); 
 820     m_state 
= STATE_PAUSED
; 
 825 bool wxThreadInternal::Resume() 
 827     DWORD nSuspendCount 
= ::ResumeThread(m_hThread
); 
 828     if ( nSuspendCount 
== (DWORD
)-1 ) 
 830         wxLogSysError(_("Can not resume thread %x"), m_hThread
); 
 835     // don't change the state from STATE_EXITED because it's special and means 
 836     // we are going to terminate without running any user code - if we did it, 
 837     // the codei n Delete() wouldn't work 
 838     if ( m_state 
!= STATE_EXITED 
) 
 840         m_state 
= STATE_RUNNING
; 
 849 wxThread 
*wxThread::This() 
 851     wxThread 
*thread 
= (wxThread 
*)::TlsGetValue(gs_tlsThisThread
); 
 853     // be careful, 0 may be a valid return value as well 
 854     if ( !thread 
&& (::GetLastError() != NO_ERROR
) ) 
 856         wxLogSysError(_("Couldn't get the current thread pointer")); 
 864 bool wxThread::IsMain() 
 866     return ::GetCurrentThreadId() == gs_idMainThread
; 
 869 void wxThread::Yield() 
 871     // 0 argument to Sleep() is special and means to just give away the rest of 
 876 void wxThread::Sleep(unsigned long milliseconds
) 
 878     ::Sleep(milliseconds
); 
 881 int wxThread::GetCPUCount() 
 886     return si
.dwNumberOfProcessors
; 
 889 unsigned long wxThread::GetCurrentId() 
 891     return (unsigned long)::GetCurrentThreadId(); 
 894 bool wxThread::SetConcurrency(size_t level
) 
 897     wxASSERT_MSG( IsMain(), _T("should only be called from the main thread") ); 
 899     // ok only for the default one 
 903     // get system affinity mask first 
 904     HANDLE hProcess 
= ::GetCurrentProcess(); 
 905     DWORD_PTR dwProcMask
, dwSysMask
; 
 906     if ( ::GetProcessAffinityMask(hProcess
, &dwProcMask
, &dwSysMask
) == 0 ) 
 908         wxLogLastError(_T("GetProcessAffinityMask")); 
 913     // how many CPUs have we got? 
 914     if ( dwSysMask 
== 1 ) 
 916         // don't bother with all this complicated stuff - on a single 
 917         // processor system it doesn't make much sense anyhow 
 921     // calculate the process mask: it's a bit vector with one bit per 
 922     // processor; we want to schedule the process to run on first level 
 927         if ( dwSysMask 
& bit 
) 
 929             // ok, we can set this bit 
 932             // another process added 
 944     // could we set all bits? 
 947         wxLogDebug(_T("bad level %u in wxThread::SetConcurrency()"), level
); 
 952     // set it: we can't link to SetProcessAffinityMask() because it doesn't 
 953     // exist in Win9x, use RT binding instead 
 955     typedef BOOL (*SETPROCESSAFFINITYMASK
)(HANDLE
, DWORD
); 
 957     // can use static var because we're always in the main thread here 
 958     static SETPROCESSAFFINITYMASK pfnSetProcessAffinityMask 
= NULL
; 
 960     if ( !pfnSetProcessAffinityMask 
) 
 962         HMODULE hModKernel 
= ::LoadLibrary(_T("kernel32")); 
 965             pfnSetProcessAffinityMask 
= (SETPROCESSAFFINITYMASK
) 
 966                 ::GetProcAddress(hModKernel
, "SetProcessAffinityMask"); 
 969         // we've discovered a MT version of Win9x! 
 970         wxASSERT_MSG( pfnSetProcessAffinityMask
, 
 971                       _T("this system has several CPUs but no SetProcessAffinityMask function?") ); 
 974     if ( !pfnSetProcessAffinityMask 
) 
 976         // msg given above - do it only once 
 980     if ( pfnSetProcessAffinityMask(hProcess
, dwProcMask
) == 0 ) 
 982         wxLogLastError(_T("SetProcessAffinityMask")); 
 986 #endif // !__WXWINCE__ 
 994 wxThread::wxThread(wxThreadKind kind
) 
 996     m_internal 
= new wxThreadInternal(this); 
 998     m_isDetached 
= kind 
== wxTHREAD_DETACHED
; 
1001 wxThread::~wxThread() 
1006 // create/start thread 
1007 // ------------------- 
1009 wxThreadError 
wxThread::Create(unsigned int stackSize
) 
1011     wxCriticalSectionLocker 
lock(m_critsect
); 
1013     if ( !m_internal
->Create(this, stackSize
) ) 
1014         return wxTHREAD_NO_RESOURCE
; 
1016     return wxTHREAD_NO_ERROR
; 
1019 wxThreadError 
wxThread::Run() 
1021     wxCriticalSectionLocker 
lock(m_critsect
); 
1023     if ( m_internal
->GetState() != STATE_NEW 
) 
1025         // actually, it may be almost any state at all, not only STATE_RUNNING 
1026         return wxTHREAD_RUNNING
; 
1029     // the thread has just been created and is still suspended - let it run 
1033 // suspend/resume thread 
1034 // --------------------- 
1036 wxThreadError 
wxThread::Pause() 
1038     wxCriticalSectionLocker 
lock(m_critsect
); 
1040     return m_internal
->Suspend() ? wxTHREAD_NO_ERROR 
: wxTHREAD_MISC_ERROR
; 
1043 wxThreadError 
wxThread::Resume() 
1045     wxCriticalSectionLocker 
lock(m_critsect
); 
1047     return m_internal
->Resume() ? wxTHREAD_NO_ERROR 
: wxTHREAD_MISC_ERROR
; 
1053 wxThread::ExitCode 
wxThread::Wait() 
1055     // although under Windows we can wait for any thread, it's an error to 
1056     // wait for a detached one in wxWin API 
1057     wxCHECK_MSG( !IsDetached(), (ExitCode
)-1, 
1058                  _T("wxThread::Wait(): can't wait for detached thread") ); 
1060     ExitCode rc 
= (ExitCode
)-1; 
1062     (void)m_internal
->WaitForTerminate(m_critsect
, &rc
); 
1067 wxThreadError 
wxThread::Delete(ExitCode 
*pRc
) 
1069     return m_internal
->WaitForTerminate(m_critsect
, pRc
, this); 
1072 wxThreadError 
wxThread::Kill() 
1075         return wxTHREAD_NOT_RUNNING
; 
1077     wxThreadError rc 
= m_internal
->Kill(); 
1085         // update the status of the joinable thread 
1086         wxCriticalSectionLocker 
lock(m_critsect
); 
1087         m_internal
->SetState(STATE_EXITED
); 
1093 void wxThread::Exit(ExitCode status
) 
1103         // update the status of the joinable thread 
1104         wxCriticalSectionLocker 
lock(m_critsect
); 
1105         m_internal
->SetState(STATE_EXITED
); 
1108 #ifdef wxUSE_BEGIN_THREAD 
1109     _endthreadex((unsigned)status
); 
1111     ::ExitThread((DWORD
)status
); 
1112 #endif // VC++/!VC++ 
1114     wxFAIL_MSG(wxT("Couldn't return from ExitThread()!")); 
1120 void wxThread::SetPriority(unsigned int prio
) 
1122     wxCriticalSectionLocker 
lock(m_critsect
); 
1124     m_internal
->SetPriority(prio
); 
1127 unsigned int wxThread::GetPriority() const 
1129     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); // const_cast 
1131     return m_internal
->GetPriority(); 
1134 unsigned long wxThread::GetId() const 
1136     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); // const_cast 
1138     return (unsigned long)m_internal
->GetId(); 
1141 bool wxThread::IsRunning() const 
1143     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); // const_cast 
1145     return m_internal
->GetState() == STATE_RUNNING
; 
1148 bool wxThread::IsAlive() const 
1150     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); // const_cast 
1152     return (m_internal
->GetState() == STATE_RUNNING
) || 
1153            (m_internal
->GetState() == STATE_PAUSED
); 
1156 bool wxThread::IsPaused() const 
1158     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); // const_cast 
1160     return m_internal
->GetState() == STATE_PAUSED
; 
1163 bool wxThread::TestDestroy() 
1165     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); // const_cast 
1167     return m_internal
->GetState() == STATE_CANCELED
; 
1170 // ---------------------------------------------------------------------------- 
1171 // Automatic initialization for thread module 
1172 // ---------------------------------------------------------------------------- 
1174 class wxThreadModule 
: public wxModule
 
1177     virtual bool OnInit(); 
1178     virtual void OnExit(); 
1181     DECLARE_DYNAMIC_CLASS(wxThreadModule
) 
1184 IMPLEMENT_DYNAMIC_CLASS(wxThreadModule
, wxModule
) 
1186 bool wxThreadModule::OnInit() 
1188     // allocate TLS index for storing the pointer to the current thread 
1189     gs_tlsThisThread 
= ::TlsAlloc(); 
1190     if ( gs_tlsThisThread 
== 0xFFFFFFFF ) 
1192         // in normal circumstances it will only happen if all other 
1193         // TLS_MINIMUM_AVAILABLE (>= 64) indices are already taken - in other 
1194         // words, this should never happen 
1195         wxLogSysError(_("Thread module initialization failed: impossible to allocate index in thread local storage")); 
1200     // main thread doesn't have associated wxThread object, so store 0 in the 
1202     if ( !::TlsSetValue(gs_tlsThisThread
, (LPVOID
)0) ) 
1204         ::TlsFree(gs_tlsThisThread
); 
1205         gs_tlsThisThread 
= 0xFFFFFFFF; 
1207         wxLogSysError(_("Thread module initialization failed: can not store value in thread local storage")); 
1212     gs_critsectWaitingForGui 
= new wxCriticalSection(); 
1214     gs_critsectGui 
= new wxCriticalSection(); 
1215     gs_critsectGui
->Enter(); 
1217     gs_critsectThreadDelete 
= new wxCriticalSection
; 
1219     // no error return for GetCurrentThreadId() 
1220     gs_idMainThread 
= ::GetCurrentThreadId(); 
1225 void wxThreadModule::OnExit() 
1227     if ( !::TlsFree(gs_tlsThisThread
) ) 
1229         wxLogLastError(wxT("TlsFree failed.")); 
1232     delete gs_critsectThreadDelete
; 
1233     gs_critsectThreadDelete 
= NULL
; 
1235     if ( gs_critsectGui 
) 
1237         gs_critsectGui
->Leave(); 
1238         delete gs_critsectGui
; 
1239         gs_critsectGui 
= NULL
; 
1242     delete gs_critsectWaitingForGui
; 
1243     gs_critsectWaitingForGui 
= NULL
; 
1246 // ---------------------------------------------------------------------------- 
1247 // under Windows, these functions are implemented using a critical section and 
1248 // not a mutex, so the names are a bit confusing 
1249 // ---------------------------------------------------------------------------- 
1251 void WXDLLIMPEXP_BASE 
wxMutexGuiEnter() 
1253     // this would dead lock everything... 
1254     wxASSERT_MSG( !wxThread::IsMain(), 
1255                   wxT("main thread doesn't want to block in wxMutexGuiEnter()!") ); 
1257     // the order in which we enter the critical sections here is crucial!! 
1259     // set the flag telling to the main thread that we want to do some GUI 
1261         wxCriticalSectionLocker 
enter(*gs_critsectWaitingForGui
); 
1263         gs_nWaitingForGui
++; 
1266     wxWakeUpMainThread(); 
1268     // now we may block here because the main thread will soon let us in 
1269     // (during the next iteration of OnIdle()) 
1270     gs_critsectGui
->Enter(); 
1273 void WXDLLIMPEXP_BASE 
wxMutexGuiLeave() 
1275     wxCriticalSectionLocker 
enter(*gs_critsectWaitingForGui
); 
1277     if ( wxThread::IsMain() ) 
1279         gs_bGuiOwnedByMainThread 
= false; 
1283         // decrement the number of threads waiting for GUI access now 
1284         wxASSERT_MSG( gs_nWaitingForGui 
> 0, 
1285                       wxT("calling wxMutexGuiLeave() without entering it first?") ); 
1287         gs_nWaitingForGui
--; 
1289         wxWakeUpMainThread(); 
1292     gs_critsectGui
->Leave(); 
1295 void WXDLLIMPEXP_BASE 
wxMutexGuiLeaveOrEnter() 
1297     wxASSERT_MSG( wxThread::IsMain(), 
1298                   wxT("only main thread may call wxMutexGuiLeaveOrEnter()!") ); 
1300     wxCriticalSectionLocker 
enter(*gs_critsectWaitingForGui
); 
1302     if ( gs_nWaitingForGui 
== 0 ) 
1304         // no threads are waiting for GUI - so we may acquire the lock without 
1305         // any danger (but only if we don't already have it) 
1306         if ( !wxGuiOwnedByMainThread() ) 
1308             gs_critsectGui
->Enter(); 
1310             gs_bGuiOwnedByMainThread 
= true; 
1312         //else: already have it, nothing to do 
1316         // some threads are waiting, release the GUI lock if we have it 
1317         if ( wxGuiOwnedByMainThread() ) 
1321         //else: some other worker thread is doing GUI 
1325 bool WXDLLIMPEXP_BASE 
wxGuiOwnedByMainThread() 
1327     return gs_bGuiOwnedByMainThread
; 
1330 // wake up the main thread if it's in ::GetMessage() 
1331 void WXDLLIMPEXP_BASE 
wxWakeUpMainThread() 
1333     // sending any message would do - hopefully WM_NULL is harmless enough 
1334     if ( !::PostThreadMessage(gs_idMainThread
, WM_NULL
, 0, 0) ) 
1336         // should never happen 
1337         wxLogLastError(wxT("PostThreadMessage(WM_NULL)")); 
1341 bool WXDLLIMPEXP_BASE 
wxIsWaitingForThread() 
1343     return gs_waitingForThread
; 
1346 // ---------------------------------------------------------------------------- 
1347 // include common implementation code 
1348 // ---------------------------------------------------------------------------- 
1350 #include "wx/thrimpl.cpp" 
1352 #endif // wxUSE_THREADS