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