]> git.saurik.com Git - wxWidgets.git/blame - src/mac/carbon/thread.cpp
removed obsolete files and added missing ones
[wxWidgets.git] / src / mac / carbon / thread.cpp
CommitLineData
e9576ca5
SC
1/////////////////////////////////////////////////////////////////////////////
2// Name: thread.cpp
e7549107 3// Purpose: wxThread Implementation
a959b088
SC
4// Author: Original from Wolfram Gloger/Guilhem Lavaux/Vadim Zeitlin
5// Modified by: Stefan Csomor
e9576ca5
SC
6// Created: 04/22/98
7// RCS-ID: $Id$
e7549107 8// Copyright: (c) Wolfram Gloger (1996, 1997); Guilhem Lavaux (1998),
a959b088 9// Vadim Zeitlin (1999) , Stefan Csomor (2000)
e9576ca5
SC
10// Licence: wxWindows licence
11/////////////////////////////////////////////////////////////////////////////
12
13#ifdef __GNUG__
e7549107 14 #pragma implementation "thread.h"
e9576ca5
SC
15#endif
16
e7549107
SC
17// ----------------------------------------------------------------------------
18// headers
19// ----------------------------------------------------------------------------
20
21// For compilers that support precompilation, includes "wx.h".
22#include "wx/wxprec.h"
23
24#if defined(__BORLANDC__)
25 #pragma hdrstop
26#endif
27
28#ifndef WX_PRECOMP
29 #include "wx/wx.h"
30#endif
31
32#if wxUSE_THREADS
33
e9576ca5
SC
34#include "wx/module.h"
35#include "wx/thread.h"
e9576ca5 36
76a5e5d2
SC
37#ifdef __WXMAC__
38#include "wx/mac/private.h"
39#endif
40
a959b088
SC
41// ----------------------------------------------------------------------------
42// constants
43// ----------------------------------------------------------------------------
44
e7549107
SC
45// the possible states of the thread ("=>" shows all possible transitions from
46// this state)
47enum wxThreadState
48{
49 STATE_NEW, // didn't start execution yet (=> RUNNING)
50 STATE_RUNNING, // thread is running (=> PAUSED, CANCELED)
51 STATE_PAUSED, // thread is temporarily suspended (=> RUNNING)
52 STATE_CANCELED, // thread should terminate a.s.a.p. (=> EXITED)
53 STATE_EXITED // thread is terminating
e9576ca5
SC
54};
55
e7549107 56// ----------------------------------------------------------------------------
a959b088 57// this module globals
e7549107 58// ----------------------------------------------------------------------------
169935ad 59
a959b088
SC
60static ThreadID gs_idMainThread = kNoThreadID ;
61static bool gs_waitingForThread = FALSE ;
e9576ca5 62
e7549107 63// ============================================================================
a959b088 64// MacOS implementation of thread classes
e7549107
SC
65// ============================================================================
66
a959b088
SC
67class wxMacStCritical
68{
69public :
6fe73788
RL
70 wxMacStCritical()
71 {
72 ThreadBeginCritical() ;
73 }
74 ~wxMacStCritical()
75 {
76 ThreadEndCritical() ;
77 }
78};
a959b088 79
e7549107
SC
80// ----------------------------------------------------------------------------
81// wxMutex implementation
82// ----------------------------------------------------------------------------
a959b088 83
e7549107
SC
84class wxMutexInternal
85{
e9576ca5 86public:
a959b088
SC
87 wxMutexInternal()
88 {
6fe73788 89 m_owner = kNoThreadID ;
a959b088
SC
90 }
91
92 ~wxMutexInternal()
93 {
94 }
95
96public:
97 ThreadID m_owner ;
98 wxArrayLong m_waiters ;
e9576ca5
SC
99};
100
101wxMutex::wxMutex()
102{
a959b088 103 m_internal = new wxMutexInternal;
e7549107 104
e9576ca5
SC
105 m_locked = 0;
106}
107
108wxMutex::~wxMutex()
109{
a959b088
SC
110 if ( m_locked > 0 )
111 {
112 wxLogDebug(_T("Warning: freeing a locked mutex (%d locks)."), m_locked);
113 }
114
115 delete m_internal;
e9576ca5
SC
116}
117
118wxMutexError wxMutex::Lock()
119{
6fe73788
RL
120 wxMacStCritical critical ;
121
122 OSErr err ;
123 ThreadID current = kNoThreadID;
124 err = ::MacGetCurrentThread(&current);
125 // if we are not the owner, add this thread to the list of waiting threads, stop this thread
126 // and invoke the scheduler to continue executing the owner's thread
127 while ( m_internal->m_owner != kNoThreadID && m_internal->m_owner != current)
128 {
129 m_internal->m_waiters.Add(current);
130 err = ::SetThreadStateEndCritical(kCurrentThreadID, kStoppedThreadState, m_internal->m_owner);
131 err = ::ThreadBeginCritical();
132 }
133 m_internal->m_owner = current;
e9576ca5 134 m_locked++;
a959b088 135
e9576ca5
SC
136 return wxMUTEX_NO_ERROR;
137}
138
139wxMutexError wxMutex::TryLock()
140{
6fe73788
RL
141 wxMacStCritical critical ;
142
143 OSErr err ;
144 ThreadID current = kNoThreadID;
145 ::MacGetCurrentThread(&current);
146 // if we are not the owner, give an error back
147 if ( m_internal->m_owner != kNoThreadID && m_internal->m_owner != current )
e7549107 148 return wxMUTEX_BUSY;
6fe73788
RL
149
150 m_internal->m_owner = current;
e9576ca5 151 m_locked++;
a959b088
SC
152
153 return wxMUTEX_NO_ERROR;
e9576ca5
SC
154}
155
156wxMutexError wxMutex::Unlock()
157{
6fe73788
RL
158 OSErr err;
159 err = ::ThreadBeginCritical();
160
e9576ca5
SC
161 if (m_locked > 0)
162 m_locked--;
a959b088 163
6fe73788
RL
164 // this mutex is not owned by anybody anmore
165 m_internal->m_owner = kNoThreadID;
166
167 // now pass on to the first waiting thread
168 ThreadID firstWaiting = kNoThreadID;
169 bool found = false;
170 while (!m_internal->m_waiters.IsEmpty() && !found)
171 {
172 firstWaiting = m_internal->m_waiters[0];
173 err = ::SetThreadState(firstWaiting, kReadyThreadState, kNoThreadID);
174 // in case this was not successful (dead thread), we just loop on and reset the id
175 found = (err != threadNotFoundErr);
176 if ( !found )
177 firstWaiting = kNoThreadID ;
178 m_internal->m_waiters.RemoveAt(0) ;
179 }
180 // now we have a valid firstWaiting thread, which has been scheduled to run next, just end the
181 // critical section and invoke the scheduler
182 err = ::SetThreadStateEndCritical(kCurrentThreadID, kReadyThreadState, firstWaiting);
a959b088 183
e9576ca5
SC
184 return wxMUTEX_NO_ERROR;
185}
186
e7549107
SC
187// ----------------------------------------------------------------------------
188// wxCondition implementation
189// ----------------------------------------------------------------------------
190
191class wxConditionInternal
192{
e9576ca5 193public:
a959b088
SC
194 wxConditionInternal()
195 {
6fe73788 196 m_excessSignals = 0 ;
a959b088
SC
197 }
198 ~wxConditionInternal()
199 {
200 }
e9576ca5 201
a959b088 202 bool Wait(unsigned long msectimeout)
e7549107 203 {
6fe73788
RL
204 wxMacStCritical critical ;
205 if ( m_excessSignals > 0 )
206 {
207 --m_excessSignals ;
208 return TRUE ;
209 }
210 else if ( msectimeout == 0 )
211 {
212 return FALSE ;
213 }
214 else
215 {
216 }
217 /*
a959b088
SC
218 waiters++;
219
220 // FIXME this should be MsgWaitForMultipleObjects() as well probably
221 DWORD rc = ::WaitForSingleObject(event, timeout);
222
223 waiters--;
224
225 return rc != WAIT_TIMEOUT;
226 */
227 return TRUE ;
e7549107 228 }
6fe73788
RL
229 void Signal()
230 {
231 wxMacStCritical critical ;
232 }
a959b088
SC
233
234 wxArrayLong m_waiters ;
6fe73788 235 wxInt32 m_excessSignals ;
a959b088 236};
e7549107 237
a959b088
SC
238wxCondition::wxCondition()
239{
240 m_internal = new wxConditionInternal;
e9576ca5
SC
241}
242
243wxCondition::~wxCondition()
244{
a959b088 245 delete m_internal;
e9576ca5
SC
246}
247
a959b088 248void wxCondition::Wait()
e9576ca5 249{
6fe73788 250 (void)m_internal->Wait(0xFFFFFFFFL);
e9576ca5
SC
251}
252
a959b088 253bool wxCondition::Wait(unsigned long sec,
e9576ca5
SC
254 unsigned long nsec)
255{
a959b088 256 return m_internal->Wait(sec*1000 + nsec/1000000);
e9576ca5
SC
257}
258
259void wxCondition::Signal()
260{
a959b088
SC
261 // set the event to signaled: if a thread is already waiting on it, it will
262 // be woken up, otherwise the event will remain in the signaled state until
263 // someone waits on it. In any case, the system will return it to a non
264 // signalled state afterwards. If multiple threads are waiting, only one
265 // will be woken up.
6fe73788 266 m_internal->Signal() ;
e9576ca5
SC
267}
268
269void wxCondition::Broadcast()
270{
a959b088
SC
271 // this works because all these threads are already waiting and so each
272 // SetEvent() inside Signal() is really a PulseEvent() because the event
273 // state is immediately returned to non-signaled
274 for ( int i = 0; i < m_internal->m_waiters.Count(); i++ )
e7549107 275 {
a959b088 276 Signal();
e7549107 277 }
e9576ca5
SC
278}
279
e7549107
SC
280// ----------------------------------------------------------------------------
281// wxCriticalSection implementation
282// ----------------------------------------------------------------------------
283
a959b088 284// it's implemented as a mutex on mac os, so it is defined in the headers
e7549107
SC
285
286// ----------------------------------------------------------------------------
287// wxThread implementation
288// ----------------------------------------------------------------------------
289
290// wxThreadInternal class
291// ----------------------
292
e7549107
SC
293class wxThreadInternal
294{
295public:
296 wxThreadInternal()
297 {
a959b088 298 m_tid = kNoThreadID ;
e7549107
SC
299 m_state = STATE_NEW;
300 m_priority = WXTHREAD_DEFAULT_PRIORITY;
301 }
302
a959b088
SC
303 ~wxThreadInternal()
304 {
305 }
306
307 void Free()
308 {
309 }
310
e7549107 311 // create a new (suspended) thread (for the given thread object)
6fe73788 312 bool Create(wxThread *thread, unsigned int stackSize);
e7549107
SC
313
314 // suspend/resume/terminate
315 bool Suspend();
316 bool Resume();
317 void Cancel() { m_state = STATE_CANCELED; }
318
319 // thread state
320 void SetState(wxThreadState state) { m_state = state; }
321 wxThreadState GetState() const { return m_state; }
322
323 // thread priority
a959b088 324 void SetPriority(unsigned int priority);
e7549107 325 unsigned int GetPriority() const { return m_priority; }
a959b088
SC
326
327 void SetResult( void *res ) { m_result = res ; }
328 void *GetResult() { return m_result ; }
e7549107
SC
329
330 // thread handle and id
a959b088 331 ThreadID GetId() const { return m_tid; }
e7549107
SC
332
333 // thread function
6fe73788 334 static pascal void* MacThreadStart(wxThread* arg);
e7549107
SC
335
336private:
6fe73788
RL
337 wxThreadState m_state; // state, see wxThreadState enum
338 unsigned int m_priority; // thread priority in "wx" units
339 ThreadID m_tid; // thread id
340 void* m_result;
341 static ThreadEntryUPP s_threadEntry ;
e7549107
SC
342};
343
a959b088
SC
344static wxArrayPtrVoid s_threads ;
345
346ThreadEntryUPP wxThreadInternal::s_threadEntry = NULL ;
347pascal void* wxThreadInternal::MacThreadStart(wxThread *thread)
e7549107 348{
a959b088
SC
349 // first of all, check whether we hadn't been cancelled already
350 if ( thread->m_internal->GetState() == STATE_EXITED )
e7549107 351 {
a959b088 352 return (void*)-1;
e7549107
SC
353 }
354
a959b088
SC
355 void* rc = thread->Entry();
356
357 // enter m_critsect before changing the thread state
358 thread->m_critsect.Enter();
359 bool wasCancelled = thread->m_internal->GetState() == STATE_CANCELED;
360 thread->m_internal->SetState(STATE_EXITED);
361 thread->m_critsect.Leave();
362
e7549107
SC
363 thread->OnExit();
364
a959b088
SC
365 // if the thread was cancelled (from Delete()), then it the handle is still
366 // needed there
367 if ( thread->IsDetached() && !wasCancelled )
368 {
369 // auto delete
370 delete thread;
371 }
372 //else: the joinable threads handle will be closed when Wait() is done
e7549107 373
a959b088
SC
374 return rc;
375}
376void wxThreadInternal::SetPriority(unsigned int priority)
377{
6fe73788 378 // Priorities don't exist on Mac
e7549107
SC
379}
380
6fe73788 381bool wxThreadInternal::Create(wxThread *thread, unsigned int stackSize)
e7549107 382{
6fe73788
RL
383 if ( s_threadEntry == NULL )
384 {
385 s_threadEntry = NewThreadEntryUPP( (ThreadEntryProcPtr) MacThreadStart ) ;
386 }
387 OSErr err = NewThread( kCooperativeThread,
388 s_threadEntry,
389 (void*) thread,
390 stackSize,
391 kNewSuspend,
392 &m_result,
393 &m_tid );
a959b088
SC
394
395 if ( err != noErr )
e7549107
SC
396 {
397 wxLogSysError(_("Can't create thread"));
e7549107
SC
398 return FALSE;
399 }
400
a959b088 401 if ( m_priority != WXTHREAD_DEFAULT_PRIORITY )
e7549107 402 {
a959b088 403 SetPriority(m_priority);
e7549107
SC
404 }
405
406 return TRUE;
407}
408
409bool wxThreadInternal::Suspend()
410{
6fe73788
RL
411 OSErr err ;
412
413 ::ThreadBeginCritical();
e7549107 414
6fe73788 415 if ( m_state != STATE_RUNNING )
a959b088 416 {
6fe73788 417 ::ThreadEndCritical() ;
a959b088 418 wxLogSysError(_("Can not suspend thread %x"), m_tid);
e7549107
SC
419 return FALSE;
420 }
421
422 m_state = STATE_PAUSED;
423
6fe73788 424 err = ::SetThreadStateEndCritical(m_tid, kStoppedThreadState, kNoThreadID);
a959b088 425
e7549107
SC
426 return TRUE;
427}
428
429bool wxThreadInternal::Resume()
430{
6fe73788
RL
431 ThreadID current ;
432 OSErr err ;
433 err = MacGetCurrentThread( &current ) ;
434
435 wxASSERT( err == noErr ) ;
436 wxASSERT( current != m_tid ) ;
437
438 ::ThreadBeginCritical();
439 if ( m_state != STATE_PAUSED && m_state != STATE_NEW )
440 {
441 ::ThreadEndCritical() ;
a959b088 442 wxLogSysError(_("Can not resume thread %x"), m_tid);
e7549107 443 return FALSE;
6fe73788
RL
444
445 }
446 err = ::SetThreadStateEndCritical(m_tid, kReadyThreadState, kNoThreadID);
447 wxASSERT( err == noErr ) ;
448
e7549107 449 m_state = STATE_RUNNING;
6fe73788
RL
450 ::ThreadEndCritical() ;
451 ::YieldToAnyThread() ;
e7549107
SC
452 return TRUE;
453}
454
455// static functions
456// ----------------
e7549107
SC
457wxThread *wxThread::This()
458{
6fe73788
RL
459 wxMacStCritical critical ;
460
461 ThreadID current ;
462 OSErr err ;
463
464 err = MacGetCurrentThread( &current ) ;
465
466 for ( int i = 0 ; i < s_threads.Count() ; ++i )
467 {
468 if ( ( (wxThread*) s_threads[i] )->GetId() == current )
469 return (wxThread*) s_threads[i] ;
470 }
e7549107 471
a959b088
SC
472 wxLogSysError(_("Couldn't get the current thread pointer"));
473 return NULL;
e7549107
SC
474}
475
476bool wxThread::IsMain()
477{
6fe73788
RL
478 ThreadID current ;
479 OSErr err ;
480
481 err = MacGetCurrentThread( &current ) ;
a959b088 482 return current == gs_idMainThread;
e7549107
SC
483}
484
485#ifdef Yield
a959b088 486#undef Yield
e7549107
SC
487#endif
488
489void wxThread::Yield()
490{
6fe73788 491 ::YieldToAnyThread() ;
e7549107
SC
492}
493
494void wxThread::Sleep(unsigned long milliseconds)
495{
6fe73788
RL
496 clock_t start = clock() ;
497 do
498 {
499 YieldToAnyThread() ;
500 } while( clock() - start < milliseconds / CLOCKS_PER_SEC ) ;
a959b088
SC
501}
502
503int wxThread::GetCPUCount()
504{
6fe73788 505 // we will use whatever MP API will be used for the new MP Macs
a959b088
SC
506 return 1;
507}
508
509bool wxThread::SetConcurrency(size_t level)
510{
511 wxASSERT_MSG( IsMain(), _T("should only be called from the main thread") );
512
513 // ok only for the default one
514 if ( level == 0 )
515 return 0;
516
517 // how many CPUs have we got?
518 if ( GetCPUCount() == 1 )
519 {
520 // don't bother with all this complicated stuff - on a single
521 // processor system it doesn't make much sense anyhow
522 return level == 1;
523 }
524
525 return TRUE ;
526}
527
528// ctor and dtor
529// -------------
530
531wxThread::wxThread(wxThreadKind kind)
532{
533 m_internal = new wxThreadInternal();
534
535 m_isDetached = kind == wxTHREAD_DETACHED;
536 s_threads.Add( (void*) this ) ;
537}
538
539wxThread::~wxThread()
540{
6fe73788 541 s_threads.Remove( (void*) this ) ;
a959b088 542 delete m_internal;
e7549107
SC
543}
544
545// create/start thread
546// -------------------
547
6fe73788 548wxThreadError wxThread::Create(unsigned int stackSize)
e9576ca5 549{
a959b088
SC
550 wxCriticalSectionLocker lock(m_critsect);
551
6fe73788 552 if ( !m_internal->Create(this, stackSize) )
e7549107
SC
553 return wxTHREAD_NO_RESOURCE;
554
e9576ca5
SC
555 return wxTHREAD_NO_ERROR;
556}
557
e7549107 558wxThreadError wxThread::Run()
e9576ca5 559{
e7549107
SC
560 wxCriticalSectionLocker lock(m_critsect);
561
a959b088 562 if ( m_internal->GetState() != STATE_NEW )
e7549107
SC
563 {
564 // actually, it may be almost any state at all, not only STATE_RUNNING
565 return wxTHREAD_RUNNING;
566 }
567
a959b088 568 // the thread has just been created and is still suspended - let it run
e7549107 569 return Resume();
e9576ca5
SC
570}
571
e7549107
SC
572// suspend/resume thread
573// ---------------------
574
e9576ca5
SC
575wxThreadError wxThread::Pause()
576{
e7549107
SC
577 wxCriticalSectionLocker lock(m_critsect);
578
a959b088 579 return m_internal->Suspend() ? wxTHREAD_NO_ERROR : wxTHREAD_MISC_ERROR;
e9576ca5
SC
580}
581
582wxThreadError wxThread::Resume()
583{
e7549107 584 wxCriticalSectionLocker lock(m_critsect);
e9576ca5 585
a959b088 586 return m_internal->Resume() ? wxTHREAD_NO_ERROR : wxTHREAD_MISC_ERROR;
e9576ca5
SC
587}
588
e7549107
SC
589// stopping thread
590// ---------------
591
a959b088
SC
592wxThread::ExitCode wxThread::Wait()
593{
594 // although under MacOS we can wait for any thread, it's an error to
595 // wait for a detached one in wxWin API
596 wxCHECK_MSG( !IsDetached(), (ExitCode)-1,
597 _T("can't wait for detached thread") );
598
599 ExitCode rc = (ExitCode)-1;
600
601 (void)Delete(&rc);
602
603 m_internal->Free();
604
605 return rc;
606}
607
608wxThreadError wxThread::Delete(ExitCode *pRc)
e9576ca5 609{
e7549107
SC
610 ExitCode rc = 0;
611
612 // Delete() is always safe to call, so consider all possible states
a959b088
SC
613
614 // has the thread started to run?
615 bool shouldResume = FALSE;
616
617 {
618 wxCriticalSectionLocker lock(m_critsect);
619
620 if ( m_internal->GetState() == STATE_NEW )
621 {
622 // WinThreadStart() will see it and terminate immediately
623 m_internal->SetState(STATE_EXITED);
624
625 shouldResume = TRUE;
626 }
627 }
628
629 // is the thread paused?
630 if ( shouldResume || IsPaused() )
e7549107
SC
631 Resume();
632
a959b088 633 // does is still run?
e7549107
SC
634 if ( IsRunning() )
635 {
636 if ( IsMain() )
637 {
638 // set flag for wxIsWaitingForThread()
a959b088 639 gs_waitingForThread = TRUE;
e7549107 640
a959b088 641#if wxUSE_GUI
e7549107 642 wxBeginBusyCursor();
a959b088 643#endif // wxUSE_GUI
e7549107
SC
644 }
645
a959b088 646 // ask the thread to terminate
e7549107
SC
647 {
648 wxCriticalSectionLocker lock(m_critsect);
649
a959b088 650 m_internal->Cancel();
e7549107
SC
651 }
652
a959b088
SC
653#if wxUSE_GUI
654 // simply wait for the thread to terminate
6fe73788
RL
655 while( TestDestroy() )
656 {
657 ::YieldToAnyThread() ;
658 }
a959b088
SC
659#else // !wxUSE_GUI
660 // simply wait for the thread to terminate
6fe73788
RL
661 while( TestDestroy() )
662 {
663 ::YieldToAnyThread() ;
664 }
a959b088 665#endif // wxUSE_GUI/!wxUSE_GUI
e7549107
SC
666
667 if ( IsMain() )
668 {
a959b088 669 gs_waitingForThread = FALSE;
e7549107 670
a959b088 671#if wxUSE_GUI
e7549107 672 wxEndBusyCursor();
a959b088 673#endif // wxUSE_GUI
e7549107 674 }
a959b088 675 }
e7549107 676
a959b088
SC
677 // if ( !::GetExitCodeThread(hThread, (LPDWORD)&rc) )
678 {
679 wxLogLastError("GetExitCodeThread");
e7549107 680
a959b088
SC
681 rc = (ExitCode)-1;
682 }
e7549107 683
a959b088
SC
684 if ( IsDetached() )
685 {
686 // if the thread exits normally, this is done in WinThreadStart, but in
687 // this case it would have been too early because
688 // MsgWaitForMultipleObject() would fail if the therad handle was
689 // closed while we were waiting on it, so we must do it here
690 delete this;
e7549107
SC
691 }
692
a959b088
SC
693 // wxASSERT_MSG( (DWORD)rc != STILL_ACTIVE,
694 // wxT("thread must be already terminated.") );
695
696 if ( pRc )
697 *pRc = rc;
698
699 return rc == (ExitCode)-1 ? wxTHREAD_MISC_ERROR : wxTHREAD_NO_ERROR;
e9576ca5
SC
700}
701
e7549107 702wxThreadError wxThread::Kill()
e9576ca5 703{
e7549107
SC
704 if ( !IsRunning() )
705 return wxTHREAD_NOT_RUNNING;
706
a959b088 707// if ( !::TerminateThread(m_internal->GetHandle(), (DWORD)-1) )
e7549107
SC
708 {
709 wxLogSysError(_("Couldn't terminate thread"));
710
711 return wxTHREAD_MISC_ERROR;
712 }
713
a959b088
SC
714 m_internal->Free();
715
716 if ( IsDetached() )
717 {
718 delete this;
719 }
e7549107
SC
720
721 return wxTHREAD_NO_ERROR;
e9576ca5
SC
722}
723
a959b088 724void wxThread::Exit(ExitCode status)
e9576ca5 725{
a959b088 726 m_internal->Free();
e7549107 727
a959b088
SC
728 if ( IsDetached() )
729 {
730 delete this;
731 }
e7549107 732
6fe73788 733 m_internal->SetResult( status ) ;
a959b088 734
6fe73788 735/*
a959b088
SC
736#if defined(__VISUALC__) || (defined(__BORLANDC__) && (__BORLANDC__ >= 0x500))
737 _endthreadex((unsigned)status);
738#else // !VC++
739 ::ExitThread((DWORD)status);
740#endif // VC++/!VC++
741*/
e7549107 742 wxFAIL_MSG(wxT("Couldn't return from ExitThread()!"));
e9576ca5
SC
743}
744
a959b088
SC
745// priority setting
746// ----------------
747
748// since all these calls are execute cooperatively we don't have to use the critical section
749
e7549107 750void wxThread::SetPriority(unsigned int prio)
e9576ca5 751{
a959b088 752 m_internal->SetPriority(prio);
e9576ca5
SC
753}
754
e7549107 755unsigned int wxThread::GetPriority() const
e9576ca5 756{
a959b088 757 return m_internal->GetPriority();
e9576ca5
SC
758}
759
a959b088 760unsigned long wxThread::GetId() const
e9576ca5 761{
a959b088 762 return (unsigned long)m_internal->GetId();
e9576ca5
SC
763}
764
e7549107 765bool wxThread::IsRunning() const
e9576ca5 766{
a959b088 767 return m_internal->GetState() == STATE_RUNNING;
e9576ca5 768}
e9576ca5
SC
769
770bool wxThread::IsAlive() const
771{
a959b088
SC
772 return (m_internal->GetState() == STATE_RUNNING) ||
773 (m_internal->GetState() == STATE_PAUSED);
e9576ca5
SC
774}
775
e7549107 776bool wxThread::IsPaused() const
e9576ca5 777{
a959b088 778 return m_internal->GetState() == STATE_PAUSED;
e9576ca5
SC
779}
780
e7549107 781bool wxThread::TestDestroy()
e9576ca5 782{
a959b088 783 return m_internal->GetState() == STATE_CANCELED;
e9576ca5
SC
784}
785
e7549107
SC
786// ----------------------------------------------------------------------------
787// Automatic initialization for thread module
788// ----------------------------------------------------------------------------
e9576ca5 789
e7549107
SC
790class wxThreadModule : public wxModule
791{
e9576ca5 792public:
e7549107
SC
793 virtual bool OnInit();
794 virtual void OnExit();
e9576ca5 795
e7549107
SC
796private:
797 DECLARE_DYNAMIC_CLASS(wxThreadModule)
e9576ca5
SC
798};
799
800IMPLEMENT_DYNAMIC_CLASS(wxThreadModule, wxModule)
801
e7549107
SC
802bool wxThreadModule::OnInit()
803{
6fe73788
RL
804 long response;
805 bool hasThreadManager ;
806 hasThreadManager = Gestalt( gestaltThreadMgrAttr, &response) == noErr && response & 1;
5b781a67
SC
807#if !TARGET_CARBON
808#if GENERATINGCFM
6fe73788
RL
809 // verify presence of shared library
810 hasThreadManager = hasThreadManager && ((Ptr)NewThread != (Ptr)kUnresolvedCFragSymbolAddress);
5b781a67 811#endif
a959b088 812#endif
6fe73788
RL
813 if ( !hasThreadManager )
814 {
815 wxMessageBox( "Error" , "Thread Support is not available on this System" , wxOK ) ;
816 return FALSE ;
817 }
e7549107
SC
818
819 // no error return for GetCurrentThreadId()
a959b088 820 MacGetCurrentThread( &gs_idMainThread ) ;
e7549107
SC
821
822 return TRUE;
823}
824
825void wxThreadModule::OnExit()
826{
e7549107
SC
827}
828
829// ----------------------------------------------------------------------------
a959b088
SC
830// under MacOS we don't have currently preemptive threads, so any thread may access
831// the GUI at any time
e7549107
SC
832// ----------------------------------------------------------------------------
833
834void WXDLLEXPORT wxMutexGuiEnter()
835{
e7549107
SC
836}
837
838void WXDLLEXPORT wxMutexGuiLeave()
839{
e7549107
SC
840}
841
842void WXDLLEXPORT wxMutexGuiLeaveOrEnter()
843{
e7549107
SC
844}
845
846bool WXDLLEXPORT wxGuiOwnedByMainThread()
847{
a959b088 848 return false ;
e7549107
SC
849}
850
a959b088 851// wake up the main thread
e7549107
SC
852void WXDLLEXPORT wxWakeUpMainThread()
853{
6fe73788 854 wxMacWakeUp() ;
e7549107
SC
855}
856
857bool WXDLLEXPORT wxIsWaitingForThread()
858{
a959b088 859 return false ;
e7549107 860}
e7549107
SC
861
862#endif // wxUSE_THREADS
a959b088 863
6fe73788 864// vi:sts=4:sw=4:et