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