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