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" 
  29     #include "wx/msw/missing.h" 
  32     #include "wx/module.h" 
  35 #include "wx/apptrait.h" 
  36 #include "wx/scopeguard.h" 
  38 #include "wx/msw/private.h" 
  39 #include "wx/msw/seh.h" 
  41 #include "wx/except.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 */) ) 
 359         if ( GetLastError() == ERROR_TOO_MANY_POSTS 
) 
 361             return wxSEMA_OVERFLOW
; 
 365             wxLogLastError(_T("ReleaseSemaphore")); 
 366             return wxSEMA_MISC_ERROR
; 
 370     return wxSEMA_NO_ERROR
; 
 372     return wxSEMA_MISC_ERROR
; 
 376 // ---------------------------------------------------------------------------- 
 377 // wxThread implementation 
 378 // ---------------------------------------------------------------------------- 
 380 // wxThreadInternal class 
 381 // ---------------------- 
 383 class wxThreadInternal
 
 386     wxThreadInternal(wxThread 
*thread
) 
 391         m_priority 
= WXTHREAD_DEFAULT_PRIORITY
; 
 404             if ( !::CloseHandle(m_hThread
) ) 
 406                 wxLogLastError(wxT("CloseHandle(thread)")); 
 413     // create a new (suspended) thread (for the given thread object) 
 414     bool Create(wxThread 
*thread
, unsigned int stackSize
); 
 416     // wait for the thread to terminate, either by itself, or by asking it 
 417     // (politely, this is not Kill()!) to do it 
 418     wxThreadError 
WaitForTerminate(wxCriticalSection
& cs
, 
 419                                    wxThread::ExitCode 
*pRc
, 
 420                                    wxThread 
*threadToDelete 
= NULL
); 
 422     // kill the thread unconditionally 
 423     wxThreadError 
Kill(); 
 425     // suspend/resume/terminate 
 428     void Cancel() { m_state 
= STATE_CANCELED
; } 
 431     void SetState(wxThreadState state
) { m_state 
= state
; } 
 432     wxThreadState 
GetState() const { return m_state
; } 
 435     void SetPriority(unsigned int priority
); 
 436     unsigned int GetPriority() const { return m_priority
; } 
 438     // thread handle and id 
 439     HANDLE 
GetHandle() const { return m_hThread
; } 
 440     DWORD  
GetId() const { return m_tid
; } 
 442     // the thread function forwarding to DoThreadStart 
 443     static THREAD_RETVAL THREAD_CALLCONV 
WinThreadStart(void *thread
); 
 445     // really start the thread (if it's not already dead) 
 446     static THREAD_RETVAL 
DoThreadStart(wxThread 
*thread
); 
 448     // call OnExit() on the thread 
 449     static void DoThreadOnExit(wxThread 
*thread
); 
 454         if ( m_thread
->IsDetached() ) 
 455             ::InterlockedIncrement(&m_nRef
); 
 460         if ( m_thread
->IsDetached() && !::InterlockedDecrement(&m_nRef
) ) 
 465     // the thread we're associated with 
 468     HANDLE        m_hThread
;    // handle of the thread 
 469     wxThreadState m_state
;      // state, see wxThreadState enum 
 470     unsigned int  m_priority
;   // thread priority in "wx" units 
 471     DWORD         m_tid
;        // thread id 
 473     // number of threads which need this thread to remain alive, when the count 
 474     // reaches 0 we kill the owning wxThread -- and die ourselves with it 
 477     DECLARE_NO_COPY_CLASS(wxThreadInternal
) 
 480 // small class which keeps a thread alive during its lifetime 
 481 class wxThreadKeepAlive
 
 484     wxThreadKeepAlive(wxThreadInternal
& thrImpl
) : m_thrImpl(thrImpl
) 
 485         { m_thrImpl
.KeepAlive(); } 
 487         { m_thrImpl
.LetDie(); } 
 490     wxThreadInternal
& m_thrImpl
; 
 494 void wxThreadInternal::DoThreadOnExit(wxThread 
*thread
) 
 500     wxCATCH_ALL( wxTheApp
->OnUnhandledException(); ) 
 504 THREAD_RETVAL 
