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