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