1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/os2/thread.cpp 
   3 // Purpose:     wxThread Implementation 
   4 // Author:      Original from Wolfram Gloger/Guilhem Lavaux/David Webster 
   5 // Modified by: Stefan Neis 
   8 // Copyright:   (c) Stefan Neis (2003) 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // ---------------------------------------------------------------------------- 
  14 // ---------------------------------------------------------------------------- 
  16 // For compilers that support precompilation, includes "wx.h". 
  17 #include "wx/wxprec.h" 
  21 #include "wx/thread.h" 
  27     #include "wx/module.h" 
  30 #include "wx/apptrait.h" 
  35 #define INCL_DOSSEMAPHORES 
  36 #define INCL_DOSPROCESS 
  43 // the possible states of the thread ("=>" shows all possible transitions from 
  47     STATE_NEW
,          // didn't start execution yet (=> RUNNING) 
  48     STATE_RUNNING
,      // thread is running (=> PAUSED, CANCELED) 
  49     STATE_PAUSED
,       // thread is temporarily suspended (=> RUNNING) 
  50     STATE_CANCELED
,     // thread should terminate a.s.a.p. (=> EXITED) 
  51     STATE_EXITED        
// thread is terminating 
  54 // ---------------------------------------------------------------------------- 
  55 // this module's globals 
  56 // ---------------------------------------------------------------------------- 
  58 // id of the main thread - the one which can call GUI functions without first 
  59 // calling wxMutexGuiEnter() 
  60 static ULONG                        s_ulIdMainThread 
= 1; 
  61 wxMutex
*                            p_wxMainMutex
; 
  63 // OS2 substitute for Tls pointer the current parent thread object 
  64 wxThread
*                           m_pThread
;    // pointer to the wxWidgets thread object 
  66 // if it's false, some secondary thread is holding the GUI lock 
  67 static bool gs_bGuiOwnedByMainThread 
= true; 
  69 // critical section which controls access to all GUI functions: any secondary 
  70 // thread (i.e. except the main one) must enter this crit section before doing 
  72 static wxCriticalSection 
*gs_pCritsectGui 
= NULL
; 
  74 // critical section which protects s_nWaitingForGui variable 
  75 static wxCriticalSection 
*gs_pCritsectWaitingForGui 
= NULL
; 
  77 // number of threads waiting for GUI in wxMutexGuiEnter() 
  78 static size_t gs_nWaitingForGui 
= 0; 
  80 // are we waiting for a thread termination? 
  81 static bool gs_bWaitingForThread 
= false; 
  83 // ============================================================================ 
  84 // OS/2 implementation of thread and related classes 
  85 // ============================================================================ 
  87 // ---------------------------------------------------------------------------- 
  88 // wxMutex implementation 
  89 // ---------------------------------------------------------------------------- 
  93     wxMutexInternal(wxMutexType mutexType
); 
  96     bool IsOk() const { return m_vMutex 
!= NULL
; } 
  98     wxMutexError 
Lock() { return LockTimeout(SEM_INDEFINITE_WAIT
); } 
  99     wxMutexError 
TryLock() { return LockTimeout(SEM_IMMEDIATE_RETURN
); } 
 100     wxMutexError 
Unlock(); 
 103     wxMutexError 
LockTimeout(ULONG ulMilliseconds
); 
 107 // all mutexes are "pseudo-"recursive under OS2 so we don't use mutexType 
 108 // (Calls to DosRequestMutexSem and DosReleaseMutexSem can be nested, but 
 109 //  the request count for a semaphore cannot exceed 65535. If an attempt is 
 110 //  made to exceed this number, ERROR_TOO_MANY_SEM_REQUESTS is returned.) 
 111 wxMutexInternal::wxMutexInternal(wxMutexType 
WXUNUSED(eMutexType
)) 
 113     APIRET ulrc 
= ::DosCreateMutexSem(NULL
, &m_vMutex
, 0L, FALSE
); 
 116         wxLogSysError(_("Can not create mutex.")); 
 121 wxMutexInternal::~wxMutexInternal() 
 125         if (::DosCloseMutexSem(m_vMutex
)) 
 126             wxLogLastError(_T("DosCloseMutexSem(mutex)")); 
 130 wxMutexError 