wxThreadInternal::DoThreadStart(wxThread 
*thread
) 
 506     wxON_BLOCK_EXIT1(DoThreadOnExit
, thread
); 
 508     THREAD_RETVAL rc 
= (THREAD_RETVAL
)-1; 
 512         // store the thread object in the TLS 
 513         if ( !::TlsSetValue(gs_tlsThisThread
, thread
) ) 
 515             wxLogSysError(_("Can not start thread: error writing TLS.")); 
 517             return (THREAD_RETVAL
)-1; 
 520         rc 
= (THREAD_RETVAL
)thread
->Entry(); 
 522     wxCATCH_ALL( wxTheApp
->OnUnhandledException(); ) 
 528 THREAD_RETVAL THREAD_CALLCONV 
wxThreadInternal::WinThreadStart(void *param
) 
 530     THREAD_RETVAL rc 
= (THREAD_RETVAL
)-1; 
 532     wxThread 
* const thread 
= (wxThread 
*)param
; 
 534     // each thread has its own SEH translator so install our own a.s.a.p. 
 535     DisableAutomaticSETranslator(); 
 537     // first of all, check whether we hadn't been cancelled already and don't 
 538     // start the user code at all then 
 539     const bool hasExited 
= thread
->m_internal
->GetState() == STATE_EXITED
; 
 541     // run the thread function itself inside a SEH try/except block 
 545             DoThreadOnExit(thread
); 
 547             rc 
= DoThreadStart(thread
); 
 549     wxSEH_HANDLE((THREAD_RETVAL
)-1) 
 552     // save IsDetached because thread object can be deleted by joinable 
 553     // threads after state is changed to STATE_EXITED. 
 554     const bool isDetached 
= thread
->IsDetached(); 
 557         // enter m_critsect before changing the thread state 
 559         // NB: can't use wxCriticalSectionLocker here as we use SEH and it's 
 560         //     incompatible with C++ object dtors 
 561         thread
->m_critsect
.Enter(); 
 562         thread
->m_internal
->SetState(STATE_EXITED
); 
 563         thread
->m_critsect
.Leave(); 
 566     // the thread may delete itself now if it wants, we don't need it any more 
 568         thread
->m_internal
->LetDie(); 
 573 void wxThreadInternal::SetPriority(unsigned int priority
) 
 575     m_priority 
= priority
; 
 577     // translate wxWidgets priority to the Windows one 
 579     if (m_priority 
<= 20) 
 580         win_priority 
= THREAD_PRIORITY_LOWEST
; 
 581     else if (m_priority 
<= 40) 
 582         win_priority 
= THREAD_PRIORITY_BELOW_NORMAL
; 
 583     else if (m_priority 
<= 60) 
 584         win_priority 
= THREAD_PRIORITY_NORMAL
; 
 585     else if (m_priority 
<= 80) 
 586         win_priority 
= THREAD_PRIORITY_ABOVE_NORMAL
; 
 587     else if (m_priority 
<= 100) 
 588         win_priority 
= THREAD_PRIORITY_HIGHEST
; 
 591         wxFAIL_MSG(wxT("invalid value of thread priority parameter")); 
 592         win_priority 
= THREAD_PRIORITY_NORMAL
; 
 595     if ( !::SetThreadPriority(m_hThread
, win_priority
) ) 
 597         wxLogSysError(_("Can't set thread priority")); 
 601 bool wxThreadInternal::Create(wxThread 
*thread
, unsigned int stackSize
) 
 603     wxASSERT_MSG( m_state 
== STATE_NEW 
&& !m_hThread
, 
 604                     _T("Create()ing thread twice?") ); 
 606     // for compilers which have it, we should use C RTL function for thread 
 607     // creation instead of Win32 API one because otherwise we will have memory 
 608     // leaks if the thread uses C RTL (and most threads do) 
 609 #ifdef wxUSE_BEGIN_THREAD 
 611     // Watcom is reported to not like 0 stack size (which means "use default" 
 612     // for the other compilers and is also the default value for stackSize) 
 616 #endif // __WATCOMC__ 
 618     m_hThread 
= (HANDLE
)_beginthreadex
 
 620                           NULL
,                             // default security 
 622                           wxThreadInternal::WinThreadStart
