1 ///////////////////////////////////////////////////////////////////////////// 
   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) 
  10 // Licence:     wxWindows licence 
  11 ///////////////////////////////////////////////////////////////////////////// 
  14     #pragma implementation "thread.h" 
  17 // ---------------------------------------------------------------------------- 
  19 // ---------------------------------------------------------------------------- 
  21 // For compilers that support precompilation, includes "wx.h". 
  22 #include "wx/wxprec.h" 
  24 #if defined(__BORLANDC__) 
  34 #include "wx/msw/private.h" 
  36 #include "wx/module.h" 
  37 #include "wx/thread.h" 
  39 // must have this symbol defined to get _beginthread/_endthread declarations 
  44 #if defined(__VISUALC__) || (defined(__BORLANDC__) && (__BORLANDC__ >= 0x500)) 
  46 #if defined(__BORLANDC__) && !defined(__MT__) 
  47 // I can't set -tWM in the IDE (anyone?) so have to do this 
  54 // ---------------------------------------------------------------------------- 
  56 // ---------------------------------------------------------------------------- 
  58 // the possible states of the thread ("=>" shows all possible transitions from 
  62     STATE_NEW
,          // didn't start execution yet (=> RUNNING) 
  63     STATE_RUNNING
,      // thread is running (=> PAUSED, CANCELED) 
  64     STATE_PAUSED
,       // thread is temporarily suspended (=> RUNNING) 
  65     STATE_CANCELED
,     // thread should terminate a.s.a.p. (=> EXITED) 
  66     STATE_EXITED        
// thread is terminating 
  69 // ---------------------------------------------------------------------------- 
  70 // this module globals 
  71 // ---------------------------------------------------------------------------- 
  73 // TLS index of the slot where we store the pointer to the current thread 
  74 static DWORD gs_tlsThisThread 
= 0xFFFFFFFF; 
  76 // id of the main thread - the one which can call GUI functions without first 
  77 // calling wxMutexGuiEnter() 
  78 static DWORD gs_idMainThread 
= 0; 
  80 // if it's FALSE, some secondary thread is holding the GUI lock 
  81 static bool gs_bGuiOwnedByMainThread 
= TRUE
; 
  83 // critical section which controls access to all GUI functions: any secondary 
  84 // thread (i.e. except the main one) must enter this crit section before doing 
  86 static wxCriticalSection 
*gs_critsectGui 
= NULL
; 
  88 // critical section which protects gs_nWaitingForGui variable 
  89 static wxCriticalSection 
*gs_critsectWaitingForGui 
= NULL
; 
  91 // number of threads waiting for GUI in wxMutexGuiEnter() 
  92 static size_t gs_nWaitingForGui 
= 0; 
  94 // are we waiting for a thread termination? 
  95 static bool gs_waitingForThread 
= FALSE
; 
  97 // ============================================================================ 
  98 // Windows implementation of thread classes 
  99 // ============================================================================ 
 101 // ---------------------------------------------------------------------------- 
 102 // wxMutex implementation 
 103 // ---------------------------------------------------------------------------- 
 105 class wxMutexInternal
 
 110         m_mutex 
= ::CreateMutex(NULL
, FALSE
, NULL
); 
 113             wxLogSysError(_("Can not create mutex")); 
 117     ~wxMutexInternal() { if ( m_mutex 
) CloseHandle(m_mutex
); } 
 125     m_internal 
= new wxMutexInternal
; 
 134         wxLogDebug(_T("Warning: freeing a locked mutex (%d locks)."), m_locked
); 
 140 wxMutexError 
wxMutex::Lock() 
 144     ret 
= WaitForSingleObject(m_internal
->m_mutex
, INFINITE
); 
 155             wxLogSysError(_("Couldn't acquire a mutex lock")); 
 156             return wxMUTEX_MISC_ERROR
; 
 160             wxFAIL_MSG(wxT("impossible return value in wxMutex::Lock")); 
 164     return wxMUTEX_NO_ERROR
; 
 167 wxMutexError 
wxMutex::TryLock() 
 171     ret 
= WaitForSingleObject(m_internal
->m_mutex
, 0); 
 172     if (ret 
== WAIT_TIMEOUT 
|| ret 
== WAIT_ABANDONED
) 
 176     return wxMUTEX_NO_ERROR