wxMutexInternal::LockTimeout(ULONG ulMilliseconds
) 
 134     ulrc 
= ::DosRequestMutexSem(m_vMutex
, ulMilliseconds
); 
 139         case ERROR_TOO_MANY_SEM_REQUESTS
: 
 146         case ERROR_INVALID_HANDLE
: 
 147         case ERROR_INTERRUPT
: 
 148         case ERROR_SEM_OWNER_DIED
: 
 149             wxLogSysError(_("Couldn't acquire a mutex lock")); 
 150             return wxMUTEX_MISC_ERROR
; 
 153             wxFAIL_MSG(wxT("impossible return value in wxMutex::Lock")); 
 154             return wxMUTEX_MISC_ERROR
; 
 156     return wxMUTEX_NO_ERROR
; 
 159 wxMutexError 
wxMutexInternal::Unlock() 
 163     ulrc 
= ::DosReleaseMutexSem(m_vMutex
); 
 166         wxLogSysError(_("Couldn't release a mutex")); 
 167         return wxMUTEX_MISC_ERROR
; 
 169     return wxMUTEX_NO_ERROR
; 
 172 // -------------------------------------------------------------------------- 
 174 // -------------------------------------------------------------------------- 
 176 // a trivial wrapper around OS2 event semaphore 
 177 class wxSemaphoreInternal
 
 180     wxSemaphoreInternal(int initialcount
, int maxcount
); 
 181     ~wxSemaphoreInternal(); 
 183     bool IsOk() const { return m_vEvent 
!= NULL
; } 
 185     wxSemaError 
Wait() { return WaitTimeout(SEM_INDEFINITE_WAIT
); } 
 186     wxSemaError 
TryWait() { return WaitTimeout(SEM_IMMEDIATE_RETURN
); } 
 187     wxSemaError 
WaitTimeout(unsigned long milliseconds
); 
 198 wxSemaphoreInternal::wxSemaphoreInternal(int initialcount
, int maxcount
) 
 203         // make it practically infinite 
 207     m_count 
= initialcount
; 
 208     m_maxcount 
= maxcount
; 
 209     ulrc 
= ::DosCreateMutexSem(NULL
, &m_vMutex
, 0L, FALSE
); 
 212         wxLogLastError(_T("DosCreateMutexSem()")); 
 217     ulrc 
= ::DosCreateEventSem(NULL
, &m_vEvent
, 0L, FALSE
); 
 220         wxLogLastError(_T("DosCreateEventSem()")); 
 221         ::DosCloseMutexSem(m_vMutex
); 
 226         ::DosPostEventSem(m_vEvent
); 
 229 wxSemaphoreInternal::~wxSemaphoreInternal() 
 233         if ( ::DosCloseEventSem(m_vEvent
) ) 
 235             wxLogLastError(_T("DosCloseEventSem(semaphore)")); 
 237         if ( ::DosCloseMutexSem(m_vMutex
) ) 
 239             wxLogLastError(_T("DosCloseMutexSem(semaphore)")); 
 246 wxSemaError 
wxSemaphoreInternal::WaitTimeout(unsigned long ulMilliseconds
) 
 250         ulrc 
= ::DosWaitEventSem(m_vEvent
, ulMilliseconds 
); 
 257                 if (ulMilliseconds 
== SEM_IMMEDIATE_RETURN
) 
 260                     return wxSEMA_TIMEOUT
; 
 263                 wxLogLastError(_T("DosWaitEventSem(semaphore)")); 
 264                 return wxSEMA_MISC_ERROR
; 
 266         ulrc 
= :: DosRequestMutexSem(m_vMutex
, ulMilliseconds
); 
 274             case ERROR_TOO_MANY_SEM_REQUESTS
: 
 275                 if (ulMilliseconds 
== SEM_IMMEDIATE_RETURN
) 
 278                     return wxSEMA_TIMEOUT
; 
 281                 wxFAIL_MSG(wxT("DosRequestMutexSem(mutex)")); 
 282                 return wxSEMA_MISC_ERROR
; 
 293             ::DosResetEventSem(m_vEvent
, &ulPostCount
); 
 295         ::DosReleaseMutexSem(m_vMutex
); 
 297             return wxSEMA_NO_ERROR
