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