; 
 179 wxMutexError 
wxMutex::Unlock() 
 184     BOOL ret 
= ReleaseMutex(m_internal
->m_mutex
); 
 187         wxLogSysError(_("Couldn't release a mutex")); 
 188         return wxMUTEX_MISC_ERROR
; 
 191     return wxMUTEX_NO_ERROR
; 
 194 // ---------------------------------------------------------------------------- 
 195 // wxCondition implementation 
 196 // ---------------------------------------------------------------------------- 
 198 class wxConditionInternal
 
 201     wxConditionInternal() 
 203         event 
= ::CreateEvent( 
 204                               NULL
,   // default secutiry 
 205                               FALSE
,  // not manual reset 
 206                               FALSE
,  // nonsignaled initially 
 207                               NULL    
// nameless event 
 211             wxLogSysError(_("Can not create event object.")); 
 216     bool Wait(DWORD timeout
) 
 220         // FIXME this should be MsgWaitForMultipleObjects() as well probably 
 221         DWORD rc 
= ::WaitForSingleObject(event
, timeout
); 
 225         return rc 
!= WAIT_TIMEOUT
; 
 228     ~wxConditionInternal() 
 232             if ( !::CloseHandle(event
) ) 
 234                 wxLogLastError("CloseHandle(event)"); 
 243 wxCondition::wxCondition() 
 245     m_internal 
= new wxConditionInternal
; 
 248 wxCondition::~wxCondition() 
 253 void wxCondition::Wait() 
 255     (void)m_internal
->Wait(INFINITE
); 
 258 bool wxCondition::Wait(unsigned long sec
, 
 261     return m_internal
->Wait(sec
*1000 + nsec
/1000000); 
 264 void wxCondition::Signal() 
 266     // set the event to signaled: if a thread is already waiting on it, it will 
 267     // be woken up, otherwise the event will remain in the signaled state until 
 268     // someone waits on it. In any case, the system will return it to a non 
 269     // signalled state afterwards. If multiple threads are waiting, only one 
 271     if ( !::SetEvent(m_internal
->event
) ) 
 273         wxLogLastError("SetEvent"); 
 277 void wxCondition::Broadcast() 
 279     // this works because all these threads are already waiting and so each 
 280     // SetEvent() inside Signal() is really a PulseEvent() because the event 
 281     // state is immediately returned to non-signaled 
 282     for ( int i 
= 0; i 
< m_internal
->waiters
; i
++ ) 
 288 // ---------------------------------------------------------------------------- 
 289 // wxCriticalSection implementation 
 290 // ---------------------------------------------------------------------------- 
 292 wxCriticalSection::wxCriticalSection() 
 294     wxASSERT_MSG( sizeof(CRITICAL_SECTION
) <= sizeof(m_buffer
), 
 295                   _T("must increase buffer size in wx/thread.h") ); 
 297     ::InitializeCriticalSection((CRITICAL_SECTION 
*)m_buffer
); 
 300 wxCriticalSection::~wxCriticalSection() 
 302     ::DeleteCriticalSection((CRITICAL_SECTION 
*)m_buffer
); 
 305 void wxCriticalSection::Enter() 
 307     ::EnterCriticalSection((CRITICAL_SECTION 
*)m_buffer
); 
 310 void wxCriticalSection::Leave() 
 312     ::LeaveCriticalSection((CRITICAL_SECTION 
*)m_buffer
); 
 315 // ---------------------------------------------------------------------------- 
 316 // wxThread implementation 
 317 // ---------------------------------------------------------------------------- 
 319 // wxThreadInternal class 
 320 // ---------------------- 
 322 class wxThreadInternal
 
 329         m_priority 
= WXTHREAD_DEFAULT_PRIORITY
; 
 341             if ( !::CloseHandle(m_hThread
) ) 
 343                 wxLogLastError("CloseHandle(thread)"); 
 350     // create a new (suspended) thread (for the given thread object) 
 351     bool Create(wxThread 
*thread
); 
 353     // suspend/resume/terminate 
 356     void Cancel() { m_state 
= STATE_CANCELED
; } 
 359     void SetState(wxThreadState state
) { m_state 
= state
; } 
 360     wxThreadState 
GetState() const { return m_state
; } 
 363     void SetPriority(unsigned int priority
); 
 364     unsigned int GetPriority() const { return m_priority
; } 
 366     // thread handle and id 
 367     HANDLE 
GetHandle() const { return m_hThread
; } 
 368     DWORD  
GetId() const { return m_tid
; } 
 371     static DWORD 
WinThreadStart(wxThread 
*thread
); 
 374     HANDLE        m_hThread
;    // handle of the thread 
 375     wxThreadState m_state
;      // state, see wxThreadState enum 
 376     unsigned int  m_priority
;   // thread priority in "wx" units 
 377     DWORD         m_tid
;        // thread id 
 380 DWORD 
wxThreadInternal::WinThreadStart(wxThread 
*thread
) 
 382     // first of all, check whether we hadn't been cancelled already 
 383     if ( thread
->m_internal
->GetState() == STATE_EXITED 
) 
 388     // store the thread object in the TLS 
 389     if ( !::TlsSetValue(gs_tlsThisThread
, thread
) ) 
 391         wxLogSysError(_("Can not start thread: error writing TLS.")); 
 396     DWORD rc 
= (DWORD
)thread
->Entry(); 
 398     // enter m_critsect before changing the thread state 
 399     thread
->m_critsect
.Enter(); 
 400     bool wasCancelled 
= thread
->m_internal
->GetState() == STATE_CANCELED
; 
 401     thread
->m_internal
->SetState(STATE_EXITED
); 
 402     thread
->m_critsect
.Leave(); 
 406     // if the thread was cancelled (from Delete()), then it the handle is still 
 408     if ( thread
->IsDetached() && !wasCancelled 
) 
 413     //else: the joinable threads handle will be closed when Wait() is done 
 418 void wxThreadInternal::SetPriority(unsigned int priority
) 
 420     m_priority 
= priority
; 
 422     // translate wxWindows priority to the Windows one 
 424     if (m_priority 
<= 20) 
 425         win_priority 
= THREAD_PRIORITY_LOWEST
; 
 426     else if (m_priority 
<= 40) 
 427         win_priority 
= THREAD_PRIORITY_BELOW_NORMAL
; 
 428     else if (m_priority 
<= 60) 
 429         win_priority 
= THREAD_PRIORITY_NORMAL
; 
 430     else if (m_priority 
<= 80) 
 431         win_priority 
= THREAD_PRIORITY_ABOVE_NORMAL
; 
 432     else if (m_priority 
<= 100) 
 433         win_priority 
= THREAD_PRIORITY_HIGHEST
; 
 436         wxFAIL_MSG(wxT("invalid value of thread priority parameter")); 
 437         win_priority 
= THREAD_PRIORITY_NORMAL
; 
 440     if ( !::SetThreadPriority(m_hThread
, win_priority
) ) 
 442         wxLogSysError(_("Can't set thread priority")); 
 446 bool wxThreadInternal::Create(wxThread 
*thread
) 
 448     // for compilers which have it, we should use C RTL function for thread 
 449     // creation instead of Win32 API one because otherwise we will have memory 
 450     // leaks if the thread uses C RTL (and most threads do) 
 451 #if defined(__VISUALC__) || (defined(__BORLANDC__) && (__BORLANDC__ >= 0x500)) 
 452     typedef unsigned (__stdcall 
*RtlThreadStart
)(void *); 
 454     m_hThread 
= (HANDLE
)_beginthreadex(NULL
, 0, 
 456                                        wxThreadInternal::WinThreadStart
, 
 457                                        thread
, CREATE_SUSPENDED
, 
 458                                        (unsigned int *)&m_tid
); 
 460     m_hThread 
= ::CreateThread
 
 462                     NULL
,                               // default security 
 463                     0,                                  // default stack size 
 464                     (LPTHREAD_START_ROUTINE
)            // thread entry point 
 465                     wxThreadInternal::WinThreadStart
,   // 
 466                     (LPVOID
)thread
,                     // parameter 
 467                     CREATE_SUSPENDED
,                   // flags 
 468                     &m_tid                              
// [out] thread id 
 472     if ( m_hThread 
== NULL 
) 
 474         wxLogSysError(_("Can't create thread")); 
 479     if ( m_priority 
!= WXTHREAD_DEFAULT_PRIORITY 
) 
 481         SetPriority(m_priority
); 
 487 bool wxThreadInternal::Suspend() 
 489     DWORD nSuspendCount 
= ::SuspendThread(m_hThread
); 
 490     if ( nSuspendCount 
== (DWORD
)-1 ) 
 492         wxLogSysError(_("Can not suspend thread %x"), m_hThread
); 
 497     m_state 
= STATE_PAUSED
; 
 502 bool wxThreadInternal::Resume() 
 504     DWORD nSuspendCount 
= ::ResumeThread(m_hThread
); 
 505     if ( nSuspendCount 
== (DWORD
)-1 ) 
 507         wxLogSysError(_("Can not resume thread %x"), m_hThread
); 
 512     m_state 
= STATE_RUNNING
; 
 520 wxThread 
*wxThread::This() 
 522     wxThread 
*thread 
= (wxThread 
*)::TlsGetValue(gs_tlsThisThread
); 
 524     // be careful, 0 may be a valid return value as well 
 525     if ( !thread 
&& (::GetLastError() != NO_ERROR
) ) 
 527         wxLogSysError(_("Couldn't get the current thread pointer")); 
 535 bool wxThread::IsMain() 
 537     return ::GetCurrentThreadId() == gs_idMainThread
; 
 544 void wxThread::Yield() 
 546     // 0 argument to Sleep() is special and means to just give away the rest of 
 551 void wxThread::Sleep(unsigned long milliseconds
) 
 553     ::Sleep(milliseconds
); 
 556 int wxThread::GetCPUCount() 
 561     return si
.dwNumberOfProcessors
; 
 564 bool wxThread::SetConcurrency(size_t level
) 
 566     wxASSERT_MSG( IsMain(), _T("should only be called from the main thread") ); 
 568     // ok only for the default one 
 572     // get system affinity mask first 
 573     HANDLE hProcess 
= ::GetCurrentProcess(); 
 574     DWORD dwProcMask
, dwSysMask
; 
 575     if ( ::GetProcessAffinityMask(hProcess
, &dwProcMask
, &dwSysMask
) == 0 ) 
 577         wxLogLastError(_T("GetProcessAffinityMask")); 
 582     // how many CPUs have we got? 
 583     if ( dwSysMask 
== 1 ) 
 585         // don't bother with all this complicated stuff - on a single 
 586         // processor system it doesn't make much sense anyhow 
 590     // calculate the process mask: it's a bit vector with one bit per 
 591     // processor; we want to schedule the process to run on first level 
 596         if ( dwSysMask 
& bit 
) 
 598             // ok, we can set this bit 
 601             // another process added 
 613     // could we set all bits? 
 616         wxLogDebug(_T("bad level %u in wxThread::SetConcurrency()"), level
); 
 621     // set it: we can't link to SetProcessAffinityMask() because it doesn't 
 622     // exist in Win9x, use RT binding instead 
 624     typedef BOOL (*SETPROCESSAFFINITYMASK
)(HANDLE
, DWORD
); 
 626     // can use static var because we're always in the main thread here 
 627     static SETPROCESSAFFINITYMASK pfnSetProcessAffinityMask 
= NULL
; 
 629     if ( !pfnSetProcessAffinityMask 
) 
 631         HMODULE hModKernel 
= ::LoadLibrary(_T("kernel32")); 
 634             pfnSetProcessAffinityMask 
= (SETPROCESSAFFINITYMASK
) 
 635                 ::GetProcAddress(hModKernel
, 
 636 #if defined(__BORLANDC__) && (__BORLANDC__ <= 0x520) 
 637                                  "SetProcessAffinityMask"); 
 639                                  _T("SetProcessAffinityMask")); 
 643         // we've discovered a MT version of Win9x! 
 644         wxASSERT_MSG( pfnSetProcessAffinityMask
, 
 645                       _T("this system has several CPUs but no " 
 646                          "SetProcessAffinityMask function?") ); 
 649     if ( !pfnSetProcessAffinityMask 
) 
 651         // msg given above - do it only once 
 655     if ( pfnSetProcessAffinityMask(hProcess
, dwProcMask
) == 0 ) 
 657         wxLogLastError(_T("SetProcessAffinityMask")); 
 668 wxThread::wxThread(wxThreadKind kind
) 
 670     m_internal 
= new wxThreadInternal(); 
 672     m_isDetached 
= kind 
== wxTHREAD_DETACHED
; 
 675 wxThread::~wxThread() 
 680 // create/start thread 
 681 // ------------------- 
 683 wxThreadError 
wxThread::Create() 
 685     wxCriticalSectionLocker 
lock(m_critsect
); 
 687     if ( !m_internal
->Create(this) ) 
 688         return wxTHREAD_NO_RESOURCE
; 
 690     return wxTHREAD_NO_ERROR
; 
 693 wxThreadError 
wxThread::Run() 
 695     wxCriticalSectionLocker 
lock(m_critsect
); 
 697     if ( m_internal
->GetState() != STATE_NEW 
) 
 699         // actually, it may be almost any state at all, not only STATE_RUNNING 
 700         return wxTHREAD_RUNNING
; 
 703     // the thread has just been created and is still suspended - let it run 
 707 // suspend/resume thread 
 708 // --------------------- 
 710 wxThreadError 
wxThread::Pause() 
 712     wxCriticalSectionLocker 
lock(m_critsect
); 
 714     return m_internal
->Suspend() ? wxTHREAD_NO_ERROR 
: wxTHREAD_MISC_ERROR
; 
 717 wxThreadError 
wxThread::Resume() 
 719     wxCriticalSectionLocker 
lock(m_critsect
); 
 721     return m_internal
->Resume() ? wxTHREAD_NO_ERROR 
: wxTHREAD_MISC_ERROR
; 
 727 wxThread::ExitCode 
wxThread::Wait() 
 729     // although under Windows we can wait for any thread, it's an error to 
 730     // wait for a detached one in wxWin API 
 731     wxCHECK_MSG( !IsDetached(), (ExitCode
)-1, 
 732                  _T("can't wait for detached thread") ); 
 734     ExitCode rc 
= (ExitCode
)-1; 
 743 wxThreadError 
wxThread::Delete(ExitCode 
*pRc
) 
 747     // Delete() is always safe to call, so consider all possible states 
 749     // has the thread started to run? 
 750     bool shouldResume 
= FALSE
; 
 753         wxCriticalSectionLocker 
lock(m_critsect
); 
 755         if ( m_internal
->GetState() == STATE_NEW 
) 
 757             // WinThreadStart() will see it and terminate immediately 
 758             m_internal
->SetState(STATE_EXITED
); 
 764     // is the thread paused? 
 765     if ( shouldResume 
|| IsPaused() ) 
 768     HANDLE hThread 
= m_internal
->GetHandle(); 
 770     // does is still run? 
 775             // set flag for wxIsWaitingForThread() 
 776             gs_waitingForThread 
= TRUE
; 
 783         // ask the thread to terminate 
 785             wxCriticalSectionLocker 
lock(m_critsect
); 
 787             m_internal
->Cancel(); 
 791         // we can't just wait for the thread to terminate because it might be 
 792         // calling some GUI functions and so it will never terminate before we 
 793         // process the Windows messages that result from these functions 
 797             result 
= ::MsgWaitForMultipleObjects
 
 799                        1,              // number of objects to wait for 
 800                        &hThread
,       // the objects 
 801                        FALSE
,          // don't wait for all objects 
 802                        INFINITE
,       // no timeout 
 803                        QS_ALLEVENTS    
// return as soon as there are any events 
 810                     wxLogSysError(_("Can not wait for thread termination")); 
 812                     return wxTHREAD_KILLED
; 
 815                     // thread we're waiting for terminated 
 818                 case WAIT_OBJECT_0 
+ 1: 
 819                     // new message arrived, process it 
 820                     if ( !wxTheApp
->DoMessage() ) 
 822                         // WM_QUIT received: kill the thread 
 825                         return wxTHREAD_KILLED
; 
 830                         // give the thread we're waiting for chance to exit 
 831                         // from the GUI call it might have been in 
 832                         if ( (gs_nWaitingForGui 
> 0) && wxGuiOwnedByMainThread() ) 
 841                     wxFAIL_MSG(wxT("unexpected result of MsgWaitForMultipleObject")); 
 843         } while ( result 
!= WAIT_OBJECT_0 
); 
 845         // simply wait for the thread to terminate 
 847         // OTOH, even console apps create windows (in wxExecute, for WinSock 
 848         // &c), so may be use MsgWaitForMultipleObject() too here? 
 849         if ( WaitForSingleObject(hThread
, INFINITE
) != WAIT_OBJECT_0 
) 
 851             wxFAIL_MSG(wxT("unexpected result of WaitForSingleObject")); 
 853 #endif // wxUSE_GUI/!wxUSE_GUI 
 857             gs_waitingForThread 
