]> git.saurik.com Git - wxWidgets.git/blob - src/mac/carbon/thread.cpp
Don't call SetItemCmd for WXK_UP or WXK_RIGHT since these values
[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 0
134 #define wxUSE_MAC_PTHREADS_MUTEX 1
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 }
351
352 wxMutexError wxMutexInternal::Lock()
353 {
354 wxCHECK_MSG( m_isOk , wxMUTEX_MISC_ERROR , wxT("Invalid Mutex") ) ;
355 OSStatus err = MPWaitOnSemaphore( m_semaphore, kDurationForever);
356 if ( err)
357 {
358 wxLogSysError(wxT("Could not lock mutex"));
359 return wxMUTEX_MISC_ERROR;
360 }
361
362 return wxMUTEX_NO_ERROR;
363 }
364
365 wxMutexError wxMutexInternal::TryLock()
366 {
367 wxCHECK_MSG( m_isOk , wxMUTEX_MISC_ERROR , wxT("Invalid Mutex") ) ;
368 OSStatus err = MPWaitOnSemaphore( m_semaphore, kDurationImmediate);
369 if ( err)
370 {
371 if ( err == kMPTimeoutErr)
372 {
373 return wxMUTEX_BUSY;
374 }
375 wxLogSysError(wxT("Could not try lock mutex"));
376 return wxMUTEX_MISC_ERROR;
377 }
378
379 return wxMUTEX_NO_ERROR;
380 }
381
382 wxMutexError wxMutexInternal::Unlock()
383 {
384 wxCHECK_MSG( m_isOk , wxMUTEX_MISC_ERROR , wxT("Invalid Mutex") ) ;
385 OSStatus err = MPSignalSemaphore( m_semaphore);
386 if ( err)
387 {
388 wxLogSysError(_("Could not unlock mutex"));
389 return wxMUTEX_MISC_ERROR;
390 }
391
392 return wxMUTEX_NO_ERROR;
393 }
394
395 #endif
396
397 #if wxUSE_MAC_CRITICAL_REGION_MUTEX
398
399 class wxMutexInternal
400 {
401 public:
402 wxMutexInternal(wxMutexType mutexType) ;
403 ~wxMutexInternal() ;
404 bool IsOk() const { return m_isOk; }
405
406 wxMutexError Lock() ;
407 wxMutexError TryLock() ;
408 wxMutexError Unlock();
409 private:
410 MPCriticalRegionID m_critRegion ;
411 bool m_isOk ;
412 };
413
414 wxMutexInternal::wxMutexInternal(wxMutexType mutexType )
415 {
416 m_isOk = false ;
417 m_critRegion = kInvalidID ;
418
419 verify_noerr( MPCreateCriticalRegion( & m_critRegion) );
420 m_isOk = ( m_critRegion != kInvalidID ) ;
421
422 if ( !IsOk() )
423 wxFAIL_MSG(wxT("Error when creating mutex") ) ;
424 }
425
426 wxMutexInternal::~wxMutexInternal()
427 {
428 if ( m_critRegion != kInvalidID )
429 MPDeleteCriticalRegion( m_critRegion);
430 }
431
432 wxMutexError wxMutexInternal::Lock()
433 {
434 wxCHECK_MSG( m_isOk , wxMUTEX_MISC_ERROR , wxT("Invalid Mutex") ) ;
435 OSStatus err = MPEnterCriticalRegion( m_critRegion, kDurationForever);
436 if ( err)
437 {
438 wxLogSysError(wxT("Could not lock mutex"));
439 return wxMUTEX_MISC_ERROR;
440 }
441
442 return wxMUTEX_NO_ERROR;
443 }
444
445 wxMutexError wxMutexInternal::TryLock()
446 {
447 wxCHECK_MSG( m_isOk , wxMUTEX_MISC_ERROR , wxT("Invalid Mutex") ) ;
448 OSStatus err = MPEnterCriticalRegion( m_critRegion, kDurationImmediate);
449 if ( err)
450 {
451 if ( err == kMPTimeoutErr)
452 {
453 return wxMUTEX_BUSY;
454 }
455 wxLogSysError(wxT("Could not try lock mutex"));
456 return wxMUTEX_MISC_ERROR;
457 }
458
459 return wxMUTEX_NO_ERROR;
460 }
461
462 wxMutexError wxMutexInternal::Unlock()
463 {
464 wxCHECK_MSG( m_isOk , wxMUTEX_MISC_ERROR , wxT("Invalid Mutex") ) ;
465 OSStatus err = MPExitCriticalRegion( m_critRegion);
466 if ( err)
467 {
468 wxLogSysError(_("Could not unlock mutex"));
469 return wxMUTEX_MISC_ERROR;
470 }
471
472 return wxMUTEX_NO_ERROR;
473 }
474
475 #endif
476
477 // --------------------------------------------------------------------------
478 // wxSemaphore
479 // --------------------------------------------------------------------------
480
481 class wxSemaphoreInternal
482 {
483 public:
484 wxSemaphoreInternal(int initialcount, int maxcount);
485 ~wxSemaphoreInternal();
486
487 bool IsOk() const { return m_isOk; }
488
489 wxSemaError WaitTimeout(unsigned long milliseconds);
490
491 wxSemaError Wait() { return WaitTimeout( kDurationForever); }
492
493 wxSemaError TryWait()
494 {
495 wxSemaError err = WaitTimeout(kDurationImmediate);
496 if ( err == wxSEMA_TIMEOUT )
497 err = wxSEMA_BUSY ;
498 return err ;
499 }
500 wxSemaError Post();
501
502 private:
503 MPSemaphoreID m_semaphore;
504 bool m_isOk ;
505 };
506
507 wxSemaphoreInternal::wxSemaphoreInternal(int initialcount, int maxcount)
508 {
509 m_isOk = false ;
510 m_semaphore = kInvalidID ;
511 if ( maxcount == 0 )
512 {
513 // make it practically infinite
514 maxcount = INT_MAX;
515 }
516 verify_noerr( MPCreateSemaphore( maxcount, initialcount, & m_semaphore) );
517 m_isOk = ( m_semaphore != kInvalidID ) ;
518
519 if ( !IsOk() )
520 wxFAIL_MSG(wxT("Error when creating semaphore") ) ;
521 }
522
523 wxSemaphoreInternal::~wxSemaphoreInternal()
524 {
525 if( m_semaphore != kInvalidID )
526 MPDeleteSemaphore( m_semaphore);
527 }
528
529 wxSemaError wxSemaphoreInternal::WaitTimeout(unsigned long milliseconds)
530 {
531 OSStatus err = MPWaitOnSemaphore( m_semaphore, milliseconds);
532 if ( err)
533 {
534 if ( err == kMPTimeoutErr)
535 {
536 return wxSEMA_TIMEOUT;
537 }
538 return wxSEMA_MISC_ERROR;
539 }
540 return wxSEMA_NO_ERROR;
541 }
542
543 wxSemaError wxSemaphoreInternal::Post()
544 {
545 OSStatus err = MPSignalSemaphore( m_semaphore);
546 if ( err)
547 {
548 return wxSEMA_MISC_ERROR;
549 }
550 return wxSEMA_NO_ERROR;
551 }
552
553 // ----------------------------------------------------------------------------
554 // wxCondition implementation
555 // ----------------------------------------------------------------------------
556
557 #if 0
558
559 class wxConditionInternal
560 {
561 public:
562
563 wxConditionInternal(wxMutex& mutex)
564 : m_mutex( mutex),
565 m_semaphore( 0, 1),
566 m_gate( 1, 1)
567 {
568 m_waiters = 0;
569 m_signals = 0;
570 m_canceled = 0;
571 }
572
573 ~wxConditionInternal()
574 {
575 }
576
577 bool IsOk() const { return m_mutex.IsOk() ; }
578
579 wxCondError Wait()
580 {
581 return WaitTimeout( kDurationForever);
582 }
583
584 wxCondError WaitTimeout(unsigned long msectimeout);
585
586 wxCondError Signal()
587 {
588 return DoSignal( false);
589 }
590
591 wxCondError Broadcast()
592 {
593 return DoSignal( true);
594 }
595
596 private:
597
598 wxCondError DoSignal( bool signalAll);
599
600 wxMutex& m_mutex;
601 wxSemaphoreInternal m_semaphore; // Signals the waiting threads.
602 wxSemaphoreInternal m_gate;
603 wxCriticalSection m_varSection;
604 size_t m_waiters; // Number of threads waiting for a signal.
605 size_t m_signals; // Number of signals to send.
606 size_t m_canceled; // Number of canceled waiters in m_waiters.
607 };
608
609
610 wxCondError wxConditionInternal::WaitTimeout(unsigned long msectimeout)
611 {
612 m_gate.Wait();
613 if ( ++ m_waiters == INT_MAX)
614 {
615 m_varSection.Enter();
616 m_waiters -= m_canceled;
617 m_signals -= m_canceled;
618 m_canceled = 0;
619 m_varSection.Leave();
620 }
621 m_gate.Post();
622
623 m_mutex.Unlock();
624
625 wxSemaError err = m_semaphore.WaitTimeout( msectimeout);
626 wxASSERT( err == wxSEMA_NO_ERROR || err == wxSEMA_TIMEOUT);
627
628 m_varSection.Enter();
629 if ( err != wxSEMA_NO_ERROR)
630 {
631 if ( m_signals > m_canceled)
632 {
633 // A signal is being sent after we timed out.
634
635 if ( m_waiters == m_signals)
636 {
637 // There are no excess waiters to catch the signal, so
638 // we must throw it away.
639
640 wxSemaError err2 = m_semaphore.Wait();
641 if ( err2 != wxSEMA_NO_ERROR)
642 {
643 wxLogSysError(_("Error while waiting on semaphore"));
644 }
645 wxASSERT( err2 == wxSEMA_NO_ERROR);
646 -- m_waiters;
647 if ( -- m_signals == m_canceled)
648 {
649 // This was the last signal. open the gate.
650 wxASSERT( m_waiters == m_canceled);
651 m_gate.Post();
652 }
653 }
654 else
655 {
656 // There are excess waiters to catch the signal, leave
657 // it be.
658 -- m_waiters;
659 }
660 }
661 else
662 {
663 // No signals is being sent.
664 // The gate may be open or closed, so we can't touch m_waiters.
665 ++ m_canceled;
666 ++ m_signals;
667 }
668 }
669 else
670 {
671 // We caught a signal.
672 wxASSERT( m_signals > m_canceled);
673 -- m_waiters;
674 if ( -- m_signals == m_canceled)
675 {
676 // This was the last signal. open the gate.
677 wxASSERT( m_waiters == m_canceled);
678 m_gate.Post();
679 }
680 }
681 m_varSection.Leave();
682
683 m_mutex.Lock();
684
685 if ( err)
686 {
687 return err == wxSEMA_TIMEOUT ? wxCOND_TIMEOUT : wxCOND_MISC_ERROR;
688 }
689
690 return wxCOND_NO_ERROR;
691 }
692
693
694 wxCondError wxConditionInternal::DoSignal( bool signalAll)
695 {
696 m_gate.Wait();
697 m_varSection.Enter();
698
699 wxASSERT( m_signals == m_canceled);
700
701 if ( m_waiters == m_canceled)
702 {
703 m_varSection.Leave();
704 m_gate.Post();
705 return wxCOND_NO_ERROR;
706 }
707
708 if ( m_canceled > 0)
709 {
710 m_waiters -= m_canceled;
711 m_signals = 0;
712 m_canceled = 0;
713 }
714
715 m_signals = signalAll ? m_waiters : 1;
716 size_t n = m_signals;
717
718 m_varSection.Leave();
719
720 // Let the waiters inherit the gate lock.
721
722 do
723 {
724 wxSemaError err = m_semaphore.Post();
725 wxASSERT( err == wxSEMA_NO_ERROR);
726 } while ( -- n);
727
728 return wxCOND_NO_ERROR;
729 }
730
731 #else
732 class wxConditionInternal
733 {
734 public:
735 wxConditionInternal(wxMutex& mutex);
736
737 bool IsOk() const { return m_mutex.IsOk() && m_semaphore.IsOk(); }
738
739 wxCondError Wait();
740 wxCondError WaitTimeout(unsigned long milliseconds);
741
742 wxCondError Signal();
743 wxCondError Broadcast();
744
745 private:
746 // the number of threads currently waiting for this condition
747 SInt32 m_numWaiters;
748
749 // the critical section protecting m_numWaiters
750 wxCriticalSection m_csWaiters;
751
752 wxMutex& m_mutex;
753 wxSemaphore m_semaphore;
754
755 DECLARE_NO_COPY_CLASS(wxConditionInternal)
756 };
757
758 wxConditionInternal::wxConditionInternal(wxMutex& mutex)
759 : m_mutex(mutex)
760 {
761 // another thread can't access it until we return from ctor, so no need to
762 // protect access to m_numWaiters here
763 m_numWaiters = 0;
764 }
765
766 wxCondError wxConditionInternal::Wait()
767 {
768 // increment the number of waiters
769 IncrementAtomic(&m_numWaiters);
770
771 m_mutex.Unlock();
772
773 // a potential race condition can occur here
774 //
775 // after a thread increments nwaiters, and unlocks the mutex and before the
776 // semaphore.Wait() is called, if another thread can cause a signal to be
777 // generated
778 //
779 // this race condition is handled by using a semaphore and incrementing the
780 // semaphore only if 'nwaiters' is greater that zero since the semaphore,
781 // can 'remember' signals the race condition will not occur
782
783 // wait ( if necessary ) and decrement semaphore
784 wxSemaError err = m_semaphore.Wait();
785 m_mutex.Lock();
786
787 return err == wxSEMA_NO_ERROR ? wxCOND_NO_ERROR : wxCOND_MISC_ERROR;
788 }
789
790 wxCondError wxConditionInternal::WaitTimeout(unsigned long milliseconds)
791 {
792 IncrementAtomic(&m_numWaiters);
793
794 m_mutex.Unlock();
795
796 // a race condition can occur at this point in the code
797 //
798 // please see the comments in Wait(), for details
799
800 wxSemaError err = m_semaphore.WaitTimeout(milliseconds);
801
802 if ( err == wxSEMA_BUSY )
803 {
804 // another potential race condition exists here it is caused when a
805 // 'waiting' thread timesout, and returns from WaitForSingleObject, but
806 // has not yet decremented 'nwaiters'.
807 //
808 // at this point if another thread calls signal() then the semaphore
809 // will be incremented, but the waiting thread will miss it.
810 //
811 // to handle this particular case, the waiting thread calls
812 // WaitForSingleObject again with a timeout of 0, after locking
813 // 'nwaiters_mutex'. this call does not block because of the zero
814 // timeout, but will allow the waiting thread to catch the missed
815 // signals.
816 wxCriticalSectionLocker lock(m_csWaiters);
817
818 err = m_semaphore.WaitTimeout(0);
819
820 if ( err != wxSEMA_NO_ERROR )
821 {
822 m_numWaiters--;
823 }
824 }
825
826 m_mutex.Lock();
827
828 return err == wxSEMA_NO_ERROR ? wxCOND_NO_ERROR : wxCOND_MISC_ERROR;
829 }
830
831 wxCondError wxConditionInternal::Signal()
832 {
833 wxCriticalSectionLocker lock(m_csWaiters);
834
835 if ( m_numWaiters > 0 )
836 {
837 // increment the semaphore by 1
838 if ( m_semaphore.Post() != wxSEMA_NO_ERROR )
839 return wxCOND_MISC_ERROR;
840
841 m_numWaiters--;
842 }
843
844 return wxCOND_NO_ERROR;
845 }
846
847 wxCondError wxConditionInternal::Broadcast()
848 {
849 wxCriticalSectionLocker lock(m_csWaiters);
850
851 while ( m_numWaiters > 0 )
852 {
853 if ( m_semaphore.Post() != wxSEMA_NO_ERROR )
854 return wxCOND_MISC_ERROR;
855
856 m_numWaiters--;
857 }
858
859 return wxCOND_NO_ERROR;
860 }
861 #endif
862
863 // ----------------------------------------------------------------------------
864 // wxCriticalSection implementation
865 // ----------------------------------------------------------------------------
866
867 // XXX currently implemented as mutex in headers. Change to critical section.
868
869 // ----------------------------------------------------------------------------
870 // wxThread implementation
871 // ----------------------------------------------------------------------------
872
873 // wxThreadInternal class
874 // ----------------------
875
876 class wxThreadInternal
877 {
878 public:
879 wxThreadInternal()
880 {
881 m_tid = kInvalidID;
882 m_state = STATE_NEW;
883 m_prio = WXTHREAD_DEFAULT_PRIORITY;
884 m_notifyQueueId = kInvalidID;
885 m_exitcode = 0;
886 m_cancelled = FALSE ;
887
888 // set to TRUE only when the thread starts waiting on m_semSuspend
889 m_isPaused = FALSE;
890
891 // defaults for joinable threads
892 m_shouldBeJoined = TRUE;
893 m_isDetached = FALSE;
894 }
895 ~wxThreadInternal()
896 {
897 if ( m_notifyQueueId)
898 {
899 MPDeleteQueue( m_notifyQueueId);
900 m_notifyQueueId = kInvalidID ;
901 }
902 }
903
904 // thread function
905 static OSStatus MacThreadStart(void* arg);
906
907 // create a new (suspended) thread (for the given thread object)
908 bool Create(wxThread *thread, unsigned int stackSize);
909
910 // thread actions
911 // start the thread
912 wxThreadError Run();
913 // unblock the thread allowing it to run
914 void SignalRun() { m_semRun.Post(); }
915 // ask the thread to terminate
916 void Wait();
917 // go to sleep until Resume() is called
918 void Pause();
919 // resume the thread
920 void Resume();
921
922 // accessors
923 // priority
924 int GetPriority() const { return m_prio; }
925 void SetPriority(int prio) ;
926 // state
927 wxThreadState GetState() const { return m_state; }
928 void SetState(wxThreadState state) { m_state = state; }
929
930 // Get the ID of this thread's underlying MP Services task.
931 MPTaskID GetId() const { return m_tid; }
932
933 void SetCancelFlag() { m_cancelled = TRUE; }
934 bool WasCancelled() const { return m_cancelled; }
935 // exit code
936 void SetExitCode(wxThread::ExitCode exitcode) { m_exitcode = exitcode; }
937 wxThread::ExitCode GetExitCode() const { return m_exitcode; }
938
939 // the pause flag
940 void SetReallyPaused(bool paused) { m_isPaused = paused; }
941 bool IsReallyPaused() const { return m_isPaused; }
942
943 // tell the thread that it is a detached one
944 void Detach()
945 {
946 wxCriticalSectionLocker lock(m_csJoinFlag);
947
948 m_shouldBeJoined = FALSE;
949 m_isDetached = TRUE;
950 }
951
952 private:
953 // the thread we're associated with
954 wxThread * m_thread;
955
956 MPTaskID m_tid; // thread id
957 MPQueueID m_notifyQueueId; // its notification queue
958
959 wxThreadState m_state; // see wxThreadState enum
960 int m_prio; // in wxWindows units: from 0 to 100
961
962 // this flag is set when the thread should terminate
963 bool m_cancelled;
964
965 // this flag is set when the thread is blocking on m_semSuspend
966 bool m_isPaused;
967
968 // the thread exit code - only used for joinable (!detached) threads and
969 // is only valid after the thread termination
970 wxThread::ExitCode m_exitcode;
971
972 // many threads may call Wait(), but only one of them should call
973 // pthread_join(), so we have to keep track of this
974 wxCriticalSection m_csJoinFlag;
975 bool m_shouldBeJoined;
976 bool m_isDetached;
977
978 // this semaphore is posted by Run() and the threads Entry() is not
979 // called before it is done
980 wxSemaphore m_semRun;
981
982 // this one is signaled when the thread should resume after having been
983 // Pause()d
984 wxSemaphore m_semSuspend;
985 };
986
987 OSStatus wxThreadInternal::MacThreadStart(void *parameter)
988 {
989 wxThread* thread = (wxThread*) parameter ;
990 wxThreadInternal *pthread = thread->m_internal;
991
992 // add to TLS so that This() will work
993 verify_noerr( MPSetTaskStorageValue( gs_tlsForWXThread , (long) thread ) ) ;
994
995 // have to declare this before pthread_cleanup_push() which defines a
996 // block!
997 bool dontRunAtAll;
998
999 // wait for the semaphore to be posted from Run()
1000 pthread->m_semRun.Wait();
1001
1002 // test whether we should run the run at all - may be it was deleted
1003 // before it started to Run()?
1004 {
1005 wxCriticalSectionLocker lock(thread->m_critsect);
1006
1007 dontRunAtAll = pthread->GetState() == STATE_NEW &&
1008 pthread->WasCancelled();
1009 }
1010
1011 if ( !dontRunAtAll )
1012 {
1013 pthread->m_exitcode = thread->Entry();
1014
1015 {
1016 wxCriticalSectionLocker lock(thread->m_critsect);
1017 pthread->SetState(STATE_EXITED);
1018 }
1019 }
1020
1021 if ( dontRunAtAll )
1022 {
1023 if ( pthread->m_isDetached )
1024 delete thread;
1025
1026 return -1 ;
1027 }
1028 else
1029 {
1030 // on mac for the running code the correct thread termination is to
1031 // return
1032
1033 // terminate the thread
1034 thread->Exit(pthread->m_exitcode);
1035
1036 return (OSStatus) NULL ; // pthread->m_exitcode;
1037 }
1038 }
1039
1040 bool wxThreadInternal::Create(wxThread *thread, unsigned int stackSize)
1041 {
1042 wxASSERT_MSG( m_state == STATE_NEW && !m_tid,
1043 _T("Create()ing thread twice?") );
1044
1045 OSStatus err = noErr ;
1046 m_thread = thread;
1047
1048 if ( m_notifyQueueId == kInvalidID )
1049 {
1050 OSStatus err = MPCreateQueue( & m_notifyQueueId);
1051 if( err)
1052 {
1053 wxLogSysError(_("Cant create the thread event queue"));
1054 return false;
1055 }
1056 }
1057
1058 m_state = STATE_NEW;
1059
1060 err = MPCreateTask( MacThreadStart,
1061 (void*) m_thread,
1062 stackSize,
1063 m_notifyQueueId,
1064 &m_exitcode,
1065 0,
1066 0,
1067 &m_tid);
1068
1069 if ( err)
1070 {
1071 wxLogSysError(_("Can't create thread"));
1072 return false;
1073 }
1074
1075 if ( m_prio != WXTHREAD_DEFAULT_PRIORITY )
1076 {
1077 SetPriority(m_prio);
1078 }
1079
1080 return true;
1081 }
1082
1083 void wxThreadInternal::SetPriority( int priority)
1084 {
1085 m_prio = priority;
1086
1087 if ( m_tid)
1088 {
1089 // Mac priorities range from 1 to 10,000, with a default of 100.
1090 // wxWindows priorities range from 0 to 100 with a default of 50.
1091 // We can map wxWindows to Mac priorities easily by assuming
1092 // the former uses a logarithmic scale.
1093 const unsigned int macPriority = ( int)( exp( priority / 25.0 * log( 10.0)) + 0.5);
1094
1095 MPSetTaskWeight( m_tid, macPriority);
1096 }
1097 }
1098
1099 wxThreadError wxThreadInternal::Run()
1100 {
1101 wxCHECK_MSG( GetState() == STATE_NEW, wxTHREAD_RUNNING,
1102 wxT("thread may only be started once after Create()") );
1103
1104 SetState(STATE_RUNNING);
1105
1106 // wake up threads waiting for our start
1107 SignalRun();
1108
1109 return wxTHREAD_NO_ERROR;
1110 }
1111
1112 void wxThreadInternal::Wait()
1113 {
1114 wxCHECK_RET( !m_isDetached, _T("can't wait for a detached thread") );
1115
1116 // if the thread we're waiting for is waiting for the GUI mutex, we will
1117 // deadlock so make sure we release it temporarily
1118 if ( wxThread::IsMain() )
1119 wxMutexGuiLeave();
1120
1121 {
1122 wxCriticalSectionLocker lock(m_csJoinFlag);
1123
1124 if ( m_shouldBeJoined )
1125 {
1126 void * param1;
1127 void * param2;
1128 void * rc;
1129
1130 OSStatus err = MPWaitOnQueue ( m_notifyQueueId,
1131 & param1,
1132 & param2,
1133 & rc,
1134 kDurationForever);
1135 if ( err)
1136 {
1137 wxLogSysError( _( "Cannot wait on thread to exit."));
1138 rc = (void*) -1;
1139 }
1140
1141 // actually param1 would be the address of m_exitcode
1142 // but we don't need this here
1143 m_exitcode = rc;
1144
1145 m_shouldBeJoined = FALSE;
1146 }
1147 }
1148
1149 // reacquire GUI mutex
1150 if ( wxThread::IsMain() )
1151 wxMutexGuiEnter();
1152 }
1153
1154 void wxThreadInternal::Pause()
1155 {
1156 // the state is set from the thread which pauses us first, this function
1157 // is called later so the state should have been already set
1158 wxCHECK_RET( m_state == STATE_PAUSED,
1159 wxT("thread must first be paused with wxThread::Pause().") );
1160
1161 // wait until the semaphore is Post()ed from Resume()
1162 m_semSuspend.Wait();
1163 }
1164
1165 void wxThreadInternal::Resume()
1166 {
1167 wxCHECK_RET( m_state == STATE_PAUSED,
1168 wxT("can't resume thread which is not suspended.") );
1169
1170 // the thread might be not actually paused yet - if there were no call to
1171 // TestDestroy() since the last call to Pause() for example
1172 if ( IsReallyPaused() )
1173 {
1174 // wake up Pause()
1175 m_semSuspend.Post();
1176
1177 // reset the flag
1178 SetReallyPaused(FALSE);
1179 }
1180
1181 SetState(STATE_RUNNING);
1182 }
1183
1184 // static functions
1185 // ----------------
1186
1187 wxThread *wxThread::This()
1188 {
1189 wxThread* thr = (wxThread*) MPGetTaskStorageValue( gs_tlsForWXThread ) ;
1190 return thr;
1191 }
1192
1193 bool wxThread::IsMain()
1194 {
1195 return GetCurrentId() == gs_idMainThread;
1196 }
1197
1198 #ifdef Yield
1199 #undef Yield
1200 #endif
1201
1202 void wxThread::Yield()
1203 {
1204 #if TARGET_API_MAC_OSX
1205 CFRunLoopRunInMode( kCFRunLoopDefaultMode , 0 , true ) ;
1206 #endif
1207 MPYield();
1208 }
1209
1210
1211 void wxThread::Sleep(unsigned long milliseconds)
1212 {
1213 AbsoluteTime wakeup = AddDurationToAbsolute( milliseconds, UpTime());
1214 MPDelayUntil( & wakeup);
1215 }
1216
1217
1218 int wxThread::GetCPUCount()
1219 {
1220 return MPProcessors();
1221 }
1222
1223 unsigned long wxThread::GetCurrentId()
1224 {
1225 return (unsigned long)MPCurrentTaskID();
1226 }
1227
1228
1229 bool wxThread::SetConcurrency(size_t level)
1230 {
1231 // Cannot be set in MacOS.
1232 return false;
1233 }
1234
1235
1236 wxThread::wxThread(wxThreadKind kind)
1237 {
1238 g_numberOfThreads++;
1239 m_internal = new wxThreadInternal();
1240
1241 m_isDetached = (kind == wxTHREAD_DETACHED);
1242 }
1243
1244 wxThread::~wxThread()
1245 {
1246 wxASSERT_MSG( g_numberOfThreads>0 , wxT("More threads deleted than created.") ) ;
1247 g_numberOfThreads--;
1248
1249 #ifdef __WXDEBUG__
1250 m_critsect.Enter();
1251
1252 // check that the thread either exited or couldn't be created
1253 if ( m_internal->GetState() != STATE_EXITED &&
1254 m_internal->GetState() != STATE_NEW )
1255 {
1256 wxLogDebug(_T("The thread %ld is being destroyed although it is still running! The application may crash."), GetId());
1257 }
1258
1259 m_critsect.Leave();
1260 #endif // __WXDEBUG__
1261
1262 wxDELETE( m_internal ) ;
1263 }
1264
1265
1266 wxThreadError wxThread::Create(unsigned int stackSize)
1267 {
1268 wxCriticalSectionLocker lock(m_critsect);
1269
1270 if ( m_isDetached )
1271 {
1272 m_internal->Detach() ;
1273 }
1274 if ( m_internal->Create(this, stackSize) == false )
1275 {
1276 m_internal->SetState(STATE_EXITED);
1277 return wxTHREAD_NO_RESOURCE;
1278 }
1279
1280 return wxTHREAD_NO_ERROR;
1281 }
1282
1283 wxThreadError wxThread::Run()
1284 {
1285 wxCriticalSectionLocker lock(m_critsect);
1286
1287 wxCHECK_MSG( m_internal->GetId(), wxTHREAD_MISC_ERROR,
1288 wxT("must call wxThread::Create() first") );
1289
1290 return m_internal->Run();
1291 }
1292
1293 // -----------------------------------------------------------------------------
1294 // pause/resume
1295 // -----------------------------------------------------------------------------
1296
1297 wxThreadError wxThread::Pause()
1298 {
1299 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR,
1300 _T("a thread can't pause itself") );
1301
1302 wxCriticalSectionLocker lock(m_critsect);
1303
1304 if ( m_internal->GetState() != STATE_RUNNING )
1305 {
1306 wxLogDebug(wxT("Can't pause thread which is not running."));
1307
1308 return wxTHREAD_NOT_RUNNING;
1309 }
1310
1311 // just set a flag, the thread will be really paused only during the next
1312 // call to TestDestroy()
1313 m_internal->SetState(STATE_PAUSED);
1314
1315 return wxTHREAD_NO_ERROR;
1316 }
1317
1318 wxThreadError wxThread::Resume()
1319 {
1320 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR,
1321 _T("a thread can't resume itself") );
1322
1323 wxCriticalSectionLocker lock(m_critsect);
1324
1325 wxThreadState state = m_internal->GetState();
1326
1327 switch ( state )
1328 {
1329 case STATE_PAUSED:
1330 m_internal->Resume();
1331 return wxTHREAD_NO_ERROR;
1332 case STATE_EXITED:
1333 return wxTHREAD_NO_ERROR;
1334
1335 default:
1336 wxLogDebug(_T("Attempt to resume a thread which is not paused."));
1337
1338 return wxTHREAD_MISC_ERROR;
1339 }
1340 }
1341
1342 // -----------------------------------------------------------------------------
1343 // exiting thread
1344 // -----------------------------------------------------------------------------
1345
1346 wxThread::ExitCode wxThread::Wait()
1347 {
1348 wxCHECK_MSG( This() != this, (ExitCode)-1,
1349 _T("a thread can't wait for itself") );
1350
1351 wxCHECK_MSG( !m_isDetached, (ExitCode)-1,
1352 _T("can't wait for detached thread") );
1353
1354 m_internal->Wait();
1355
1356 return m_internal->GetExitCode();
1357 }
1358
1359 wxThreadError wxThread::Delete(ExitCode *rc)
1360 {
1361 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR,
1362 _T("a thread can't delete itself") );
1363
1364 bool isDetached = m_isDetached;
1365
1366 m_critsect.Enter();
1367 wxThreadState state = m_internal->GetState();
1368
1369 // ask the thread to stop
1370 m_internal->SetCancelFlag();
1371
1372 m_critsect.Leave();
1373
1374 switch ( state )
1375 {
1376 case STATE_NEW:
1377 // we need to wake up the thread so that PthreadStart() will
1378 // terminate - right now it's blocking on run semaphore in
1379 // PthreadStart()
1380 m_internal->SignalRun();
1381
1382 // fall through
1383
1384 case STATE_EXITED:
1385 // nothing to do
1386 break;
1387
1388 case STATE_PAUSED:
1389 // resume the thread first
1390 m_internal->Resume();
1391
1392 // fall through
1393
1394 default:
1395 if ( !isDetached )
1396 {
1397 // wait until the thread stops
1398 m_internal->Wait();
1399
1400 if ( rc )
1401 {
1402 // return the exit code of the thread
1403 *rc = m_internal->GetExitCode();
1404 }
1405 }
1406 //else: can't wait for detached threads
1407 }
1408
1409 return wxTHREAD_NO_ERROR;
1410 }
1411
1412 wxThreadError wxThread::Kill()
1413 {
1414 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR,
1415 _T("a thread can't kill itself") );
1416
1417 switch ( m_internal->GetState() )
1418 {
1419 case STATE_NEW:
1420 case STATE_EXITED:
1421 return wxTHREAD_NOT_RUNNING;
1422
1423 case STATE_PAUSED:
1424 // resume the thread first
1425 Resume();
1426
1427 // fall through
1428
1429 default:
1430 OSStatus err = MPTerminateTask( m_internal->GetId() , -1 ) ;
1431 if ( err )
1432 {
1433 wxLogError(_("Failed to terminate a thread."));
1434
1435 return wxTHREAD_MISC_ERROR;
1436 }
1437
1438 if ( m_isDetached )
1439 {
1440 delete this ;
1441 }
1442 else
1443 {
1444 // this should be retrieved by Wait actually
1445 m_internal->SetExitCode((void*)-1);
1446 }
1447
1448 return wxTHREAD_NO_ERROR;
1449 }
1450 }
1451
1452 void wxThread::Exit(ExitCode status)
1453 {
1454 wxASSERT_MSG( This() == this,
1455 _T("wxThread::Exit() can only be called in the context of the same thread") );
1456
1457 // don't enter m_critsect before calling OnExit() because the user code
1458 // might deadlock if, for example, it signals a condition in OnExit() (a
1459 // common case) while the main thread calls any of functions entering
1460 // m_critsect on us (almost all of them do)
1461 OnExit();
1462
1463 MPTerminateTask( m_internal->GetId() , (long) status) ;
1464
1465 if ( IsDetached() )
1466 {
1467 delete this;
1468 }
1469 else // joinable
1470 {
1471 // update the status of the joinable thread
1472 wxCriticalSectionLocker lock(m_critsect);
1473 m_internal->SetState(STATE_EXITED);
1474 }
1475 }
1476
1477 // also test whether we were paused
1478 bool wxThread::TestDestroy()
1479 {
1480 wxASSERT_MSG( This() == this,
1481 _T("wxThread::TestDestroy() can only be called in the context of the same thread") );
1482
1483 m_critsect.Enter();
1484
1485 if ( m_internal->GetState() == STATE_PAUSED )
1486 {
1487 m_internal->SetReallyPaused(TRUE);
1488
1489 // leave the crit section or the other threads will stop too if they
1490 // try to call any of (seemingly harmless) IsXXX() functions while we
1491 // sleep
1492 m_critsect.Leave();
1493
1494 m_internal->Pause();
1495 }
1496 else
1497 {
1498 // thread wasn't requested to pause, nothing to do
1499 m_critsect.Leave();
1500 }
1501
1502 return m_internal->WasCancelled();
1503 }
1504
1505 // -----------------------------------------------------------------------------
1506 // priority setting
1507 // -----------------------------------------------------------------------------
1508
1509 void wxThread::SetPriority(unsigned int prio)
1510 {
1511 wxCHECK_RET( ((int)WXTHREAD_MIN_PRIORITY <= (int)prio) &&
1512 ((int)prio <= (int)WXTHREAD_MAX_PRIORITY),
1513 wxT("invalid thread priority") );
1514
1515 wxCriticalSectionLocker lock(m_critsect);
1516
1517 switch ( m_internal->GetState() )
1518 {
1519 case STATE_RUNNING:
1520 case STATE_PAUSED:
1521 case STATE_NEW:
1522 // thread not yet started, priority will be set when it is
1523 m_internal->SetPriority(prio);
1524 break;
1525
1526 case STATE_EXITED:
1527 default:
1528 wxFAIL_MSG(wxT("impossible to set thread priority in this state"));
1529 }
1530 }
1531
1532 unsigned int wxThread::GetPriority() const
1533 {
1534 wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect); // const_cast
1535
1536 return m_internal->GetPriority();
1537 }
1538
1539 unsigned long wxThread::GetId() const
1540 {
1541 wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect); // const_cast
1542
1543 return (unsigned long)m_internal->GetId();
1544 }
1545
1546 // -----------------------------------------------------------------------------
1547 // state tests
1548 // -----------------------------------------------------------------------------
1549
1550 bool wxThread::IsRunning() const
1551 {
1552 wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect);
1553
1554 return m_internal->GetState() == STATE_RUNNING;
1555 }
1556
1557 bool wxThread::IsAlive() const
1558 {
1559 wxCriticalSectionLocker lock((wxCriticalSection&)m_critsect);
1560
1561 switch ( m_internal->GetState() )
1562 {
1563 case STATE_RUNNING:
1564 case STATE_PAUSED:
1565 return TRUE;
1566
1567 default:
1568 return FALSE;
1569 }
1570 }
1571
1572 bool wxThread::IsPaused() const
1573 {
1574 wxCriticalSectionLocker lock((wxCriticalSection&)m_critsect);
1575
1576 return (m_internal->GetState() == STATE_PAUSED);
1577 }
1578
1579 // ----------------------------------------------------------------------------
1580 // Automatic initialization for thread module
1581 // ----------------------------------------------------------------------------
1582
1583 class wxThreadModule : public wxModule
1584 {
1585 public:
1586 virtual bool OnInit();
1587 virtual void OnExit();
1588
1589 private:
1590 DECLARE_DYNAMIC_CLASS(wxThreadModule)
1591 };
1592
1593 IMPLEMENT_DYNAMIC_CLASS(wxThreadModule, wxModule)
1594
1595 bool wxThreadModule::OnInit()
1596 {
1597 bool hasThreadManager = false ;
1598 hasThreadManager = MPLibraryIsLoaded();
1599
1600 if ( !hasThreadManager )
1601 {
1602 wxLogError( _("MP Thread Support is not available on this System" ) ) ;
1603 return FALSE ;
1604 }
1605
1606 verify_noerr( MPAllocateTaskStorageIndex( &gs_tlsForWXThread ) ) ;
1607 // main thread's This() is NULL
1608 verify_noerr( MPSetTaskStorageValue( gs_tlsForWXThread , NULL ) ) ;
1609
1610 gs_idMainThread = wxThread::GetCurrentId() ;
1611
1612 gs_critsectWaitingForGui = new wxCriticalSection();
1613
1614 gs_critsectGui = new wxCriticalSection();
1615 gs_critsectGui->Enter();
1616
1617 return TRUE;
1618 }
1619
1620 void wxThreadModule::OnExit()
1621 {
1622 if ( gs_critsectGui )
1623 {
1624 gs_critsectGui->Leave();
1625 delete gs_critsectGui;
1626 gs_critsectGui = NULL;
1627 }
1628
1629 delete gs_critsectWaitingForGui;
1630 gs_critsectWaitingForGui = NULL;
1631 }
1632
1633 // ----------------------------------------------------------------------------
1634 // GUI Serialization copied from MSW implementation
1635 // ----------------------------------------------------------------------------
1636
1637 void WXDLLIMPEXP_BASE wxMutexGuiEnter()
1638 {
1639 // this would dead lock everything...
1640 wxASSERT_MSG( !wxThread::IsMain(),
1641 wxT("main thread doesn't want to block in wxMutexGuiEnter()!") );
1642
1643 // the order in which we enter the critical sections here is crucial!!
1644
1645 // set the flag telling to the main thread that we want to do some GUI
1646 {
1647 wxCriticalSectionLocker enter(*gs_critsectWaitingForGui);
1648
1649 gs_nWaitingForGui++;
1650 }
1651
1652 wxWakeUpMainThread();
1653
1654 // now we may block here because the main thread will soon let us in
1655 // (during the next iteration of OnIdle())
1656 gs_critsectGui->Enter();
1657 }
1658
1659 void WXDLLIMPEXP_BASE wxMutexGuiLeave()
1660 {
1661 wxCriticalSectionLocker enter(*gs_critsectWaitingForGui);
1662
1663 if ( wxThread::IsMain() )
1664 {
1665 gs_bGuiOwnedByMainThread = false;
1666 }
1667 else
1668 {
1669 // decrement the number of threads waiting for GUI access now
1670 wxASSERT_MSG( gs_nWaitingForGui > 0,
1671 wxT("calling wxMutexGuiLeave() without entering it first?") );
1672
1673 gs_nWaitingForGui--;
1674
1675 wxWakeUpMainThread();
1676 }
1677
1678 gs_critsectGui->Leave();
1679 }
1680
1681 void WXDLLIMPEXP_BASE wxMutexGuiLeaveOrEnter()
1682 {
1683 wxASSERT_MSG( wxThread::IsMain(),
1684 wxT("only main thread may call wxMutexGuiLeaveOrEnter()!") );
1685
1686 wxCriticalSectionLocker enter(*gs_critsectWaitingForGui);
1687
1688 if ( gs_nWaitingForGui == 0 )
1689 {
1690 // no threads are waiting for GUI - so we may acquire the lock without
1691 // any danger (but only if we don't already have it)
1692 if ( !wxGuiOwnedByMainThread() )
1693 {
1694 gs_critsectGui->Enter();
1695
1696 gs_bGuiOwnedByMainThread = true;
1697 }
1698 //else: already have it, nothing to do
1699 }
1700 else
1701 {
1702 // some threads are waiting, release the GUI lock if we have it
1703 if ( wxGuiOwnedByMainThread() )
1704 {
1705 wxMutexGuiLeave();
1706 }
1707 //else: some other worker thread is doing GUI
1708 }
1709 }
1710
1711 bool WXDLLIMPEXP_BASE wxGuiOwnedByMainThread()
1712 {
1713 return gs_bGuiOwnedByMainThread;
1714 }
1715
1716 // wake up the main thread
1717 void WXDLLEXPORT wxWakeUpMainThread()
1718 {
1719 wxMacWakeUp() ;
1720 }
1721
1722 // ----------------------------------------------------------------------------
1723 // include common implementation code
1724 // ----------------------------------------------------------------------------
1725
1726 #include "wx/thrimpl.cpp"
1727
1728 #endif // wxUSE_THREADS