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