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 wxThreadIdType                      
wxThread::ms_idMainThread 
= 0; 
  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(_("Cannot create mutex.")); 
 122 wxMutexInternal::~wxMutexInternal() 
 126         if (::DosCloseMutexSem(m_vMutex
)) 
 128             wxLogLastError(wxT("DosCloseMutexSem(mutex)")); 
 133 wxMutexError 
wxMutexInternal::TryLock() 
 135     const wxMutexError rc 
= LockTimeout( SEM_IMMEDIATE_RETURN 
); 
 137     // we have a special return code for timeout in this case 
 138     return rc 
== wxMUTEX_TIMEOUT 
? wxMUTEX_BUSY 
: rc
; 
 141 wxMutexError 
wxMutexInternal::LockTimeout(ULONG ulMilliseconds
) 
 145     ulrc 
= ::DosRequestMutexSem(m_vMutex
, ulMilliseconds
); 
 150             return wxMUTEX_TIMEOUT
; 
 151         case ERROR_TOO_MANY_SEM_REQUESTS
: 
 158         case ERROR_INVALID_HANDLE
: 
 159         case ERROR_INTERRUPT
: 
 160         case ERROR_SEM_OWNER_DIED
: 
 161             wxLogSysError(_("Couldn't acquire a mutex lock")); 
 162             return wxMUTEX_MISC_ERROR
; 
 165             wxFAIL_MSG(wxT("impossible return value in wxMutex::Lock")); 
 166             return wxMUTEX_MISC_ERROR
; 
 168     return wxMUTEX_NO_ERROR
; 
 171 wxMutexError 
wxMutexInternal::Unlock() 
 175     ulrc 
= ::DosReleaseMutexSem(m_vMutex
); 
 178         wxLogSysError(_("Couldn't release a mutex")); 
 179         return wxMUTEX_MISC_ERROR
; 
 181     return wxMUTEX_NO_ERROR
; 
 184 // -------------------------------------------------------------------------- 
 186 // -------------------------------------------------------------------------- 
 188 // a trivial wrapper around OS2 event semaphore 
 189 class wxSemaphoreInternal
 
 192     wxSemaphoreInternal(int initialcount
, int maxcount
); 
 193     ~wxSemaphoreInternal(); 
 195     bool IsOk() const { return m_vEvent 
!= NULL
; } 
 197     wxSemaError 
Wait() { return WaitTimeout(SEM_INDEFINITE_WAIT
); } 
 198     wxSemaError 
TryWait() { return WaitTimeout(SEM_IMMEDIATE_RETURN
); } 
 199     wxSemaError 
WaitTimeout(unsigned long milliseconds
); 
 210 wxSemaphoreInternal::wxSemaphoreInternal(int initialcount
, int maxcount
) 
 215         // make it practically infinite 
 219     m_count 
= initialcount
; 
 220     m_maxcount 
= maxcount
; 
 221     ulrc 
= ::DosCreateMutexSem(NULL
, &m_vMutex
, 0L, FALSE
); 
 224         wxLogLastError(wxT("DosCreateMutexSem()")); 
 229     ulrc 
= ::DosCreateEventSem(NULL
, &m_vEvent
, 0L, FALSE
); 
 232         wxLogLastError(wxT("DosCreateEventSem()")); 
 233         ::DosCloseMutexSem(m_vMutex
); 
 238         ::DosPostEventSem(m_vEvent
); 
 241 wxSemaphoreInternal::~wxSemaphoreInternal() 
 245         if ( ::DosCloseEventSem(m_vEvent
) ) 
 247             wxLogLastError(wxT("DosCloseEventSem(semaphore)")); 
 249         if ( ::DosCloseMutexSem(m_vMutex
) ) 
 251             wxLogLastError(wxT("DosCloseMutexSem(semaphore)")); 
 258 wxSemaError 
wxSemaphoreInternal::WaitTimeout(unsigned long ulMilliseconds
) 
 262         ulrc 
= ::DosWaitEventSem(m_vEvent
, ulMilliseconds 
); 
 269                 if (ulMilliseconds 
== SEM_IMMEDIATE_RETURN
) 
 272                     return wxSEMA_TIMEOUT
; 
 275                 wxLogLastError(wxT("DosWaitEventSem(semaphore)")); 
 276                 return wxSEMA_MISC_ERROR
