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) 
  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" 
  29 #include "wx/apptrait.h" 
  30 #include "wx/module.h" 
  34 #include "wx/thread.h" 
  36 #define INCL_DOSSEMAPHORES 
  37 #define INCL_DOSPROCESS 
  44 // the possible states of the thread ("=>" shows all possible transitions from 
  48     STATE_NEW
,          // didn't start execution yet (=> RUNNING) 
  49     STATE_RUNNING
,      // thread is running (=> PAUSED, CANCELED) 
  50     STATE_PAUSED
,       // thread is temporarily suspended (=> RUNNING) 
  51     STATE_CANCELED
,     // thread should terminate a.s.a.p. (=> EXITED) 
  52     STATE_EXITED        
// thread is terminating 
  55 // ---------------------------------------------------------------------------- 
  56 // this module's globals 
  57 // ---------------------------------------------------------------------------- 
  59 // id of the main thread - the one which can call GUI functions without first 
  60 // calling wxMutexGuiEnter() 
  61 static ULONG                        s_ulIdMainThread 
= 1; 
  62 wxMutex
*                            p_wxMainMutex
; 
  64 // OS2 substitute for Tls pointer the current parent thread object 
  65 wxThread
*                           m_pThread
;    // pointer to the wxWidgets thread object 
  67 // if it's FALSE, some secondary thread is holding the GUI lock 
  68 static bool gs_bGuiOwnedByMainThread 
= TRUE
; 
  70 // critical section which controls access to all GUI functions: any secondary 
  71 // thread (i.e. except the main one) must enter this crit section before doing 
  73 static wxCriticalSection 
*gs_pCritsectGui 
= NULL
; 
  75 // critical section which protects s_nWaitingForGui variable 
  76 static wxCriticalSection 
*gs_pCritsectWaitingForGui 
= NULL
; 
  78 // number of threads waiting for GUI in wxMutexGuiEnter() 
  79 static size_t gs_nWaitingForGui 
= 0; 
  81 // are we waiting for a thread termination? 
  82 static bool gs_bWaitingForThread 
= FALSE
; 
  84 // ============================================================================ 
  85 // OS/2 implementation of thread and related classes 
  86 // ============================================================================ 
  88 // ---------------------------------------------------------------------------- 
  89 // wxMutex implementation 
  90 // ---------------------------------------------------------------------------- 
  94     wxMutexInternal(wxMutexType mutexType
); 
  97     bool IsOk() const { return m_vMutex 
!= NULL
; } 
  99     wxMutexError 
Lock() { return LockTimeout(SEM_INDEFINITE_WAIT
); } 
 100     wxMutexError 