= FALSE
; 
 865     if ( !::GetExitCodeThread(hThread
, (LPDWORD
)&rc
) ) 
 867         wxLogLastError("GetExitCodeThread"); 
 874         // if the thread exits normally, this is done in WinThreadStart, but in 
 875         // this case it would have been too early because 
 876         // MsgWaitForMultipleObject() would fail if the therad handle was 
 877         // closed while we were waiting on it, so we must do it here 
 881     wxASSERT_MSG( (DWORD
)rc 
!= STILL_ACTIVE
, 
 882                   wxT("thread must be already terminated.") ); 
 887     return rc 
== (ExitCode
)-1 ? wxTHREAD_MISC_ERROR 
: wxTHREAD_NO_ERROR
; 
 890 wxThreadError 
wxThread::Kill() 
 893         return wxTHREAD_NOT_RUNNING
; 
 895     if ( !::TerminateThread(m_internal
->GetHandle(), (DWORD
)-1) ) 
 897         wxLogSysError(_("Couldn't terminate thread")); 
 899         return wxTHREAD_MISC_ERROR
; 
 909     return wxTHREAD_NO_ERROR
; 
 912 void wxThread::Exit(ExitCode status
) 
 921 #if defined(__VISUALC__) || (defined(__BORLANDC__) && (__BORLANDC__ >= 0x500)) 
 922     _endthreadex((unsigned)status
); 
 924     ::ExitThread((DWORD
)status
); 
 927     wxFAIL_MSG(wxT("Couldn't return from ExitThread()!")); 
 933 void wxThread::SetPriority(unsigned int prio
) 
 935     wxCriticalSectionLocker 
