]> git.saurik.com Git - wxWidgets.git/blame - src/os2/thread.cpp
added ScrollLines/Pages
[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
43543d98 56static bool gs_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
43543d98 61static wxCriticalSection *gs_pCritsectGui = NULL;
d90895ac
DW
62
63// critical section which protects s_nWaitingForGui variable
43543d98 64static wxCriticalSection *gs_pCritsectWaitingForGui = NULL;
d90895ac
DW
65
66// number of threads waiting for GUI in wxMutexGuiEnter()
43543d98 67static size_t gs_nWaitingForGui = 0;
d90895ac
DW
68
69// are we waiting for a thread termination?
43543d98 70static bool gs_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{
43543d98 235 (void)m_internal->Wait(SEM_INDEFINITE_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
43543d98 359 bool bWasCancelled = pThread->m_internal->GetState() == STATE_CANCELED;
d01cc696
DW
360
361 pThread->m_internal->SetState(STATE_EXITED);
43543d98 362 pThread->m_critsect.Leave();
d01cc696 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
43543d98 371 delete pThread;
d01cc696
DW
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;
43543d98 383 ULONG ulrc;
c5fb56c0 384
d01cc696
DW
385 m_nPriority = nPriority;
386
c5fb56c0
DW
387 if (m_nPriority <= 20)
388 ulOS2_Priority = PRTYC_NOCHANGE;
389 else if (m_nPriority <= 40)
390 ulOS2_Priority = PRTYC_IDLETIME;
391 else if (m_nPriority <= 60)
392 ulOS2_Priority = PRTYC_REGULAR;
393 else if (m_nPriority <= 80)
394 ulOS2_Priority = PRTYC_TIMECRITICAL;
395 else if (m_nPriority <= 100)
396 ulOS2_Priority = PRTYC_FOREGROUNDSERVER;
d90895ac
DW
397 else
398 {
399 wxFAIL_MSG(wxT("invalid value of thread priority parameter"));
c5fb56c0 400 ulOS2_Priority = PRTYC_REGULAR;
d90895ac 401 }
c5fb56c0
DW
402 ulrc = ::DosSetPriority( PRTYS_THREAD
403 ,ulOS2_Priority
404 ,0
405 ,(ULONG)m_hThread
406 );
407 if (ulrc != 0)
d90895ac
DW
408 {
409 wxLogSysError(_("Can't set thread priority"));
410 }
d01cc696
DW
411}
412
413bool wxThreadInternal::Create(
414 wxThread* pThread
415)
416{
417 APIRET ulrc;
418
419 ulrc = ::DosCreateThread( &m_hThread
420 ,(PFNTHREAD)wxThreadInternal::OS2ThreadStart
421 ,(ULONG)pThread
422 ,CREATE_SUSPENDED | STACK_SPARSE
423 ,8192L
424 );
425 if(ulrc != 0)
426 {
427 wxLogSysError(_("Can't create thread"));
428
429 return FALSE;
430 }
431 if (m_nPriority != WXTHREAD_DEFAULT_PRIORITY)
432 {
433 SetPriority(m_nPriority);
434 }
435 return(TRUE);
d90895ac
DW
436}
437
438bool wxThreadInternal::Suspend()
439{
c5fb56c0 440 ULONG ulrc = ::DosSuspendThread(m_hThread);
d90895ac 441
c5fb56c0
DW
442 if (ulrc != 0)
443 {
444 wxLogSysError(_("Can not suspend thread %lu"), m_hThread);
d90895ac
DW
445 return FALSE;
446 }
c5fb56c0
DW
447 m_eState = STATE_PAUSED;
448 return TRUE;
d90895ac
DW
449}
450
451bool wxThreadInternal::Resume()
452{
c5fb56c0 453 ULONG ulrc = ::DosResumeThread(m_hThread);
d90895ac 454
c5fb56c0
DW
455 if (ulrc != 0)
456 {
457 wxLogSysError(_("Can not suspend thread %lu"), m_hThread);
d90895ac
DW
458 return FALSE;
459 }
c5fb56c0
DW
460 m_eState = STATE_PAUSED;
461 return TRUE;
d90895ac
DW
462}
463
464// static functions
465// ----------------
466
467wxThread *wxThread::This()
468{
c5fb56c0
DW
469 wxThread* pThread = m_pThread;
470 return pThread;
d90895ac
DW
471}
472
473bool wxThread::IsMain()
474{
c5fb56c0
DW
475 PTIB ptib;
476 PPIB ppib;
477
478 ::DosGetInfoBlocks(&ptib, &ppib);
479
480 if (ptib->tib_ptib2->tib2_ultid == s_ulIdMainThread)
481 return TRUE;
d90895ac
DW
482 return FALSE;
483}
484
485#ifdef Yield
486 #undef Yield
487#endif
488
489void wxThread::Yield()
490{
d90895ac
DW
491 ::DosSleep(0);
492}
493
c5fb56c0
DW
494void wxThread::Sleep(
495 unsigned long ulMilliseconds
496)
d90895ac 497{
c5fb56c0 498 ::DosSleep(ulMilliseconds);
d90895ac
DW
499}
500
d01cc696
DW
501// ctor and dtor
502// -------------
503
504wxThread::wxThread(wxThreadKind kind)
505{
506 m_internal = new wxThreadInternal();
507
508 m_isDetached = kind == wxTHREAD_DETACHED;
509}
510
511wxThread::~wxThread()
512{
513 delete m_internal;
514}
515
d90895ac
DW
516// create/start thread
517// -------------------
518
0e320a79
DW
519wxThreadError wxThread::Create()
520{
d01cc696 521 if ( !m_internal->Create(this) )
d90895ac
DW
522 return wxTHREAD_NO_RESOURCE;
523
0e320a79
DW
524 return wxTHREAD_NO_ERROR;
525}
526
d90895ac 527wxThreadError wxThread::Run()
0e320a79 528{
c5fb56c0 529 wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect);
d90895ac 530
d01cc696 531 if ( m_internal->GetState() != STATE_NEW )
d90895ac
DW
532 {
533 // actually, it may be almost any state at all, not only STATE_RUNNING
534 return wxTHREAD_RUNNING;
535 }
d90895ac 536 return Resume();
0e320a79
DW
537}
538
d90895ac
DW
539// suspend/resume thread
540// ---------------------
541
0e320a79
DW
542wxThreadError wxThread::Pause()
543{
c5fb56c0 544 wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect);
d90895ac 545
d01cc696 546 return m_internal->Suspend() ? wxTHREAD_NO_ERROR : wxTHREAD_MISC_ERROR;
0e320a79
DW
547}
548
549wxThreadError wxThread::Resume()
550{
c5fb56c0 551 wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect);
0e320a79 552
d01cc696 553 return m_internal->Resume() ? wxTHREAD_NO_ERROR : wxTHREAD_MISC_ERROR;
0e320a79
DW
554}
555
d90895ac
DW
556// stopping thread
557// ---------------
558
d01cc696 559wxThread::ExitCode wxThread::Wait()
0e320a79 560{
d01cc696
DW
561 // although under Windows we can wait for any thread, it's an error to
562 // wait for a detached one in wxWin API
563 wxCHECK_MSG( !IsDetached(), (ExitCode)-1,
564 _T("can't wait for detached thread") );
565 ExitCode rc = (ExitCode)-1;
566 (void)Delete(&rc);
567 m_internal->Free();
568 return(rc);
569}
570
571wxThreadError wxThread::Delete(ExitCode *pRc)
572{
573 ExitCode rc = 0;
d90895ac
DW
574
575 // Delete() is always safe to call, so consider all possible states
c5fb56c0 576 if (IsPaused())
d90895ac
DW
577 Resume();
578
d01cc696
DW
579 TID hThread = m_internal->GetHandle();
580
c5fb56c0 581 if (IsRunning())
d90895ac 582 {
c5fb56c0 583 if (IsMain())
d90895ac
DW
584 {
585 // set flag for wxIsWaitingForThread()
43543d98 586 gs_bWaitingForThread = TRUE;
d01cc696
DW
587
588#if wxUSE_GUI
d90895ac 589 wxBeginBusyCursor();
d01cc696 590#endif // wxUSE_GUI
d90895ac
DW
591 }
592
d01cc696 593 // ask the thread to terminate
d90895ac 594 {
d01cc696
DW
595 wxCriticalSectionLocker lock(m_critsect);
596 m_internal->Cancel();
d90895ac
DW
597 }
598
d01cc696 599#if wxUSE_GUI
3b9e3455
DW
600 // need a way to finish GUI processing before killing the thread
601 // until then we just exit
602
603 if ((gs_nWaitingForGui > 0) && wxGuiOwnedByMainThread())
d01cc696 604 {
3b9e3455 605 wxMutexGuiLeave();
d01cc696 606 }
3b9e3455
DW
607#else // !wxUSE_GUI
608
609 // can't wait for yourself to end under OS/2 so just quit
610
d01cc696 611#endif // wxUSE_GUI/!wxUSE_GUI
d90895ac 612
d01cc696 613 if ( IsMain() )
d90895ac 614 {
43543d98 615 gs_bWaitingForThread = FALSE;
d01cc696
DW
616
617#if wxUSE_GUI
c5fb56c0 618 wxEndBusyCursor();
d01cc696 619#endif // wxUSE_GUI
d90895ac 620 }
d01cc696
DW
621 }
622
3b9e3455
DW
623 ::DosExit(0, 0);
624 // probably won't get this far, but
625 if (IsDetached())
d01cc696 626 {
d01cc696
DW
627 delete this;
628 }
629
d01cc696
DW
630 if ( pRc )
631 *pRc = rc;
632
633 return rc == (ExitCode)-1 ? wxTHREAD_MISC_ERROR : wxTHREAD_NO_ERROR;
0e320a79
DW
634}
635
d90895ac 636wxThreadError wxThread::Kill()
0e320a79 637{
c5fb56c0 638 if (!IsRunning())
d90895ac
DW
639 return wxTHREAD_NOT_RUNNING;
640
d01cc696 641 ::DosKillThread(m_internal->GetHandle());
3b9e3455
DW
642 m_internal->Free();
643 if (IsDetached())
644 {
645 delete this;
646 }
d90895ac 647 return wxTHREAD_NO_ERROR;
0e320a79
DW
648}
649
c5fb56c0 650void wxThread::Exit(
3b9e3455 651 ExitCode pStatus
c5fb56c0 652)
0e320a79 653{
3b9e3455 654 m_internal->Free();
d90895ac 655 delete this;
c5fb56c0
DW
656 ::DosExit(EXIT_THREAD, ULONG(pStatus));
657 wxFAIL_MSG(wxT("Couldn't return from DosExit()!"));
0e320a79
DW
658}
659
c5fb56c0
DW
660void wxThread::SetPriority(
661 unsigned int nPrio
662)
0e320a79 663{
c5fb56c0 664 wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect);
d90895ac 665
d01cc696 666 m_internal->SetPriority(nPrio);
0e320a79
DW
667}
668
d90895ac 669unsigned int wxThread::GetPriority() const
0e320a79 670{
c5fb56c0 671 wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect);
d90895ac 672
d01cc696 673 return m_internal->GetPriority();
0e320a79
DW
674}
675
3b9e3455
DW
676unsigned long wxThread::GetId() const
677{
678 wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect); // const_cast
679
680 return (unsigned long)m_internal->GetId();
681}
682
d90895ac 683bool wxThread::IsRunning() const
0e320a79 684{
c5fb56c0 685 wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect);
d90895ac 686
3b9e3455 687 return(m_internal->GetState() == STATE_RUNNING);
0e320a79 688}
0e320a79
DW
689
690bool wxThread::IsAlive() const
691{
c5fb56c0 692 wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect);
d90895ac 693
d01cc696
DW
694 return (m_internal->GetState() == STATE_RUNNING) ||
695 (m_internal->GetState() == STATE_PAUSED);
0e320a79
DW
696}
697
d90895ac 698bool wxThread::IsPaused() const
0e320a79 699{
c5fb56c0 700 wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect);
d90895ac 701
d01cc696 702 return (m_internal->GetState() == STATE_PAUSED);
0e320a79
DW
703}
704
d90895ac 705bool wxThread::TestDestroy()
0e320a79 706{
c5fb56c0 707 wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect);
d90895ac 708
d01cc696 709 return m_internal->GetState() == STATE_CANCELED;
0e320a79
DW
710}
711
d90895ac
DW
712// ----------------------------------------------------------------------------
713// Automatic initialization for thread module
714// ----------------------------------------------------------------------------
0e320a79 715
d90895ac
DW
716class wxThreadModule : public wxModule
717{
0e320a79 718public:
d90895ac
DW
719 virtual bool OnInit();
720 virtual void OnExit();
0e320a79 721
d90895ac
DW
722private:
723 DECLARE_DYNAMIC_CLASS(wxThreadModule)
0e320a79
DW
724};
725
726IMPLEMENT_DYNAMIC_CLASS(wxThreadModule, wxModule)
727
d90895ac
DW
728bool wxThreadModule::OnInit()
729{
43543d98 730 gs_pCritsectWaitingForGui = new wxCriticalSection();
d90895ac 731
43543d98
DW
732 gs_pCritsectGui = new wxCriticalSection();
733 gs_pCritsectGui->Enter();
d90895ac 734
c5fb56c0
DW
735 PTIB ptib;
736 PPIB ppib;
d90895ac 737
c5fb56c0 738 ::DosGetInfoBlocks(&ptib, &ppib);
d90895ac 739
c5fb56c0 740 s_ulIdMainThread = ptib->tib_ptib2->tib2_ultid;
d90895ac
DW
741 return TRUE;
742}
743
744void wxThreadModule::OnExit()
745{
43543d98 746 if (gs_pCritsectGui)
d90895ac 747 {
43543d98 748 gs_pCritsectGui->Leave();
f6bcfd97 749#if (!(defined(__VISAGECPP__) && (__IBMCPP__ < 400 || __IBMC__ < 400 )))
43543d98 750 delete gs_pCritsectGui;
f6bcfd97 751#endif
43543d98 752 gs_pCritsectGui = NULL;
d90895ac
DW
753 }
754
f6bcfd97 755#if (!(defined(__VISAGECPP__) && (__IBMCPP__ < 400 || __IBMC__ < 400 )))
43543d98 756 wxDELETE(gs_pCritsectWaitingForGui);
f6bcfd97 757#endif
d90895ac
DW
758}
759
760// ----------------------------------------------------------------------------
c5fb56c0 761// Helper functions
d90895ac
DW
762// ----------------------------------------------------------------------------
763
c5fb56c0
DW
764// Does nothing under OS/2 [for now]
765void WXDLLEXPORT wxWakeUpMainThread()
d90895ac 766{
d90895ac
DW
767}
768
769void WXDLLEXPORT wxMutexGuiLeave()
770{
43543d98 771 wxCriticalSectionLocker enter(*gs_pCritsectWaitingForGui);
d90895ac
DW
772
773 if ( wxThread::IsMain() )
774 {
43543d98 775 gs_bGuiOwnedByMainThread = FALSE;
d90895ac
DW
776 }
777 else
778 {
779 // decrement the number of waiters now
43543d98 780 wxASSERT_MSG(gs_nWaitingForGui > 0,
d90895ac
DW
781 wxT("calling wxMutexGuiLeave() without entering it first?") );
782
43543d98 783 gs_nWaitingForGui--;
d90895ac
DW
784
785 wxWakeUpMainThread();
786 }
787
43543d98 788 gs_pCritsectGui->Leave();
d90895ac
DW
789}
790
791void WXDLLEXPORT wxMutexGuiLeaveOrEnter()
792{
793 wxASSERT_MSG( wxThread::IsMain(),
794 wxT("only main thread may call wxMutexGuiLeaveOrEnter()!") );
795
43543d98 796 wxCriticalSectionLocker enter(*gs_pCritsectWaitingForGui);
d90895ac 797
43543d98 798 if (gs_nWaitingForGui == 0)
d90895ac
DW
799 {
800 // no threads are waiting for GUI - so we may acquire the lock without
801 // any danger (but only if we don't already have it)
c5fb56c0 802 if (!wxGuiOwnedByMainThread())
d90895ac 803 {
43543d98 804 gs_pCritsectGui->Enter();
d90895ac 805
43543d98 806 gs_bGuiOwnedByMainThread = TRUE;
d90895ac
DW
807 }
808 //else: already have it, nothing to do
809 }
810 else
811 {
812 // some threads are waiting, release the GUI lock if we have it
c5fb56c0 813 if (wxGuiOwnedByMainThread())
d90895ac
DW
814 {
815 wxMutexGuiLeave();
816 }
817 //else: some other worker thread is doing GUI
818 }
819}
820
821bool WXDLLEXPORT wxGuiOwnedByMainThread()
822{
43543d98 823 return gs_bGuiOwnedByMainThread;
d90895ac
DW
824}
825
9ed0fac8
DW
826bool WXDLLEXPORT wxIsWaitingForThread()
827{
43543d98 828 return gs_bWaitingForThread;
9ed0fac8
DW
829}
830
0e320a79
DW
831#endif
832 // wxUSE_THREADS