, // entry point 
 625                           (unsigned int *)&m_tid
 
 627 #else // compiler doesn't have _beginthreadex 
 628     m_hThread 
= ::CreateThread
 
 630                     NULL
,                               // default security 
 631                     stackSize
,                          // stack size 
 632                     wxThreadInternal::WinThreadStart
,   // thread entry point 
 633                     (LPVOID
)thread
,                     // parameter 
 634                     CREATE_SUSPENDED
,                   // flags 
 635                     &m_tid                              
// [out] thread id 
 637 #endif // _beginthreadex/CreateThread 
 639     if ( m_hThread 
== NULL 
) 
 641         wxLogSysError(_("Can't create thread")); 
 646     if ( m_priority 
!= WXTHREAD_DEFAULT_PRIORITY 
) 
 648         SetPriority(m_priority
); 
 654 wxThreadError 
wxThreadInternal::Kill() 
 656     if ( !::TerminateThread(m_hThread
, (DWORD
)-1) ) 
 658         wxLogSysError(_("Couldn't terminate thread")); 
 660         return wxTHREAD_MISC_ERROR
; 
 665     return wxTHREAD_NO_ERROR
; 
 669 wxThreadInternal::WaitForTerminate(wxCriticalSection
& cs
, 
 670                                    wxThread::ExitCode 
*pRc
, 
 671                                    wxThread 
*threadToDelete
) 
 673     // prevent the thread C++ object from disappearing as long as we are using 
 675     wxThreadKeepAlive 
keepAlive(*this); 
 678     // we may either wait passively for the thread to terminate (when called 
 679     // from Wait()) or ask it to terminate (when called from Delete()) 
 680     bool shouldDelete 
= threadToDelete 
!= NULL
; 
 682     wxThread::ExitCode rc 
= 0; 
 684     // we might need to resume the thread if it's currently stopped 
 685     bool shouldResume 
= false; 
 687     // as Delete() (which calls us) is always safe to call we need to consider 
 688     // all possible states 
 690         wxCriticalSectionLocker 
lock(cs
); 
 692         if ( m_state 
== STATE_NEW 
) 
 696                 // WinThreadStart() will see it and terminate immediately, no 
 697                 // need to cancel the thread -- but we still need to resume it 
 699                 m_state 
= STATE_EXITED
; 
 701                 // we must call Resume() as the thread hasn't been initially 
 702                 // resumed yet (and as Resume() it knows about STATE_EXITED 
 703                 // special case, it won't touch it and WinThreadStart() will 
 704                 // just exit immediately) 
 706                 shouldDelete 
= false; 
 708             //else: shouldResume is correctly set to false here, wait until 
 709             //      someone else runs the thread and it finishes 
 711         else // running, paused, cancelled or even exited 
 713             shouldResume 
= m_state 
== STATE_PAUSED
; 
 717     // resume the thread if it is paused 
 721     // ask the thread to terminate 
 724         wxCriticalSectionLocker 
lock(cs
); 
 730     // now wait for thread to finish 
 731     if ( wxThread::IsMain() ) 
 733         // set flag for wxIsWaitingForThread() 
 734         gs_waitingForThread 
= true; 
 737     // we can't just wait for the thread to terminate because it might be 
 738     // calling some GUI functions and so it will never terminate before we 
 739     // process the Windows messages that result from these functions 
 740     // (note that even in console applications we might have to process 
 741     // messages if we use wxExecute() or timers or ...) 
 742     DWORD result 
wxDUMMY_INITIALIZE(0); 
 745         if ( wxThread::IsMain() ) 
 747             // give the thread we're waiting for chance to do the GUI call 
 749             if ( (gs_nWaitingForGui 
> 0) && wxGuiOwnedByMainThread() ) 
 755 #if !defined(QS_ALLPOSTMESSAGE) 
 756 #define QS_ALLPOSTMESSAGE 0 
 759         result 
= ::MsgWaitForMultipleObjects
 
 761                    1,              // number of objects to wait for 
 762                    &m_hThread
,     // the objects 
 763                    false,          // don't wait for all objects 
 764                    INFINITE
,       // no timeout 
 765                    QS_ALLINPUT
