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