; 
 298     } while (ulMilliseconds 
== SEM_INDEFINITE_WAIT
); 
 300     if (ulMilliseconds 
== SEM_IMMEDIATE_RETURN
) 
 302     return wxSEMA_TIMEOUT
; 
 305 wxSemaError 
wxSemaphoreInternal::Post() 
 308     ulrc 
= ::DosRequestMutexSem(m_vMutex
, SEM_INDEFINITE_WAIT
); 
 309     if (ulrc 
!= NO_ERROR
) 
 310         return wxSEMA_MISC_ERROR
; 
 312     if (m_count 
< m_maxcount
) 
 315         ulrc 
= ::DosPostEventSem(m_vEvent
); 
 318     ::DosReleaseMutexSem(m_vMutex
); 
 320         return wxSEMA_OVERFLOW
; 
 321     if ( ulrc 
!= NO_ERROR 
&& ulrc 
!= ERROR_ALREADY_POSTED 
) 
 323         wxLogLastError(_T("DosPostEventSem(semaphore)")); 
 325         return wxSEMA_MISC_ERROR
; 
 328     return wxSEMA_NO_ERROR
; 
 331 // ---------------------------------------------------------------------------- 
 332 // wxThread implementation 
 333 // ---------------------------------------------------------------------------- 
 335 // wxThreadInternal class 
 336 // ---------------------- 
 338 class wxThreadInternal
 
 341     inline wxThreadInternal() 
 344         m_eState 
= STATE_NEW
; 
 345         m_nPriority 