lock(m_critsect
); 
 937     m_internal
->SetPriority(prio
); 
 940 unsigned int wxThread::GetPriority() const 
 942     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); // const_cast 
 944     return m_internal
->GetPriority(); 
 947 unsigned long wxThread::GetId() const 
 949     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); // const_cast 
 951     return (unsigned long)m_internal
->GetId(); 
 954 bool wxThread::IsRunning() const 
 956     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); // const_cast 
 958     return m_internal
->GetState() == STATE_RUNNING
; 
 961 bool wxThread::IsAlive() const 
 963     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); // const_cast 
 965     return (m_internal
->GetState() == STATE_RUNNING
) || 
 966            (m_internal
->GetState() == STATE_PAUSED
); 
 969 bool wxThread::IsPaused() const 
 971     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); // const_cast 
 973     return m_internal
->GetState() == STATE_PAUSED
; 
 976 bool wxThread::TestDestroy() 
 978     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); // const_cast 
 980     return m_internal
->GetState() == STATE_CANCELED
; 
 983 // ---------------------------------------------------------------------------- 
 984 // Automatic initialization for thread module 
 985 // ---------------------------------------------------------------------------- 
 987 class wxThreadModule 
: public wxModule
 
 990     virtual bool OnInit(); 
 991     virtual void OnExit(); 
 994     DECLARE_DYNAMIC_CLASS(wxThreadModule
) 
 997 IMPLEMENT_DYNAMIC_CLASS(wxThreadModule
, wxModule
) 
 999 bool wxThreadModule::OnInit() 
