home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wxos2240.zip / wxWindows-2.4.0 / src / os2 / thread.cpp < prev    next >
C/C++ Source or Header  |  2002-11-24  |  23KB  |  887 lines

  1. /////////////////////////////////////////////////////////////////////////////
  2. // Name:        thread.cpp
  3. // Purpose:     wxThread Implementation. For Unix ports, see e.g. src/gtk
  4. // Author:      Original from Wolfram Gloger/Guilhem Lavaux
  5. // Modified by: David Webster
  6. // Created:     04/22/98
  7. // RCS-ID:      $Id: THREAD.CPP,v 1.16.2.1 2002/11/24 16:09:42 SN Exp $
  8. // Copyright:   (c) Wolfram Gloger (1996, 1997); Guilhem Lavaux (1998)
  9. // Licence:     wxWindows licence
  10. /////////////////////////////////////////////////////////////////////////////
  11.  
  12. #ifdef __GNUG__
  13.     #pragma implementation "thread.h"
  14. #endif
  15.  
  16. // ----------------------------------------------------------------------------
  17. // headers
  18. // ----------------------------------------------------------------------------
  19.  
  20. // For compilers that support precompilation, includes "wx.h".
  21. #include "wx/wxprec.h"
  22.  
  23. #if wxUSE_THREADS
  24.  
  25. #include <stdio.h>
  26.  
  27. #include "wx/module.h"
  28. #include "wx/intl.h"
  29. #include "wx/utils.h"
  30. #include "wx/log.h"
  31. #include "wx/thread.h"
  32.  
  33. #define INCL_DOSSEMAPHORES
  34. #define INCL_DOSPROCESS
  35. #define INCL_ERRORS
  36. #include <os2.h>
  37. #ifndef __EMX__
  38. #include <bseerr.h>
  39. #endif
  40. // the possible states of the thread ("=>" shows all possible transitions from
  41. // this state)
  42. enum wxThreadState
  43. {
  44.     STATE_NEW,          // didn't start execution yet (=> RUNNING)
  45.     STATE_RUNNING,      // thread is running (=> PAUSED, CANCELED)
  46.     STATE_PAUSED,       // thread is temporarily suspended (=> RUNNING)
  47.     STATE_CANCELED,     // thread should terminate a.s.a.p. (=> EXITED)
  48.     STATE_EXITED        // thread is terminating
  49. };
  50.  
  51. // ----------------------------------------------------------------------------
  52. // static variables
  53. // ----------------------------------------------------------------------------
  54.  
  55. // id of the main thread - the one which can call GUI functions without first
  56. // calling wxMutexGuiEnter()
  57. static ULONG                        s_ulIdMainThread = 0;
  58. wxMutex*                            p_wxMainMutex;
  59.  
  60. // OS2 substitute for Tls pointer the current parent thread object
  61. wxThread*                           m_pThread;    // pointer to the wxWindows thread object
  62.  
  63. // if it's FALSE, some secondary thread is holding the GUI lock
  64. static bool gs_bGuiOwnedByMainThread = TRUE;
  65.  
  66. // critical section which controls access to all GUI functions: any secondary
  67. // thread (i.e. except the main one) must enter this crit section before doing
  68. // any GUI calls
  69. static wxCriticalSection *gs_pCritsectGui = NULL;
  70.  
  71. // critical section which protects s_nWaitingForGui variable
  72. static wxCriticalSection *gs_pCritsectWaitingForGui = NULL;
  73.  
  74. // number of threads waiting for GUI in wxMutexGuiEnter()
  75. static size_t gs_nWaitingForGui = 0;
  76.  
  77. // are we waiting for a thread termination?
  78. static bool gs_bWaitingForThread = FALSE;
  79.  
  80. // ============================================================================
  81. // OS/2 implementation of thread classes
  82. // ============================================================================
  83.  
  84. // ----------------------------------------------------------------------------
  85. // wxMutex implementation
  86. // ----------------------------------------------------------------------------
  87. class wxMutexInternal
  88. {
  89. public:
  90.     HMTX                            m_vMutex;
  91. };
  92.  
  93. wxMutex::wxMutex(
  94.   wxMutexType                       eMutexType
  95. )
  96. {
  97.     APIRET                          ulrc;
  98.  
  99.     m_internal = new wxMutexInternal;
  100.     ulrc = ::DosCreateMutexSem(NULL, &m_internal->m_vMutex, 0L, FALSE);
  101.     if (ulrc != 0)
  102.     {
  103.         wxLogSysError(_("Can not create mutex."));
  104.     }
  105. }
  106.  
  107. wxMutex::~wxMutex()
  108. {
  109.     ::DosCloseMutexSem(m_internal->m_vMutex);
  110.     m_internal->m_vMutex = NULL;
  111. }
  112.  
  113. wxMutexError wxMutex::Lock()
  114. {
  115.     APIRET                          ulrc;
  116.  
  117.     ulrc = ::DosRequestMutexSem(m_internal->m_vMutex, SEM_INDEFINITE_WAIT);
  118.  
  119.     switch (ulrc)
  120.     {
  121.         case ERROR_TOO_MANY_SEM_REQUESTS:
  122.             return wxMUTEX_BUSY;
  123.  
  124.         case NO_ERROR:
  125.             // ok
  126.             break;
  127.  
  128.         case ERROR_INVALID_HANDLE:
  129.         case ERROR_INTERRUPT:
  130.         case ERROR_SEM_OWNER_DIED:
  131.             wxLogSysError(_("Couldn't acquire a mutex lock"));
  132.             return wxMUTEX_MISC_ERROR;
  133.  
  134.         case ERROR_TIMEOUT:
  135.         default:
  136.             wxFAIL_MSG(wxT("impossible return value in wxMutex::Lock"));
  137.     }
  138.     return wxMUTEX_NO_ERROR;
  139. }
  140.  
  141. wxMutexError wxMutex::TryLock()
  142. {
  143.     ULONG                           ulrc;
  144.  
  145.     ulrc = ::DosRequestMutexSem(m_internal->m_vMutex, SEM_IMMEDIATE_RETURN /*0L*/);
  146.     if (ulrc == ERROR_TIMEOUT || ulrc == ERROR_TOO_MANY_SEM_REQUESTS)
  147.         return wxMUTEX_BUSY;
  148.  
  149.     return wxMUTEX_NO_ERROR;
  150. }
  151.  
  152. wxMutexError wxMutex::Unlock()
  153. {
  154.     APIRET                          ulrc;
  155.  
  156.     ulrc = ::DosReleaseMutexSem(m_internal->m_vMutex);
  157.     if (ulrc != 0)
  158.     {
  159.         wxLogSysError(_("Couldn't release a mutex"));
  160.         return wxMUTEX_MISC_ERROR;
  161.     }
  162.     return wxMUTEX_NO_ERROR;
  163. }
  164.  
  165. // ----------------------------------------------------------------------------
  166. // wxCondition implementation
  167. // ----------------------------------------------------------------------------
  168.  
  169. class wxConditionInternal
  170. {
  171. public:
  172.     inline wxConditionInternal (wxMutex& rMutex) : m_vMutex(rMutex)
  173.     {
  174.         ::DosCreateEventSem(NULL, &m_vEvent, DC_SEM_SHARED, FALSE);
  175.         if (!m_vEvent)
  176.         {
  177.             wxLogSysError(_("Can not create event semaphore."));
  178.         }
  179.         m_nWaiters = 0;
  180.     }
  181.  
  182.     inline APIRET Wait(
  183.       unsigned long                 ulTimeout
  184.     )
  185.     {
  186.         APIRET                      ulrc;
  187.  
  188.         m_nWaiters++;
  189.         ulrc = ::DosWaitEventSem(m_vEvent, ulTimeout);
  190.         m_nWaiters--;
  191.         return (ulrc);
  192.     }
  193.  
  194.     inline ~wxConditionInternal ()
  195.     {
  196.         APIRET                      ulrc;
  197.  
  198.         if (m_vEvent)
  199.         {
  200.             ulrc = ::DosCloseEventSem(m_vEvent);
  201.             if (!ulrc)
  202.             {
  203.                 wxLogLastError("DosCloseEventSem(m_vEvent)");
  204.             }
  205.         }
  206.     }
  207.  
  208.     HEV                             m_vEvent;
  209.     int                             m_nWaiters;
  210.     wxMutex&                        m_vMutex;
  211. };
  212.  
  213. wxCondition::wxCondition(wxMutex& rMutex)
  214. {
  215.     APIRET                          ulrc;
  216.     ULONG                           ulCount;
  217.  
  218.     m_internal = new wxConditionInternal(rMutex);
  219.     ulrc = ::DosCreateEventSem(NULL, &m_internal->m_vEvent, 0L, FALSE);
  220.     if (ulrc != 0)
  221.     {
  222.         wxLogSysError(_("Can not create event object."));
  223.     }
  224.     m_internal->m_nWaiters = 0;
  225.     // ?? just for good measure?
  226.     ::DosResetEventSem(m_internal->m_vEvent, &ulCount);
  227. }
  228.  
  229. wxCondition::~wxCondition()
  230. {
  231.     ::DosCloseEventSem(m_internal->m_vEvent);
  232.     delete m_internal;
  233.     m_internal = NULL;
  234. }
  235.  
  236. wxCondError wxCondition::Wait()
  237. {
  238.     APIRET                          rc = m_internal->Wait(SEM_INDEFINITE_WAIT);
  239.  
  240.     switch(rc)
  241.     {
  242.         case NO_ERROR:
  243.             return wxCOND_NO_ERROR;
  244.         case ERROR_INVALID_HANDLE:
  245.             return wxCOND_INVALID;
  246.         case ERROR_TIMEOUT:
  247.             return wxCOND_TIMEOUT;
  248.         default:
  249.             return wxCOND_MISC_ERROR;
  250.     }
  251. }
  252.  
  253. wxCondError wxCondition::WaitTimeout(
  254.   unsigned long                     lMilliSec
  255. )
  256. {
  257.     APIRET                          rc = m_internal->Wait(lMilliSec);
  258.  
  259.     switch(rc)
  260.     {
  261.         case NO_ERROR:
  262.             return wxCOND_NO_ERROR;
  263.         case ERROR_INVALID_HANDLE:
  264.             return wxCOND_INVALID;
  265.         case ERROR_TIMEOUT:
  266.             return wxCOND_TIMEOUT;
  267.         default:
  268.             return wxCOND_MISC_ERROR;
  269.     }
  270. }
  271.  
  272. wxCondError wxCondition::Signal()
  273. {
  274.     APIRET                          rc = ::DosPostEventSem(m_internal->m_vEvent);
  275.  
  276.     switch(rc)
  277.     {
  278.         case NO_ERROR:
  279.             return wxCOND_NO_ERROR;
  280.         case ERROR_INVALID_HANDLE:
  281.             return wxCOND_INVALID;
  282.         default:
  283.             return wxCOND_MISC_ERROR;
  284.     }
  285. }
  286.  
  287. wxCondError wxCondition::Broadcast()
  288. {
  289.     int                             i;
  290.     APIRET                          rc = NO_ERROR;
  291.  
  292.     for (i = 0; i < m_internal->m_nWaiters; i++)
  293.     {
  294.         if ((rc = ::DosPostEventSem(m_internal->m_vEvent)) != NO_ERROR)
  295.         {
  296.             wxLogSysError(_("Couldn't change the state of event object."));
  297.             break;
  298.         }
  299.     }
  300.  
  301.     switch(rc)
  302.     {
  303.         case NO_ERROR:
  304.             return wxCOND_NO_ERROR;
  305.         case ERROR_INVALID_HANDLE:
  306.             return wxCOND_INVALID;
  307.         default:
  308.             return wxCOND_MISC_ERROR;
  309.     }
  310. }
  311.  
  312. // ----------------------------------------------------------------------------
  313. // wxCriticalSection implementation
  314. // ----------------------------------------------------------------------------
  315.  
  316. wxCriticalSection::wxCriticalSection()
  317. {
  318. }
  319.  
  320. wxCriticalSection::~wxCriticalSection()
  321. {
  322. }
  323.  
  324. void wxCriticalSection::Enter()
  325. {
  326.     ::DosEnterCritSec();
  327. }
  328.  
  329. void wxCriticalSection::Leave()
  330. {
  331.     ::DosExitCritSec();
  332. }
  333.  
  334. // ----------------------------------------------------------------------------
  335. // wxThread implementation
  336. // ----------------------------------------------------------------------------
  337.  
  338. // wxThreadInternal class
  339. // ----------------------
  340.  
  341. class wxThreadInternal
  342. {
  343. public:
  344.     inline wxThreadInternal()
  345.     {
  346.         m_hThread = 0;
  347.         m_eState = STATE_NEW;
  348.         m_nPriority = 0;
  349.     }
  350.  
  351.     ~wxThreadInternal()
  352.     {
  353.         Free();
  354.     }
  355.  
  356.     void Free()
  357.     {
  358.         if (m_hThread)
  359.         {
  360.             ::DosExit(0,0);
  361.             m_hThread = 0;
  362.         }
  363.     }
  364.  
  365.     // create a new (suspended) thread (for the given thread object)
  366.     bool Create( wxThread*    pThread
  367.                 ,unsigned int uStackSize
  368.                );
  369.  
  370.     // suspend/resume/terminate
  371.     bool Suspend();
  372.     bool Resume();
  373.     inline void Cancel() { m_eState = STATE_CANCELED; }
  374.  
  375.     // thread state
  376.     inline void SetState(wxThreadState eState) { m_eState = eState; }
  377.     inline wxThreadState GetState() const { return m_eState; }
  378.  
  379.     // thread priority
  380.     void                SetPriority(unsigned int nPriority);
  381.     inline unsigned int GetPriority() const { return m_nPriority; }
  382.  
  383.     // thread handle and id
  384.     inline TID GetHandle() const { return m_hThread; }
  385.     TID  GetId() const { return m_hThread; }
  386.  
  387.     // thread function
  388.     static DWORD OS2ThreadStart(wxThread *thread);
  389.  
  390. private:
  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 wxWindows 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
  397. };
  398.  
  399. ULONG wxThreadInternal::OS2ThreadStart(
  400.   wxThread*                         pThread
  401. )
  402. {
  403.     m_pThread = pThread;
  404.  
  405.     DWORD                           dwRet = (DWORD)pThread->Entry();
  406.  
  407.     // enter m_critsect before changing the thread state
  408.     pThread->m_critsect.Enter();
  409.  
  410.     bool                            bWasCancelled = pThread->m_internal->GetState() == STATE_CANCELED;
  411.  
  412.     pThread->m_internal->SetState(STATE_EXITED);
  413.     pThread->m_critsect.Leave();
  414.  
  415.     pThread->OnExit();
  416.  
  417.     // if the thread was cancelled (from Delete()), then it the handle is still
  418.     // needed there
  419.     if (pThread->IsDetached() && !bWasCancelled)
  420.     {
  421.         // auto delete
  422.         delete pThread;
  423.     }
  424.     //else: the joinable threads handle will be closed when Wait() is done
  425.     return dwRet;
  426. }
  427.  
  428. void wxThreadInternal::SetPriority(
  429.   unsigned int                      nPriority
  430. )
  431. {
  432.     // translate wxWindows priority to the PM one
  433.     ULONG                           ulOS2_Priority;
  434.     ULONG                           ulrc;
  435.  
  436.     m_nPriority = nPriority;
  437.  
  438.     if (m_nPriority <= 20)
  439.         ulOS2_Priority = PRTYC_NOCHANGE;
  440.     else if (m_nPriority <= 40)
  441.         ulOS2_Priority = PRTYC_IDLETIME;
  442.     else if (m_nPriority <= 60)
  443.         ulOS2_Priority = PRTYC_REGULAR;
  444.     else if (m_nPriority <= 80)
  445.         ulOS2_Priority = PRTYC_TIMECRITICAL;
  446.     else if (m_nPriority <= 100)
  447.         ulOS2_Priority = PRTYC_FOREGROUNDSERVER;
  448.     else
  449.     {
  450.         wxFAIL_MSG(wxT("invalid value of thread priority parameter"));
  451.         ulOS2_Priority = PRTYC_REGULAR;
  452.     }
  453.     ulrc = ::DosSetPriority( PRTYS_THREAD
  454.                             ,ulOS2_Priority
  455.                             ,0
  456.                             ,(ULONG)m_hThread
  457.                            );
  458.     if (ulrc != 0)
  459.     {
  460.         wxLogSysError(_("Can't set thread priority"));
  461.     }
  462. }
  463.  
  464. bool wxThreadInternal::Create(
  465.   wxThread*                         pThread
  466. , unsigned int                      uStackSize
  467. )
  468. {
  469.     APIRET                          ulrc;
  470.  
  471.     ulrc = ::DosCreateThread( &m_hThread
  472.                              ,(PFNTHREAD)wxThreadInternal::OS2ThreadStart
  473.                              ,(ULONG)pThread
  474.                              ,CREATE_SUSPENDED | STACK_SPARSE
  475.                              ,(ULONG)uStackSize
  476.                             );
  477.     if(ulrc != 0)
  478.     {
  479.         wxLogSysError(_("Can't create thread"));
  480.  
  481.         return FALSE;
  482.     }
  483.     if (m_nPriority != WXTHREAD_DEFAULT_PRIORITY)
  484.     {
  485.         SetPriority(m_nPriority);
  486.     }
  487.     return(TRUE);
  488. }
  489.  
  490. bool wxThreadInternal::Suspend()
  491. {
  492.     ULONG                           ulrc = ::DosSuspendThread(m_hThread);
  493.  
  494.     if (ulrc != 0)
  495.     {
  496.         wxLogSysError(_("Can not suspend thread %lu"), m_hThread);
  497.         return FALSE;
  498.     }
  499.     m_eState = STATE_PAUSED;
  500.     return TRUE;
  501. }
  502.  
  503. bool wxThreadInternal::Resume()
  504. {
  505.     ULONG                           ulrc = ::DosResumeThread(m_hThread);
  506.  
  507.     if (ulrc != 0)
  508.     {
  509.         wxLogSysError(_("Can not suspend thread %lu"), m_hThread);
  510.         return FALSE;
  511.     }
  512.     m_eState = STATE_PAUSED;
  513.     return TRUE;
  514. }
  515.  
  516. // static functions
  517. // ----------------
  518.  
  519. wxThread *wxThread::This()
  520. {
  521.     wxThread*                       pThread = m_pThread;
  522.     return pThread;
  523. }
  524.  
  525. bool wxThread::IsMain()
  526. {
  527.     PTIB                            ptib;
  528.     PPIB                            ppib;
  529.  
  530.     ::DosGetInfoBlocks(&ptib, &ppib);
  531.  
  532.     if (ptib->tib_ptib2->tib2_ultid == s_ulIdMainThread)
  533.         return TRUE;
  534.     return FALSE;
  535. }
  536.  
  537. #ifdef Yield
  538.     #undef Yield
  539. #endif
  540.  
  541. void wxThread::Yield()
  542. {
  543.     ::DosSleep(0);
  544. }
  545.  
  546. void wxThread::Sleep(
  547.   unsigned long                     ulMilliseconds
  548. )
  549. {
  550.     ::DosSleep(ulMilliseconds);
  551. }
  552.  
  553. // ctor and dtor
  554. // -------------
  555.  
  556. wxThread::wxThread(wxThreadKind kind)
  557. {
  558.     m_internal = new wxThreadInternal();
  559.  
  560.     m_isDetached = kind == wxTHREAD_DETACHED;
  561. }
  562.  
  563. wxThread::~wxThread()
  564. {
  565.     delete m_internal;
  566. }
  567.  
  568. // create/start thread
  569. // -------------------
  570.  
  571. wxThreadError wxThread::Create(
  572.   unsigned int                      uStackSize
  573. )
  574. {
  575.     if ( !m_internal->Create(this, uStackSize) )
  576.         return wxTHREAD_NO_RESOURCE;
  577.  
  578.     return wxTHREAD_NO_ERROR;
  579. }
  580.  
  581. wxThreadError wxThread::Run()
  582. {
  583.     wxCriticalSectionLocker         lock((wxCriticalSection &)m_critsect);
  584.  
  585.     if ( m_internal->GetState() != STATE_NEW )
  586.     {
  587.         // actually, it may be almost any state at all, not only STATE_RUNNING
  588.         return wxTHREAD_RUNNING;
  589.     }
  590.     return Resume();
  591. }
  592.  
  593. // suspend/resume thread
  594. // ---------------------
  595.  
  596. wxThreadError wxThread::Pause()
  597. {
  598.     wxCriticalSectionLocker         lock((wxCriticalSection &)m_critsect);
  599.  
  600.     return m_internal->Suspend() ? wxTHREAD_NO_ERROR : wxTHREAD_MISC_ERROR;
  601. }
  602.  
  603. wxThreadError wxThread::Resume()
  604. {
  605.     wxCriticalSectionLocker         lock((wxCriticalSection &)m_critsect);
  606.  
  607.     return m_internal->Resume() ? wxTHREAD_NO_ERROR : wxTHREAD_MISC_ERROR;
  608. }
  609.  
  610. // stopping thread
  611. // ---------------
  612.  
  613. wxThread::ExitCode wxThread::Wait()
  614. {
  615.     // although under Windows we can wait for any thread, it's an error to
  616.     // wait for a detached one in wxWin API
  617.     wxCHECK_MSG( !IsDetached(), (ExitCode)-1,
  618.                  _T("can't wait for detached thread") );
  619.     ExitCode rc = (ExitCode)-1;
  620.     (void)Delete(&rc);
  621.     m_internal->Free();
  622.     return(rc);
  623. }
  624.  
  625. wxThreadError wxThread::Delete(ExitCode *pRc)
  626. {
  627.     ExitCode rc = 0;
  628.  
  629.     // Delete() is always safe to call, so consider all possible states
  630.     if (IsPaused())
  631.         Resume();
  632.  
  633.     TID                             hThread = m_internal->GetHandle();
  634.  
  635.     if (IsRunning())
  636.     {
  637.         if (IsMain())
  638.         {
  639.             // set flag for wxIsWaitingForThread()
  640.             gs_bWaitingForThread = TRUE;
  641.  
  642. #if wxUSE_GUI
  643.             wxBeginBusyCursor();
  644. #endif // wxUSE_GUI
  645.         }
  646.  
  647.         // ask the thread to terminate
  648.         {
  649.             wxCriticalSectionLocker lock(m_critsect);
  650.             m_internal->Cancel();
  651.         }
  652.  
  653. #if wxUSE_GUI
  654.         // need a way to finish GUI processing before killing the thread
  655.         // until then we just exit
  656.  
  657.         if ((gs_nWaitingForGui > 0) && wxGuiOwnedByMainThread())
  658.         {
  659.             wxMutexGuiLeave();
  660.         }
  661. #else // !wxUSE_GUI
  662.  
  663.         // can't wait for yourself to end under OS/2 so just quit
  664.  
  665. #endif // wxUSE_GUI/!wxUSE_GUI
  666.  
  667.         if ( IsMain() )
  668.         {
  669.             gs_bWaitingForThread = FALSE;
  670.  
  671. #if wxUSE_GUI
  672.             wxEndBusyCursor();
  673. #endif // wxUSE_GUI
  674.         }
  675.     }
  676.  
  677.     ::DosExit(0, 0);
  678.     // probably won't get this far, but
  679.     if (IsDetached())
  680.     {
  681.         delete this;
  682.     }
  683.  
  684.     if ( pRc )
  685.         *pRc = rc;
  686.  
  687.     return rc == (ExitCode)-1 ? wxTHREAD_MISC_ERROR : wxTHREAD_NO_ERROR;
  688. }
  689.  
  690. wxThreadError wxThread::Kill()
  691. {
  692.     if (!IsRunning())
  693.         return wxTHREAD_NOT_RUNNING;
  694.  
  695.     ::DosKillThread(m_internal->GetHandle());
  696.     m_internal->Free();
  697.     if (IsDetached())
  698.     {
  699.         delete this;
  700.     }
  701.     return wxTHREAD_NO_ERROR;
  702. }
  703.  
  704. void wxThread::Exit(
  705.   ExitCode                          pStatus
  706. )
  707. {
  708.     m_internal->Free();
  709.     delete this;
  710.     ::DosExit(EXIT_THREAD, ULONG(pStatus));
  711.     wxFAIL_MSG(wxT("Couldn't return from DosExit()!"));
  712. }
  713.  
  714. void wxThread::SetPriority(
  715.   unsigned int                      nPrio
  716. )
  717. {
  718.     wxCriticalSectionLocker         lock((wxCriticalSection &)m_critsect);
  719.  
  720.     m_internal->SetPriority(nPrio);
  721. }
  722.  
  723. unsigned int wxThread::GetPriority() const
  724. {
  725.     wxCriticalSectionLocker         lock((wxCriticalSection &)m_critsect);
  726.  
  727.     return m_internal->GetPriority();
  728. }
  729.  
  730. unsigned long wxThread::GetId() const
  731. {
  732.     wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect); // const_cast
  733.  
  734.     return (unsigned long)m_internal->GetId();
  735. }
  736.  
  737. bool wxThread::IsRunning() const
  738. {
  739.     wxCriticalSectionLocker         lock((wxCriticalSection &)m_critsect);
  740.  
  741.     return(m_internal->GetState() == STATE_RUNNING);
  742. }
  743.  
  744. bool wxThread::IsAlive() const
  745. {
  746.     wxCriticalSectionLocker         lock((wxCriticalSection &)m_critsect);
  747.  
  748.     return (m_internal->GetState() == STATE_RUNNING) ||
  749.            (m_internal->GetState() == STATE_PAUSED);
  750. }
  751.  
  752. bool wxThread::IsPaused() const
  753. {
  754.     wxCriticalSectionLocker         lock((wxCriticalSection &)m_critsect);
  755.  
  756.     return (m_internal->GetState() == STATE_PAUSED);
  757. }
  758.  
  759. bool wxThread::TestDestroy()
  760. {
  761.     wxCriticalSectionLocker         lock((wxCriticalSection &)m_critsect);
  762.  
  763.     return m_internal->GetState() == STATE_CANCELED;
  764. }
  765.  
  766. // ----------------------------------------------------------------------------
  767. // Automatic initialization for thread module
  768. // ----------------------------------------------------------------------------
  769.  
  770. class wxThreadModule : public wxModule
  771. {
  772. public:
  773.     virtual bool OnInit();
  774.     virtual void OnExit();
  775.  
  776. private:
  777.     DECLARE_DYNAMIC_CLASS(wxThreadModule)
  778. };
  779.  
  780. IMPLEMENT_DYNAMIC_CLASS(wxThreadModule, wxModule)
  781.  
  782. bool wxThreadModule::OnInit()
  783. {
  784.     gs_pCritsectWaitingForGui = new wxCriticalSection();
  785.  
  786.     gs_pCritsectGui = new wxCriticalSection();
  787.     gs_pCritsectGui->Enter();
  788.  
  789.     PTIB                            ptib;
  790.     PPIB                            ppib;
  791.  
  792.     ::DosGetInfoBlocks(&ptib, &ppib);
  793.  
  794.     s_ulIdMainThread = ptib->tib_ptib2->tib2_ultid;
  795.     return TRUE;
  796. }
  797.  
  798. void wxThreadModule::OnExit()
  799. {
  800.     if (gs_pCritsectGui)
  801.     {
  802.         gs_pCritsectGui->Leave();
  803. #if (!(defined(__VISAGECPP__) && (__IBMCPP__ < 400 || __IBMC__ < 400 )))
  804.         delete gs_pCritsectGui;
  805. #endif
  806.         gs_pCritsectGui = NULL;
  807.     }
  808.  
  809. #if (!(defined(__VISAGECPP__) && (__IBMCPP__ < 400 || __IBMC__ < 400 )))
  810.     wxDELETE(gs_pCritsectWaitingForGui);
  811. #endif
  812. }
  813.  
  814. // ----------------------------------------------------------------------------
  815. // Helper functions
  816. // ----------------------------------------------------------------------------
  817.  
  818. // Does nothing under OS/2 [for now]
  819. void WXDLLEXPORT wxWakeUpMainThread()
  820. {
  821. }
  822.  
  823. void WXDLLEXPORT wxMutexGuiLeave()
  824. {
  825.     wxCriticalSectionLocker enter(*gs_pCritsectWaitingForGui);
  826.  
  827.     if ( wxThread::IsMain() )
  828.     {
  829.         gs_bGuiOwnedByMainThread = FALSE;
  830.     }
  831.     else
  832.     {
  833.         // decrement the number of waiters now
  834.         wxASSERT_MSG(gs_nWaitingForGui > 0,
  835.                       wxT("calling wxMutexGuiLeave() without entering it first?") );
  836.  
  837.         gs_nWaitingForGui--;
  838.  
  839.         wxWakeUpMainThread();
  840.     }
  841.  
  842.     gs_pCritsectGui->Leave();
  843. }
  844.  
  845. void WXDLLEXPORT wxMutexGuiLeaveOrEnter()
  846. {
  847.     wxASSERT_MSG( wxThread::IsMain(),
  848.                   wxT("only main thread may call wxMutexGuiLeaveOrEnter()!") );
  849.  
  850.     wxCriticalSectionLocker enter(*gs_pCritsectWaitingForGui);
  851.  
  852.     if (gs_nWaitingForGui == 0)
  853.     {
  854.         // no threads are waiting for GUI - so we may acquire the lock without
  855.         // any danger (but only if we don't already have it)
  856.         if (!wxGuiOwnedByMainThread())
  857.         {
  858.             gs_pCritsectGui->Enter();
  859.  
  860.             gs_bGuiOwnedByMainThread = TRUE;
  861.         }
  862.         //else: already have it, nothing to do
  863.     }
  864.     else
  865.     {
  866.         // some threads are waiting, release the GUI lock if we have it
  867.         if (wxGuiOwnedByMainThread())
  868.         {
  869.             wxMutexGuiLeave();
  870.         }
  871.         //else: some other worker thread is doing GUI
  872.     }
  873. }
  874.  
  875. bool WXDLLEXPORT wxGuiOwnedByMainThread()
  876. {
  877.     return gs_bGuiOwnedByMainThread;
  878. }
  879.  
  880. bool WXDLLEXPORT wxIsWaitingForThread()
  881. {
  882.     return gs_bWaitingForThread;
  883. }
  884.  
  885. #endif
  886.   // wxUSE_THREADS
  887.