|QS_ALLPOSTMESSAGE   
// return as soon as there are any events 
 772                 wxLogSysError(_("Can not wait for thread termination")); 
 774                 return wxTHREAD_KILLED
; 
 777                 // thread we're waiting for terminated 
 780             case WAIT_OBJECT_0 
+ 1: 
 781                 // new message arrived, process it -- but only if we're the 
 782                 // main thread as we don't support processing messages in 
 785                 // NB: we still must include QS_ALLINPUT even when waiting 
 786                 //     in a secondary thread because if it had created some 
 787                 //     window somehow (possible not even using wxWidgets) 
 788                 //     the system might dead lock then 
 789                 if ( wxThread::IsMain() ) 
 791                     wxAppTraits 
*traits 
= wxTheApp 
? wxTheApp
->GetTraits() 
 794                     if ( traits 
&& !traits
->DoMessageFromThreadWait() ) 
 796                         // WM_QUIT received: kill the thread 
 799                         return wxTHREAD_KILLED
; 
 805                 wxFAIL_MSG(wxT("unexpected result of MsgWaitForMultipleObject")); 
 807     } while ( result 
!= WAIT_OBJECT_0 
); 
 809     if ( wxThread::IsMain() ) 
 811         gs_waitingForThread 
= false; 
 815     // although the thread might be already in the EXITED state it might not 
 816     // have terminated yet and so we are not sure that it has actually 
 817     // terminated if the "if" above hadn't been taken 
 820         if ( !::GetExitCodeThread(m_hThread
, (LPDWORD
)&rc
) ) 
 822             wxLogLastError(wxT("GetExitCodeThread")); 
 824             rc 
= (wxThread::ExitCode
)-1; 
 829         if ( (DWORD
)rc 
!= STILL_ACTIVE 
) 
 832         // give the other thread some time to terminate, otherwise we may be 
 840     // we don't need the thread handle any more in any case 
 844     return rc 
== (wxThread::ExitCode
)-1 ? wxTHREAD_MISC_ERROR
 
 848 bool wxThreadInternal::Suspend() 
 850     DWORD nSuspendCount 
= ::SuspendThread(m_hThread
); 
 851     if ( nSuspendCount 
== (DWORD
)-1 ) 
 853         wxLogSysError(_("Can not suspend thread %x"), m_hThread
); 
 858     m_state 
= STATE_PAUSED
; 
 863 bool wxThreadInternal::Resume() 
 865     DWORD nSuspendCount 
= ::ResumeThread(m_hThread
); 
 866     if ( nSuspendCount 
== (DWORD
)-1 ) 
 868         wxLogSysError(_("Can not resume thread %x"), m_hThread
); 
 873     // don't change the state from STATE_EXITED because it's special and means 
 874     // we are going to terminate without running any user code - if we did it, 
 875     // the code in WaitForTerminate() wouldn't work 
 876     if ( m_state 
!= STATE_EXITED 
) 
 878         m_state 
= STATE_RUNNING
; 
 887 wxThread 
*wxThread::This() 
 889     wxThread 
*thread 
= (wxThread 
*)::TlsGetValue(gs_tlsThisThread
); 
 891     // be careful, 0 may be a valid return value as well 
 892     if ( !thread 
&& (::GetLastError() != NO_ERROR
) ) 
 894         wxLogSysError(_("Couldn't get the current thread pointer")); 
 902 bool wxThread::IsMain() 
 904     return ::GetCurrentThreadId() == gs_idMainThread 
|| gs_idMainThread 
== 0; 
 907 void wxThread::Yield() 
 909     // 0 argument to Sleep() is special and means to just give away the rest of 
 914 void wxThread::Sleep(unsigned long milliseconds
) 
 916     ::Sleep(milliseconds
); 
 919 int wxThread::GetCPUCount() 
 924     return si
.dwNumberOfProcessors
; 
 927 unsigned long wxThread::GetCurrentId() 
 929     return (unsigned long)::GetCurrentThreadId(); 
 932 bool wxThread::SetConcurrency(size_t WXUNUSED_IN_WINCE(level
)) 
 937     wxASSERT_MSG( IsMain(), _T("should only be called from the main thread") ); 
 939     // ok only for the default one 
 943     // get system affinity mask first 
 944     HANDLE hProcess 
