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 void wxThread::Sleep( 
 573   unsigned long                     ulMilliseconds
 
 576     ::DosSleep(ulMilliseconds
); 
 579 int wxThread::GetCPUCount() 
 583     ulrc 
= ::DosQuerySysInfo(26, 26, (void *)&CPUCount
, sizeof(ULONG
)); 
 584     // QSV_NUMPROCESSORS(26) is typically not defined in header files 
 592 unsigned long wxThread::GetCurrentId() 
 597     ::DosGetInfoBlocks(&ptib
, &ppib
); 
 598     return (unsigned long) ptib
->tib_ptib2
->tib2_ultid
; 
 601 bool wxThread::SetConcurrency(size_t level
) 
 603     wxASSERT_MSG( IsMain(), _T("should only be called from the main thread") ); 
 605     // ok only for the default one 
 609     // Don't know how to realize this on OS/2. 
 616 wxThread::wxThread(wxThreadKind kind
) 
 618     m_internal 
= new wxThreadInternal(); 
 620     m_isDetached 
= kind 
== wxTHREAD_DETACHED
; 
 623 wxThread::~wxThread() 
 628 // create/start thread 
 629 // ------------------- 
 631 wxThreadError 
wxThread::Create( 
 632   unsigned int                      uStackSize
 
 635     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); 
 637     if ( !m_internal
->Create(this, uStackSize
) ) 
 638         return wxTHREAD_NO_RESOURCE
; 
 640     return wxTHREAD_NO_ERROR
; 
 643 wxThreadError 
wxThread::Run() 
 645     wxCriticalSectionLocker         
lock((wxCriticalSection 
&)m_critsect
); 
 647     if ( m_internal
->GetState() != STATE_NEW 
) 
 649         // actually, it may be almost any state at all, not only STATE_RUNNING 
 650         return wxTHREAD_RUNNING
; 
 655 // suspend/resume thread 
 656 // --------------------- 
 658 wxThreadError 
wxThread::Pause() 
 660     wxCriticalSectionLocker         
lock((wxCriticalSection 
&)m_critsect
); 
 662     return m_internal
->Suspend() ? wxTHREAD_NO_ERROR 
: wxTHREAD_MISC_ERROR
; 
 665 wxThreadError 
wxThread::Resume() 
 667     if (m_internal
->GetState() == STATE_NEW
) 
 669         m_internal
->SetState(STATE_RUNNING
); 
 671         return wxTHREAD_NO_ERROR
; 
 674     wxCriticalSectionLocker         
lock((wxCriticalSection 
&)m_critsect
); 
 676     return m_internal
->Resume() ? wxTHREAD_NO_ERROR 
: wxTHREAD_MISC_ERROR
; 
 682 wxThread::ExitCode 
wxThread::Wait() 
 684     // although under Windows we can wait for any thread, it's an error to 
 685     // wait for a detached one in wxWin API 
 686     wxCHECK_MSG( !IsDetached(), (ExitCode
)-1, 
 687                  _T("can't wait for detached thread") ); 
 688     ExitCode rc 
= (ExitCode
)-1; 
 693 wxThreadError 
wxThread::Delete(ExitCode 
*pRc
) 
 697     // Delete() is always safe to call, so consider all possible states 
 699     // we might need to resume the thread, but we might also not need to cancel 
 700     // it if it doesn't run yet 
 701     bool shouldResume 
= false, 
 705     // check if the thread already started to run 
 707         wxCriticalSectionLocker         
lock((wxCriticalSection 
&)m_critsect
); 
 709         if ( m_internal
->GetState() == STATE_NEW 
) 
 711             // WinThreadStart() will see it and terminate immediately, no need 
 712             // to cancel the thread - but we still need to resume it to let it 
 714             m_internal
->SetState(STATE_EXITED
); 
 716             Resume();   // it knows about STATE_EXITED special case 
 718             shouldCancel 
= false; 
 721             // shouldResume is correctly set to false here 
 725             shouldResume 
= IsPaused(); 
 729     // resume the thread if it is paused 
 733     TID hThread 
= m_internal
->GetHandle(); 
 735     if ( isRunning 
|| IsRunning()) 
 739             // set flag for wxIsWaitingForThread() 
 740             gs_bWaitingForThread 
= true; 
 743         // ask the thread to terminate 
 746             wxCriticalSectionLocker 
lock(m_critsect
); 
 748             m_internal
->Cancel(); 
 752         // we can't just wait for the thread to terminate because it might be 
 753         // calling some GUI functions and so it will never terminate before we 
 754         // process the Windows messages that result from these functions 
 755         DWORD result 
= 0;       // suppress warnings from broken compilers 
 760                 // give the thread we're waiting for chance to do the GUI call 
 762                 if ( (gs_nWaitingForGui 
> 0) && wxGuiOwnedByMainThread() ) 
 768             result 
= ::DosWaitThread(&hThread
, DCWW_NOWAIT
); 
 769             // FIXME: We ought to have a message processing loop here!! 
 773                 case ERROR_INTERRUPT
: 
 774                 case ERROR_THREAD_NOT_TERMINATED
: 
 776                 case ERROR_INVALID_THREADID
: 
 778                     // thread we're waiting for just terminated 
 779                     // or even does not exist any more. 
 783                     wxFAIL_MSG(wxT("unexpected result of DosWaitThread")); 
 787                 // event processing - needed if we are the main thread 
 788                 // to give other threads a chance to do remaining GUI 
 789                 // processing and terminate cleanly. 
 790                 wxTheApp
->HandleSockets(); 
 791                 if (wxTheApp
->Pending()) 
 792                   if ( !wxTheApp
->DoMessage() ) 
 794                       // WM_QUIT received: kill the thread 
 797                       return wxTHREAD_KILLED
; 
 804         } while ( result 
!= NO_ERROR 
); 
 806         // simply wait for the thread to terminate 
 808         // OTOH, even console apps create windows (in wxExecute, for WinSock 
 809         // &c), so may be use MsgWaitForMultipleObject() too here? 
 810         if ( ::DosWaitThread(&hThread
, DCWW_WAIT
) != NO_ERROR 
) 
 812             wxFAIL_MSG(wxT("unexpected result of DosWaitThread")); 
 814 #endif // wxUSE_GUI/!wxUSE_GUI 
 818             gs_bWaitingForThread 
