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 
Lock(unsigned long ms
) { return LockTimeout(ms
); } 
 100     wxMutexError 
TryLock(); 
 101     wxMutexError 
Unlock(); 
 104     wxMutexError 
LockTimeout(ULONG ulMilliseconds
); 
 108 // all mutexes are "pseudo-"recursive under OS2 so we don't use mutexType 
 109 // (Calls to DosRequestMutexSem and DosReleaseMutexSem can be nested, but 
 110 //  the request count for a semaphore cannot exceed 65535. If an attempt is 
 111 //  made to exceed this number, ERROR_TOO_MANY_SEM_REQUESTS is returned.) 
 112 wxMutexInternal::wxMutexInternal(wxMutexType 
WXUNUSED(eMutexType
)) 
 114     APIRET ulrc 
= ::DosCreateMutexSem(NULL
, &m_vMutex
, 0L, FALSE
); 
 117         wxLogSysError(_("Can not create mutex.")); 
 122 wxMutexInternal::~wxMutexInternal() 
 126         if (::DosCloseMutexSem(m_vMutex
)) 
 127             wxLogLastError(_T("DosCloseMutexSem(mutex)")); 
 131 wxMutexError 
wxMutexInternal::TryLock() 
 133     const wxMutexError rc 
= LockTimeout( SEM_IMMEDIATE_RETURN 
); 
 135     // we have a special return code for timeout in this case 
 136     return rc 
== wxMUTEX_TIMEOUT 
? wxMUTEX_BUSY 
: rc
; 
 139 wxMutexError 
wxMutexInternal::LockTimeout(ULONG ulMilliseconds
) 
 143     ulrc 
= ::DosRequestMutexSem(m_vMutex
, ulMilliseconds
); 
 148             return wxMUTEX_TIMEOUT
; 
 149         case ERROR_TOO_MANY_SEM_REQUESTS
: 
 156         case ERROR_INVALID_HANDLE
: 
 157         case ERROR_INTERRUPT
: 
 158         case ERROR_SEM_OWNER_DIED
: 
 159             wxLogSysError(_("Couldn't acquire a mutex lock")); 
 160             return wxMUTEX_MISC_ERROR
; 
 163             wxFAIL_MSG(wxT("impossible return value in wxMutex::Lock")); 
 164             return wxMUTEX_MISC_ERROR
; 
 166     return wxMUTEX_NO_ERROR
; 
 169 wxMutexError 
wxMutexInternal::Unlock() 
 173     ulrc 
= ::DosReleaseMutexSem(m_vMutex
); 
 176         wxLogSysError(_("Couldn't release a mutex")); 
 177         return wxMUTEX_MISC_ERROR
; 
 179     return wxMUTEX_NO_ERROR
; 
 182 // -------------------------------------------------------------------------- 
 184 // -------------------------------------------------------------------------- 
 186 // a trivial wrapper around OS2 event semaphore 
 187 class wxSemaphoreInternal
 
 190     wxSemaphoreInternal(int initialcount
, int maxcount
); 
 191     ~wxSemaphoreInternal(); 
 193     bool IsOk() const { return m_vEvent 
!= NULL
; } 
 195     wxSemaError 
Wait() { return WaitTimeout(SEM_INDEFINITE_WAIT
); } 
 196     wxSemaError 
TryWait() { return WaitTimeout(SEM_IMMEDIATE_RETURN
); } 
 197     wxSemaError 
WaitTimeout(unsigned long milliseconds
); 
 208 wxSemaphoreInternal::wxSemaphoreInternal(int initialcount
, int maxcount
) 
 213         // make it practically infinite 
 217     m_count 
= initialcount
; 
 218     m_maxcount 
= maxcount
; 
 219     ulrc 
= ::DosCreateMutexSem(NULL
, &m_vMutex
, 0L, FALSE
); 
 222         wxLogLastError(_T("DosCreateMutexSem()")); 
 227     ulrc 
= ::DosCreateEventSem(NULL
, &m_vEvent
, 0L, FALSE
); 
 230         wxLogLastError(_T("DosCreateEventSem()")); 
 231         ::DosCloseMutexSem(m_vMutex
); 
 236         ::DosPostEventSem(m_vEvent
); 
 239 wxSemaphoreInternal::~wxSemaphoreInternal() 
 243         if ( ::DosCloseEventSem(m_vEvent
) ) 
 245             wxLogLastError(_T("DosCloseEventSem(semaphore)")); 
 247         if ( ::DosCloseMutexSem(m_vMutex
) ) 
 249             wxLogLastError(_T("DosCloseMutexSem(semaphore)")); 
 256 wxSemaError 
