]> git.saurik.com Git - wxWidgets.git/blame - src/os2/thread.cpp
Compile fixes
[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
0e320a79 89 p_internal = new wxMutexInternal;
c5fb56c0
DW
90 ulrc = ::DosCreateMutexSem(NULL, &p_internal->m_vMutex, 0L, FALSE);
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);
c5fb56c0 102 ::DosCloseMutexSem(p_internal->m_vMutex);
5d4b632b 103 p_internal->m_vMutex = NULL;
0e320a79
DW
104}
105
106wxMutexError wxMutex::Lock()
107{
c5fb56c0
DW
108 APIRET ulrc;
109
110 ulrc = ::DosRequestMutexSem(p_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
c5fb56c0
DW
139 ulrc = ::DosRequestMutexSem(p_internal->m_vMutex, SEM_IMMEDIATE_RETURN /*0L*/);
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
c5fb56c0
DW
154 ulrc = ::DosReleaseMutexSem(p_internal->m_vMutex);
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:
c5fb56c0
DW
170 HEV m_vEvent;
171 int m_nWaiters;
0e320a79
DW
172};
173
174wxCondition::wxCondition()
175{
c5fb56c0
DW
176 APIRET ulrc;
177 ULONG ulCount;
178
0e320a79 179 p_internal = new wxConditionInternal;
c5fb56c0
DW
180 ulrc = ::DosCreateEventSem(NULL, &p_internal->m_vEvent, 0L, FALSE);
181 if (ulrc != 0)
d90895ac
DW
182 {
183 wxLogSysError(_("Can not create event object."));
184 }
c5fb56c0
DW
185 p_internal->m_nWaiters = 0;
186 // ?? just for good measure?
187 ::DosResetEventSem(p_internal->m_vEvent, &ulCount);
0e320a79
DW
188}
189
190wxCondition::~wxCondition()
191{
c5fb56c0
DW
192 ::DosCloseEventSem(p_internal->m_vEvent);
193 delete p_internal;
194 p_internal = NULL;
0e320a79
DW
195}
196
c5fb56c0
DW
197void wxCondition::Wait(
198 wxMutex& rMutex
199)
0e320a79 200{
c5fb56c0
DW
201 rMutex.Unlock();
202 p_internal->m_nWaiters++;
203 ::DosWaitEventSem(p_internal->m_vEvent, SEM_INDEFINITE_WAIT);
204 p_internal->m_nWaiters--;
205 rMutex.Lock();
0e320a79
DW
206}
207
c5fb56c0
DW
208bool wxCondition::Wait(
209 wxMutex& rMutex
210, unsigned long ulSec
211, unsigned long ulMillisec)
0e320a79 212{
c5fb56c0 213 APIRET ulrc;
d90895ac 214
c5fb56c0
DW
215 rMutex.Unlock();
216 p_internal->m_nWaiters++;
217 ulrc = ::DosWaitEventSem(p_internal->m_vEvent, ULONG((ulSec * 1000L) + ulMillisec));
218 p_internal->m_nWaiters--;
219 rMutex.Lock();
0e320a79 220
c5fb56c0 221 return (ulrc != ERROR_TIMEOUT);
0e320a79
DW
222}
223
224void wxCondition::Signal()
225{
c5fb56c0 226 ::DosPostEventSem(p_internal->m_vEvent);
0e320a79
DW
227}
228
229void wxCondition::Broadcast()
230{
c5fb56c0 231 int i;
d90895ac 232
c5fb56c0 233 for (i = 0; i < p_internal->m_nWaiters; i++)
d90895ac 234 {
c5fb56c0 235 if (::DosPostEventSem(p_internal->m_vEvent) != 0)
d90895ac
DW
236 {
237 wxLogSysError(_("Couldn't change the state of event object."));
238 }
239 }
0e320a79
DW
240}
241
892b89f3
DW
242// ----------------------------------------------------------------------------
243// wxCriticalSection implementation
244// ----------------------------------------------------------------------------
245
246wxCriticalSection::wxCriticalSection()
247{
248}
249
250wxCriticalSection::~wxCriticalSection()
251{
252}
253
254void wxCriticalSection::Enter()
255{
256 ::DosEnterCritSec();
257}
258
259void wxCriticalSection::Leave()
260{
261 ::DosExitCritSec();
262}
263
d90895ac
DW
264// ----------------------------------------------------------------------------
265// wxThread implementation
266// ----------------------------------------------------------------------------
267
268// wxThreadInternal class
269// ----------------------
270
271class wxThreadInternal
272{
273public:
c5fb56c0 274 inline wxThreadInternal()
d90895ac
DW
275 {
276 m_hThread = 0;
c5fb56c0
DW
277 m_eState = STATE_NEW;
278 m_nPriority = 0;
d90895ac
DW
279 }
280
281 // create a new (suspended) thread (for the given thread object)
c5fb56c0 282 bool Create(wxThread* pThread);
d90895ac
DW
283
284 // suspend/resume/terminate
285 bool Suspend();
286 bool Resume();
c5fb56c0 287 inline void Cancel() { m_eState = STATE_CANCELED; }
d90895ac
DW
288
289 // thread state
c5fb56c0
DW
290 inline void SetState(wxThreadState eState) { m_eState = eState; }
291 inline wxThreadState GetState() const { return m_eState; }
d90895ac
DW
292
293 // thread priority
c5fb56c0
DW
294 inline void SetPriority(unsigned int nPriority) { m_nPriority = nPriority; }
295 inline unsigned int GetPriority() const { return m_nPriority; }
d90895ac
DW
296
297 // thread handle and id
c5fb56c0
DW
298 inline TID GetHandle() const { return m_hThread; }
299 TID GetId() const { return m_hThread; }
d90895ac
DW
300
301 // thread function
302 static DWORD OS2ThreadStart(wxThread *thread);
303
304private:
c5fb56c0
DW
305 // Threads in OS/2 have only an ID, so m_hThread is both it's handle and ID
306 // PM also has no real Tls mechanism to index pointers by so we'll just
307 // keep track of the wxWindows parent object here.
308 TID m_hThread; // handle and ID of the thread
309 wxThreadState m_eState; // state, see wxThreadState enum
310 unsigned int m_nPriority; // thread priority in "wx" units
d90895ac
DW
311};
312
c5fb56c0
DW
313ULONG wxThreadInternal::OS2ThreadStart(
314 wxThread* pThread
315)
d90895ac 316{
c5fb56c0 317 m_pThread = pThread;
d90895ac 318
c5fb56c0 319 DWORD dwRet = (DWORD)pThread->Entry();
d90895ac 320
c5fb56c0
DW
321 pThread->p_internal->SetState(STATE_EXITED);
322 pThread->OnExit();
d90895ac 323
c5fb56c0
DW
324 delete pThread;
325 m_pThread = NULL;
326 return dwRet;
d90895ac
DW
327}
328
c5fb56c0
DW
329bool wxThreadInternal::Create(
330 wxThread* pThread
331)
d90895ac 332{
c5fb56c0 333 APIRET ulrc;
d90895ac 334
c5fb56c0
DW
335 ulrc = ::DosCreateThread( &m_hThread
336 ,(PFNTHREAD)wxThreadInternal::OS2ThreadStart
337 ,(ULONG)pThread
338 ,CREATE_SUSPENDED | STACK_SPARSE
339 ,8192L
340 );
341 if(ulrc != 0)
d90895ac
DW
342 {
343 wxLogSysError(_("Can't create thread"));
344
345 return FALSE;
346 }
347
c5fb56c0
DW
348 // translate wxWindows priority to the PM one
349 ULONG ulOS2_Priority;
350
351 if (m_nPriority <= 20)
352 ulOS2_Priority = PRTYC_NOCHANGE;
353 else if (m_nPriority <= 40)
354 ulOS2_Priority = PRTYC_IDLETIME;
355 else if (m_nPriority <= 60)
356 ulOS2_Priority = PRTYC_REGULAR;
357 else if (m_nPriority <= 80)
358 ulOS2_Priority = PRTYC_TIMECRITICAL;
359 else if (m_nPriority <= 100)
360 ulOS2_Priority = PRTYC_FOREGROUNDSERVER;
d90895ac
DW
361 else
362 {
363 wxFAIL_MSG(wxT("invalid value of thread priority parameter"));
c5fb56c0 364 ulOS2_Priority = PRTYC_REGULAR;
d90895ac 365 }
c5fb56c0
DW
366 ulrc = ::DosSetPriority( PRTYS_THREAD
367 ,ulOS2_Priority
368 ,0
369 ,(ULONG)m_hThread
370 );
371 if (ulrc != 0)
d90895ac
DW
372 {
373 wxLogSysError(_("Can't set thread priority"));
374 }
c5fb56c0 375 return TRUE;
d90895ac
DW
376}
377
378bool wxThreadInternal::Suspend()
379{
c5fb56c0 380 ULONG ulrc = ::DosSuspendThread(m_hThread);
d90895ac 381
c5fb56c0
DW
382 if (ulrc != 0)
383 {
384 wxLogSysError(_("Can not suspend thread %lu"), m_hThread);
d90895ac
DW
385 return FALSE;
386 }
c5fb56c0
DW
387 m_eState = STATE_PAUSED;
388 return TRUE;
d90895ac
DW
389}
390
391bool wxThreadInternal::Resume()
392{
c5fb56c0 393 ULONG ulrc = ::DosResumeThread(m_hThread);
d90895ac 394
c5fb56c0
DW
395 if (ulrc != 0)
396 {
397 wxLogSysError(_("Can not suspend thread %lu"), m_hThread);
d90895ac
DW
398 return FALSE;
399 }
c5fb56c0
DW
400 m_eState = STATE_PAUSED;
401 return TRUE;
d90895ac
DW
402}
403
404// static functions
405// ----------------
406
407wxThread *wxThread::This()
408{
c5fb56c0
DW
409 wxThread* pThread = m_pThread;
410 return pThread;
d90895ac
DW
411}
412
413bool wxThread::IsMain()
414{
c5fb56c0
DW
415 PTIB ptib;
416 PPIB ppib;
417
418 ::DosGetInfoBlocks(&ptib, &ppib);
419
420 if (ptib->tib_ptib2->tib2_ultid == s_ulIdMainThread)
421 return TRUE;
d90895ac
DW
422 return FALSE;
423}
424
425#ifdef Yield
426 #undef Yield
427#endif
428
429void wxThread::Yield()
430{
d90895ac
DW
431 ::DosSleep(0);
432}
433
c5fb56c0
DW
434void wxThread::Sleep(
435 unsigned long ulMilliseconds
436)
d90895ac 437{
c5fb56c0 438 ::DosSleep(ulMilliseconds);
d90895ac
DW
439}
440
441// create/start thread
442// -------------------
443
0e320a79
DW
444wxThreadError wxThread::Create()
445{
d90895ac
DW
446 if ( !p_internal->Create(this) )
447 return wxTHREAD_NO_RESOURCE;
448
0e320a79
DW
449 return wxTHREAD_NO_ERROR;
450}
451
d90895ac 452wxThreadError wxThread::Run()
0e320a79 453{
c5fb56c0 454 wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect);
d90895ac
DW
455
456 if ( p_internal->GetState() != STATE_NEW )
457 {
458 // actually, it may be almost any state at all, not only STATE_RUNNING
459 return wxTHREAD_RUNNING;
460 }
d90895ac 461 return Resume();
0e320a79
DW
462}
463
d90895ac
DW
464// suspend/resume thread
465// ---------------------
466
0e320a79
DW
467wxThreadError wxThread::Pause()
468{
c5fb56c0 469 wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect);
d90895ac
DW
470
471 return p_internal->Suspend() ? wxTHREAD_NO_ERROR : wxTHREAD_MISC_ERROR;
0e320a79
DW
472}
473
474wxThreadError wxThread::Resume()
475{
c5fb56c0 476 wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect);
0e320a79 477
d90895ac 478 return p_internal->Resume() ? wxTHREAD_NO_ERROR : wxTHREAD_MISC_ERROR;
0e320a79
DW
479}
480
d90895ac
DW
481// stopping thread
482// ---------------
483
484wxThread::ExitCode wxThread::Delete()
0e320a79 485{
c5fb56c0
DW
486 ExitCode rc = 0;
487 ULONG ulrc;
d90895ac
DW
488
489 // Delete() is always safe to call, so consider all possible states
c5fb56c0 490 if (IsPaused())
d90895ac
DW
491 Resume();
492
c5fb56c0 493 if (IsRunning())
d90895ac 494 {
c5fb56c0 495 if (IsMain())
d90895ac
DW
496 {
497 // set flag for wxIsWaitingForThread()
c5fb56c0 498 s_bWaitingForThread = TRUE;
d90895ac
DW
499 wxBeginBusyCursor();
500 }
501
c5fb56c0
DW
502 TID hThread;
503
d90895ac 504 {
c5fb56c0 505 wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect);
d90895ac
DW
506
507 p_internal->Cancel();
508 hThread = p_internal->GetHandle();
509 }
510
511 // we can't just wait for the thread to terminate because it might be
512 // calling some GUI functions and so it will never terminate before we
513 // process the Windows messages that result from these functions
c5fb56c0 514
d90895ac
DW
515 do
516 {
c5fb56c0
DW
517 ulrc = ::DosWaitThread( &hThread
518 ,DCWW_NOWAIT
519 );
520 switch (ulrc)
d90895ac 521 {
c5fb56c0
DW
522 case ERROR_INTERRUPT:
523 case ERROR_INVALID_THREADID:
d90895ac
DW
524 // error
525 wxLogSysError(_("Can not wait for thread termination"));
526 Kill();
527 return (ExitCode)-1;
528
c5fb56c0 529 case 0:
d90895ac
DW
530 // thread we're waiting for terminated
531 break;
532
c5fb56c0 533 case ERROR_THREAD_NOT_TERMINATED:
d90895ac 534 // new message arrived, process it
c5fb56c0 535 if (!wxTheApp->DoMessage())
d90895ac
DW
536 {
537 // WM_QUIT received: kill the thread
538 Kill();
d90895ac
DW
539 return (ExitCode)-1;
540 }
c5fb56c0 541 if (IsMain())
d90895ac
DW
542 {
543 // give the thread we're waiting for chance to exit
544 // from the GUI call it might have been in
c5fb56c0 545 if ((s_nWaitingForGui > 0) && wxGuiOwnedByMainThread())
d90895ac
DW
546 {
547 wxMutexGuiLeave();
548 }
549 }
d90895ac
DW
550 break;
551
552 default:
c5fb56c0 553 wxFAIL_MSG(wxT("unexpected result of DosWatiThread"));
d90895ac 554 }
c5fb56c0 555 } while (ulrc != 0);
d90895ac 556
c5fb56c0 557 if (IsMain())
d90895ac 558 {
c5fb56c0
DW
559 s_bWaitingForThread = FALSE;
560 wxEndBusyCursor();
d90895ac
DW
561 }
562
c5fb56c0 563 ::DosExit(EXIT_THREAD, ulrc);
d90895ac 564 }
c5fb56c0 565 rc = (ExitCode)ulrc;
d90895ac 566 return rc;
0e320a79
DW
567}
568
d90895ac 569wxThreadError wxThread::Kill()
0e320a79 570{
c5fb56c0 571 if (!IsRunning())
d90895ac
DW
572 return wxTHREAD_NOT_RUNNING;
573
c5fb56c0 574 ::DosKillThread(p_internal->GetHandle());
d90895ac 575 delete this;
d90895ac 576 return wxTHREAD_NO_ERROR;
0e320a79
DW
577}
578
c5fb56c0
DW
579void wxThread::Exit(
580 void* pStatus
581)
0e320a79 582{
d90895ac 583 delete this;
c5fb56c0
DW
584 ::DosExit(EXIT_THREAD, ULONG(pStatus));
585 wxFAIL_MSG(wxT("Couldn't return from DosExit()!"));
0e320a79
DW
586}
587
c5fb56c0
DW
588void wxThread::SetPriority(
589 unsigned int nPrio
590)
0e320a79 591{
c5fb56c0 592 wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect);
d90895ac 593
c5fb56c0 594 p_internal->SetPriority(nPrio);
0e320a79
DW
595}
596
d90895ac 597unsigned int wxThread::GetPriority() const
0e320a79 598{
c5fb56c0 599 wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect);
d90895ac
DW
600
601 return p_internal->GetPriority();
0e320a79
DW
602}
603
604unsigned long wxThread::GetID() const
605{
c5fb56c0 606 wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect);
d90895ac
DW
607
608 return (unsigned long)p_internal->GetId();
0e320a79
DW
609}
610
d90895ac 611bool wxThread::IsRunning() const
0e320a79 612{
c5fb56c0 613 wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect);
d90895ac
DW
614
615 return p_internal->GetState() == STATE_RUNNING;
0e320a79 616}
0e320a79
DW
617
618bool wxThread::IsAlive() const
619{
c5fb56c0 620 wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect);
d90895ac
DW
621
622 return (p_internal->GetState() == STATE_RUNNING) ||
623 (p_internal->GetState() == STATE_PAUSED);
0e320a79
DW
624}
625
d90895ac 626bool wxThread::IsPaused() const
0e320a79 627{
c5fb56c0 628 wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect);
d90895ac
DW
629
630 return (p_internal->GetState() == STATE_PAUSED);
0e320a79
DW
631}
632
d90895ac 633bool wxThread::TestDestroy()
0e320a79 634{
c5fb56c0 635 wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect);
d90895ac
DW
636
637 return p_internal->GetState() == STATE_CANCELED;
0e320a79
DW
638}
639
640wxThread::wxThread()
641{
642 p_internal = new wxThreadInternal();
0e320a79
DW
643}
644
645wxThread::~wxThread()
646{
0e320a79
DW
647 delete p_internal;
648}
649
d90895ac
DW
650// ----------------------------------------------------------------------------
651// Automatic initialization for thread module
652// ----------------------------------------------------------------------------
0e320a79 653
d90895ac
DW
654class wxThreadModule : public wxModule
655{
0e320a79 656public:
d90895ac
DW
657 virtual bool OnInit();
658 virtual void OnExit();
0e320a79 659
d90895ac
DW
660private:
661 DECLARE_DYNAMIC_CLASS(wxThreadModule)
0e320a79
DW
662};
663
664IMPLEMENT_DYNAMIC_CLASS(wxThreadModule, wxModule)
665
d90895ac
DW
666bool wxThreadModule::OnInit()
667{
c5fb56c0 668 s_pCritsectWaitingForGui = new wxCriticalSection();
d90895ac 669
c5fb56c0
DW
670 s_pCritsectGui = new wxCriticalSection();
671 s_pCritsectGui->Enter();
d90895ac 672
c5fb56c0
DW
673 PTIB ptib;
674 PPIB ppib;
d90895ac 675
c5fb56c0 676 ::DosGetInfoBlocks(&ptib, &ppib);
d90895ac 677
c5fb56c0 678 s_ulIdMainThread = ptib->tib_ptib2->tib2_ultid;
d90895ac
DW
679 return TRUE;
680}
681
682void wxThreadModule::OnExit()
683{
c5fb56c0 684 if (s_pCritsectGui)
d90895ac 685 {
c5fb56c0
DW
686 s_pCritsectGui->Leave();
687 delete s_pCritsectGui;
688 s_pCritsectGui = NULL;
d90895ac
DW
689 }
690
c5fb56c0 691 wxDELETE(s_pCritsectWaitingForGui);
d90895ac
DW
692}
693
694// ----------------------------------------------------------------------------
c5fb56c0 695// Helper functions
d90895ac
DW
696// ----------------------------------------------------------------------------
697
c5fb56c0
DW
698// Does nothing under OS/2 [for now]
699void WXDLLEXPORT wxWakeUpMainThread()
d90895ac 700{
d90895ac
DW
701}
702
703void WXDLLEXPORT wxMutexGuiLeave()
704{
c5fb56c0 705 wxCriticalSectionLocker enter(*s_pCritsectWaitingForGui);
d90895ac
DW
706
707 if ( wxThread::IsMain() )
708 {
709 s_bGuiOwnedByMainThread = FALSE;
710 }
711 else
712 {
713 // decrement the number of waiters now
714 wxASSERT_MSG( s_nWaitingForGui > 0,
715 wxT("calling wxMutexGuiLeave() without entering it first?") );
716
717 s_nWaitingForGui--;
718
719 wxWakeUpMainThread();
720 }
721
c5fb56c0 722 s_pCritsectGui->Leave();
d90895ac
DW
723}
724
725void WXDLLEXPORT wxMutexGuiLeaveOrEnter()
726{
727 wxASSERT_MSG( wxThread::IsMain(),
728 wxT("only main thread may call wxMutexGuiLeaveOrEnter()!") );
729
c5fb56c0 730 wxCriticalSectionLocker enter(*s_pCritsectWaitingForGui);
d90895ac
DW
731
732 if ( s_nWaitingForGui == 0 )
733 {
734 // no threads are waiting for GUI - so we may acquire the lock without
735 // any danger (but only if we don't already have it)
c5fb56c0 736 if (!wxGuiOwnedByMainThread())
d90895ac 737 {
c5fb56c0 738 s_pCritsectGui->Enter();
d90895ac
DW
739
740 s_bGuiOwnedByMainThread = TRUE;
741 }
742 //else: already have it, nothing to do
743 }
744 else
745 {
746 // some threads are waiting, release the GUI lock if we have it
c5fb56c0 747 if (wxGuiOwnedByMainThread())
d90895ac
DW
748 {
749 wxMutexGuiLeave();
750 }
751 //else: some other worker thread is doing GUI
752 }
753}
754
755bool WXDLLEXPORT wxGuiOwnedByMainThread()
756{
757 return s_bGuiOwnedByMainThread;
758}
759
9ed0fac8
DW
760bool WXDLLEXPORT wxIsWaitingForThread()
761{
762 return s_bWaitingForThread;
763}
764
0e320a79
DW
765#endif
766 // wxUSE_THREADS