]> git.saurik.com Git - wxWidgets.git/blob - src/mac/carbon/thread.cpp
wxWinCE (small screen) adjustements. Added possible testing of sizable calendar control.
[wxWidgets.git] / src / mac / carbon / thread.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: thread.cpp
3 // Purpose: wxThread Implementation
4 // Author: Original from Wolfram Gloger/Guilhem Lavaux/Vadim Zeitlin
5 // Modified by: Aj Lavin, Stefan Csomor
6 // Created: 04/22/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Wolfram Gloger (1996, 1997); Guilhem Lavaux (1998),
9 // Vadim Zeitlin (1999) , Stefan Csomor (2000)
10 // Licence: wxWindows licence
11 /////////////////////////////////////////////////////////////////////////////
12
13 // ----------------------------------------------------------------------------
14 // headers
15 // ----------------------------------------------------------------------------
16
17 // For compilers that support precompilation, includes "wx.h".
18 #include "wx/wxprec.h"
19
20 #if defined(__BORLANDC__)
21 #pragma hdrstop
22 #endif
23
24 #ifndef WX_PRECOMP
25 #include "wx/wx.h"
26 #endif
27
28 #if wxUSE_THREADS
29
30 #include "wx/module.h"
31 #include "wx/thread.h"
32
33 #ifdef __WXMAC__
34 #ifdef __DARWIN__
35 #include <CoreServices/CoreServices.h>
36 #else
37 #include <DriverServices.h>
38 #include <Multiprocessing.h>
39 #include "wx/math.h"
40 #endif
41 #include "wx/mac/uma.h"
42 #endif
43
44 #include "wx/mac/macnotfy.h"
45
46 // ----------------------------------------------------------------------------
47 // constants
48 // ----------------------------------------------------------------------------
49
50 // the possible states of the thread ("=>" shows all possible transitions from
51 // this state)
52 enum 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
59 };
60
61 // ----------------------------------------------------------------------------
62 // this module globals
63 // ----------------------------------------------------------------------------
64
65
66 // the task ID of the main thread
67 static wxThreadIdType gs_idMainThread = kInvalidID;
68
69 // this is the Per-Task Storage for the pointer to the appropriate wxThread
70 TaskStorageIndex gs_tlsForWXThread = 0 ;
71
72 // if it's false, some secondary thread is holding the GUI lock
73 static bool gs_bGuiOwnedByMainThread = true;
74
75 // critical section which controls access to all GUI functions: any secondary
76 // thread (i.e. except the main one) must enter this crit section before doing
77 // any GUI calls
78 static wxCriticalSection *gs_critsectGui = NULL;
79
80 // critical section which protects gs_nWaitingForGui variable
81 static wxCriticalSection *gs_critsectWaitingForGui = NULL;
82
83 // number of threads waiting for GUI in wxMutexGuiEnter()
84 static size_t gs_nWaitingForGui = 0;
85
86 // overall number of threads, needed for determining the sleep value of the main
87 // event loop
88 size_t g_numberOfThreads = 0;
89
90
91
92 #if wxUSE_GUI
93
94 MPCriticalRegionID gs_guiCritical = kInvalidID;
95
96 #endif
97
98 // ============================================================================
99 // MacOS implementation of thread classes
100 // ============================================================================
101
102 /*
103 Notes :
104
105 The implementation is very close to the phtreads implementation, the reason for
106 using MPServices is the fact that these are also available under OS 9. Thus allowing
107 for one common API for all current builds.
108
109 As soon as wxThreads are on a 64 bit address space, the TLS must be extended
110 to use two indices one for each 32 bit part as the MP implementation is limited
111 to longs.
112
113 I have three implementations for mutexes :
114 version A based on a binary semaphore, problem - not reentrant, version B based
115 on a critical region, allows for reentrancy, performance implications not
116 yet tested, and third a plain pthreads implementation
117
118 The same for condition internal, one implementation by Aj Lavin and the other one
119 copied from the thrimpl.cpp which I assume has been more broadly tested, I've just
120 replaced the interlock increment with the appropriate PPC calls
121 */
122
123 // ----------------------------------------------------------------------------
124 // wxCriticalSection
125 // ----------------------------------------------------------------------------
126
127 wxCriticalSection::wxCriticalSection()
128 {
129 MPCreateCriticalRegion( (MPCriticalRegionID*) &m_critRegion ) ;
130 }
131
132 wxCriticalSection::~wxCriticalSection()
133 {
134 MPDeleteCriticalRegion( (MPCriticalRegionID) m_critRegion ) ;
135 }
136
137 void wxCriticalSection::Enter()
138 {
139 MPEnterCriticalRegion( (MPCriticalRegionID) m_critRegion , kDurationForever ) ;
140 }
141
142 void wxCriticalSection::Leave()
143 {
144 MPExitCriticalRegion((MPCriticalRegionID) m_critRegion ) ;
145 }
146
147 // ----------------------------------------------------------------------------
148 // wxMutex implementation
149 // ----------------------------------------------------------------------------
150
151 #if TARGET_API_MAC_OSX
152 #define wxUSE_MAC_SEMAPHORE_MUTEX 0
153 #define wxUSE_MAC_CRITICAL_REGION_MUTEX 1
154 #define wxUSE_MAC_PTHREADS_MUTEX 0
155 #else
156 #define wxUSE_MAC_SEMAPHORE_MUTEX 0
157 #define wxUSE_MAC_CRITICAL_REGION_MUTEX 1
158 #define wxUSE_MAC_PTHREADS_MUTEX 0
159 #endif
160
161 #if wxUSE_MAC_PTHREADS_MUTEX
162
163 #include <pthread.h>
164
165 class wxMutexInternal
166 {
167 public:
168 wxMutexInternal(wxMutexType mutexType);
169 ~wxMutexInternal();
170
171 wxMutexError Lock();
172 wxMutexError TryLock();
173 wxMutexError Unlock();
174
175 bool IsOk() const { return m_isOk; }
176
177 private:
178 pthread_mutex_t m_mutex;
179 bool m_isOk;
180
181 // wxConditionInternal uses our m_mutex
182 friend class wxConditionInternal;
183 };
184
185 #ifdef HAVE_PTHREAD_MUTEXATTR_T
186 // on some systems pthread_mutexattr_settype() is not in the headers (but it is
187 // in the library, otherwise we wouldn't compile this code at all)
188 extern "C" int pthread_mutexattr_settype(pthread_mutexattr_t *, int);
189 #endif
190
191 wxMutexInternal::wxMutexInternal(wxMutexType mutexType)
192 {
193 int err;
194 switch ( mutexType )
195 {
196 case wxMUTEX_RECURSIVE:
197 // support recursive locks like Win32, i.e. a thread can lock a
198 // mutex which it had itself already locked
199 //
200 // unfortunately initialization of recursive mutexes is non
201 // portable, so try several methods
202 #ifdef HAVE_PTHREAD_MUTEXATTR_T
203 {
204 pthread_mutexattr_t attr;
205 pthread_mutexattr_init(&attr);
206 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
207
208 err = pthread_mutex_init(&m_mutex, &attr);
209 }
210 #elif defined(HAVE_PTHREAD_RECURSIVE_MUTEX_INITIALIZER)
211 // we can use this only as initializer so we have to assign it
212 // first to a temp var - assigning directly to m_mutex wouldn't
213 // even compile
214 {
215 pthread_mutex_t mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
216 m_mutex = mutex;
217 }
218 #else // no recursive mutexes
219 err = EINVAL;
220 #endif // HAVE_PTHREAD_MUTEXATTR_T/...
221 break;
222
223 default:
224 wxFAIL_MSG( _T("unknown mutex type") );
225 // fall through
226
227 case wxMUTEX_DEFAULT:
228 err = pthread_mutex_init(&m_mutex, NULL);
229 break;
230 }
231
232 m_isOk = err == 0;
233 if ( !m_isOk )
234 {
235 wxLogApiError( wxT("pthread_mutex_init()"), err);
236 }
237 }
238
239 wxMutexInternal::~wxMutexInternal()
240 {
241 if ( m_isOk )
242 {
243 int err = pthread_mutex_destroy(&m_mutex);
244 if ( err != 0 )
245 {
246 wxLogApiError( wxT("pthread_mutex_destroy()"), err);
247 }
248 }
249 }
250
251 wxMutexError wxMutexInternal::Lock()
252 {
253 int err = pthread_mutex_lock(&m_mutex);
254 switch ( err )
255 {
256 case EDEADLK:
257 // only error checking mutexes return this value and so it's an
258 // unexpected situation -- hence use assert, not wxLogDebug
259 wxFAIL_MSG( _T("mutex deadlock prevented") );
260 return wxMUTEX_DEAD_LOCK;
261
262 case EINVAL:
263 wxLogDebug(_T("pthread_mutex_lock(): mutex not initialized."));
264 break;
265
266 case 0:
267 return wxMUTEX_NO_ERROR;
268
269 default:
270 wxLogApiError(_T("pthread_mutex_lock()"), err);
271 }
272
273 return wxMUTEX_MISC_ERROR;
274 }
275
276 wxMutexError wxMutexInternal::TryLock()
277 {
278 int err = pthread_mutex_trylock(&m_mutex);
279 switch ( err )
280 {
281 case EBUSY:
282 // not an error: mutex is already locked, but we're prepared for
283 // this
284 return wxMUTEX_BUSY;
285
286 case EINVAL:
287 wxLogDebug(_T("pthread_mutex_trylock(): mutex not initialized."));
288 break;
289
290 case 0:
291 return wxMUTEX_NO_ERROR;
292
293 default:
294 wxLogApiError(_T("pthread_mutex_trylock()"), err);
295 }
296
297 return wxMUTEX_MISC_ERROR;
298 }
299
300 wxMutexError wxMutexInternal::Unlock()
301 {
302 int err = pthread_mutex_unlock(&m_mutex);
303 switch ( err )
304 {
305 case EPERM:
306 // we don't own the mutex
307 return wxMUTEX_UNLOCKED;
308
309 case EINVAL:
310 wxLogDebug(_T("pthread_mutex_unlock(): mutex not initialized."));
311 break;
312
313 case 0:
314 return wxMUTEX_NO_ERROR;
315
316 default:
317 wxLogApiError(_T("pthread_mutex_unlock()"), err);
318 }
319
320 return wxMUTEX_MISC_ERROR;
321 }
322
323
324 #endif
325
326 #if wxUSE_MAC_SEMAPHORE_MUTEX
327
328 class wxMutexInternal
329 {
330 public:
331 wxMutexInternal(wxMutexType mutexType) ;
332 ~wxMutexInternal() ;
333 bool IsOk() const { return m_isOk; }
334
335 wxMutexError Lock() ;
336 wxMutexError TryLock() ;
337 wxMutexError Unlock();
338 private:
339 MPSemaphoreID m_semaphore;
340 bool m_isOk ;
341 };
342
343 wxMutexInternal::wxMutexInternal(wxMutexType mutexType )
344 {
345 m_isOk = false ;
346 m_semaphore = kInvalidID ;
347
348 OSStatus err = noErr ;
349 switch( mutexType )
350 {
351 case wxMUTEX_DEFAULT :
352 {
353 verify_noerr( MPCreateBinarySemaphore( & m_semaphore) );
354 m_isOk = ( m_semaphore != kInvalidID ) ;
355 }
356 break ;
357 case wxMUTEX_RECURSIVE :
358 wxFAIL_MSG(wxT("Recursive Mutex not supported yet") ) ;
359 break ;
360 default :
361 wxFAIL_MSG(wxT("Unknown mutex type") ) ;
362 break ;
363 }
364 }
365
366 wxMutexInternal::~wxMutexInternal()
367 {
368 if ( m_semaphore != kInvalidID )
369 MPDeleteSemaphore( m_semaphore);
370 MPYield() ;
371 }
372
373 wxMutexError wxMutexInternal::Lock()
374 {
375 wxCHECK_MSG( m_isOk , wxMUTEX_MISC_ERROR , wxT("Invalid Mutex") ) ;
376 OSStatus err = MPWaitOnSemaphore( m_semaphore, kDurationForever);
377 if ( err)
378 {
379 wxLogSysError(wxT("Could not lock mutex"));
380 return wxMUTEX_MISC_ERROR;
381 }
382
383 return wxMUTEX_NO_ERROR;
384 }
385
386 wxMutexError wxMutexInternal::TryLock()
387 {
388 wxCHECK_MSG( m_isOk , wxMUTEX_MISC_ERROR , wxT("Invalid Mutex") ) ;
389 OSStatus err = MPWaitOnSemaphore( m_semaphore, kDurationImmediate);
390 if ( err)
391 {
392 if ( err == kMPTimeoutErr)
393 {
394 return wxMUTEX_BUSY;
395 }
396 wxLogSysError(wxT("Could not try lock mutex"));
397 return wxMUTEX_MISC_ERROR;
398 }
399
400 return wxMUTEX_NO_ERROR;
401 }
402
403 wxMutexError wxMutexInternal::Unlock()
404 {
405 wxCHECK_MSG( m_isOk , wxMUTEX_MISC_ERROR , wxT("Invalid Mutex") ) ;
406 OSStatus err = MPSignalSemaphore( m_semaphore);
407 MPYield() ;
408 if ( err)
409 {
410 wxLogSysError(_("Could not unlock mutex"));
411 return wxMUTEX_MISC_ERROR;
412 }
413 return wxMUTEX_NO_ERROR;
414 }
415
416 #endif
417
418 #if wxUSE_MAC_CRITICAL_REGION_MUTEX
419
420 class wxMutexInternal
421 {
422 public:
423 wxMutexInternal(wxMutexType mutexType) ;
424 ~wxMutexInternal() ;
425 bool IsOk() const { return m_isOk; }
426
427 wxMutexError Lock() ;
428 wxMutexError TryLock() ;
429 wxMutexError Unlock();
430 private:
431 MPCriticalRegionID m_critRegion ;
432 bool m_isOk ;
433 };
434
435 wxMutexInternal::wxMutexInternal(wxMutexType mutexType )
436 {
437 m_isOk = false ;
438 m_critRegion = kInvalidID ;
439
440 verify_noerr( MPCreateCriticalRegion( & m_critRegion) );
441 m_isOk = ( m_critRegion != kInvalidID ) ;
442
443 if ( !IsOk() )
444 wxFAIL_MSG(wxT("Error when creating mutex") ) ;
445 }
446
447 wxMutexInternal::~wxMutexInternal()
448 {
449 if ( m_critRegion != kInvalidID )
450 MPDeleteCriticalRegion( m_critRegion);
451 MPYield() ;
452 }
453
454 wxMutexError wxMutexInternal::Lock()
455 {
456 wxCHECK_MSG( m_isOk , wxMUTEX_MISC_ERROR , wxT("Invalid Mutex") ) ;
457 OSStatus err = MPEnterCriticalRegion( m_critRegion, kDurationForever);
458 if ( err)
459 {
460 wxLogSysError(wxT("Could not lock mutex"));
461 return wxMUTEX_MISC_ERROR;
462 }
463
464 return wxMUTEX_NO_ERROR;
465 }
466
467 wxMutexError wxMutexInternal::TryLock()
468 {
469 wxCHECK_MSG( m_isOk , wxMUTEX_MISC_ERROR , wxT("Invalid Mutex") ) ;
470 OSStatus err = MPEnterCriticalRegion( m_critRegion, kDurationImmediate);
471 if ( err)
472 {
473 if ( err == kMPTimeoutErr)
474 {
475 return wxMUTEX_BUSY;
476 }
477 wxLogSysError(wxT("Could not try lock mutex"));
478 return wxMUTEX_MISC_ERROR;
479 }
480
481 return wxMUTEX_NO_ERROR;
482 }
483
484 wxMutexError wxMutexInternal::Unlock()
485 {
486 wxCHECK_MSG( m_isOk , wxMUTEX_MISC_ERROR , wxT("Invalid Mutex") ) ;
487 OSStatus err = MPExitCriticalRegion( m_critRegion);
488 MPYield() ;
489 if ( err)
490 {
491 wxLogSysError(_("Could not unlock mutex"));
492 return wxMUTEX_MISC_ERROR;
493 }
494
495 return wxMUTEX_NO_ERROR;
496 }
497
498 #endif
499
500 // --------------------------------------------------------------------------
501 // wxSemaphore
502 // --------------------------------------------------------------------------
503
504 class wxSemaphoreInternal
505 {
506 public:
507 wxSemaphoreInternal(int initialcount, int maxcount);
508 ~wxSemaphoreInternal();
509
510 bool IsOk() const { return m_isOk; }
511
512 wxSemaError WaitTimeout(unsigned long milliseconds);
513
514 wxSemaError Wait() { return WaitTimeout( kDurationForever); }
515
516 wxSemaError TryWait()
517 {
518 wxSemaError err = WaitTimeout(kDurationImmediate);
519 if ( err == wxSEMA_TIMEOUT )
520 err = wxSEMA_BUSY ;
521 return err ;
522 }
523 wxSemaError Post();
524
525 private:
526 MPSemaphoreID m_semaphore;
527 bool m_isOk ;
528 };
529
530 wxSemaphoreInternal::wxSemaphoreInternal(int initialcount, int maxcount)
531 {
532 m_isOk = false ;
533 m_semaphore = kInvalidID ;
534 if ( maxcount == 0 )
535 {
536 // make it practically infinite
537 maxcount = INT_MAX;
538 }
539 verify_noerr( MPCreateSemaphore( maxcount, initialcount, & m_semaphore) );
540 m_isOk = ( m_semaphore != kInvalidID ) ;
541
542 if ( !IsOk() )
543 wxFAIL_MSG(wxT("Error when creating semaphore") ) ;
544 }
545
546 wxSemaphoreInternal::~wxSemaphoreInternal()
547 {
548 if( m_semaphore != kInvalidID )
549 MPDeleteSemaphore( m_semaphore);
550 MPYield() ;
551 }
552
553 wxSemaError wxSemaphoreInternal::WaitTimeout(unsigned long milliseconds)
554 {
555 OSStatus err = MPWaitOnSemaphore( m_semaphore, milliseconds);
556 if ( err)
557 {
558 if ( err == kMPTimeoutErr)
559 {
560 return wxSEMA_TIMEOUT;
561 }
562 return wxSEMA_MISC_ERROR;
563 }
564 return wxSEMA_NO_ERROR;
565 }
566
567 wxSemaError wxSemaphoreInternal::Post()
568 {
569 OSStatus err = MPSignalSemaphore( m_semaphore);
570 MPYield() ;
571 if ( err)
572 {
573 return wxSEMA_MISC_ERROR;
574 }
575 return wxSEMA_NO_ERROR;
576 }
577
578 // ----------------------------------------------------------------------------
579 // wxCondition implementation
580 // ----------------------------------------------------------------------------
581
582 #if 0
583
584 class wxConditionInternal
585 {
586 public:
587
588 wxConditionInternal(wxMutex& mutex)
589 : m_mutex( mutex),
590 m_semaphore( 0, 1),
591 m_gate( 1, 1)
592 {
593 m_waiters = 0;
594 m_signals = 0;
595 m_canceled = 0;
596 }
597
598 ~wxConditionInternal()
599 {
600 }
601
602 bool IsOk() const { return m_mutex.IsOk() ; }
603
604 wxCondError Wait()
605 {
606 return WaitTimeout( kDurationForever);
607 }
608
609 wxCondError WaitTimeout(unsigned long msectimeout);
610
611 wxCondError Signal()
612 {
613 return DoSignal( false);
614 }
615
616 wxCondError Broadcast()
617 {
618 return DoSignal( true);
619 }
620
621 private:
622
623 wxCondError DoSignal( bool signalAll);
624
625 wxMutex& m_mutex;
626 wxSemaphoreInternal m_semaphore; // Signals the waiting threads.
627 wxSemaphoreInternal m_gate;
628 wxCriticalSection m_varSection;
629 size_t m_waiters; // Number of threads waiting for a signal.
630 size_t m_signals; // Number of signals to send.
631 size_t m_canceled; // Number of canceled waiters in m_waiters.
632 };
633
634
635 wxCondError wxConditionInternal::WaitTimeout(unsigned long msectimeout)
636 {
637 m_gate.Wait();
638 if ( ++ m_waiters == INT_MAX)
639 {
640 m_varSection.Enter();
641 m_waiters -= m_canceled;
642 m_signals -= m_canceled;
643 m_canceled = 0;
644 m_varSection.Leave();
645 }
646 m_gate.Post();
647
648 m_mutex.Unlock();
649
650 wxSemaError err = m_semaphore.WaitTimeout( msectimeout);
651 wxASSERT( err == wxSEMA_NO_ERROR || err == wxSEMA_TIMEOUT);
652
653 m_varSection.Enter();
654 if ( err != wxSEMA_NO_ERROR)
655 {
656 if ( m_signals > m_canceled)
657 {
658 // A signal is being sent after we timed out.
659
660 if ( m_waiters == m_signals)
661 {
662 // There are no excess waiters to catch the signal, so
663 // we must throw it away.
664
665 wxSemaError err2 = m_semaphore.Wait();
666 if ( err2 != wxSEMA_NO_ERROR)
667 {
668 wxLogSysError(_("Error while waiting on semaphore"));
669 }
670 wxASSERT( err2 == wxSEMA_NO_ERROR);
671 -- m_waiters;
672 if ( -- m_signals == m_canceled)
673 {
674 // This was the last signal. open the gate.
675 wxASSERT( m_waiters == m_canceled);
676 m_gate.Post();
677 }
678 }
679 else
680 {
681 // There are excess waiters to catch the signal, leave
682 // it be.
683 -- m_waiters;
684 }
685 }
686 else
687 {
688 // No signals is being sent.
689 // The gate may be open or closed, so we can't touch m_waiters.
690 ++ m_canceled;
691 ++ m_signals;
692 }
693 }
694 else
695 {
696 // We caught a signal.
697 wxASSERT( m_signals > m_canceled);
698 -- m_waiters;
699 if ( -- m_signals == m_canceled)
700 {
701 // This was the last signal. open the gate.
702 wxASSERT( m_waiters == m_canceled);
703 m_gate.Post();
704 }
705 }
706 m_varSection.Leave();
707
708 m_mutex.Lock();
709
710 if ( err)
711 {
712 return err == wxSEMA_TIMEOUT ? wxCOND_TIMEOUT : wxCOND_MISC_ERROR;
713 }
714
715 return wxCOND_NO_ERROR;
716 }
717
718
719 wxCondError wxConditionInternal::DoSignal( bool signalAll)
720 {
721 m_gate.Wait();
722 m_varSection.Enter();
723
724 wxASSERT( m_signals == m_canceled);
725
726 if ( m_waiters == m_canceled)
727 {
728 m_varSection.Leave();
729 m_gate.Post();
730 return wxCOND_NO_ERROR;
731 }
732
733 if ( m_canceled > 0)
734 {
735 m_waiters -= m_canceled;
736 m_signals = 0;
737 m_canceled = 0;
738 }
739
740 m_signals = signalAll ? m_waiters : 1;
741 size_t n = m_signals;
742
743 m_varSection.Leave();
744
745 // Let the waiters inherit the gate lock.
746
747 do
748 {
749 wxSemaError err = m_semaphore.Post();
750 wxASSERT( err == wxSEMA_NO_ERROR);
751 } while ( -- n);
752
753 return wxCOND_NO_ERROR;
754 }
755
756 #else
757 class wxConditionInternal
758 {
759 public:
760 wxConditionInternal(wxMutex& mutex);
761
762 bool IsOk() const { return m_mutex.IsOk() && m_semaphore.IsOk(); }
763
764 wxCondError Wait();
765 wxCondError WaitTimeout(unsigned long milliseconds);
766
767 wxCondError Signal();
768 wxCondError Broadcast();
769
770 private:
771 // the number of threads currently waiting for this condition
772 SInt32 m_numWaiters;
773
774 // the critical section protecting m_numWaiters
775 wxCriticalSection m_csWaiters;
776
777 wxMutex& m_mutex;
778 wxSemaphore m_semaphore;
779
780 DECLARE_NO_COPY_CLASS(wxConditionInternal)
781 };
782
783 wxConditionInternal::wxConditionInternal(wxMutex& mutex)
784 : m_mutex(mutex)
785 {
786 // another thread can't access it until we return from ctor, so no need to
787 // protect access to m_numWaiters here
788 m_numWaiters = 0;
789 }
790
791 wxCondError wxConditionInternal::Wait()
792 {
793 // increment the number of waiters
794 IncrementAtomic(&m_numWaiters);
795
796 m_mutex.Unlock();
797
798 // a potential race condition can occur here
799 //
800 // after a thread increments nwaiters, and unlocks the mutex and before the
801 // semaphore.Wait() is called, if another thread can cause a signal to be
802 // generated
803 //
804 // this race condition is handled by using a semaphore and incrementing the
805 // semaphore only if 'nwaiters' is greater that zero since the semaphore,
806 // can 'remember' signals the race condition will not occur
807
808 // wait ( if necessary ) and decrement semaphore
809 wxSemaError err = m_semaphore.Wait();
810 m_mutex.Lock();
811
812 return err == wxSEMA_NO_ERROR ? wxCOND_NO_ERROR : wxCOND_MISC_ERROR;
813 }
814
815 wxCondError wxConditionInternal::WaitTimeout(unsigned long milliseconds)
816 {
817 IncrementAtomic(&m_numWaiters);
818
819 m_mutex.Unlock();
820
821 // a race condition can occur at this point in the code
822 //
823 // please see the comments in Wait(), for details
824
825 wxSemaError err = m_semaphore.WaitTimeout(milliseconds);
826
827 if ( err == wxSEMA_BUSY )
828 {
829 // another potential race condition exists here it is caused when a
830 // 'waiting' thread timesout, and returns from WaitForSingleObject, but
831 // has not yet decremented 'nwaiters'.
832 //
833 // at this point if another thread calls signal() then the semaphore
834 // will be incremented, but the waiting thread will miss it.
835 //
836 // to handle this particular case, the waiting thread calls
837 // WaitForSingleObject again with a timeout of 0, after locking
838 // 'nwaiters_mutex'. this call does not block because of the zero
839 // timeout, but will allow the waiting thread to catch the missed
840 // signals.
841 wxCriticalSectionLocker lock(m_csWaiters);
842
843 err = m_semaphore.WaitTimeout(0);
844
845 if ( err != wxSEMA_NO_ERROR )
846 {
847 m_numWaiters--;
848 }
849 }
850
851 m_mutex.Lock();
852
853 return err == wxSEMA_NO_ERROR ? wxCOND_NO_ERROR : wxCOND_MISC_ERROR;
854 }
855
856 wxCondError wxConditionInternal::Signal()
857 {
858 wxCriticalSectionLocker lock(m_csWaiters);
859
860 if ( m_numWaiters > 0 )
861 {
862 // increment the semaphore by 1
863 if ( m_semaphore.Post() != wxSEMA_NO_ERROR )
864 return wxCOND_MISC_ERROR;
865
866 m_numWaiters--;
867 }
868
869 return wxCOND_NO_ERROR;
870 }
871
872 wxCondError wxConditionInternal::Broadcast()
873 {
874 wxCriticalSectionLocker lock(m_csWaiters);
875
876 while ( m_numWaiters > 0 )
877 {
878 if ( m_semaphore.Post() != wxSEMA_NO_ERROR )
879 return wxCOND_MISC_ERROR;
880
881 m_numWaiters--;
882 }
883
884 return wxCOND_NO_ERROR;
885 }
886 #endif
887
888 // ----------------------------------------------------------------------------
889 // wxCriticalSection implementation
890 // ----------------------------------------------------------------------------
891
892 // XXX currently implemented as mutex in headers. Change to critical section.
893
894 // ----------------------------------------------------------------------------
895 // wxThread implementation
896 // ----------------------------------------------------------------------------
897
898 // wxThreadInternal class
899 // ----------------------
900
901 class wxThreadInternal
902 {
903 public:
904 wxThreadInternal()
905 {
906 m_tid = kInvalidID;
907 m_state = STATE_NEW;
908 m_prio = WXTHREAD_DEFAULT_PRIORITY;
909 m_notifyQueueId = kInvalidID;
910 m_exitcode = 0;
911 m_cancelled = FALSE ;
912
913 // set to TRUE only when the thread starts waiting on m_semSuspend
914 m_isPaused = FALSE;
915
916 // defaults for joinable threads
917 m_shouldBeJoined = TRUE;
918 m_isDetached = FALSE;
919 }
920 ~wxThreadInternal()
921 {
922 if ( m_notifyQueueId)
923 {
924 MPDeleteQueue( m_notifyQueueId);
925 m_notifyQueueId = kInvalidID ;
926 }
927 }
928
929 // thread function
930 static OSStatus MacThreadStart(void* arg);
931
932 // create a new (suspended) thread (for the given thread object)
933 bool Create(wxThread *thread, unsigned int stackSize);
934
935 // thread actions
936 // start the thread
937 wxThreadError Run();
938 // unblock the thread allowing it to run
939 void SignalRun() { m_semRun.Post(); }
940 // ask the thread to terminate
941 void Wait();
942 // go to sleep until Resume() is called
943 void Pause();
944 // resume the thread
945 void Resume();
946
947 // accessors
948 // priority
949 int GetPriority() const { return m_prio; }
950 void SetPriority(int prio) ;
951 // state
952 wxThreadState GetState() const { return m_state; }
953 void SetState(wxThreadState state) { m_state = state; }
954
955 // Get the ID of this thread's underlying MP Services task.
956 MPTaskID GetId() const { return m_tid; }
957
958 void SetCancelFlag() { m_cancelled = TRUE; }
959 bool WasCancelled() const { return m_cancelled; }
960 // exit code
961 void SetExitCode(wxThread::ExitCode exitcode) { m_exitcode = exitcode; }
962 wxThread::ExitCode GetExitCode() const { return m_exitcode; }
963
964 // the pause flag
965 void SetReallyPaused(bool paused) { m_isPaused = paused; }
966 bool IsReallyPaused() const { return m_isPaused; }
967
968 // tell the thread that it is a detached one
969 void Detach()
970 {
971 wxCriticalSectionLocker lock(m_csJoinFlag);
972
973 m_shouldBeJoined = FALSE;
974 m_isDetached = TRUE;
975 }
976
977 private:
978 // the thread we're associated with
979 wxThread * m_thread;
980
981 MPTaskID m_tid; // thread id
982 MPQueueID m_notifyQueueId; // its notification queue
983
984 wxThreadState m_state; // see wxThreadState enum
985 int m_prio; // in wxWidgets units: from 0 to 100
986
987 // this flag is set when the thread should terminate
988 bool m_cancelled;
989
990 // this flag is set when the thread is blocking on m_semSuspend
991 bool m_isPaused;
992
993 // the thread exit code - only used for joinable (!detached) threads and
994 // is only valid after the thread termination
995 wxThread::ExitCode m_exitcode;
996
997 // many threads may call Wait(), but only one of them should call
998 // pthread_join(), so we have to keep track of this
999 wxCriticalSection m_csJoinFlag;
1000 bool m_shouldBeJoined;
1001 bool m_isDetached;
1002
1003 // this semaphore is posted by Run() and the threads Entry() is not
1004 // called before it is done
1005 wxSemaphore m_semRun;
1006
1007 // this one is signaled when the thread should resume after having been
1008 // Pause()d
1009 wxSemaphore m_semSuspend;
1010 };
1011
1012 OSStatus wxThreadInternal::MacThreadStart(void *parameter)
1013 {
1014 wxThread* thread = (wxThread*) parameter ;
1015 wxThreadInternal *pthread = thread->m_internal;
1016
1017 // add to TLS so that This() will work
1018 verify_noerr( MPSetTaskStorageValue( gs_tlsForWXThread , (long) thread ) ) ;
1019
1020 // have to declare this before pthread_cleanup_push() which defines a
1021 // block!
1022 bool dontRunAtAll;
1023
1024 // wait for the semaphore to be posted from Run()
1025 pthread->m_semRun.Wait();
1026
1027 // test whether we should run the run at all - may be it was deleted
1028 // before it started to Run()?
1029 {
1030 wxCriticalSectionLocker lock(thread->m_critsect);
1031
1032 dontRunAtAll = pthread->GetState() == STATE_NEW &&
1033 pthread->WasCancelled();
1034 }
1035
1036 if ( !dontRunAtAll )
1037 {
1038 pthread->m_exitcode = thread->Entry();
1039
1040 {
1041 wxCriticalSectionLocker lock(thread->m_critsect);
1042 pthread->SetState(STATE_EXITED);
1043 }
1044 }
1045
1046 if ( dontRunAtAll )
1047 {
1048 if ( pthread->m_isDetached )
1049 delete thread;
1050
1051 return -1 ;
1052 }
1053 else
1054 {
1055 // on mac for the running code the correct thread termination is to
1056 // return
1057
1058 // terminate the thread
1059 thread->Exit(pthread->m_exitcode);
1060
1061 return (OSStatus) NULL ; // pthread->m_exitcode;
1062 }
1063 }
1064
1065 bool wxThreadInternal::Create(wxThread *thread, unsigned int stackSize)
1066 {
1067 wxASSERT_MSG( m_state == STATE_NEW && !m_tid,
1068 _T("Create()ing thread twice?") );
1069
1070 OSStatus err = noErr ;
1071 m_thread = thread;
1072
1073 if ( m_notifyQueueId == kInvalidID )
1074 {
1075 OSStatus err = MPCreateQueue( & m_notifyQueueId);
1076 if( err)
1077 {
1078 wxLogSysError(_("Cant create the thread event queue"));
1079 return false;
1080 }
1081 }
1082
1083 m_state = STATE_NEW;
1084
1085 err = MPCreateTask( MacThreadStart,
1086 (void*) m_thread,
1087 stackSize,
1088 m_notifyQueueId,
1089 &m_exitcode,
1090 0,
1091 0,
1092 &m_tid);
1093
1094 if ( err)
1095 {
1096 wxLogSysError(_("Can't create thread"));
1097 return false;
1098 }
1099
1100 if ( m_prio != WXTHREAD_DEFAULT_PRIORITY )
1101 {
1102 SetPriority(m_prio);
1103 }
1104
1105 return true;
1106 }
1107
1108 void wxThreadInternal::SetPriority( int priority)
1109 {
1110 m_prio = priority;
1111
1112 if ( m_tid)
1113 {
1114 // Mac priorities range from 1 to 10,000, with a default of 100.
1115 // wxWidgets priorities range from 0 to 100 with a default of 50.
1116 // We can map wxWidgets to Mac priorities easily by assuming
1117 // the former uses a logarithmic scale.
1118 const unsigned int macPriority = ( int)( exp( priority / 25.0 * log( 10.0)) + 0.5);
1119
1120 MPSetTaskWeight( m_tid, macPriority);
1121 }
1122 }
1123
1124 wxThreadError wxThreadInternal::Run()
1125 {
1126 wxCHECK_MSG( GetState() == STATE_NEW, wxTHREAD_RUNNING,
1127 wxT("thread may only be started once after Create()") );
1128
1129 SetState(STATE_RUNNING);
1130
1131 // wake up threads waiting for our start
1132 SignalRun();
1133
1134 return wxTHREAD_NO_ERROR;
1135 }
1136
1137 void wxThreadInternal::Wait()
1138 {
1139 wxCHECK_RET( !m_isDetached, _T("can't wait for a detached thread") );
1140
1141 // if the thread we're waiting for is waiting for the GUI mutex, we will
1142 // deadlock so make sure we release it temporarily
1143 if ( wxThread::IsMain() )
1144 {
1145 // give the thread we're waiting for chance to do the GUI call
1146 // it might be in, we don't do this conditionally as the to be waited on
1147 // thread might have to acquire the mutex later but before terminating
1148 if ( wxGuiOwnedByMainThread() )
1149 {
1150 wxMutexGuiLeave();
1151 }
1152 }
1153
1154 {
1155 wxCriticalSectionLocker lock(m_csJoinFlag);
1156
1157 if ( m_shouldBeJoined )
1158 {
1159 void * param1;
1160 void * param2;
1161 void * rc;
1162
1163 OSStatus err = MPWaitOnQueue ( m_notifyQueueId,
1164 & param1,
1165 & param2,
1166 & rc,
1167 kDurationForever);
1168 if ( err)
1169 {
1170 wxLogSysError( _( "Cannot wait for thread termination."));
1171 rc = (void*) -1;
1172 }
1173
1174 // actually param1 would be the address of m_exitcode
1175 // but we don't need this here
1176 m_exitcode = rc;
1177
1178 m_shouldBeJoined = FALSE;
1179 }
1180 }
1181 }
1182
1183 void wxThreadInternal::Pause()
1184 {
1185 // the state is set from the thread which pauses us first, this function
1186 // is called later so the state should have been already set
1187 wxCHECK_RET( m_state == STATE_PAUSED,
1188 wxT("thread must first be paused with wxThread::Pause().") );
1189
1190 // wait until the semaphore is Post()ed from Resume()
1191 m_semSuspend.Wait();
1192 }
1193
1194 void wxThreadInternal::Resume()
1195 {
1196 wxCHECK_RET( m_state == STATE_PAUSED,
1197 wxT("can't resume thread which is not suspended.") );
1198
1199 // the thread might be not actually paused yet - if there were no call to
1200 // TestDestroy() since the last call to Pause() for example
1201 if ( IsReallyPaused() )
1202 {
1203 // wake up Pause()
1204 m_semSuspend.Post();
1205
1206 // reset the flag
1207 SetReallyPaused(FALSE);
1208 }
1209
1210 SetState(STATE_RUNNING);
1211 }
1212
1213 // static functions
1214 // ----------------
1215
1216 wxThread *wxThread::This()
1217 {
1218 wxThread* thr = (wxThread*) MPGetTaskStorageValue( gs_tlsForWXThread ) ;
1219 return thr;
1220 }
1221
1222 bool wxThread::IsMain()
1223 {
1224 return GetCurrentId() == gs_idMainThread || gs_idMainThread == kInvalidID ;
1225 }
1226
1227 #ifdef Yield
1228 #undef Yield
1229 #endif
1230
1231 void wxThread::Yield()
1232 {
1233 #if TARGET_API_MAC_OSX
1234 CFRunLoopRunInMode( kCFRunLoopDefaultMode , 0 , true ) ;
1235 #endif
1236 MPYield();
1237 }
1238
1239
1240 void wxThread::Sleep(unsigned long milliseconds)
1241 {
1242 AbsoluteTime wakeup = AddDurationToAbsolute( milliseconds, UpTime());
1243 MPDelayUntil( & wakeup);
1244 }
1245
1246
1247 int wxThread::GetCPUCount()
1248 {
1249 return MPProcessors();
1250 }
1251
1252 unsigned long wxThread::GetCurrentId()
1253 {
1254 return (unsigned long)MPCurrentTaskID();
1255 }
1256
1257
1258 bool wxThread::SetConcurrency(size_t level)
1259 {
1260 // Cannot be set in MacOS.
1261 return false;
1262 }
1263
1264
1265 wxThread::wxThread(wxThreadKind kind)
1266 {
1267 g_numberOfThreads++;
1268 m_internal = new wxThreadInternal();
1269
1270 m_isDetached = (kind == wxTHREAD_DETACHED);
1271 }
1272
1273 wxThread::~wxThread()
1274 {
1275 wxASSERT_MSG( g_numberOfThreads>0 , wxT("More threads deleted than created.") ) ;
1276 g_numberOfThreads--;
1277
1278 #ifdef __WXDEBUG__
1279 m_critsect.Enter();
1280
1281 // check that the thread either exited or couldn't be created
1282 if ( m_internal->GetState() != STATE_EXITED &&
1283 m_internal->GetState() != STATE_NEW )
1284 {
1285 wxLogDebug(_T("The thread %ld is being destroyed although it is still running! The application may crash."), GetId());
1286 }
1287
1288 m_critsect.Leave();
1289 #endif // __WXDEBUG__
1290
1291 wxDELETE( m_internal ) ;
1292 }
1293
1294
1295 wxThreadError wxThread::Create(unsigned int stackSize)
1296 {
1297 wxCriticalSectionLocker lock(m_critsect);
1298
1299 if ( m_isDetached )
1300 {
1301 m_internal->Detach() ;
1302 }
1303 if ( m_internal->Create(this, stackSize) == false )
1304 {
1305 m_internal->SetState(STATE_EXITED);
1306 return wxTHREAD_NO_RESOURCE;
1307 }
1308
1309 return wxTHREAD_NO_ERROR;
1310 }
1311
1312 wxThreadError wxThread::Run()
1313 {
1314 wxCriticalSectionLocker lock(m_critsect);
1315
1316 wxCHECK_MSG( m_internal->GetId(), wxTHREAD_MISC_ERROR,
1317 wxT("must call wxThread::Create() first") );
1318
1319 return m_internal->Run();
1320 }
1321
1322 // -----------------------------------------------------------------------------
1323 // pause/resume
1324 // -----------------------------------------------------------------------------
1325
1326 wxThreadError wxThread::Pause()
1327 {
1328 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR,
1329 _T("a thread can't pause itself") );
1330
1331 wxCriticalSectionLocker lock(m_critsect);
1332
1333 if ( m_internal->GetState() != STATE_RUNNING )
1334 {
1335 wxLogDebug(wxT("Can't pause thread which is not running."));
1336
1337 return wxTHREAD_NOT_RUNNING;
1338 }
1339
1340 // just set a flag, the thread will be really paused only during the next
1341 // call to TestDestroy()
1342 m_internal->SetState(STATE_PAUSED);
1343
1344 return wxTHREAD_NO_ERROR;
1345 }
1346
1347 wxThreadError wxThread::Resume()
1348 {
1349 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR,
1350 _T("a thread can't resume itself") );
1351
1352 wxCriticalSectionLocker lock(m_critsect);
1353
1354 wxThreadState state = m_internal->GetState();
1355
1356 switch ( state )
1357 {
1358 case STATE_PAUSED:
1359 m_internal->Resume();
1360 return wxTHREAD_NO_ERROR;
1361 case STATE_EXITED:
1362 return wxTHREAD_NO_ERROR;
1363
1364 default:
1365 wxLogDebug(_T("Attempt to resume a thread which is not paused."));
1366
1367 return wxTHREAD_MISC_ERROR;
1368 }
1369 }
1370
1371 // -----------------------------------------------------------------------------
1372 // exiting thread
1373 // -----------------------------------------------------------------------------
1374
1375 wxThread::ExitCode wxThread::Wait()
1376 {
1377 wxCHECK_MSG( This() != this, (ExitCode)-1,
1378 _T("a thread can't wait for itself") );
1379
1380 wxCHECK_MSG( !m_isDetached, (ExitCode)-1,
1381 _T("can't wait for detached thread") );
1382
1383 m_internal->Wait();
1384
1385 return m_internal->GetExitCode();
1386 }
1387
1388 wxThreadError wxThread::Delete(ExitCode *rc)
1389 {
1390 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR,
1391 _T("a thread can't delete itself") );
1392
1393 bool isDetached = m_isDetached;
1394
1395 m_critsect.Enter();
1396 wxThreadState state = m_internal->GetState();
1397
1398 // ask the thread to stop
1399 m_internal->SetCancelFlag();
1400
1401 m_critsect.Leave();
1402
1403 switch ( state )
1404 {
1405 case STATE_NEW:
1406 // we need to wake up the thread so that PthreadStart() will
1407 // terminate - right now it's blocking on run semaphore in
1408 // PthreadStart()
1409 m_internal->SignalRun();
1410
1411 // fall through
1412
1413 case STATE_EXITED:
1414 // nothing to do
1415 break;
1416
1417 case STATE_PAUSED:
1418 // resume the thread first
1419 m_internal->Resume();
1420
1421 // fall through
1422
1423 default:
1424 if ( !isDetached )
1425 {
1426 // wait until the thread stops
1427 m_internal->Wait();
1428
1429 if ( rc )
1430 {
1431 // return the exit code of the thread
1432 *rc = m_internal->GetExitCode();
1433 }
1434 }
1435 }
1436
1437 return wxTHREAD_NO_ERROR;
1438 }
1439
1440 wxThreadError wxThread::Kill()
1441 {
1442 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR,
1443 _T("a thread can't kill itself") );
1444
1445 switch ( m_internal->GetState() )
1446 {
1447 case STATE_NEW:
1448 case STATE_EXITED:
1449 return wxTHREAD_NOT_RUNNING;
1450
1451 case STATE_PAUSED:
1452 // resume the thread first
1453 Resume();
1454
1455 // fall through
1456
1457 default:
1458 OSStatus err = MPTerminateTask( m_internal->GetId() , -1 ) ;
1459 if ( err )
1460 {
1461 wxLogError(_("Failed to terminate a thread."));
1462
1463 return wxTHREAD_MISC_ERROR;
1464 }
1465
1466 if ( m_isDetached )
1467 {
1468 delete this ;
1469 }
1470 else
1471 {
1472 // this should be retrieved by Wait actually
1473 m_internal->SetExitCode((void*)-1);
1474 }
1475
1476 return wxTHREAD_NO_ERROR;
1477 }
1478 }
1479
1480 void wxThread::Exit(ExitCode status)
1481 {
1482 wxASSERT_MSG( This() == this,
1483 _T("wxThread::Exit() can only be called in the context of the same thread") );
1484
1485 // don't enter m_critsect before calling OnExit() because the user code
1486 // might deadlock if, for example, it signals a condition in OnExit() (a
1487 // common case) while the main thread calls any of functions entering
1488 // m_critsect on us (almost all of them do)
1489 OnExit();
1490
1491 MPTaskID threadid = m_internal->GetId() ;
1492
1493 if ( IsDetached() )
1494 {
1495 delete this;
1496 }
1497 else // joinable
1498 {
1499 // update the status of the joinable thread
1500 wxCriticalSectionLocker lock(m_critsect);
1501 m_internal->SetState(STATE_EXITED);
1502 }
1503 MPTerminateTask( threadid , (long) status) ;
1504 }
1505
1506 // also test whether we were paused
1507 bool wxThread::TestDestroy()
1508 {
1509 wxASSERT_MSG( This() == this,
1510 _T("wxThread::TestDestroy() can only be called in the context of the same thread") );
1511
1512 m_critsect.Enter();
1513
1514 if ( m_internal->GetState() == STATE_PAUSED )
1515 {
1516 m_internal->SetReallyPaused(TRUE);
1517
1518 // leave the crit section or the other threads will stop too if they
1519 // try to call any of (seemingly harmless) IsXXX() functions while we
1520 // sleep
1521 m_critsect.Leave();
1522
1523 m_internal->Pause();
1524 }
1525 else
1526 {
1527 // thread wasn't requested to pause, nothing to do
1528 m_critsect.Leave();
1529 }
1530
1531 return m_internal->WasCancelled();
1532 }
1533
1534 // -----------------------------------------------------------------------------
1535 // priority setting
1536 // -----------------------------------------------------------------------------
1537
1538 void wxThread::SetPriority(unsigned int prio)
1539 {
1540 wxCHECK_RET( ((int)WXTHREAD_MIN_PRIORITY <= (int)prio) &&
1541 ((int)prio <= (int)WXTHREAD_MAX_PRIORITY),
1542 wxT("invalid thread priority") );
1543
1544 wxCriticalSectionLocker lock(m_critsect);
1545
1546 switch ( m_internal->GetState() )
1547 {
1548 case STATE_RUNNING:
1549 case STATE_PAUSED:
1550 case STATE_NEW:
1551 // thread not yet started, priority will be set when it is
1552 m_internal->SetPriority(prio);
1553 break;
1554
1555 case STATE_EXITED:
1556 default:
1557 wxFAIL_MSG(wxT("impossible to set thread priority in this state"));
1558 }
1559 }
1560
1561 unsigned int wxThread::GetPriority() const
1562 {
1563 wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect); // const_cast
1564
1565 return m_internal->GetPriority();
1566 }
1567
1568 unsigned long wxThread::GetId() const
1569 {
1570 wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect); // const_cast
1571
1572 return (unsigned long)m_internal->GetId();
1573 }
1574
1575 // -----------------------------------------------------------------------------
1576 // state tests
1577 // -----------------------------------------------------------------------------
1578
1579 bool wxThread::IsRunning() const
1580 {
1581 wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect);
1582
1583 return m_internal->GetState() == STATE_RUNNING;
1584 }
1585
1586 bool wxThread::IsAlive() const
1587 {
1588 wxCriticalSectionLocker lock((wxCriticalSection&)m_critsect);
1589
1590 switch ( m_internal->GetState() )
1591 {
1592 case STATE_RUNNING:
1593 case STATE_PAUSED:
1594 return TRUE;
1595
1596 default:
1597 return FALSE;
1598 }
1599 }
1600
1601 bool wxThread::IsPaused() const
1602 {
1603 wxCriticalSectionLocker lock((wxCriticalSection&)m_critsect);
1604
1605 return (m_internal->GetState() == STATE_PAUSED);
1606 }
1607
1608 // ----------------------------------------------------------------------------
1609 // Automatic initialization for thread module
1610 // ----------------------------------------------------------------------------
1611
1612 class wxThreadModule : public wxModule
1613 {
1614 public:
1615 virtual bool OnInit();
1616 virtual void OnExit();
1617
1618 private:
1619 DECLARE_DYNAMIC_CLASS(wxThreadModule)
1620 };
1621
1622 IMPLEMENT_DYNAMIC_CLASS(wxThreadModule, wxModule)
1623
1624 bool wxThreadModule::OnInit()
1625 {
1626 bool hasThreadManager = false ;
1627 hasThreadManager = MPLibraryIsLoaded();
1628
1629 if ( !hasThreadManager )
1630 {
1631 wxLogError( _("MP Thread Support is not available on this System" ) ) ;
1632 return FALSE ;
1633 }
1634
1635 verify_noerr( MPAllocateTaskStorageIndex( &gs_tlsForWXThread ) ) ;
1636 // main thread's This() is NULL
1637 verify_noerr( MPSetTaskStorageValue( gs_tlsForWXThread , 0 ) ) ;
1638
1639 gs_idMainThread = wxThread::GetCurrentId() ;
1640
1641 gs_critsectWaitingForGui = new wxCriticalSection();
1642
1643 gs_critsectGui = new wxCriticalSection();
1644 gs_critsectGui->Enter();
1645
1646 return TRUE;
1647 }
1648
1649 void wxThreadModule::OnExit()
1650 {
1651 if ( gs_critsectGui )
1652 {
1653 if ( !wxGuiOwnedByMainThread() )
1654 {
1655 gs_critsectGui->Enter();
1656 gs_bGuiOwnedByMainThread = true;
1657 }
1658 gs_critsectGui->Leave();
1659 delete gs_critsectGui;
1660 gs_critsectGui = NULL;
1661 }
1662
1663 delete gs_critsectWaitingForGui;
1664 gs_critsectWaitingForGui = NULL;
1665 }
1666
1667 // ----------------------------------------------------------------------------
1668 // GUI Serialization copied from MSW implementation
1669 // ----------------------------------------------------------------------------
1670
1671 void WXDLLIMPEXP_BASE wxMutexGuiEnter()
1672 {
1673 // this would dead lock everything...
1674 wxASSERT_MSG( !wxThread::IsMain(),
1675 wxT("main thread doesn't want to block in wxMutexGuiEnter()!") );
1676
1677 // the order in which we enter the critical sections here is crucial!!
1678
1679 // set the flag telling to the main thread that we want to do some GUI
1680 {
1681 wxCriticalSectionLocker enter(*gs_critsectWaitingForGui);
1682
1683 gs_nWaitingForGui++;
1684 }
1685
1686 wxWakeUpMainThread();
1687
1688 // now we may block here because the main thread will soon let us in
1689 // (during the next iteration of OnIdle())
1690 gs_critsectGui->Enter();
1691 }
1692
1693 void WXDLLIMPEXP_BASE wxMutexGuiLeave()
1694 {
1695 wxCriticalSectionLocker enter(*gs_critsectWaitingForGui);
1696
1697 if ( wxThread::IsMain() )
1698 {
1699 gs_bGuiOwnedByMainThread = false;
1700 }
1701 else
1702 {
1703 // decrement the number of threads waiting for GUI access now
1704 wxASSERT_MSG( gs_nWaitingForGui > 0,
1705 wxT("calling wxMutexGuiLeave() without entering it first?") );
1706
1707 gs_nWaitingForGui--;
1708
1709 wxWakeUpMainThread();
1710 }
1711
1712 gs_critsectGui->Leave();
1713 }
1714
1715 void WXDLLIMPEXP_BASE wxMutexGuiLeaveOrEnter()
1716 {
1717 wxASSERT_MSG( wxThread::IsMain(),
1718 wxT("only main thread may call wxMutexGuiLeaveOrEnter()!") );
1719
1720 if( !gs_critsectWaitingForGui )
1721 return;
1722
1723 wxCriticalSectionLocker enter(*gs_critsectWaitingForGui);
1724
1725 if ( gs_nWaitingForGui == 0 )
1726 {
1727 // no threads are waiting for GUI - so we may acquire the lock without
1728 // any danger (but only if we don't already have it)
1729 if ( !wxGuiOwnedByMainThread() )
1730 {
1731 gs_critsectGui->Enter();
1732
1733 gs_bGuiOwnedByMainThread = true;
1734 }
1735 //else: already have it, nothing to do
1736 }
1737 else
1738 {
1739 // some threads are waiting, release the GUI lock if we have it
1740 if ( wxGuiOwnedByMainThread() )
1741 {
1742 wxMutexGuiLeave();
1743 }
1744 //else: some other worker thread is doing GUI
1745 }
1746 }
1747
1748 bool WXDLLIMPEXP_BASE wxGuiOwnedByMainThread()
1749 {
1750 return gs_bGuiOwnedByMainThread;
1751 }
1752
1753 // wake up the main thread
1754 void WXDLLEXPORT wxWakeUpMainThread()
1755 {
1756 wxMacWakeUp() ;
1757 }
1758
1759 // ----------------------------------------------------------------------------
1760 // include common implementation code
1761 // ----------------------------------------------------------------------------
1762
1763 #include "wx/thrimpl.cpp"
1764
1765 #endif // wxUSE_THREADS