; 
 278         ulrc 
= :: DosRequestMutexSem(m_vMutex
, ulMilliseconds
); 
 286             case ERROR_TOO_MANY_SEM_REQUESTS
: 
 287                 if (ulMilliseconds 
== SEM_IMMEDIATE_RETURN
) 
 290                     return wxSEMA_TIMEOUT
; 
 293                 wxFAIL_MSG(wxT("DosRequestMutexSem(mutex)")); 
 294                 return wxSEMA_MISC_ERROR
; 
 305             ::DosResetEventSem(m_vEvent
, &ulPostCount
); 
 307         ::DosReleaseMutexSem(m_vMutex
); 
 309             return wxSEMA_NO_ERROR
; 
 310     } while (ulMilliseconds 
== SEM_INDEFINITE_WAIT
); 
 312     if (ulMilliseconds 
== SEM_IMMEDIATE_RETURN
) 
 314     return wxSEMA_TIMEOUT
; 
 317 wxSemaError 
wxSemaphoreInternal::Post() 
 320     ulrc 
= ::DosRequestMutexSem(m_vMutex
, SEM_INDEFINITE_WAIT
); 
 321     if (ulrc 
!= NO_ERROR
) 
 322         return wxSEMA_MISC_ERROR
; 
 324     if (m_count 
< m_maxcount
) 
 327         ulrc 
= ::DosPostEventSem(m_vEvent
); 
 330     ::DosReleaseMutexSem(m_vMutex
); 
 332         return wxSEMA_OVERFLOW
; 
 333     if ( ulrc 
!= NO_ERROR 
&& ulrc 
!= ERROR_ALREADY_POSTED 
) 
 335         wxLogLastError(wxT("DosPostEventSem(semaphore)")); 
 337         return wxSEMA_MISC_ERROR
; 
 340     return wxSEMA_NO_ERROR
; 
 343 // ---------------------------------------------------------------------------- 
 344 // wxThread implementation 
 345 // ---------------------------------------------------------------------------- 
 347 // wxThreadInternal class 
 348 // ---------------------- 
 350 class wxThreadInternal
 
 353     inline wxThreadInternal() 
 356         m_eState 
= STATE_NEW
; 
 357         m_nPriority 