= false; 
 823     // although the thread might be already in the EXITED state it might not 
 824     // have terminated yet and so we are not sure that it has actually 
 825     // terminated if the "if" above hadn't been taken 
 828         if ( !::GetExitCodeThread(hThread
, (LPDWORD
)&rc
) ) 
 830             wxLogLastError(wxT("GetExitCodeThread")); 
 834     } while ( (DWORD
)rc 
== STILL_ACTIVE 
); 
 839         // if the thread exits normally, this is done in WinThreadStart, but in 
 840         // this case it would have been too early because 
 841         // MsgWaitForMultipleObject() would fail if the thread handle was 
 842         // closed while we were waiting on it, so we must do it here 
 849     return rc 
== (ExitCode
)-1 ? wxTHREAD_MISC_ERROR 
: wxTHREAD_NO_ERROR
; 
 852 wxThreadError 
wxThread::Kill() 
 855         return wxTHREAD_NOT_RUNNING
; 
 857     ::DosKillThread(m_internal
->GetHandle()); 
 862     return wxTHREAD_NO_ERROR
; 
 865 void wxThread::Exit(ExitCode 
WXUNUSED(pStatus
)) 
 869     wxFAIL_MSG(wxT("Couldn't return from DosExit()!")); 
 872 void wxThread::SetPriority( 
 876     wxCriticalSectionLocker         
lock((wxCriticalSection 
&)m_critsect
); 
 878     m_internal
->SetPriority(nPrio
); 
 881 unsigned int wxThread::GetPriority() const 
 883     wxCriticalSectionLocker         
lock((wxCriticalSection 
&)m_critsect
); 
 885     return m_internal
->GetPriority(); 
 888 unsigned long wxThread::GetId() const 
 890     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); // const_cast 
 892     return (unsigned long)m_internal
->GetId(); 
 895 bool wxThread::IsRunning() const 
 897     wxCriticalSectionLocker         
lock((wxCriticalSection 
&)m_critsect
); 
 899     return(m_internal
->GetState() == STATE_RUNNING
); 
 902 bool wxThread::IsAlive() const 
 904     wxCriticalSectionLocker         
lock((wxCriticalSection 
&)m_critsect
); 
 906     return (m_internal
->GetState() == STATE_RUNNING
) || 
 907            (m_internal
->GetState() == STATE_PAUSED
); 
 910 bool wxThread::IsPaused() const 
 912     wxCriticalSectionLocker         
lock((wxCriticalSection 
&)m_critsect
); 
 914     return (m_internal
->GetState() == STATE_PAUSED
); 
 917 bool wxThread::TestDestroy() 
 919     wxCriticalSectionLocker         
lock((wxCriticalSection 
&)m_critsect
); 
 921     return m_internal
->GetState() == STATE_CANCELED
; 
 924 // ---------------------------------------------------------------------------- 
 925 // Automatic initialization for thread module 
 926 // ---------------------------------------------------------------------------- 
 928 class wxThreadModule 