= WXTHREAD_DEFAULT_PRIORITY
; 
 353     // create a new (suspended) thread (for the given thread object) 
 354     bool Create( wxThread
*    pThread
 
 355                 ,unsigned int uStackSize
 
 358     // suspend/resume/terminate 
 361     inline void Cancel() { m_eState 
= STATE_CANCELED
; } 
 364     inline void SetState(wxThreadState eState
) { m_eState 
= eState
; } 
 365     inline wxThreadState 
GetState() const { return m_eState
; } 
 368     void                SetPriority(unsigned int nPriority
); 
 369     inline unsigned int GetPriority() const { return m_nPriority
; } 
 371     // thread handle and id 
 372     inline TID 
GetHandle() const { return m_hThread
; } 
 373     TID  
GetId() const { return m_hThread
; } 
 376     static void OS2ThreadStart(void* pParam
); 
 379     // Threads in OS/2 have only an ID, so m_hThread is both it's handle and ID 
 380     // PM also has no real Tls mechanism to index pointers by so we'll just 
 381     // keep track of the wxWidgets parent object here. 
 382     TID                             m_hThread
;    // handle and ID of the thread 
 383     wxThreadState                   m_eState
;     // state, see wxThreadState enum 
 384     unsigned int                    m_nPriority
;  // thread priority in "wx" units 
 387 void wxThreadInternal::OS2ThreadStart( void * pParam 
) 
 392     wxThread 
*pThread 
= (wxThread 
*)pParam
; 
 394     // first of all, wait for the thread to be started. 
 395     pThread
->m_critsect
.Enter(); 
 396     pThread
->m_critsect
.Leave(); 
 397     // Now check whether we hadn't been cancelled already and don't 
 398     // start the user code at all in this case. 
 399     if ( pThread
->m_internal
->GetState() == STATE_EXITED 
) 
 402         bWasCancelled 
= true; 
 404     else // do run thread 
 406         wxAppTraits 
*traits 
= wxTheApp 
? wxTheApp
->GetTraits() : NULL
; 
 409             traits
->InitializeGui(ulHab
); 
 410         dwRet 
= (DWORD
)pThread
->Entry(); 
 412             traits
->TerminateGui(ulHab
); 
 414         // enter m_critsect before changing the thread state 
 415         pThread
->m_critsect
.Enter(); 
 417         bWasCancelled 
= pThread
->m_internal
->GetState() == STATE_CANCELED
; 
 419         pThread
->m_internal
->SetState(STATE_EXITED
); 
 420         pThread
->m_critsect
.Leave(); 
 424     // if the thread was cancelled (from Delete()), then it the handle is still 
 426     if (pThread
->IsDetached() && !bWasCancelled
) 
 431     //else: the joinable threads handle will be closed when Wait() is done 
 435 void wxThreadInternal::SetPriority( 
 436   unsigned int                      nPriority
 
 439     // translate wxWidgets priority to the PM one 
 440     ULONG                           ulOS2_PriorityClass
; 
 441     ULONG                           ulOS2_SubPriority
; 
 444     m_nPriority 
= nPriority
; 
 445     if (m_nPriority 
<= 25) 
 446         ulOS2_PriorityClass 
= PRTYC_IDLETIME
; 
 447     else if (m_nPriority 
<= 50) 
 448         ulOS2_PriorityClass 
= PRTYC_REGULAR
; 
 449     else if (m_nPriority 
<= 75) 
 450         ulOS2_PriorityClass 
= PRTYC_TIMECRITICAL
; 
 451     else if (m_nPriority 
<= 100) 
 452         ulOS2_PriorityClass 
= PRTYC_FOREGROUNDSERVER
; 
 455         wxFAIL_MSG(wxT("invalid value of thread priority parameter")); 
 456         ulOS2_PriorityClass 
= PRTYC_REGULAR
; 
 458     ulOS2_SubPriority 
= (ULONG
) (((m_nPriority 
- 1) % 25 + 1) * 31.0 / 25); 
 459     ulrc 
= ::DosSetPriority( PRTYS_THREAD
 
 466         wxLogSysError(_("Can't set thread priority")); 
 470 bool wxThreadInternal::Create( wxThread
* pThread
, 
 471                                unsigned int uStackSize
) 
 478     pThread
->m_critsect
.Enter(); 
 479     tid 
= _beginthread(wxThreadInternal::OS2ThreadStart
, 
 480                              NULL
, uStackSize
, pThread
); 
 483         wxLogSysError(_("Can't create thread")); 
 488     if (m_nPriority 
!= WXTHREAD_DEFAULT_PRIORITY
) 
 490         SetPriority(m_nPriority
); 
 496 bool wxThreadInternal::Suspend() 
 498     ULONG ulrc 
= ::DosSuspendThread(m_hThread
); 
 502         wxLogSysError(_("Can not suspend thread %lu"), m_hThread
); 
 505     m_eState 
= STATE_PAUSED
; 
 510 bool wxThreadInternal::Resume() 
 512     ULONG ulrc 
= ::DosResumeThread(m_hThread
); 
 516         wxLogSysError(_("Can not resume thread %lu"), m_hThread
); 
 520     // don't change the state from STATE_EXITED because it's special and means 
 521     // we are going to terminate without running any user code - if we did it, 
 522     // the codei n Delete() wouldn't work 
 523     if ( m_eState 
!= STATE_EXITED 
) 
 525         m_eState 
= STATE_RUNNING
; 
 534 wxThread 
*wxThread::This() 
 536     wxThread
*                       pThread 
= m_pThread
; 
 540 bool wxThread::IsMain() 
 545     ::DosGetInfoBlocks(&ptib
, &ppib
); 
 547     if (ptib
->tib_ptib2
->tib2_ultid 
== s_ulIdMainThread
) 
 557 void wxThread::Yield() 
 562 void wxThread::Sleep( 
 563   unsigned long                     ulMilliseconds
 
 566     ::DosSleep(ulMilliseconds
); 
 569 int wxThread::GetCPUCount() 
 573     ulrc 
= ::DosQuerySysInfo(26, 26, (void *)&CPUCount
, sizeof(ULONG
)); 
 574     // QSV_NUMPROCESSORS(26) is typically not defined in header files 
 582 unsigned long wxThread::GetCurrentId() 
 587     ::DosGetInfoBlocks(&ptib
, &ppib
); 
 588     return (unsigned long) ptib
->tib_ptib2
->tib2_ultid
; 
 591 bool wxThread::SetConcurrency(size_t level
) 
 593     wxASSERT_MSG( IsMain(), _T("should only be called from the main thread") ); 
 595     // ok only for the default one 
 599     // Don't know how to realize this on OS/2. 
 606 wxThread::wxThread(wxThreadKind kind
) 
 608     m_internal 
= new wxThreadInternal(); 
 610     m_isDetached 
= kind 
== wxTHREAD_DETACHED
; 
 613 wxThread::~wxThread() 
 618 // create/start thread 
 619 // ------------------- 
 621 wxThreadError 
wxThread::Create( 
 622   unsigned int                      uStackSize
 
 625     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); 
 627     if ( !m_internal
->Create(this, uStackSize
) ) 
 628         return wxTHREAD_NO_RESOURCE
; 
 630     return wxTHREAD_NO_ERROR
; 
 633 wxThreadError 
wxThread::Run() 
 635     wxCriticalSectionLocker         
lock((wxCriticalSection 
&)m_critsect
); 
 637     if ( m_internal
->GetState() != STATE_NEW 
) 
 639         // actually, it may be almost any state at all, not only STATE_RUNNING 
 640         return wxTHREAD_RUNNING
; 
 645 // suspend/resume thread 
 646 // --------------------- 
 648 wxThreadError 
wxThread::Pause() 
 650     wxCriticalSectionLocker         
lock((wxCriticalSection 
&)m_critsect
); 
 652     return m_internal
->Suspend() ? wxTHREAD_NO_ERROR 
: wxTHREAD_MISC_ERROR
; 
 655 wxThreadError 
wxThread::Resume() 
 657     if (m_internal
->GetState() == STATE_NEW
) 
 659         m_internal
->SetState(STATE_RUNNING
); 
 661         return wxTHREAD_NO_ERROR
; 
 664     wxCriticalSectionLocker         
lock((wxCriticalSection 
&)m_critsect
); 
 666     return m_internal
->Resume() ? wxTHREAD_NO_ERROR 
: wxTHREAD_MISC_ERROR
; 
 672 wxThread::ExitCode 
wxThread::Wait() 
 674     // although under Windows we can wait for any thread, it's an error to 
 675     // wait for a detached one in wxWin API 
 676     wxCHECK_MSG( !IsDetached(), (ExitCode
)-1, 
 677                  _T("can't wait for detached thread") ); 
 678     ExitCode rc 
= (ExitCode
)-1; 
 683 wxThreadError 
wxThread::Delete(ExitCode 
*pRc
) 
 687     // Delete() is always safe to call, so consider all possible states 
 689     // we might need to resume the thread, but we might also not need to cancel 
 690     // it if it doesn't run yet 
 691     bool shouldResume 
= false, 
 695     // check if the thread already started to run 
 697         wxCriticalSectionLocker         
lock((wxCriticalSection 
&)m_critsect
); 
 699         if ( m_internal
->GetState() == STATE_NEW 
) 
 701             // WinThreadStart() will see it and terminate immediately, no need 
 702             // to cancel the thread - but we still need to resume it to let it 
 704             m_internal
->SetState(STATE_EXITED
); 
 706             Resume();   // it knows about STATE_EXITED special case 
 708             shouldCancel 
= false; 
 711             // shouldResume is correctly set to false here 
 715             shouldResume 
= IsPaused(); 
 719     // resume the thread if it is paused 
 723     TID hThread 
= m_internal
->GetHandle(); 
 725     if ( isRunning 
|| IsRunning()) 
 729             // set flag for wxIsWaitingForThread() 
 730             gs_bWaitingForThread 
= true; 
 733         // ask the thread to terminate 
 736             wxCriticalSectionLocker 
lock(m_critsect
); 
 738             m_internal
->Cancel(); 
 742         // we can't just wait for the thread to terminate because it might be 
 743         // calling some GUI functions and so it will never terminate before we 
 744         // process the Windows messages that result from these functions 
 745         DWORD result 
= 0;       // suppress warnings from broken compilers 
 750                 // give the thread we're waiting for chance to do the GUI call 
 752                 if ( (gs_nWaitingForGui 
> 0) && wxGuiOwnedByMainThread() ) 
 758             result 
= ::DosWaitThread(&hThread
, DCWW_NOWAIT
); 
 759             // FIXME: We ought to have a message processing loop here!! 
 763                 case ERROR_INTERRUPT
: 
 764                 case ERROR_THREAD_NOT_TERMINATED
: 
 766                 case ERROR_INVALID_THREADID
: 
 768                     // thread we're waiting for just terminated 
 769                     // or even does not exist any more. 
 773                     wxFAIL_MSG(wxT("unexpected result of DosWaitThread")); 
 777                 // event processing - needed if we are the main thread 
 778                 // to give other threads a chance to do remaining GUI 
 779                 // processing and terminate cleanly. 
 780                 wxTheApp
->HandleSockets(); 
 781                 if (wxTheApp
->Pending()) 
 782                   if ( !wxTheApp
->DoMessage() ) 
 784                       // WM_QUIT received: kill the thread 
 787                       return wxTHREAD_KILLED
; 
 794         } while ( result 
!= NO_ERROR 
); 
 796         // simply wait for the thread to terminate 
 798         // OTOH, even console apps create windows (in wxExecute, for WinSock 
 799         // &c), so may be use MsgWaitForMultipleObject() too here? 
 800         if ( ::DosWaitThread(&hThread
, DCWW_WAIT
) != NO_ERROR 
) 
 802             wxFAIL_MSG(wxT("unexpected result of DosWaitThread")); 
 804 #endif // wxUSE_GUI/!wxUSE_GUI 
 808             gs_bWaitingForThread 
= false; 
 813     // although the thread might be already in the EXITED state it might not 
 814     // have terminated yet and so we are not sure that it has actually 
 815     // terminated if the "if" above hadn't been taken 
 818         if ( !::GetExitCodeThread(hThread
, (LPDWORD
)&rc
) ) 
 820             wxLogLastError(wxT("GetExitCodeThread")); 
 824     } while ( (DWORD
)rc 
== STILL_ACTIVE 
); 
 829         // if the thread exits normally, this is done in WinThreadStart, but in 
 830         // this case it would have been too early because 
 831         // MsgWaitForMultipleObject() would fail if the thread handle was 
 832         // closed while we were waiting on it, so we must do it here 
 839     return rc 
== (ExitCode
)-1 ? wxTHREAD_MISC_ERROR 
: wxTHREAD_NO_ERROR
; 
 842 wxThreadError 
wxThread::Kill() 
 845         return wxTHREAD_NOT_RUNNING
; 
 847     ::DosKillThread(m_internal
->GetHandle()); 
 852     return wxTHREAD_NO_ERROR
; 
 855 void wxThread::Exit(ExitCode 
WXUNUSED(pStatus
)) 
 859     wxFAIL_MSG(wxT("Couldn't return from DosExit()!")); 
 862 void wxThread::SetPriority( 
 866     wxCriticalSectionLocker         
lock((wxCriticalSection 
&)m_critsect
); 
 868     m_internal
->SetPriority(nPrio
); 
 871 unsigned int wxThread::GetPriority() const 
 873     wxCriticalSectionLocker         
lock((wxCriticalSection 
&)m_critsect
); 
 875     return m_internal
->GetPriority(); 
 878 unsigned long wxThread::GetId() const 
 880     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); // const_cast 
 882     return (unsigned long)m_internal
->GetId(); 
 885 bool wxThread::IsRunning() const 
 887     wxCriticalSectionLocker         
lock((wxCriticalSection 
&)m_critsect
); 
 889     return(m_internal
->GetState() == STATE_RUNNING
); 
 892 bool wxThread::IsAlive() const 
 894     wxCriticalSectionLocker         
lock((wxCriticalSection 
&)m_critsect
); 
 896     return (m_internal
->GetState() == STATE_RUNNING
) || 
 897            (m_internal
->GetState() == STATE_PAUSED
); 
 900 bool wxThread::IsPaused() const 
 902     wxCriticalSectionLocker         
lock((wxCriticalSection 
&)m_critsect
); 
 904     return (m_internal
->GetState() == STATE_PAUSED
); 
 907 bool wxThread::TestDestroy() 
 909     wxCriticalSectionLocker         
lock((wxCriticalSection 
&)m_critsect
); 
 911     return m_internal
->GetState() == STATE_CANCELED
; 
 914 // ---------------------------------------------------------------------------- 
 915 // Automatic initialization for thread module 
 916 // ---------------------------------------------------------------------------- 
 918 class wxThreadModule 
: public wxModule
 
 921     virtual bool OnInit(); 
 922     virtual void OnExit(); 
 925     DECLARE_DYNAMIC_CLASS(wxThreadModule
) 
 928 IMPLEMENT_DYNAMIC_CLASS(wxThreadModule
, wxModule
) 
 930 bool wxThreadModule::OnInit() 
 932     gs_pCritsectWaitingForGui 
= new wxCriticalSection(); 
 934     gs_pCritsectGui 
= new wxCriticalSection(); 
 935     gs_pCritsectGui
->Enter(); 
 940     ::DosGetInfoBlocks(&ptib
, &ppib
); 
 942     s_ulIdMainThread 
= ptib
->tib_ptib2
->tib2_ultid
; 
 946 void wxThreadModule::OnExit() 
 950         gs_pCritsectGui
->Leave(); 
 951 #if (!(defined(__VISAGECPP__) && (__IBMCPP__ < 400 || __IBMC__ < 400 ))) 
 952         delete gs_pCritsectGui
; 
 954         gs_pCritsectGui 
= NULL
; 
 957 #if (!(defined(__VISAGECPP__) && (__IBMCPP__ < 400 || __IBMC__ < 400 ))) 
 958     wxDELETE(gs_pCritsectWaitingForGui
); 
 962 // ---------------------------------------------------------------------------- 
 964 // ---------------------------------------------------------------------------- 
 966 // wake up the main thread if it's in ::GetMessage() 
 967 void WXDLLEXPORT 
wxWakeUpMainThread() 
 970     if ( !::WinPostQueueMsg(wxTheApp
->m_hMq
, WM_NULL
, 0, 0) ) 
 972         // should never happen 
 973         wxLogLastError(wxT("WinPostMessage(WM_NULL)")); 
 978 void WXDLLEXPORT 
wxMutexGuiEnter() 
 980     // this would dead lock everything... 
 981     wxASSERT_MSG( !wxThread::IsMain(), 
 982                   wxT("main thread doesn't want to block in wxMutexGuiEnter()!") ); 
 984     // the order in which we enter the critical sections here is crucial!! 
 986     // set the flag telling to the main thread that we want to do some GUI 
 988         wxCriticalSectionLocker 
enter(*gs_pCritsectWaitingForGui
); 
 993     wxWakeUpMainThread(); 
 995     // now we may block here because the main thread will soon let us in 
 996     // (during the next iteration of OnIdle()) 
 997     gs_pCritsectGui
->Enter(); 
1000 void WXDLLEXPORT 
wxMutexGuiLeave() 
1002     wxCriticalSectionLocker 
enter(*gs_pCritsectWaitingForGui
); 
1004     if ( wxThread::IsMain() ) 
1006         gs_bGuiOwnedByMainThread 
= false; 
1010         // decrement the number of waiters now 
1011         wxASSERT_MSG(gs_nWaitingForGui 
> 0, 
1012                       wxT("calling wxMutexGuiLeave() without entering it first?") ); 
1014         gs_nWaitingForGui
--; 
1016         wxWakeUpMainThread(); 
1019     gs_pCritsectGui
->Leave(); 
1022 void WXDLLEXPORT 
wxMutexGuiLeaveOrEnter() 
1024     wxASSERT_MSG( wxThread::IsMain(), 
1025                   wxT("only main thread may call wxMutexGuiLeaveOrEnter()!") ); 
1027     wxCriticalSectionLocker 
enter(*gs_pCritsectWaitingForGui
); 
1029     if (gs_nWaitingForGui 
== 0) 
1031         // no threads are waiting for GUI - so we may acquire the lock without 
1032         // any danger (but only if we don't already have it) 
1033         if (!wxGuiOwnedByMainThread()) 
1035             gs_pCritsectGui
->Enter(); 
1037             gs_bGuiOwnedByMainThread 
= true; 
1039         //else: already have it, nothing to do 
1043         // some threads are waiting, release the GUI lock if we have it 
1044         if (wxGuiOwnedByMainThread()) 
1048         //else: some other worker thread is doing GUI 
1052 bool WXDLLEXPORT 
wxGuiOwnedByMainThread() 
1054     return gs_bGuiOwnedByMainThread
; 
1057 bool WXDLLEXPORT 
wxIsWaitingForThread() 
1059     return gs_bWaitingForThread
; 
1062 // ---------------------------------------------------------------------------- 
1063 // include common implementation code 
1064 // ---------------------------------------------------------------------------- 
1066 #include "wx/thrimpl.cpp"