= ::GetCurrentProcess(); 
 945     DWORD_PTR dwProcMask
, dwSysMask
; 
 946     if ( ::GetProcessAffinityMask(hProcess
, &dwProcMask
, &dwSysMask
) == 0 ) 
 948         wxLogLastError(_T("GetProcessAffinityMask")); 
 953     // how many CPUs have we got? 
 954     if ( dwSysMask 
== 1 ) 
 956         // don't bother with all this complicated stuff - on a single 
 957         // processor system it doesn't make much sense anyhow 
 961     // calculate the process mask: it's a bit vector with one bit per 
 962     // processor; we want to schedule the process to run on first level 
 967         if ( dwSysMask 
& bit 
) 
 969             // ok, we can set this bit 
 972             // another process added 
 984     // could we set all bits? 
 987         wxLogDebug(_T("bad level %u in wxThread::SetConcurrency()"), level
); 
 992     // set it: we can't link to SetProcessAffinityMask() because it doesn't 
 993     // exist in Win9x, use RT binding instead 
 995     typedef BOOL (*SETPROCESSAFFINITYMASK
)(HANDLE
, DWORD
); 
 997     // can use static var because we're always in the main thread here 
 998     static SETPROCESSAFFINITYMASK pfnSetProcessAffinityMask 
= NULL
; 
1000     if ( !pfnSetProcessAffinityMask 
) 
1002         HMODULE hModKernel 
= ::LoadLibrary(_T("kernel32")); 
1005             pfnSetProcessAffinityMask 
= (SETPROCESSAFFINITYMASK
) 
1006                 ::GetProcAddress(hModKernel
, "SetProcessAffinityMask"); 
1009         // we've discovered a MT version of Win9x! 
1010         wxASSERT_MSG( pfnSetProcessAffinityMask
, 
1011                       _T("this system has several CPUs but no SetProcessAffinityMask function?") ); 
1014     if ( !pfnSetProcessAffinityMask 
) 
1016         // msg given above - do it only once 
1020     if ( pfnSetProcessAffinityMask(hProcess
, dwProcMask
) == 0 ) 
1022         wxLogLastError(_T("SetProcessAffinityMask")); 
1028 #endif // __WXWINCE__/!__WXWINCE__ 
1034 wxThread::wxThread(wxThreadKind kind
) 
1036     m_internal 
= new wxThreadInternal(this); 
1038     m_isDetached 
= kind 
== wxTHREAD_DETACHED
; 
1041 wxThread::~wxThread() 
1046 // create/start thread 
1047 // ------------------- 
1049 wxThreadError 
wxThread::Create(unsigned int stackSize
) 
1051     wxCriticalSectionLocker 
lock(m_critsect
); 
1053     if ( !m_internal
->Create(this, stackSize
) ) 
1054         return wxTHREAD_NO_RESOURCE
; 
1056     return wxTHREAD_NO_ERROR
; 
1059 wxThreadError 
wxThread::Run() 
1061     wxCriticalSectionLocker 
lock(m_critsect
); 
1063     if ( m_internal
->GetState() != STATE_NEW 
) 
1065         // actually, it may be almost any state at all, not only STATE_RUNNING 
1066         return wxTHREAD_RUNNING
; 
1069     // the thread has just been created and is still suspended - let it run 
1073 // suspend/resume thread 
1074 // --------------------- 
1076 wxThreadError 
wxThread::Pause() 
1078     wxCriticalSectionLocker 
lock(m_critsect
); 
1080     return m_internal
->Suspend() ? wxTHREAD_NO_ERROR 
: wxTHREAD_MISC_ERROR
; 
1083 wxThreadError 
wxThread::Resume() 
1085     wxCriticalSectionLocker 
lock(m_critsect
); 
1087     return m_internal
->Resume() ? wxTHREAD_NO_ERROR 
: wxTHREAD_MISC_ERROR
; 
1093 wxThread::ExitCode 
wxThread::Wait() 
1095     // although under Windows we can wait for any thread, it's an error to 
1096     // wait for a detached one in wxWin API 
1097     wxCHECK_MSG( !IsDetached(), (ExitCode
)-1, 
1098                  _T("wxThread::Wait(): can't wait for detached thread") ); 
1100     ExitCode rc 
= (ExitCode
)-1; 
1102     (void)m_internal
->WaitForTerminate(m_critsect
, &rc
); 
1107 wxThreadError 
wxThread::Delete(ExitCode 
*pRc
) 
1109     return m_internal
->WaitForTerminate(m_critsect
, pRc
, this); 
1112 wxThreadError 
wxThread::Kill() 
1115         return wxTHREAD_NOT_RUNNING
; 
1117     wxThreadError rc 
= m_internal
->Kill(); 
1125         // update the status of the joinable thread 
1126         wxCriticalSectionLocker 
lock(m_critsect
); 
1127         m_internal
->SetState(STATE_EXITED
); 
1133 void wxThread::Exit(ExitCode status
) 
1143         // update the status of the joinable thread 
1144         wxCriticalSectionLocker 
lock(m_critsect
); 
1145         m_internal
->SetState(STATE_EXITED
); 
1148 #ifdef wxUSE_BEGIN_THREAD 
1149     _endthreadex((unsigned)status
); 
1151     ::ExitThread((DWORD
)status
); 
1152 #endif // VC++/!VC++ 
1154     wxFAIL_MSG(wxT("Couldn't return from ExitThread()!")); 
1160 void wxThread::SetPriority(unsigned int prio
) 
1162     wxCriticalSectionLocker 
lock(m_critsect
); 
1164     m_internal
->SetPriority(prio
); 
1167 unsigned int wxThread::GetPriority() const 
1169     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); // const_cast 
1171     return m_internal
->GetPriority(); 
1174 unsigned long wxThread::GetId() const 
1176     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); // const_cast 
1178     return (unsigned long)m_internal
->GetId(); 
1181 bool wxThread::IsRunning() const 
1183     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); // const_cast 
1185     return m_internal
->GetState() == STATE_RUNNING
; 
1188 bool wxThread::IsAlive() const 
1190     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); // const_cast 
1192     return (m_internal
->GetState() == STATE_RUNNING
) || 
1193            (m_internal
->GetState() == STATE_PAUSED
); 
1196 bool wxThread::IsPaused() const 
1198     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); // const_cast 
1200     return m_internal
->GetState() == STATE_PAUSED
; 
1203 bool wxThread::TestDestroy() 
1205     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); // const_cast 
1207     return m_internal
->GetState() == STATE_CANCELED
; 
1210 // ---------------------------------------------------------------------------- 
1211 // Automatic initialization for thread module 
1212 // ---------------------------------------------------------------------------- 
1214 class wxThreadModule 
: public wxModule
 