: public wxModule
 
 931     virtual bool OnInit(); 
 932     virtual void OnExit(); 
 935     DECLARE_DYNAMIC_CLASS(wxThreadModule
) 
 938 IMPLEMENT_DYNAMIC_CLASS(wxThreadModule
, wxModule
) 
 940 bool wxThreadModule::OnInit() 
 942     gs_pCritsectWaitingForGui 
= new wxCriticalSection(); 
 944     gs_pCritsectGui 
= new wxCriticalSection(); 
 945     gs_pCritsectGui
->Enter(); 
 950     ::DosGetInfoBlocks(&ptib
, &ppib
); 
 952     s_ulIdMainThread 
= ptib
->tib_ptib2
->tib2_ultid
; 
 956 void wxThreadModule::OnExit() 
 960         gs_pCritsectGui
->Leave(); 
 961 #if (!(defined(__VISAGECPP__) && (__IBMCPP__ < 400 || __IBMC__ < 400 ))) 
 962         delete gs_pCritsectGui
; 
 964         gs_pCritsectGui 
= NULL
; 
 967 #if (!(defined(__VISAGECPP__) && (__IBMCPP__ < 400 || __IBMC__ < 400 ))) 
 968     wxDELETE(gs_pCritsectWaitingForGui
); 
 972 // ---------------------------------------------------------------------------- 
 974 // ---------------------------------------------------------------------------- 
 976 // wake up the main thread if it's in ::GetMessage() 
 977 void WXDLLEXPORT 
wxWakeUpMainThread() 
 980     if ( !::WinPostQueueMsg(wxTheApp
->m_hMq
, WM_NULL
, 0, 0) ) 
 982         // should never happen 
 983         wxLogLastError(wxT("WinPostMessage(WM_NULL)")); 
 988 void WXDLLEXPORT 
wxMutexGuiEnter() 
 990     // this would dead lock everything... 
 991     wxASSERT_MSG( !wxThread::IsMain(), 
 992                   wxT("main thread doesn't want to block in wxMutexGuiEnter()!") ); 
 994     // the order in which we enter the critical sections here is crucial!! 
 996     // set the flag telling to the main thread that we want to do some GUI 
 998         wxCriticalSectionLocker 
enter(*gs_pCritsectWaitingForGui
); 
1000         gs_nWaitingForGui
++; 
1003     wxWakeUpMainThread(); 
1005     // now we may block here because the main thread will soon let us in 
1006     // (during the next iteration of OnIdle()) 
1007     gs_pCritsectGui
->Enter(); 
1010 void WXDLLEXPORT 
wxMutexGuiLeave() 
1012     wxCriticalSectionLocker 
enter(*gs_pCritsectWaitingForGui
); 
1014     if ( wxThread::IsMain() ) 
1016         gs_bGuiOwnedByMainThread 
= false; 
1020         // decrement the number of waiters now 
1021         wxASSERT_MSG(gs_nWaitingForGui 
> 0, 
1022                       wxT("calling wxMutexGuiLeave() without entering it first?") ); 
1024         gs_nWaitingForGui
--; 
1026         wxWakeUpMainThread(); 
1029     gs_pCritsectGui
->Leave(); 
1032 void WXDLLEXPORT 
wxMutexGuiLeaveOrEnter() 
1034     wxASSERT_MSG( wxThread::IsMain(), 
1035                   wxT("only main thread may call wxMutexGuiLeaveOrEnter()!") ); 
1037     wxCriticalSectionLocker 
enter(*gs_pCritsectWaitingForGui
); 
1039     if (gs_nWaitingForGui 
== 0) 
1041         // no threads are waiting for GUI - so we may acquire the lock without 
1042         // any danger (but only if we don't already have it) 
1043         if (!wxGuiOwnedByMainThread()) 
1045             gs_pCritsectGui
->Enter(); 
1047             gs_bGuiOwnedByMainThread 
= true; 
1049         //else: already have it, nothing to do 
1053         // some threads are waiting, release the GUI lock if we have it 
1054         if (wxGuiOwnedByMainThread()) 
1058         //else: some other worker thread is doing GUI 
1062 bool WXDLLEXPORT 
wxGuiOwnedByMainThread() 
1064     return gs_bGuiOwnedByMainThread
; 
1067 bool WXDLLEXPORT 
wxIsWaitingForThread() 
1069     return gs_bWaitingForThread
; 
1072 // ---------------------------------------------------------------------------- 
1073 // include common implementation code 
1074 // ---------------------------------------------------------------------------- 
1076 #include "wx/thrimpl.cpp"