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