TryLock() { return LockTimeout(SEM_IMMEDIATE_RETURN
); } 
 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( 
 113   wxMutexType                       
WXUNUSED(eMutexType
) 
 118     ulrc 
= ::DosCreateMutexSem(NULL
, &m_vMutex
, 0L, FALSE
); 
 121         wxLogSysError(_("Can not create mutex.")); 
 126 wxMutexInternal::~wxMutexInternal() 
 130         if (::DosCloseMutexSem(m_vMutex
)) 
 131             wxLogLastError(_T("DosCloseMutexSem(mutex)")); 
 135 wxMutexError 
wxMutexInternal::LockTimeout(ULONG ulMilliseconds
) 
 139     ulrc 
= ::DosRequestMutexSem(m_vMutex
, ulMilliseconds
); 
 144         case ERROR_TOO_MANY_SEM_REQUESTS
: 
 151         case ERROR_INVALID_HANDLE
: 
 152         case ERROR_INTERRUPT
: 
 153         case ERROR_SEM_OWNER_DIED
: 
 154             wxLogSysError(_("Couldn't acquire a mutex lock")); 
 155             return wxMUTEX_MISC_ERROR
; 
 158             wxFAIL_MSG(wxT("impossible return value in wxMutex::Lock")); 
 159             return wxMUTEX_MISC_ERROR
; 
 161     return wxMUTEX_NO_ERROR
; 
 164 wxMutexError 
wxMutexInternal::Unlock() 
 168     ulrc 
= ::DosReleaseMutexSem(m_vMutex
); 
 171         wxLogSysError(_("Couldn't release a mutex")); 
 172         return wxMUTEX_MISC_ERROR
; 
 174     return wxMUTEX_NO_ERROR
; 
 177 // -------------------------------------------------------------------------- 
 179 // -------------------------------------------------------------------------- 
 181 // a trivial wrapper around OS2 event semaphore 
 182 class wxSemaphoreInternal
 
 185     wxSemaphoreInternal(int initialcount
, int maxcount
); 
 186     ~wxSemaphoreInternal(); 
 188     bool IsOk() const { return m_vEvent 
!= NULL
; } 
 190     wxSemaError 
Wait() { return WaitTimeout(SEM_INDEFINITE_WAIT
); } 
 191     wxSemaError 
TryWait() { return WaitTimeout(SEM_IMMEDIATE_RETURN
); } 
 192     wxSemaError 
WaitTimeout(unsigned long milliseconds
); 
 203 wxSemaphoreInternal::wxSemaphoreInternal(int initialcount
, int maxcount
) 
 208         // make it practically infinite 
 212     m_count 
= initialcount
; 
 213     m_maxcount 
= maxcount
; 
 214     ulrc 
= ::DosCreateMutexSem(NULL
, &m_vMutex
, 0L, FALSE
); 
 217         wxLogLastError(_T("DosCreateMutexSem()")); 
 222     ulrc 
= ::DosCreateEventSem(NULL
, &m_vEvent
, 0L, FALSE
); 
 225         wxLogLastError(_T("DosCreateEventSem()")); 
 226         ::DosCloseMutexSem(m_vMutex
); 
 231         ::DosPostEventSem(m_vEvent
); 
 234 wxSemaphoreInternal::~wxSemaphoreInternal() 
 238         if ( ::DosCloseEventSem(m_vEvent
) ) 
 240             wxLogLastError(_T("DosCloseEventSem(semaphore)")); 
 242         if ( ::DosCloseMutexSem(m_vMutex
) ) 
 244             wxLogLastError(_T("DosCloseMutexSem(semaphore)")); 
 251 wxSemaError 
wxSemaphoreInternal::WaitTimeout(unsigned long ulMilliseconds
) 
 255         ulrc 
= ::DosWaitEventSem(m_vEvent
, ulMilliseconds 
); 
 262                 if (ulMilliseconds 
== SEM_IMMEDIATE_RETURN
) 
 265                     return wxSEMA_TIMEOUT
; 
 268                 wxLogLastError(_T("DosWaitEventSem(semaphore)")); 
 269                 return wxSEMA_MISC_ERROR
; 
 271         ulrc 
= :: DosRequestMutexSem(m_vMutex
, ulMilliseconds
); 
 279             case ERROR_TOO_MANY_SEM_REQUESTS
: 
 280                 if (ulMilliseconds 
== SEM_IMMEDIATE_RETURN
) 
 283                     return wxSEMA_TIMEOUT
; 
 286                 wxFAIL_MSG(wxT("DosRequestMutexSem(mutex)")); 
 287                 return wxSEMA_MISC_ERROR
; 
 298             ::DosResetEventSem(m_vEvent
, &ulPostCount
); 
 300         ::DosReleaseMutexSem(m_vMutex
); 
 302             return wxSEMA_NO_ERROR
; 
 303     } while (ulMilliseconds 
== SEM_INDEFINITE_WAIT
); 
 305     if (ulMilliseconds 
== SEM_IMMEDIATE_RETURN
) 
 307     return wxSEMA_TIMEOUT
; 
 310 wxSemaError 
wxSemaphoreInternal::Post() 
 313     ulrc 
= ::DosRequestMutexSem(m_vMutex
, SEM_INDEFINITE_WAIT
); 
 314     if (ulrc 
!= NO_ERROR
) 
 315         return wxSEMA_MISC_ERROR
; 
 317     if (m_count 
< m_maxcount
) 
 320         ulrc 