1001     // allocate TLS index for storing the pointer to the current thread 
1002     gs_tlsThisThread 
= ::TlsAlloc(); 
1003     if ( gs_tlsThisThread 
== 0xFFFFFFFF ) 
1005         // in normal circumstances it will only happen if all other 
1006         // TLS_MINIMUM_AVAILABLE (>= 64) indices are already taken - in other 
1007         // words, this should never happen 
1008         wxLogSysError(_("Thread module initialization failed: " 
1009                         "impossible to allocate index in thread " 
1015     // main thread doesn't have associated wxThread object, so store 0 in the 
1017     if ( !::TlsSetValue(gs_tlsThisThread
, (LPVOID
)0) ) 
1019         ::TlsFree(gs_tlsThisThread
); 
1020         gs_tlsThisThread 
= 0xFFFFFFFF; 
1022         wxLogSysError(_("Thread module initialization failed: " 
1023                         "can not store value in thread local storage")); 
1028     gs_critsectWaitingForGui 
= new wxCriticalSection(); 
1030     gs_critsectGui 
= new wxCriticalSection(); 
1031     gs_critsectGui
->Enter(); 
1033     // no error return for GetCurrentThreadId() 
1034     gs_idMainThread 
= ::GetCurrentThreadId(); 
1039 void wxThreadModule::OnExit() 
1041     if ( !::TlsFree(gs_tlsThisThread
) ) 
1043         wxLogLastError("TlsFree failed."); 
1046     if ( gs_critsectGui 
) 
1048         gs_critsectGui
->Leave(); 
1049         delete gs_critsectGui
; 
1050         gs_critsectGui 
= NULL
; 
1053     delete gs_critsectWaitingForGui
; 
1054     gs_critsectWaitingForGui 
= NULL
; 
1057 // ---------------------------------------------------------------------------- 
1058 // under Windows, these functions are implemented using a critical section and 
1059 // not a mutex, so the names are a bit confusing 
1060 // ---------------------------------------------------------------------------- 
1062 void WXDLLEXPORT 
wxMutexGuiEnter() 
1064     // this would dead lock everything... 
1065     wxASSERT_MSG( !wxThread::IsMain(), 
1066                   wxT("main thread doesn't want to block in wxMutexGuiEnter()!") ); 
1068     // the order in which we enter the critical sections here is crucial!! 
1070     // set the flag telling to the main thread that we want to do some GUI 
1072         wxCriticalSectionLocker 
enter(*gs_critsectWaitingForGui
); 
1074         gs_nWaitingForGui
++; 
1077     wxWakeUpMainThread(); 
1079     // now we may block here because the main thread will soon let us in 
1080     // (during the next iteration of OnIdle()) 
1081     gs_critsectGui
->Enter(); 
1084 void WXDLLEXPORT 
wxMutexGuiLeave() 
1086     wxCriticalSectionLocker 
enter(*gs_critsectWaitingForGui
); 
1088     if ( wxThread::IsMain() ) 
1090         gs_bGuiOwnedByMainThread 
= FALSE
; 
1094         // decrement the number of waiters now 
1095         wxASSERT_MSG( gs_nWaitingForGui 
> 0, 
1096                       wxT("calling wxMutexGuiLeave() without entering it first?") ); 
1098         gs_nWaitingForGui
--; 
1100         wxWakeUpMainThread(); 
1103     gs_critsectGui
->Leave(); 
1106 void WXDLLEXPORT 
wxMutexGuiLeaveOrEnter() 
1108     wxASSERT_MSG( wxThread::IsMain(), 
1109                   wxT("only main thread may call wxMutexGuiLeaveOrEnter()!") ); 
1111     wxCriticalSectionLocker 
enter(*gs_critsectWaitingForGui
); 
1113     if ( gs_nWaitingForGui 
== 0 ) 
1115         // no threads are waiting for GUI - so we may acquire the lock without 
1116         // any danger (but only if we don't already have it) 
1117         if ( !wxGuiOwnedByMainThread() ) 
1119             gs_critsectGui
->Enter(); 
1121             gs_bGuiOwnedByMainThread 
= TRUE
; 
1123         //else: already have it, nothing to do 
1127         // some threads are waiting, release the GUI lock if we have it 
1128         if ( wxGuiOwnedByMainThread() ) 
1132         //else: some other worker thread is doing GUI 
1136 bool WXDLLEXPORT 
wxGuiOwnedByMainThread() 
1138     return gs_bGuiOwnedByMainThread
; 
1141 // wake up the main thread if it's in ::GetMessage() 
1142 void WXDLLEXPORT 
wxWakeUpMainThread() 
1144     // sending any message would do - hopefully WM_NULL is harmless enough 
1145     if ( !::PostThreadMessage(gs_idMainThread
, WM_NULL
, 0, 0) ) 
1147         // should never happen 
1148         wxLogLastError("PostThreadMessage(WM_NULL)"); 
1152 bool WXDLLEXPORT 
wxIsWaitingForThread() 
1154     return gs_waitingForThread
; 
1157 #endif // wxUSE_THREADS