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