= ::DosPostEventSem(m_vEvent
); 
 323     ::DosReleaseMutexSem(m_vMutex
); 
 325         return wxSEMA_OVERFLOW
; 
 326     if ( ulrc 
!= NO_ERROR 
&& ulrc 
!= ERROR_ALREADY_POSTED 
) 
 328         wxLogLastError(_T("DosPostEventSem(semaphore)")); 
 330         return wxSEMA_MISC_ERROR
; 
 333     return wxSEMA_NO_ERROR
; 
 336 // ---------------------------------------------------------------------------- 
 337 // wxThread implementation 
 338 // ---------------------------------------------------------------------------- 
 340 // wxThreadInternal class 
 341 // ---------------------- 
 343 class wxThreadInternal
 
 346     inline wxThreadInternal() 
 349         m_eState 
= STATE_NEW
; 
 350         m_nPriority 
= WXTHREAD_DEFAULT_PRIORITY
; 
 358     // create a new (suspended) thread (for the given thread object) 
 359     bool Create( wxThread
*    pThread
 
 360                 ,unsigned int uStackSize
 
 363     // suspend/resume/terminate 
 366     inline void Cancel() { m_eState 
= STATE_CANCELED
; } 
 369     inline void SetState(wxThreadState eState
) { m_eState 
= eState
; } 
 370     inline wxThreadState 
GetState() const { return m_eState
; } 
 373     void                SetPriority(unsigned int nPriority
); 
 374     inline unsigned int GetPriority() const { return m_nPriority
; } 
 376     // thread handle and id 
 377     inline TID 
GetHandle() const { return m_hThread
; } 
 378     TID  
GetId() const { return m_hThread
; } 
 381     static void OS2ThreadStart(void* pParam
); 
 384     // Threads in OS/2 have only an ID, so m_hThread is both it's handle and ID 
 385     // PM also has no real Tls mechanism to index pointers by so we'll just 
 386     // keep track of the wxWidgets parent object here. 
 387     TID                             m_hThread
;    // handle and ID of the thread 
 388     wxThreadState                   m_eState
;     // state, see wxThreadState enum 
 389     unsigned int                    m_nPriority
;  // thread priority in "wx" units 
 392 void wxThreadInternal::OS2ThreadStart( 
 399     wxThread 
*pThread 
= (wxThread 
*)pParam
; 
 401     // first of all, wait for the thread to be started. 
 402     pThread
->m_critsect
.Enter(); 
 403     pThread
->m_critsect
.Leave(); 
 404     // Now check whether we hadn't been cancelled already and don't 
 405     // start the user code at all in this case. 
 406     if ( pThread
->m_internal
->GetState() == STATE_EXITED 
) 
 409         bWasCancelled 
= TRUE
; 
 411     else // do run thread 
 413         wxAppTraits 
*traits 
= wxTheApp 
? wxTheApp
->GetTraits() : NULL
; 
 416             traits
->InitializeGui(ulHab
); 
 417         dwRet 
= (DWORD
)pThread
->Entry(); 
 419             traits
->TerminateGui(ulHab
); 
 421         // enter m_critsect before changing the thread state 
 422         pThread
->m_critsect
.Enter(); 
 424         bWasCancelled 
= pThread
->m_internal
->GetState() == STATE_CANCELED
; 
 426         pThread
->m_internal
->SetState(STATE_EXITED
); 
 427         pThread
->m_critsect
.Leave(); 
 431     // if the thread was cancelled (from Delete()), then it the handle is still 
 433     if (pThread
->IsDetached() && !bWasCancelled
) 
 438     //else: the joinable threads handle will be closed when Wait() is done 
 442 void wxThreadInternal::SetPriority( 
 443   unsigned int                      nPriority
 
 446     // translate wxWidgets priority to the PM one 
 447     ULONG                           ulOS2_PriorityClass
; 
 448     ULONG                           ulOS2_SubPriority
; 
 451     m_nPriority 
= nPriority
; 
 452     if (m_nPriority 
<= 25) 
 453         ulOS2_PriorityClass 
= PRTYC_IDLETIME
; 
 454     else if (m_nPriority 
<= 50) 
 455         ulOS2_PriorityClass 
= PRTYC_REGULAR
; 
 456     else if (m_nPriority 
<= 75) 
 457         ulOS2_PriorityClass 
= PRTYC_TIMECRITICAL
; 
 458     else if (m_nPriority 
<= 100) 
 459         ulOS2_PriorityClass 
= PRTYC_FOREGROUNDSERVER
; 
 462         wxFAIL_MSG(wxT("invalid value of thread priority parameter")); 
 463         ulOS2_PriorityClass 
= PRTYC_REGULAR
; 
 465     ulOS2_SubPriority 
= (ULONG
) (((m_nPriority 
- 1) % 25 + 1) * 31.0 / 25); 
 466     ulrc 
= ::DosSetPriority( PRTYS_THREAD
 
 473         wxLogSysError(_("Can't set thread priority")); 
 477 bool wxThreadInternal::Create( 
 479 , unsigned int                      uStackSize
 
 486     pThread
->m_critsect
.Enter(); 
 487     tid 
= _beginthread(wxThreadInternal::OS2ThreadStart
, 
 488                              NULL
, uStackSize
, pThread
); 
 491         wxLogSysError(_("Can't create thread")); 
 496     if (m_nPriority 
!= WXTHREAD_DEFAULT_PRIORITY
) 
 498         SetPriority(m_nPriority
); 
 504 bool wxThreadInternal::Suspend() 
 506     ULONG                           ulrc 
= ::DosSuspendThread(m_hThread
); 
 510         wxLogSysError(_("Can not suspend thread %lu"), m_hThread
); 
 513     m_eState 
= STATE_PAUSED
; 
 517 bool wxThreadInternal::Resume() 
 519     ULONG                           ulrc 
= ::DosResumeThread(m_hThread
); 
 523         wxLogSysError(_("Can not resume thread %lu"), m_hThread
); 
 527     // don't change the state from STATE_EXITED because it's special and means 
 528     // we are going to terminate without running any user code - if we did it, 
 529     // the codei n Delete() wouldn't work 
 530     if ( m_eState 
!= STATE_EXITED 
) 
 532         m_eState 
= STATE_RUNNING
; 
 541 wxThread 
*wxThread::This() 
 543     wxThread
*                       pThread 
= m_pThread
; 
 547 bool wxThread::IsMain() 
 552     ::DosGetInfoBlocks(&ptib
, &ppib
); 
 554     if (ptib
->tib_ptib2
->tib2_ultid 
== s_ulIdMainThread
) 
 563 void wxThread::Yield() 
 568 void wxThread::Sleep( 
 569   unsigned long                     ulMilliseconds
 
 572     ::DosSleep(ulMilliseconds
); 
 575 int wxThread::GetCPUCount() 
 579     ulrc 
= ::DosQuerySysInfo(26, 26, (void *)&CPUCount
, sizeof(ULONG
)); 
 580     // QSV_NUMPROCESSORS(26) is typically not defined in header files 
 588 unsigned long wxThread::GetCurrentId() 
 593     ::DosGetInfoBlocks(&ptib
, &ppib
); 
 594     return (unsigned long) ptib
->tib_ptib2
->tib2_ultid
; 
 597 bool wxThread::SetConcurrency(size_t level
) 
 599     wxASSERT_MSG( IsMain(), _T("should only be called from the main thread") ); 
 601     // ok only for the default one 
 605     // Don't know how to realize this on OS/2. 
 612 wxThread::wxThread(wxThreadKind kind
) 
 614     m_internal 
= new wxThreadInternal(); 
 616     m_isDetached 
= kind 
== wxTHREAD_DETACHED
; 
 619 wxThread::~wxThread() 
 624 // create/start thread 
 625 // ------------------- 
 627 wxThreadError 
wxThread::Create( 
 628   unsigned int                      uStackSize
 
 631     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); 
 633     if ( !m_internal
->Create(this, uStackSize
) ) 
 634         return wxTHREAD_NO_RESOURCE
; 
 636     return wxTHREAD_NO_ERROR
; 
 639 wxThreadError 
wxThread::Run() 
 641     wxCriticalSectionLocker         
lock((wxCriticalSection 
&)m_critsect
); 
 643     if ( m_internal
->GetState() != STATE_NEW 
) 
 645         // actually, it may be almost any state at all, not only STATE_RUNNING 
 646         return wxTHREAD_RUNNING
; 
 651 // suspend/resume thread 
 652 // --------------------- 
 654 wxThreadError 
wxThread::Pause() 
 656     wxCriticalSectionLocker         
lock((wxCriticalSection 
&)m_critsect
); 
 658     return m_internal
->Suspend() ? wxTHREAD_NO_ERROR 
: wxTHREAD_MISC_ERROR
; 
 661 wxThreadError 
wxThread::Resume() 
 663     if (m_internal
->GetState() == STATE_NEW
) 
 665         m_internal
->SetState(STATE_RUNNING
); 
 667         return wxTHREAD_NO_ERROR
; 
 670     wxCriticalSectionLocker         
lock((wxCriticalSection 
&)m_critsect
); 
 672     return m_internal
->Resume() ? wxTHREAD_NO_ERROR 
: wxTHREAD_MISC_ERROR
; 
 678 wxThread::ExitCode 
wxThread::Wait() 
 680     // although under Windows we can wait for any thread, it's an error to 
 681     // wait for a detached one in wxWin API 
 682     wxCHECK_MSG( !IsDetached(), (ExitCode
)-1, 
 683                  _T("can't wait for detached thread") ); 
 684     ExitCode rc 
= (ExitCode
)-1; 
 689 wxThreadError 
wxThread::Delete(ExitCode 
*pRc
) 
 693     // Delete() is always safe to call, so consider all possible states 
 695     // we might need to resume the thread, but we might also not need to cancel 
 696     // it if it doesn't run yet 
 697     bool shouldResume 
= FALSE
, 
 701     // check if the thread already started to run 
 703         wxCriticalSectionLocker         
lock((wxCriticalSection 
&)m_critsect
); 
 705         if ( m_internal
->GetState() == STATE_NEW 
) 
 707             // WinThreadStart() will see it and terminate immediately, no need 
 708             // to cancel the thread - but we still need to resume it to let it 
 710             m_internal
->SetState(STATE_EXITED
); 
 712             Resume();   // it knows about STATE_EXITED special case 
 714             shouldCancel 
= FALSE
; 
 717             // shouldResume is correctly set to FALSE here 
 721             shouldResume 
= IsPaused(); 
 725     // resume the thread if it is paused 
 729     TID                             hThread 
= m_internal
->GetHandle(); 
 731     if ( isRunning 
|| IsRunning()) 
 735             // set flag for wxIsWaitingForThread() 
 736             gs_bWaitingForThread 
= TRUE
; 
 739         // ask the thread to terminate 
 742             wxCriticalSectionLocker 
lock(m_critsect
); 
 744             m_internal
->Cancel(); 
 748         // we can't just wait for the thread to terminate because it might be 
 749         // calling some GUI functions and so it will never terminate before we 
 750         // process the Windows messages that result from these functions 
 751         DWORD result 
= 0;       // suppress warnings from broken compilers 
 756                 // give the thread we're waiting for chance to do the GUI call 
 758                 if ( (gs_nWaitingForGui 
> 0) && wxGuiOwnedByMainThread() ) 
 764             result 
= ::DosWaitThread(&hThread
, DCWW_NOWAIT
); 
 765             // FIXME: We ought to have a message processing loop here!! 
 769                 case ERROR_INTERRUPT
: 
 770                 case ERROR_THREAD_NOT_TERMINATED
: 
 772                 case ERROR_INVALID_THREADID
: 
 774                     // thread we're waiting for just terminated 
 775                     // or even does not exist any more. 
 779                     wxFAIL_MSG(wxT("unexpected result of DosWaitThread")); 
 783                 // event processing - needed if we are the main thread 
 784                 // to give other threads a chance to do remaining GUI 
 785                 // processing and terminate cleanly. 
 786                 wxTheApp
->HandleSockets(); 
 787                 if (wxTheApp
->Pending()) 
 788                   if ( !wxTheApp
->DoMessage() ) 
 790                       // WM_QUIT received: kill the thread 
 793                       return wxTHREAD_KILLED
; 
 800         } while ( result 
!= NO_ERROR 
); 
 802         // simply wait for the thread to terminate 
 804         // OTOH, even console apps create windows (in wxExecute, for WinSock 
 805         // &c), so may be use MsgWaitForMultipleObject() too here? 
 806         if ( ::DosWaitThread(&hThread
, DCWW_WAIT
) != NO_ERROR 
) 
 808             wxFAIL_MSG(wxT("unexpected result of DosWaitThread")); 
 810 #endif // wxUSE_GUI/!wxUSE_GUI 
 814             gs_bWaitingForThread 
= FALSE
; 
 819     // although the thread might be already in the EXITED state it might not 
 820     // have terminated yet and so we are not sure that it has actually 
 821     // terminated if the "if" above hadn't been taken 
 824         if ( !::GetExitCodeThread(hThread
, (LPDWORD
)&rc
) ) 
 826             wxLogLastError(wxT("GetExitCodeThread")); 
 830     } while ( (DWORD
)rc 
== STILL_ACTIVE 
); 
 835         // if the thread exits normally, this is done in WinThreadStart, but in 
 836         // this case it would have been too early because 
 837         // MsgWaitForMultipleObject() would fail if the thread handle was 
 838         // closed while we were waiting on it, so we must do it here 
 845     return rc 
== (ExitCode
)-1 ? wxTHREAD_MISC_ERROR 
: wxTHREAD_NO_ERROR
; 
 848 wxThreadError 
wxThread::Kill() 
 851         return wxTHREAD_NOT_RUNNING
; 
 853     ::DosKillThread(m_internal
->GetHandle()); 
 858     return wxTHREAD_NO_ERROR
; 
 867     wxFAIL_MSG(wxT("Couldn't return from DosExit()!")); 
 870 void wxThread::SetPriority( 
 874     wxCriticalSectionLocker         
lock((wxCriticalSection 
&)m_critsect
); 
 876     m_internal
->SetPriority(nPrio
); 
 879 unsigned int wxThread::GetPriority() const 
 881     wxCriticalSectionLocker         
lock((wxCriticalSection 
&)m_critsect
); 
 883     return m_internal
->GetPriority(); 
 886 unsigned long wxThread::GetId() const 
 888     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); // const_cast 
 890     return (unsigned long)m_internal
->GetId(); 
 893 bool wxThread::IsRunning() const 
 895     wxCriticalSectionLocker         
lock((wxCriticalSection 
&)m_critsect
); 
 897     return(m_internal
->GetState() == STATE_RUNNING
); 
 900 bool wxThread::IsAlive() const 
 902     wxCriticalSectionLocker         
lock((wxCriticalSection 
&)m_critsect
); 
 904     return (m_internal
->GetState() == STATE_RUNNING
) || 
 905            (m_internal
->GetState() == STATE_PAUSED
); 
 908 bool wxThread::IsPaused() const 
 910     wxCriticalSectionLocker         
lock((wxCriticalSection 
&)m_critsect
); 
 912     return (m_internal
->GetState() == STATE_PAUSED
); 
 915 bool wxThread::TestDestroy() 
 917     wxCriticalSectionLocker         
lock((wxCriticalSection 
&)m_critsect
); 
 919     return m_internal
->GetState() == STATE_CANCELED
; 
 922 // ---------------------------------------------------------------------------- 
 923 // Automatic initialization for thread module 
 924 // ---------------------------------------------------------------------------- 
 926 class wxThreadModule 
: public wxModule
 
 929     virtual bool OnInit(); 
 930     virtual void OnExit(); 
 933     DECLARE_DYNAMIC_CLASS(wxThreadModule
) 
 936 IMPLEMENT_DYNAMIC_CLASS(wxThreadModule
, wxModule
) 
 938 bool wxThreadModule::OnInit() 
 940     gs_pCritsectWaitingForGui 
= new wxCriticalSection(); 
 942     gs_pCritsectGui 
= new wxCriticalSection(); 
 943     gs_pCritsectGui
->Enter(); 
 948     ::DosGetInfoBlocks(&ptib
, &ppib
); 
 950     s_ulIdMainThread 
= ptib
->tib_ptib2
->tib2_ultid
; 
 954 void wxThreadModule::OnExit() 
 958         gs_pCritsectGui
->Leave(); 
 959 #if (!(defined(__VISAGECPP__) && (__IBMCPP__ < 400 || __IBMC__ < 400 ))) 
 960         delete gs_pCritsectGui
; 
 962         gs_pCritsectGui 
= NULL
; 
 965 #if (!(defined(__VISAGECPP__) && (__IBMCPP__ < 400 || __IBMC__ < 400 ))) 
 966     wxDELETE(gs_pCritsectWaitingForGui
); 
 970 // ---------------------------------------------------------------------------- 
 972 // ---------------------------------------------------------------------------- 
 974 // wake up the main thread if it's in ::GetMessage() 
 975 void WXDLLEXPORT 
wxWakeUpMainThread() 
 978     if ( !::WinPostQueueMsg(wxTheApp
->m_hMq
, WM_NULL
, 0, 0) ) 
 980         // should never happen 
 981         wxLogLastError(wxT("WinPostMessage(WM_NULL)")); 
 986 void WXDLLEXPORT 
wxMutexGuiEnter() 
 988     // this would dead lock everything... 
 989     wxASSERT_MSG( !wxThread::IsMain(), 
 990                   wxT("main thread doesn't want to block in wxMutexGuiEnter()!") ); 
 992     // the order in which we enter the critical sections here is crucial!! 
 994     // set the flag telling to the main thread that we want to do some GUI 
 996         wxCriticalSectionLocker 
enter(*gs_pCritsectWaitingForGui
); 
1001     wxWakeUpMainThread(); 
1003     // now we may block here because the main thread will soon let us in 
1004     // (during the next iteration of OnIdle()) 
1005     gs_pCritsectGui
->Enter(); 
1008 void WXDLLEXPORT 
wxMutexGuiLeave() 
1010     wxCriticalSectionLocker 
enter(*gs_pCritsectWaitingForGui
); 
1012     if ( wxThread::IsMain() ) 
1014         gs_bGuiOwnedByMainThread 
= FALSE
; 
1018         // decrement the number of waiters now 
1019         wxASSERT_MSG(gs_nWaitingForGui 
> 0, 
1020                       wxT("calling wxMutexGuiLeave() without entering it first?") ); 
1022         gs_nWaitingForGui
--; 
1024         wxWakeUpMainThread(); 
1027     gs_pCritsectGui
->Leave(); 
1030 void WXDLLEXPORT 
wxMutexGuiLeaveOrEnter() 
1032     wxASSERT_MSG( wxThread::IsMain(), 
1033                   wxT("only main thread may call wxMutexGuiLeaveOrEnter()!") ); 
1035     wxCriticalSectionLocker 
enter(*gs_pCritsectWaitingForGui
); 
1037     if (gs_nWaitingForGui 
== 0) 
1039         // no threads are waiting for GUI - so we may acquire the lock without 
1040         // any danger (but only if we don't already have it) 
1041         if (!wxGuiOwnedByMainThread()) 
1043             gs_pCritsectGui
->Enter(); 
1045             gs_bGuiOwnedByMainThread 
= TRUE
; 
1047         //else: already have it, nothing to do 
1051         // some threads are waiting, release the GUI lock if we have it 
1052         if (wxGuiOwnedByMainThread()) 
1056         //else: some other worker thread is doing GUI 
1060 bool WXDLLEXPORT 
wxGuiOwnedByMainThread() 
1062     return gs_bGuiOwnedByMainThread
; 
1065 bool WXDLLEXPORT 
wxIsWaitingForThread() 
1067     return gs_bWaitingForThread
; 
1070 // ---------------------------------------------------------------------------- 
1071 // include common implementation code 
1072 // ---------------------------------------------------------------------------- 
1074 #include "wx/thrimpl.cpp"