wxSemaphoreInternal::WaitTimeout(unsigned long ulMilliseconds
) 
 260         ulrc 
= ::DosWaitEventSem(m_vEvent
, ulMilliseconds 
); 
 267                 if (ulMilliseconds 
== SEM_IMMEDIATE_RETURN
) 
 270                     return wxSEMA_TIMEOUT
; 
 273                 wxLogLastError(_T("DosWaitEventSem(semaphore)")); 
 274                 return wxSEMA_MISC_ERROR
; 
 276         ulrc 
= :: DosRequestMutexSem(m_vMutex
, ulMilliseconds
); 
 284             case ERROR_TOO_MANY_SEM_REQUESTS
: 
 285                 if (ulMilliseconds 
== SEM_IMMEDIATE_RETURN
) 
 288                     return wxSEMA_TIMEOUT
; 
 291                 wxFAIL_MSG(wxT("DosRequestMutexSem(mutex)")); 
 292                 return wxSEMA_MISC_ERROR
; 
 303             ::DosResetEventSem(m_vEvent
, &ulPostCount
); 
 305         ::DosReleaseMutexSem(m_vMutex
); 
 307             return wxSEMA_NO_ERROR
; 
 308     } while (ulMilliseconds 
== SEM_INDEFINITE_WAIT
); 
 310     if (ulMilliseconds 
== SEM_IMMEDIATE_RETURN
) 
 312     return wxSEMA_TIMEOUT
; 
 315 wxSemaError 
wxSemaphoreInternal::Post() 
 318     ulrc 
= ::DosRequestMutexSem(m_vMutex
, SEM_INDEFINITE_WAIT
); 
 319     if (ulrc 
!= NO_ERROR
) 
 320         return wxSEMA_MISC_ERROR
; 
 322     if (m_count 
< m_maxcount
) 
 325         ulrc 
= ::DosPostEventSem(m_vEvent
); 
 328     ::DosReleaseMutexSem(m_vMutex
); 
 330         return wxSEMA_OVERFLOW
; 
 331     if ( ulrc 
!= NO_ERROR 
&& ulrc 
!= ERROR_ALREADY_POSTED 
) 
 333         wxLogLastError(_T("DosPostEventSem(semaphore)")); 
 335         return wxSEMA_MISC_ERROR
; 
 338     return wxSEMA_NO_ERROR
; 
 341 // ---------------------------------------------------------------------------- 
 342 // wxThread implementation 
 343 // ---------------------------------------------------------------------------- 
 345 // wxThreadInternal class 
 346 // ---------------------- 
 348 class wxThreadInternal
 
 351     inline wxThreadInternal() 
 354         m_eState 
= STATE_NEW
; 
 355         m_nPriority 