= wxPRIORITY_DEFAULT
; 
 365     // create a new (suspended) thread (for the given thread object) 
 366     bool Create( wxThread
*    pThread
 
 367                 ,unsigned int uStackSize
 
 370     // suspend/resume/terminate 
 373     inline void Cancel() { m_eState 
= STATE_CANCELED
; } 
 376     inline void SetState(wxThreadState eState
) { m_eState 
= eState
; } 
 377     inline wxThreadState 
GetState() const { return m_eState
; } 
 380     void                SetPriority(unsigned int nPriority
); 
 381     inline unsigned int GetPriority() const { return m_nPriority
; } 
 383     // thread handle and id 
 384     inline TID 
GetHandle() const { return m_hThread
; } 
 385     TID  
GetId() const { return m_hThread
; } 
 388     static void OS2ThreadStart(void* pParam
); 
 391     // Threads in OS/2 have only an ID, so m_hThread is both it's handle and ID 
 392     // PM also has no real Tls mechanism to index pointers by so we'll just 
 393     // keep track of the wxWidgets parent object here. 
 394     TID                             m_hThread
;    // handle and ID of the thread 
 395     wxThreadState                   m_eState
;     // state, see wxThreadState enum 
 396     unsigned int                    m_nPriority
;  // thread priority in "wx" units 
 399 void wxThreadInternal::OS2ThreadStart( void * pParam 
) 
 404     wxThread 
*pThread 
= (wxThread 
*)pParam
; 
 406     // first of all, wait for the thread to be started. 
 407     pThread
->m_critsect
.Enter(); 
 408     pThread
->m_critsect
.Leave(); 
 409     // Now check whether we hadn't been cancelled already and don't 
 410     // start the user code at all in this case. 
 411     if ( pThread
->m_internal
->GetState() == STATE_EXITED 
) 
 414         bWasCancelled 
= true; 
 416     else // do run thread 
 418         wxAppTraits 
*traits 
= wxTheApp 
? wxTheApp
->GetTraits() : NULL
; 
 421             traits
->InitializeGui(ulHab
); 
 422         dwRet 
= (DWORD
)pThread
->Entry(); 
 424             traits
->TerminateGui(ulHab
); 
 426         // enter m_critsect before changing the thread state 
 427         pThread
->m_critsect
.Enter(); 
 429         bWasCancelled 
= pThread
->m_internal
->GetState() == STATE_CANCELED
; 
 431         pThread
->m_internal
->SetState(STATE_EXITED
); 
 432         pThread
->m_critsect
.Leave(); 
 436     // if the thread was cancelled (from Delete()), then it the handle is still 
 438     if (pThread
->IsDetached() && !bWasCancelled
) 
 443     //else: the joinable threads handle will be closed when Wait() is done 
 447 void wxThreadInternal::SetPriority( 
 448   unsigned int                      nPriority
 
 451     // translate wxWidgets priority to the PM one 
 452     ULONG                           ulOS2_PriorityClass
; 
 453     ULONG                           ulOS2_SubPriority
; 
 456     m_nPriority 
= nPriority
; 
 457     if (m_nPriority 
<= 25) 
 458         ulOS2_PriorityClass 
= PRTYC_IDLETIME
; 
 459     else if (m_nPriority 
<= 50) 
 460         ulOS2_PriorityClass 
= PRTYC_REGULAR
; 
 461     else if (m_nPriority 
<= 75) 
 462         ulOS2_PriorityClass 
= PRTYC_TIMECRITICAL
; 
 463     else if (m_nPriority 
<= 100) 
 464         ulOS2_PriorityClass 
= PRTYC_FOREGROUNDSERVER
; 
 467         wxFAIL_MSG(wxT("invalid value of thread priority parameter")); 
 468         ulOS2_PriorityClass 
= PRTYC_REGULAR
; 
 470     ulOS2_SubPriority 
= (ULONG
) (((m_nPriority 
- 1) % 25 + 1) * 31.0 / 25); 
 471     ulrc 
= ::DosSetPriority( PRTYS_THREAD
 
 478         wxLogSysError(_("Can't set thread priority")); 
 482 bool wxThreadInternal::Create( wxThread
* pThread
, 
 483                                unsigned int uStackSize
) 
 490     pThread
->m_critsect
.Enter(); 
 491     tid 
= _beginthread(wxThreadInternal::OS2ThreadStart
, 
 492                              NULL
, uStackSize
, pThread
); 
 495         wxLogSysError(_("Can't create thread")); 
 500     if (m_nPriority 
!= wxPRIORITY_DEFAULT
) 
 502         SetPriority(m_nPriority
); 
 508 bool wxThreadInternal::Suspend() 
 510     ULONG ulrc 
= ::DosSuspendThread(m_hThread
); 
 514         wxLogSysError(_("Cannot suspend thread %lu"), m_hThread
); 
 517     m_eState 
= STATE_PAUSED
; 
 522 bool wxThreadInternal::Resume() 
 524     ULONG ulrc 
= ::DosResumeThread(m_hThread
); 
 528         wxLogSysError(_("Cannot resume thread %lu"), m_hThread
); 
 532     // don't change the state from STATE_EXITED because it's special and means 
 533     // we are going to terminate without running any user code - if we did it, 
 534     // the codei n Delete() wouldn't work 
 535     if ( m_eState 
!= STATE_EXITED 
) 
 537         m_eState 
= STATE_RUNNING
; 
 546 wxThread 
*wxThread::This() 
 548     wxThread
*                       pThread 
= m_pThread
; 
 556 void wxThread::Yield() 
 561 int wxThread::GetCPUCount() 
 565     ulrc 
= ::DosQuerySysInfo(26, 26, (void *)&CPUCount
, sizeof(ULONG
)); 
 566     // QSV_NUMPROCESSORS(26) is typically not defined in header files 
 574 wxThreadIdType 
wxThread::GetCurrentId() 
 579     ::DosGetInfoBlocks(&ptib
, &ppib
); 
 580     return (wxThreadIdType
) ptib
->tib_ptib2
->tib2_ultid
; 
 583 bool wxThread::SetConcurrency(size_t level
) 
 585     wxASSERT_MSG( IsMain(), wxT("should only be called from the main thread") ); 
 587     // ok only for the default one 
 591     // Don't know how to realize this on OS/2. 
 598 wxThread::wxThread(wxThreadKind kind
) 
 600     m_internal 
= new wxThreadInternal(); 
 602     m_isDetached 
= kind 
== wxTHREAD_DETACHED
; 
 605 wxThread::~wxThread() 
 610 // create/start thread 
 611 // ------------------- 
 613 wxThreadError 
wxThread::Create( 
 614   unsigned int                      uStackSize
 
 617     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); 
 619     if ( !m_internal
->Create(this, uStackSize
) ) 
 620         return wxTHREAD_NO_RESOURCE
; 
 622     return wxTHREAD_NO_ERROR
; 
 625 wxThreadError 
wxThread::Run() 
 627     wxCriticalSectionLocker         
lock((wxCriticalSection 
&)m_critsect
); 
 629     if ( m_internal
->GetState() != STATE_NEW 
) 
 631         // actually, it may be almost any state at all, not only STATE_RUNNING 
 632         return wxTHREAD_RUNNING
; 
 637 // suspend/resume thread 
 638 // --------------------- 
 640 wxThreadError 
wxThread::Pause() 
 642     wxCriticalSectionLocker         
lock((wxCriticalSection 
&)m_critsect
); 
 644     return m_internal
->Suspend() ? wxTHREAD_NO_ERROR 
: wxTHREAD_MISC_ERROR
; 
 647 wxThreadError 
wxThread::Resume() 
 649     if (m_internal
->GetState() == STATE_NEW
) 
 651         m_internal
->SetState(STATE_RUNNING
); 
 653         return wxTHREAD_NO_ERROR
; 
 656     wxCriticalSectionLocker         
lock((wxCriticalSection 
&)m_critsect
); 
 658     return m_internal
->Resume() ? wxTHREAD_NO_ERROR 
: wxTHREAD_MISC_ERROR
; 
 664 wxThread::ExitCode 
wxThread::Wait(wxThreadWait waitMode
) 
 666     // although under Windows we can wait for any thread, it's an error to 
 667     // wait for a detached one in wxWin API 
 668     wxCHECK_MSG( !IsDetached(), (ExitCode
)-1, 
 669                  wxT("can't wait for detached thread") ); 
 670     ExitCode rc 
= (ExitCode
)-1; 
 671     (void)Delete(&rc
, waitMode
); 
 675 wxThreadError 
wxThread::Delete(ExitCode 
*pRc
, wxThreadWait 
WXUNUSED(waitMode
)) 
 679     // Delete() is always safe to call, so consider all possible states 
 681     // we might need to resume the thread, but we might also not need to cancel 
 682     // it if it doesn't run yet 
 683     bool shouldResume 
= false, 
 687     // check if the thread already started to run 
 689         wxCriticalSectionLocker         
lock((wxCriticalSection 
&)m_critsect
); 
 691         if ( m_internal
->GetState() == STATE_NEW 
) 
 693             // WinThreadStart() will see it and terminate immediately, no need 
 694             // to cancel the thread - but we still need to resume it to let it 
 696             m_internal
->SetState(STATE_EXITED
); 
 698             Resume();   // it knows about STATE_EXITED special case 
 700             shouldCancel 
= false; 
 703             // shouldResume is correctly set to false here 
 707             shouldResume 
= IsPaused(); 
 711     // resume the thread if it is paused 
 715     TID hThread 
= m_internal
->GetHandle(); 
 717     if ( isRunning 
|| IsRunning()) 
 721             // set flag for wxIsWaitingForThread() 
 722             gs_bWaitingForThread 
= true; 
 725         // ask the thread to terminate 
 728             wxCriticalSectionLocker 
lock(m_critsect
); 
 730             m_internal
->Cancel(); 
 734         // we can't just wait for the thread to terminate because it might be 
 735         // calling some GUI functions and so it will never terminate before we 
 736         // process the Windows messages that result from these functions 
 737         DWORD result 
= 0;       // suppress warnings from broken compilers 
 742                 // give the thread we're waiting for chance to do the GUI call 
 744                 if ( (gs_nWaitingForGui 
> 0) && wxGuiOwnedByMainThread() ) 
 750             result 
= ::DosWaitThread(&hThread
, DCWW_NOWAIT
); 
 751             // FIXME: We ought to have a message processing loop here!! 
 755                 case ERROR_INTERRUPT
: 
 756                 case ERROR_THREAD_NOT_TERMINATED
: 
 758                 case ERROR_INVALID_THREADID
: 
 760                     // thread we're waiting for just terminated 
 761                     // or even does not exist any more. 
 765                     wxFAIL_MSG(wxT("unexpected result of DosWaitThread")); 
 769                 // event processing - needed if we are the main thread 
 770                 // to give other threads a chance to do remaining GUI 
 771                 // processing and terminate cleanly. 
 772                 wxTheApp
->HandleSockets(); 
 773                 if (wxTheApp
->Pending()) 
 774                   if ( !wxTheApp
->DoMessage() ) 
 776                       // WM_QUIT received: kill the thread 
 779                       return wxTHREAD_KILLED
; 
 786         } while ( result 
!= NO_ERROR 
); 
 788         // simply wait for the thread to terminate 
 790         // OTOH, even console apps create windows (in wxExecute, for WinSock 
 791         // &c), so may be use MsgWaitForMultipleObject() too here? 
 792         if ( ::DosWaitThread(&hThread
, DCWW_WAIT
) != NO_ERROR 
) 
 794             wxFAIL_MSG(wxT("unexpected result of DosWaitThread")); 
 796 #endif // wxUSE_GUI/!wxUSE_GUI 
 800             gs_bWaitingForThread 
= false; 
 805     // although the thread might be already in the EXITED state it might not 
 806     // have terminated yet and so we are not sure that it has actually 
 807     // terminated if the "if" above hadn't been taken 
 810         if ( !::GetExitCodeThread(hThread
, (LPDWORD
)&rc
) ) 
 812             wxLogLastError(wxT("GetExitCodeThread")); 
 816     } while ( (DWORD
)rc 
== STILL_ACTIVE 
); 
 821         // if the thread exits normally, this is done in WinThreadStart, but in 
 822         // this case it would have been too early because 
 823         // MsgWaitForMultipleObject() would fail if the thread handle was 
 824         // closed while we were waiting on it, so we must do it here 
 831     return rc 
== (ExitCode
)-1 ? wxTHREAD_MISC_ERROR 
: wxTHREAD_NO_ERROR
; 
 834 wxThreadError 
wxThread::Kill() 
 837         return wxTHREAD_NOT_RUNNING
; 
 839     ::DosKillThread(m_internal
->GetHandle()); 
 844     return wxTHREAD_NO_ERROR
; 
 847 void wxThread::Exit(ExitCode 
WXUNUSED(pStatus
)) 
 851     wxFAIL_MSG(wxT("Couldn't return from DosExit()!")); 
 854 void wxThread::SetPriority( 
 858     wxCriticalSectionLocker         
lock((wxCriticalSection 
&)m_critsect
); 
 860     m_internal
->SetPriority(nPrio
); 
 863 unsigned int wxThread::GetPriority() const 
 865     wxCriticalSectionLocker         
lock((wxCriticalSection 
&)m_critsect
); 
 867     return m_internal
->GetPriority(); 
 870 unsigned long wxThread::GetId() const 
 872     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); // const_cast 
 874     return (unsigned long)m_internal
->GetId(); 
 877 bool wxThread::IsRunning() const 
 879     wxCriticalSectionLocker         
lock((wxCriticalSection 
&)m_critsect
); 
 881     return(m_internal
->GetState() == STATE_RUNNING
); 
 884 bool wxThread::IsAlive() const 
 886     wxCriticalSectionLocker         
lock((wxCriticalSection 
&)m_critsect
); 
 888     return (m_internal
->GetState() == STATE_RUNNING
) || 
 889            (m_internal
->GetState() == STATE_PAUSED
); 
 892 bool wxThread::IsPaused() const 
 894     wxCriticalSectionLocker         
lock((wxCriticalSection 
&)m_critsect
); 
 896     return (m_internal
->GetState() == STATE_PAUSED
); 
 899 bool wxThread::TestDestroy() 
 901     wxCriticalSectionLocker         
lock((wxCriticalSection 
&)m_critsect
); 
 903     return m_internal
->GetState() == STATE_CANCELED
; 
 906 // ---------------------------------------------------------------------------- 
 907 // Automatic initialization for thread module 
 908 // ---------------------------------------------------------------------------- 
 910 class wxThreadModule 
: public wxModule
 
 913     virtual bool OnInit(); 
 914     virtual void OnExit(); 
 917     DECLARE_DYNAMIC_CLASS(wxThreadModule
) 
 920 IMPLEMENT_DYNAMIC_CLASS(wxThreadModule
, wxModule
) 
 922 bool wxThreadModule::OnInit() 
 924     gs_pCritsectWaitingForGui 
= new wxCriticalSection(); 
 926     gs_pCritsectGui 
= new wxCriticalSection(); 
 927     gs_pCritsectGui
->Enter(); 
 929     wxThread::ms_idMainThread 
= wxThread::GetCurrentId(); 
 934 void wxThreadModule::OnExit() 
 938         gs_pCritsectGui
->Leave(); 
 939 #if (!(defined(__VISAGECPP__) && (__IBMCPP__ < 400 || __IBMC__ < 400 ))) 
 940         delete gs_pCritsectGui
; 
 942         gs_pCritsectGui 
= NULL
; 
 945 #if (!(defined(__VISAGECPP__) && (__IBMCPP__ < 400 || __IBMC__ < 400 ))) 
 946     wxDELETE(gs_pCritsectWaitingForGui
); 
 950 // ---------------------------------------------------------------------------- 
 952 // ---------------------------------------------------------------------------- 
 954 // wake up the main thread if it's in ::GetMessage() 
 955 void WXDLLEXPORT 
wxWakeUpMainThread() 
 958     if ( !::WinPostQueueMsg(wxTheApp
->m_hMq
, WM_NULL
, 0, 0) ) 
 960         // should never happen 
 961         wxLogLastError(wxT("WinPostMessage(WM_NULL)")); 
 966 void wxMutexGuiEnterImpl() 
 968     // this would dead lock everything... 
 969     wxASSERT_MSG( !wxThread::IsMain(), 
 970                   wxT("main thread doesn't want to block in wxMutexGuiEnter()!") ); 
 972     // the order in which we enter the critical sections here is crucial!! 
 974     // set the flag telling to the main thread that we want to do some GUI 
 976         wxCriticalSectionLocker 
enter(*gs_pCritsectWaitingForGui
); 
 981     wxWakeUpMainThread(); 
 983     // now we may block here because the main thread will soon let us in 
 984     // (during the next iteration of OnIdle()) 
 985     gs_pCritsectGui
->Enter(); 
 988 void wxMutexGuiLeaveImpl() 
 990     wxCriticalSectionLocker 
enter(*gs_pCritsectWaitingForGui
); 
 992     if ( wxThread::IsMain() ) 
 994         gs_bGuiOwnedByMainThread 
= false; 
 998         // decrement the number of waiters now 
 999         wxASSERT_MSG(gs_nWaitingForGui 
> 0, 
1000                       wxT("calling wxMutexGuiLeave() without entering it first?") ); 
1002         gs_nWaitingForGui
--; 
1004         wxWakeUpMainThread(); 
1007     gs_pCritsectGui
->Leave(); 
1010 void WXDLLEXPORT 
wxMutexGuiLeaveOrEnter() 
1012     wxASSERT_MSG( wxThread::IsMain(), 
1013                   wxT("only main thread may call wxMutexGuiLeaveOrEnter()!") ); 
1015     wxCriticalSectionLocker 
enter(*gs_pCritsectWaitingForGui
); 
1017     if (gs_nWaitingForGui 
== 0) 
1019         // no threads are waiting for GUI - so we may acquire the lock without 
1020         // any danger (but only if we don't already have it) 
1021         if (!wxGuiOwnedByMainThread()) 
1023             gs_pCritsectGui
->Enter(); 
1025             gs_bGuiOwnedByMainThread 
= true; 
1027         //else: already have it, nothing to do 
1031         // some threads are waiting, release the GUI lock if we have it 
1032         if (wxGuiOwnedByMainThread()) 
1036         //else: some other worker thread is doing GUI 
1040 bool WXDLLEXPORT 
wxGuiOwnedByMainThread() 
1042     return gs_bGuiOwnedByMainThread
; 
1045 bool WXDLLEXPORT 
wxIsWaitingForThread() 
1047     return gs_bWaitingForThread
; 
1050 // ---------------------------------------------------------------------------- 
1051 // include common implementation code 
1052 // ---------------------------------------------------------------------------- 
1054 #include "wx/thrimpl.cpp"