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