1217     virtual bool OnInit(); 
1218     virtual void OnExit(); 
1221     DECLARE_DYNAMIC_CLASS(wxThreadModule
) 
1224 IMPLEMENT_DYNAMIC_CLASS(wxThreadModule
, wxModule
) 
1226 bool wxThreadModule::OnInit() 
1228     // allocate TLS index for storing the pointer to the current thread 
1229     gs_tlsThisThread 
= ::TlsAlloc(); 
1230     if ( gs_tlsThisThread 
== 0xFFFFFFFF ) 
1232         // in normal circumstances it will only happen if all other 
1233         // TLS_MINIMUM_AVAILABLE (>= 64) indices are already taken - in other 
1234         // words, this should never happen 
1235         wxLogSysError(_("Thread module initialization failed: impossible to allocate index in thread local storage")); 
1240     // main thread doesn't have associated wxThread object, so store 0 in the 
1242     if ( !::TlsSetValue(gs_tlsThisThread
, (LPVOID
)0) ) 
1244         ::TlsFree(gs_tlsThisThread
); 
1245         gs_tlsThisThread 
= 0xFFFFFFFF; 
1247         wxLogSysError(_("Thread module initialization failed: can not store value in thread local storage")); 
1252     gs_critsectWaitingForGui 
= new wxCriticalSection(); 
1254     gs_critsectGui 
= new wxCriticalSection(); 
1255     gs_critsectGui
->Enter(); 
1257     gs_critsectThreadDelete 
= new wxCriticalSection
; 
1259     // no error return for GetCurrentThreadId() 
1260     gs_idMainThread 
= ::GetCurrentThreadId(); 
1265 void wxThreadModule::OnExit() 
1267     if ( !::TlsFree(gs_tlsThisThread
) ) 
1269         wxLogLastError(wxT("TlsFree failed.")); 
1272     delete gs_critsectThreadDelete
; 
1273     gs_critsectThreadDelete 
= NULL
; 
1275     if ( gs_critsectGui 
) 
1277         gs_critsectGui
->Leave(); 
1278         delete gs_critsectGui
; 
1279         gs_critsectGui 
= NULL
; 
1282     delete gs_critsectWaitingForGui
; 
1283     gs_critsectWaitingForGui 
= NULL
; 
1286 // ---------------------------------------------------------------------------- 
1287 // under Windows, these functions are implemented using a critical section and 
1288 // not a mutex, so the names are a bit confusing 
1289 // ---------------------------------------------------------------------------- 
1291 void WXDLLIMPEXP_BASE 
wxMutexGuiEnter() 
1293     // this would dead lock everything... 
1294     wxASSERT_MSG( !wxThread::IsMain(), 
1295                   wxT("main thread doesn't want to block in wxMutexGuiEnter()!") ); 
1297     // the order in which we enter the critical sections here is crucial!! 
1299     // set the flag telling to the main thread that we want to do some GUI 
1301         wxCriticalSectionLocker 
enter(*gs_critsectWaitingForGui
); 
1303         gs_nWaitingForGui
++; 
1306     wxWakeUpMainThread(); 
1308     // now we may block here because the main thread will soon let us in 
1309     // (during the next iteration of OnIdle()) 
1310     gs_critsectGui
->Enter(); 
1313 void WXDLLIMPEXP_BASE 
wxMutexGuiLeave() 
1315     wxCriticalSectionLocker 
enter(*gs_critsectWaitingForGui
); 
1317     if ( wxThread::IsMain() ) 
1319         gs_bGuiOwnedByMainThread 
= false; 
1323         // decrement the number of threads waiting for GUI access now 
1324         wxASSERT_MSG( gs_nWaitingForGui 
> 0, 
1325                       wxT("calling wxMutexGuiLeave() without entering it first?") ); 
1327         gs_nWaitingForGui
--; 
1329         wxWakeUpMainThread(); 
1332     gs_critsectGui
->Leave(); 
1335 void WXDLLIMPEXP_BASE 
wxMutexGuiLeaveOrEnter() 
1337     wxASSERT_MSG( wxThread::IsMain(), 
1338                   wxT("only main thread may call wxMutexGuiLeaveOrEnter()!") ); 
1340     wxCriticalSectionLocker 
enter(*gs_critsectWaitingForGui
); 
1342     if ( gs_nWaitingForGui 
== 0 ) 
1344         // no threads are waiting for GUI - so we may acquire the lock without 
1345         // any danger (but only if we don't already have it) 
1346         if ( !wxGuiOwnedByMainThread() ) 
1348             gs_critsectGui
->Enter(); 
1350             gs_bGuiOwnedByMainThread 
= true; 
1352         //else: already have it, nothing to do 
1356         // some threads are waiting, release the GUI lock if we have it 
1357         if ( wxGuiOwnedByMainThread() ) 
1361         //else: some other worker thread is doing GUI 
1365 bool WXDLLIMPEXP_BASE 
wxGuiOwnedByMainThread() 
1367     return gs_bGuiOwnedByMainThread
; 
1370 // wake up the main thread if it's in ::GetMessage() 
1371 void WXDLLIMPEXP_BASE 
wxWakeUpMainThread() 
1373     // sending any message would do - hopefully WM_NULL is harmless enough 
1374     if ( !::PostThreadMessage(gs_idMainThread
, WM_NULL
, 0, 0) ) 
1376         // should never happen 
1377         wxLogLastError(wxT("PostThreadMessage(WM_NULL)")); 
1381 bool WXDLLIMPEXP_BASE 
wxIsWaitingForThread() 
1383     return gs_waitingForThread
; 
1386 // ---------------------------------------------------------------------------- 
1387 // include common implementation code 
1388 // ---------------------------------------------------------------------------- 
1390 #include "wx/thrimpl.cpp" 
1392 #endif // wxUSE_THREADS