= WXTHREAD_DEFAULT_PRIORITY
; 
 363     // create a new (suspended) thread (for the given thread object) 
 364     bool Create( wxThread
*    pThread
 
 365                 ,unsigned int uStackSize
 
 368     // suspend/resume/terminate 
 371     inline void Cancel() { m_eState 
= STATE_CANCELED
; } 
 374     inline void SetState(wxThreadState eState
) { m_eState 
= eState
; } 
 375     inline wxThreadState 
GetState() const { return m_eState
; } 
 378     void                SetPriority(unsigned int nPriority
); 
 379     inline unsigned int GetPriority() const { return m_nPriority
; } 
 381     // thread handle and id 
 382     inline TID 
GetHandle() const { return m_hThread
; } 
 383     TID  
GetId() const { return m_hThread
; } 
 386     static void OS2ThreadStart(void* pParam
); 
 389     // Threads in OS/2 have only an ID, so m_hThread is both it's handle and ID 
 390     // PM also has no real Tls mechanism to index pointers by so we'll just 
 391     // keep track of the wxWidgets parent object here. 
 392     TID                             m_hThread
;    // handle and ID of the thread 
 393     wxThreadState                   m_eState
;     // state, see wxThreadState enum 
 394     unsigned int                    m_nPriority
;  // thread priority in "wx" units 
 397 void wxThreadInternal::OS2ThreadStart( void * pParam 
) 
 402     wxThread 
*pThread 
= (wxThread 
*)pParam
; 
 404     // first of all, wait for the thread to be started. 
 405     pThread
->m_critsect
.Enter(); 
 406     pThread
->m_critsect
.Leave(); 
 407     // Now check whether we hadn't been cancelled already and don't 
 408     // start the user code at all in this case. 
 409     if ( pThread
->m_internal
->GetState() == STATE_EXITED 
) 
 412         bWasCancelled 
= true; 
 414     else // do run thread 
 416         wxAppTraits 
*traits 
= wxTheApp 
? wxTheApp
->GetTraits() : NULL
; 
 419             traits
->InitializeGui(ulHab
); 
 420         dwRet 
= (DWORD
)pThread
->Entry(); 
 422             traits
->TerminateGui(ulHab
); 
 424         // enter m_critsect before changing the thread state 
 425         pThread
->m_critsect
.Enter(); 
 427         bWasCancelled 
= pThread
->m_internal
->GetState() == STATE_CANCELED
; 
 429         pThread
->m_internal
->SetState(STATE_EXITED
); 
 430         pThread
->m_critsect
.Leave(); 
 434     // if the thread was cancelled (from Delete()), then it the handle is still 
 436     if (pThread
->IsDetached() && !bWasCancelled
) 
 441     //else: the joinable threads handle will be closed when Wait() is done 
 445 void wxThreadInternal::SetPriority( 
 446   unsigned int                      nPriority
 
 449     // translate wxWidgets priority to the PM one 
 450     ULONG                           ulOS2_PriorityClass
; 
 451     ULONG                           ulOS2_SubPriority
; 
 454     m_nPriority 
= nPriority
; 
 455     if (m_nPriority 
<= 25) 
 456         ulOS2_PriorityClass 
= PRTYC_IDLETIME
; 
 457     else if (m_nPriority 
<= 50) 
 458         ulOS2_PriorityClass 
= PRTYC_REGULAR
; 
 459     else if (m_nPriority 
<= 75) 
 460         ulOS2_PriorityClass 
= PRTYC_TIMECRITICAL
; 
 461     else if (m_nPriority 
<= 100) 
 462         ulOS2_PriorityClass 
= PRTYC_FOREGROUNDSERVER
; 
 465         wxFAIL_MSG(wxT("invalid value of thread priority parameter")); 
 466         ulOS2_PriorityClass 
= PRTYC_REGULAR
; 
 468     ulOS2_SubPriority 
= (ULONG
) (((m_nPriority 
- 1) % 25 + 1) * 31.0 / 25); 
 469     ulrc 
= ::DosSetPriority( PRTYS_THREAD
 
 476         wxLogSysError(_("Can't set thread priority")); 
 480 bool wxThreadInternal::Create( wxThread
* pThread
, 
 481                                unsigned int uStackSize
) 
 488     pThread
->m_critsect
.Enter(); 
 489     tid 
= _beginthread(wxThreadInternal::OS2ThreadStart
, 
 490                              NULL
, uStackSize
, pThread
); 
 493         wxLogSysError(_("Can't create thread")); 
 498     if (m_nPriority 
!= WXTHREAD_DEFAULT_PRIORITY
) 
 500         SetPriority(m_nPriority
); 
 506 bool wxThreadInternal::Suspend() 
 508     ULONG ulrc 
= ::DosSuspendThread(m_hThread
); 
 512         wxLogSysError(_("Can not suspend thread %lu"), m_hThread
); 
 515     m_eState 
= STATE_PAUSED
; 
 520 bool wxThreadInternal::Resume() 
 522     ULONG ulrc 
= ::DosResumeThread(m_hThread
); 
 526         wxLogSysError(_("Can not resume thread %lu"), m_hThread
); 
 530     // don't change the state from STATE_EXITED because it's special and means 
 531     // we are going to terminate without running any user code - if we did it, 
 532     // the codei n Delete() wouldn't work 
 533     if ( m_eState 
!= STATE_EXITED 
) 
 535         m_eState 
= STATE_RUNNING
; 
 544 wxThread 
*wxThread::This() 
 546     wxThread
*                       pThread 
= m_pThread
; 
 550 bool wxThread::IsMain() 
 555     ::DosGetInfoBlocks(&ptib
, &ppib
); 
 557     if (ptib
->tib_ptib2
->tib2_ultid 
== s_ulIdMainThread
) 
 567 void wxThread::Yield() 
 572 int wxThread::GetCPUCount() 
 576     ulrc 
= ::DosQuerySysInfo(26, 26, (void *)&CPUCount
, sizeof(ULONG
)); 
 577     // QSV_NUMPROCESSORS(26) is typically not defined in header files 
 585 unsigned long wxThread::GetCurrentId() 
 590     ::DosGetInfoBlocks(&ptib
, &ppib
); 
 591     return (unsigned long) ptib
->tib_ptib2
->tib2_ultid
; 
 594 bool wxThread::SetConcurrency(size_t level
) 
 596     wxASSERT_MSG( IsMain(), _T("should only be called from the main thread") ); 
 598     // ok only for the default one 
 602     // Don't know how to realize this on OS/2. 
 609 wxThread::wxThread(wxThreadKind kind
) 
 611     m_internal 
= new wxThreadInternal(); 
 613     m_isDetached 
= kind 
== wxTHREAD_DETACHED
; 
 616 wxThread::~wxThread() 
 621 // create/start thread 
 622 // ------------------- 
 624 wxThreadError 
wxThread::Create( 
 625   unsigned int                      uStackSize
 
 628     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); 
 630     if ( !m_internal
->Create(this, uStackSize
) ) 
 631         return wxTHREAD_NO_RESOURCE
; 
 633     return wxTHREAD_NO_ERROR
; 
 636 wxThreadError 
wxThread::Run() 
 638     wxCriticalSectionLocker         
lock((wxCriticalSection 
&)m_critsect
); 
 640     if ( m_internal
->GetState() != STATE_NEW 
) 
 642         // actually, it may be almost any state at all, not only STATE_RUNNING 
 643         return wxTHREAD_RUNNING
; 
 648 // suspend/resume thread 
 649 // --------------------- 
 651 wxThreadError 
wxThread::Pause() 
 653     wxCriticalSectionLocker         
lock((wxCriticalSection 
&)m_critsect
); 
 655     return m_internal
->Suspend() ? wxTHREAD_NO_ERROR 
: wxTHREAD_MISC_ERROR
; 
 658 wxThreadError 
wxThread::Resume() 
 660     if (m_internal
->GetState() == STATE_NEW
) 
 662         m_internal
->SetState(STATE_RUNNING
); 
 664         return wxTHREAD_NO_ERROR
; 
 667     wxCriticalSectionLocker         
lock((wxCriticalSection 
&)m_critsect
); 
 669     return m_internal
->Resume() ? wxTHREAD_NO_ERROR 
: wxTHREAD_MISC_ERROR
; 
 675 wxThread::ExitCode 
wxThread::Wait() 
 677     // although under Windows we can wait for any thread, it's an error to 
 678     // wait for a detached one in wxWin API 
 679     wxCHECK_MSG( !IsDetached(), (ExitCode
)-1, 
 680                  _T("can't wait for detached thread") ); 
 681     ExitCode rc 
= (ExitCode
)-1; 
 686 wxThreadError 
wxThread::Delete(ExitCode 
*pRc
) 
 690     // Delete() is always safe to call, so consider all possible states 
 692     // we might need to resume the thread, but we might also not need to cancel 
 693     // it if it doesn't run yet 
 694     bool shouldResume 
= false, 
 698     // check if the thread already started to run 
 700         wxCriticalSectionLocker         
lock((wxCriticalSection 
&)m_critsect
); 
 702         if ( m_internal
->GetState() == STATE_NEW 
) 
 704             // WinThreadStart() will see it and terminate immediately, no need 
 705             // to cancel the thread - but we still need to resume it to let it 
 707             m_internal
->SetState(STATE_EXITED
); 
 709             Resume();   // it knows about STATE_EXITED special case 
 711             shouldCancel 
= false; 
 714             // shouldResume is correctly set to false here 
 718             shouldResume 
= IsPaused(); 
 722     // resume the thread if it is paused 
 726     TID hThread 
= m_internal
->GetHandle(); 
 728     if ( isRunning 
|| IsRunning()) 
 732             // set flag for wxIsWaitingForThread() 
 733             gs_bWaitingForThread 
= true; 
 736         // ask the thread to terminate 
 739             wxCriticalSectionLocker 
lock(m_critsect
); 
 741             m_internal
->Cancel(); 
 745         // we can't just wait for the thread to terminate because it might be 
 746         // calling some GUI functions and so it will never terminate before we 
 747         // process the Windows messages that result from these functions 
 748         DWORD result 
= 0;       // suppress warnings from broken compilers 
 753                 // give the thread we're waiting for chance to do the GUI call 
 755                 if ( (gs_nWaitingForGui 
> 0) && wxGuiOwnedByMainThread() ) 
 761             result 
= ::DosWaitThread(&hThread
, DCWW_NOWAIT
); 
 762             // FIXME: We ought to have a message processing loop here!! 
 766                 case ERROR_INTERRUPT
: 
 767                 case ERROR_THREAD_NOT_TERMINATED
: 
 769                 case ERROR_INVALID_THREADID
: 
 771                     // thread we're waiting for just terminated 
 772                     // or even does not exist any more. 
 776                     wxFAIL_MSG(wxT("unexpected result of DosWaitThread")); 
 780                 // event processing - needed if we are the main thread 
 781                 // to give other threads a chance to do remaining GUI 
 782                 // processing and terminate cleanly. 
 783                 wxTheApp
->HandleSockets(); 
 784                 if (wxTheApp
->Pending()) 
 785                   if ( !wxTheApp
->DoMessage() ) 
 787                       // WM_QUIT received: kill the thread 
 790                       return wxTHREAD_KILLED
; 
 797         } while ( result 
!= NO_ERROR 
); 
 799         // simply wait for the thread to terminate 
 801         // OTOH, even console apps create windows (in wxExecute, for WinSock 
 802         // &c), so may be use MsgWaitForMultipleObject() too here? 
 803         if ( ::DosWaitThread(&hThread
, DCWW_WAIT
) != NO_ERROR 
) 
 805             wxFAIL_MSG(wxT("unexpected result of DosWaitThread")); 
 807 #endif // wxUSE_GUI/!wxUSE_GUI 
 811             gs_bWaitingForThread 
= false; 
 816     // although the thread might be already in the EXITED state it might not 
 817     // have terminated yet and so we are not sure that it has actually 
 818     // terminated if the "if" above hadn't been taken 
 821         if ( !::GetExitCodeThread(hThread
, (LPDWORD
)&rc
) ) 
 823             wxLogLastError(wxT("GetExitCodeThread")); 
 827     } while ( (DWORD
)rc 
== STILL_ACTIVE 
); 
 832         // if the thread exits normally, this is done in WinThreadStart, but in 
 833         // this case it would have been too early because 
 834         // MsgWaitForMultipleObject() would fail if the thread handle was 
 835         // closed while we were waiting on it, so we must do it here 
 842     return rc 
== (ExitCode
)-1 ? wxTHREAD_MISC_ERROR 
: wxTHREAD_NO_ERROR
; 
 845 wxThreadError 
wxThread::Kill() 
 848         return wxTHREAD_NOT_RUNNING
; 
 850     ::DosKillThread(m_internal
->GetHandle()); 
 855     return wxTHREAD_NO_ERROR
; 
 858 void wxThread::Exit(ExitCode 
WXUNUSED(pStatus
)) 
 862     wxFAIL_MSG(wxT("Couldn't return from DosExit()!")); 
 865 void wxThread::SetPriority( 
 869     wxCriticalSectionLocker         
lock((wxCriticalSection 
&)m_critsect
); 
 871     m_internal
->SetPriority(nPrio
); 
 874 unsigned int wxThread::GetPriority() const 
 876     wxCriticalSectionLocker         
lock((wxCriticalSection 
&)m_critsect
); 
 878     return m_internal
->GetPriority(); 
 881 unsigned long wxThread::GetId() const 
 883     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); // const_cast 
 885     return (unsigned long)m_internal
->GetId(); 
 888 bool wxThread::IsRunning() const 
 890     wxCriticalSectionLocker         
lock((wxCriticalSection 
&)m_critsect
); 
 892     return(m_internal
->GetState() == STATE_RUNNING
); 
 895 bool wxThread::IsAlive() const 
 897     wxCriticalSectionLocker         
lock((wxCriticalSection 
&)m_critsect
); 
 899     return (m_internal
->GetState() == STATE_RUNNING
) || 
 900            (m_internal
->GetState() == STATE_PAUSED
); 
 903 bool wxThread::IsPaused() const 
 905     wxCriticalSectionLocker         
lock((wxCriticalSection 
&)m_critsect
); 
 907     return (m_internal
->GetState() == STATE_PAUSED
); 
 910 bool wxThread::TestDestroy() 
 912     wxCriticalSectionLocker         
lock((wxCriticalSection 
&)m_critsect
); 
 914     return m_internal
->GetState() == STATE_CANCELED
; 
 917 // ---------------------------------------------------------------------------- 
 918 // Automatic initialization for thread module 
 919 // ---------------------------------------------------------------------------- 
 921 class wxThreadModule 
: public wxModule
 
 924     virtual bool OnInit(); 
 925     virtual void OnExit(); 
 928     DECLARE_DYNAMIC_CLASS(wxThreadModule
) 
 931 IMPLEMENT_DYNAMIC_CLASS(wxThreadModule
, wxModule
) 
 933 bool wxThreadModule::OnInit() 
 935     gs_pCritsectWaitingForGui 
= new wxCriticalSection(); 
 937     gs_pCritsectGui 
= new wxCriticalSection(); 
 938     gs_pCritsectGui
->Enter(); 
 943     ::DosGetInfoBlocks(&ptib
, &ppib
); 
 945     s_ulIdMainThread 
= ptib
->tib_ptib2
->tib2_ultid
; 
 949 void wxThreadModule::OnExit() 
 953         gs_pCritsectGui
->Leave(); 
 954 #if (!(defined(__VISAGECPP__) && (__IBMCPP__ < 400 || __IBMC__ < 400 ))) 
 955         delete gs_pCritsectGui
; 
 957         gs_pCritsectGui 
= NULL
; 
 960 #if (!(defined(__VISAGECPP__) && (__IBMCPP__ < 400 || __IBMC__ < 400 ))) 
 961     wxDELETE(gs_pCritsectWaitingForGui
); 
 965 // ---------------------------------------------------------------------------- 
 967 // ---------------------------------------------------------------------------- 
 969 // wake up the main thread if it's in ::GetMessage() 
 970 void WXDLLEXPORT 
wxWakeUpMainThread() 
 973     if ( !::WinPostQueueMsg(wxTheApp
->m_hMq
, WM_NULL
, 0, 0) ) 
 975         // should never happen 
 976         wxLogLastError(wxT("WinPostMessage(WM_NULL)")); 
 981 void wxMutexGuiEnterImpl() 
 983     // this would dead lock everything... 
 984     wxASSERT_MSG( !wxThread::IsMain(), 
 985                   wxT("main thread doesn't want to block in wxMutexGuiEnter()!") ); 
 987     // the order in which we enter the critical sections here is crucial!! 
 989     // set the flag telling to the main thread that we want to do some GUI 
 991         wxCriticalSectionLocker 
enter(*gs_pCritsectWaitingForGui
); 
 996     wxWakeUpMainThread(); 
 998     // now we may block here because the main thread will soon let us in 
 999     // (during the next iteration of OnIdle()) 
1000     gs_pCritsectGui
->Enter(); 
1003 void wxMutexGuiLeaveImpl() 
1005     wxCriticalSectionLocker 
enter(*gs_pCritsectWaitingForGui
); 
1007     if ( wxThread::IsMain() ) 
1009         gs_bGuiOwnedByMainThread 
= false; 
1013         // decrement the number of waiters now 
1014         wxASSERT_MSG(gs_nWaitingForGui 
> 0, 
1015                       wxT("calling wxMutexGuiLeave() without entering it first?") ); 
1017         gs_nWaitingForGui
--; 
1019         wxWakeUpMainThread(); 
1022     gs_pCritsectGui
->Leave(); 
1025 void WXDLLEXPORT 
wxMutexGuiLeaveOrEnter() 
1027     wxASSERT_MSG( wxThread::IsMain(), 
1028                   wxT("only main thread may call wxMutexGuiLeaveOrEnter()!") ); 
1030     wxCriticalSectionLocker 
enter(*gs_pCritsectWaitingForGui
); 
1032     if (gs_nWaitingForGui 
== 0) 
1034         // no threads are waiting for GUI - so we may acquire the lock without 
1035         // any danger (but only if we don't already have it) 
1036         if (!wxGuiOwnedByMainThread()) 
1038             gs_pCritsectGui
->Enter(); 
1040             gs_bGuiOwnedByMainThread 
= true; 
1042         //else: already have it, nothing to do 
1046         // some threads are waiting, release the GUI lock if we have it 
1047         if (wxGuiOwnedByMainThread()) 
1051         //else: some other worker thread is doing GUI 
1055 bool WXDLLEXPORT 
wxGuiOwnedByMainThread() 
1057     return gs_bGuiOwnedByMainThread
; 
1060 bool WXDLLEXPORT 
wxIsWaitingForThread() 
1062     return gs_bWaitingForThread
; 
1065 // ---------------------------------------------------------------------------- 
1066 // include common implementation code 
1067 // ---------------------------------------------------------------------------- 
1069 #include "wx/thrimpl.cpp"