]> git.saurik.com Git - wxWidgets.git/blob - src/unix/threadpsx.cpp
Minor changes
[wxWidgets.git] / src / unix / threadpsx.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: threadpsx.cpp
3 // Purpose: wxThread (Posix) Implementation
4 // Author: Original from Wolfram Gloger/Guilhem Lavaux
5 // Modified by:
6 // Created: 04/22/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Wolfram Gloger (1996, 1997)
9 // Guilhem Lavaux (1998)
10 // Vadim Zeitlin (1999)
11 // Robert Roebling (1999)
12 // Licence: wxWindows licence
13 /////////////////////////////////////////////////////////////////////////////
14
15 // ============================================================================
16 // declaration
17 // ============================================================================
18
19 // ----------------------------------------------------------------------------
20 // headers
21 // ----------------------------------------------------------------------------
22
23 #ifdef __GNUG__
24 #pragma implementation "thread.h"
25 #endif
26
27 // With simple makefiles, we must ignore the file body if not using
28 // threads.
29 #include "wx/setup.h"
30
31 #if wxUSE_THREADS
32
33 #include "wx/thread.h"
34 #include "wx/module.h"
35 #include "wx/utils.h"
36 #include "wx/log.h"
37 #include "wx/intl.h"
38 #include "wx/dynarray.h"
39
40 #include <stdio.h>
41 #include <unistd.h>
42 #include <pthread.h>
43 #include <errno.h>
44 #include <time.h>
45
46 #if HAVE_SCHED_H
47 #include <sched.h>
48 #endif
49
50 // ----------------------------------------------------------------------------
51 // constants
52 // ----------------------------------------------------------------------------
53
54 // the possible states of the thread and transitions from them
55 enum wxThreadState
56 {
57 STATE_NEW, // didn't start execution yet (=> RUNNING)
58 STATE_RUNNING, // running (=> PAUSED or EXITED)
59 STATE_PAUSED, // suspended (=> RUNNING or EXITED)
60 STATE_EXITED // thread doesn't exist any more
61 };
62
63 // ----------------------------------------------------------------------------
64 // types
65 // ----------------------------------------------------------------------------
66
67 WX_DEFINE_ARRAY(wxThread *, wxArrayThread);
68
69 // -----------------------------------------------------------------------------
70 // global data
71 // -----------------------------------------------------------------------------
72
73 // we keep the list of all threads created by the application to be able to
74 // terminate them on exit if there are some left - otherwise the process would
75 // be left in memory
76 static wxArrayThread gs_allThreads;
77
78 // the id of the main thread
79 static pthread_t gs_tidMain;
80
81 // the key for the pointer to the associated wxThread object
82 static pthread_key_t gs_keySelf;
83
84 // this mutex must be acquired before any call to a GUI function
85 static wxMutex *gs_mutexGui;
86
87 // ============================================================================
88 // implementation
89 // ============================================================================
90
91 //--------------------------------------------------------------------
92 // wxMutex (Posix implementation)
93 //--------------------------------------------------------------------
94
95 class wxMutexInternal
96 {
97 public:
98 pthread_mutex_t p_mutex;
99 };
100
101 wxMutex::wxMutex()
102 {
103 p_internal = new wxMutexInternal;
104
105 #if 0
106 /* I don't know where this function is supposed to exist,
107 and NP actually means non-portable, RR. */
108 pthread_mutexattr_t attr_type;
109 pthread_mutexattr_settype( &attr_type, PTHREAD_MUTEX_FAST_NP );
110
111 pthread_mutex_init( &(p_internal->p_mutex), (const pthread_mutexattr_t*) &attr_type );
112 #else
113 pthread_mutex_init( &(p_internal->p_mutex), (const pthread_mutexattr_t*) NULL );
114 #endif
115 m_locked = 0;
116 }
117
118 wxMutex::~wxMutex()
119 {
120 if (m_locked > 0)
121 wxLogDebug(_T("Freeing a locked mutex (%d locks)"), m_locked);
122
123 pthread_mutex_destroy( &(p_internal->p_mutex) );
124 delete p_internal;
125 }
126
127 wxMutexError wxMutex::Lock()
128 {
129 int err = pthread_mutex_lock( &(p_internal->p_mutex) );
130 if (err == EDEADLK)
131 {
132 wxLogDebug(_T("Locking this mutex would lead to deadlock!"));
133
134 return wxMUTEX_DEAD_LOCK;
135 }
136
137 m_locked++;
138
139 return wxMUTEX_NO_ERROR;
140 }
141
142 wxMutexError wxMutex::TryLock()
143 {
144 if (m_locked)
145 {
146 return wxMUTEX_BUSY;
147 }
148
149 int err = pthread_mutex_trylock( &(p_internal->p_mutex) );
150 switch (err)
151 {
152 case EBUSY: return wxMUTEX_BUSY;
153 }
154
155 m_locked++;
156
157 return wxMUTEX_NO_ERROR;
158 }
159
160 wxMutexError wxMutex::Unlock()
161 {
162 if (m_locked > 0)
163 {
164 m_locked--;
165 }
166 else
167 {
168 wxLogDebug(_T("Unlocking not locked mutex."));
169
170 return wxMUTEX_UNLOCKED;
171 }
172
173 pthread_mutex_unlock( &(p_internal->p_mutex) );
174
175 return wxMUTEX_NO_ERROR;
176 }
177
178 //--------------------------------------------------------------------
179 // wxCondition (Posix implementation)
180 //--------------------------------------------------------------------
181
182 class wxConditionInternal
183 {
184 public:
185 pthread_cond_t p_condition;
186 };
187
188 wxCondition::wxCondition()
189 {
190 p_internal = new wxConditionInternal;
191 pthread_cond_init( &(p_internal->p_condition), (const pthread_condattr_t *) NULL );
192 }
193
194 wxCondition::~wxCondition()
195 {
196 pthread_cond_destroy( &(p_internal->p_condition) );
197
198 delete p_internal;
199 }
200
201 void wxCondition::Wait(wxMutex& mutex)
202 {
203 pthread_cond_wait( &(p_internal->p_condition), &(mutex.p_internal->p_mutex) );
204 }
205
206 bool wxCondition::Wait(wxMutex& mutex, unsigned long sec, unsigned long nsec)
207 {
208 struct timespec tspec;
209
210 tspec.tv_sec = time(0L)+sec;
211 tspec.tv_nsec = nsec;
212 return (pthread_cond_timedwait(&(p_internal->p_condition), &(mutex.p_internal->p_mutex), &tspec) != ETIMEDOUT);
213 }
214
215 void wxCondition::Signal()
216 {
217 pthread_cond_signal( &(p_internal->p_condition) );
218 }
219
220 void wxCondition::Broadcast()
221 {
222 pthread_cond_broadcast( &(p_internal->p_condition) );
223 }
224
225 //--------------------------------------------------------------------
226 // wxThread (Posix implementation)
227 //--------------------------------------------------------------------
228
229 class wxThreadInternal
230 {
231 public:
232 wxThreadInternal();
233 ~wxThreadInternal();
234
235 // thread entry function
236 static void *PthreadStart(void *ptr);
237
238 #if HAVE_THREAD_CLEANUP_FUNCTIONS
239 // thread exit function
240 static void PthreadCleanup(void *ptr);
241 #endif
242
243 // thread actions
244 // start the thread
245 wxThreadError Run();
246 // ask the thread to terminate
247 void Wait();
248 // wake up threads waiting for our termination
249 void SignalExit();
250 // go to sleep until Resume() is called
251 void Pause();
252 // resume the thread
253 void Resume();
254
255 // accessors
256 // priority
257 int GetPriority() const { return m_prio; }
258 void SetPriority(int prio) { m_prio = prio; }
259 // state
260 wxThreadState GetState() const { return m_state; }
261 void SetState(wxThreadState state) { m_state = state; }
262 // id
263 pthread_t GetId() const { return m_threadId; }
264 pthread_t *GetIdPtr() { return &m_threadId; }
265 // "cancelled" flag
266 void SetCancelFlag() { m_cancelled = TRUE; }
267 bool WasCancelled() const { return m_cancelled; }
268
269 private:
270 pthread_t m_threadId; // id of the thread
271 wxThreadState m_state; // see wxThreadState enum
272 int m_prio; // in wxWindows units: from 0 to 100
273
274 // set when the thread should terminate
275 bool m_cancelled;
276
277 // this (mutex, cond) pair is used to synchronize the main thread and this
278 // thread in several situations:
279 // 1. The thread function blocks until condition is signaled by Run() when
280 // it's initially created - this allows thread creation in "suspended"
281 // state
282 // 2. The Delete() function blocks until the condition is signaled when the
283 // thread exits.
284 // GL: On Linux, this may fail because we can have a deadlock in either
285 // SignalExit() or Wait(): so we add m_end_mutex for the finalization.
286 wxMutex m_mutex, m_end_mutex;
287 wxCondition m_cond;
288
289 // another (mutex, cond) pair for Pause()/Resume() usage
290 //
291 // VZ: it's possible that we might reuse the mutex and condition from above
292 // for this too, but as I'm not at all sure that it won't create subtle
293 // problems with race conditions between, say, Pause() and Delete() I
294 // prefer this may be a bit less efficient but much safer solution
295 wxMutex m_mutexSuspend;
296 wxCondition m_condSuspend;
297 };
298
299 void *wxThreadInternal::PthreadStart(void *ptr)
300 {
301 wxThread *thread = (wxThread *)ptr;
302 wxThreadInternal *pthread = thread->p_internal;
303 void *status;
304
305 int rc = pthread_setspecific(gs_keySelf, thread);
306 if ( rc != 0 )
307 {
308 wxLogSysError(rc, _("Cannot start thread: error writing TLS"));
309
310 return (void *)-1;
311 }
312 #if HAVE_THREAD_CLEANUP_FUNCTIONS
313 // Install the cleanup handler.
314 pthread_cleanup_push(wxThreadInternal::PthreadCleanup, ptr);
315 #endif
316
317 // wait for the condition to be signaled from Run()
318 // mutex state: currently locked by the thread which created us
319 pthread->m_cond.Wait(pthread->m_mutex);
320 // mutex state: locked again on exit of Wait()
321
322 // call the main entry
323 status = thread->Entry();
324
325 #if HAVE_THREAD_CLEANUP_FUNCTIONS
326 pthread_cleanup_pop(FALSE);
327 #endif
328
329 // terminate the thread
330 thread->Exit(status);
331
332 wxFAIL_MSG(_T("wxThread::Exit() can't return."));
333
334 return NULL;
335 }
336
337 #if HAVE_THREAD_CLEANUP_FUNCTIONS
338 // Only called when the thread is explicitely killed.
339
340 void wxThreadInternal::PthreadCleanup(void *ptr)
341 {
342 wxThread *thread = (wxThread *) ptr;
343
344 // The thread is already considered as finished.
345 if (thread->p_internal->GetState() == STATE_EXITED)
346 return;
347
348 // first call user-level clean up code
349 thread->OnExit();
350
351 // next wake up the threads waiting for us (OTOH, this function won't retur
352 // until someone waited for us!)
353 thread->p_internal->SetState(STATE_EXITED);
354
355 thread->p_internal->SignalExit();
356 }
357 #endif
358
359 wxThreadInternal::wxThreadInternal()
360 {
361 m_state = STATE_NEW;
362 m_cancelled = FALSE;
363
364 // this mutex is locked during almost all thread lifetime - it will only be
365 // unlocked in the very end
366 m_mutex.Lock();
367
368 // this mutex is used by wxThreadInternal::Wait() and by
369 // wxThreadInternal::SignalExit(). We don't use m_mutex because of a
370 // possible deadlock in either Wait() or SignalExit().
371 m_end_mutex.Lock();
372
373 // this mutex is used in Pause()/Resume() and is also locked all the time
374 // unless the thread is paused
375 m_mutexSuspend.Lock();
376 }
377
378 wxThreadInternal::~wxThreadInternal()
379 {
380 // GL: moved to SignalExit
381 // m_mutexSuspend.Unlock();
382
383 // note that m_mutex will be unlocked by the thread which waits for our
384 // termination
385
386 // In the case, we didn't start the thread, all these mutex are locked:
387 // we must unlock them.
388 if (m_mutex.IsLocked())
389 m_mutex.Unlock();
390
391 if (m_end_mutex.IsLocked())
392 m_end_mutex.Unlock();
393
394 if (m_mutexSuspend.IsLocked())
395 m_mutexSuspend.Unlock();
396 }
397
398 wxThreadError wxThreadInternal::Run()
399 {
400 wxCHECK_MSG( GetState() == STATE_NEW, wxTHREAD_RUNNING,
401 _T("thread may only be started once after successful Create()") );
402
403 // the mutex was locked on Create(), so we will be able to lock it again
404 // only when the thread really starts executing and enters the wait -
405 // otherwise we might signal the condition before anybody is waiting for it
406 wxMutexLocker lock(m_mutex);
407 m_cond.Signal();
408
409 m_state = STATE_RUNNING;
410
411 return wxTHREAD_NO_ERROR;
412
413 // now the mutex is unlocked back - but just to allow Wait() function to
414 // terminate by relocking it, so the net result is that the worker thread
415 // starts executing and the mutex is still locked
416 }
417
418 void wxThreadInternal::Wait()
419 {
420 wxCHECK_RET( WasCancelled(), _T("thread should have been cancelled first") );
421
422 // if the thread we're waiting for is waiting for the GUI mutex, we will
423 // deadlock so make sure we release it temporarily
424 if ( wxThread::IsMain() )
425 wxMutexGuiLeave();
426
427 // entering Wait() releases the mutex thus allowing SignalExit() to acquire
428 // it and to signal us its termination
429 m_cond.Wait(m_end_mutex);
430
431 // mutex is still in the locked state - relocked on exit from Wait(), so
432 // unlock it - we don't need it any more, the thread has already terminated
433 m_end_mutex.Unlock();
434
435 // After that, we wait for the real end of the other thread.
436 pthread_join(GetId(), NULL);
437
438 // reacquire GUI mutex
439 if ( wxThread::IsMain() )
440 wxMutexGuiEnter();
441 }
442
443 void wxThreadInternal::SignalExit()
444 {
445 // GL: Unlock mutexSuspend here.
446 m_mutexSuspend.Unlock();
447
448 // as mutex is currently locked, this will block until some other thread
449 // (normally the same which created this one) unlocks it by entering Wait()
450 m_end_mutex.Lock();
451
452 // wake up all the threads waiting for our termination
453 m_cond.Broadcast();
454
455 // after this call mutex will be finally unlocked
456 m_end_mutex.Unlock();
457 }
458
459 void wxThreadInternal::Pause()
460 {
461 // the state is set from the thread which pauses us first, this function
462 // is called later so the state should have been already set
463 wxCHECK_RET( m_state == STATE_PAUSED,
464 _T("thread must first be paused with wxThread::Pause().") );
465
466 // don't pause the thread which is being terminated - this would lead to
467 // deadlock if the thread is paused after Delete() had called Resume() but
468 // before it had time to call Wait()
469 if ( WasCancelled() )
470 return;
471
472 // wait until the condition is signaled from Resume()
473 m_condSuspend.Wait(m_mutexSuspend);
474 }
475
476 void wxThreadInternal::Resume()
477 {
478 wxCHECK_RET( m_state == STATE_PAUSED,
479 _T("can't resume thread which is not suspended.") );
480
481 // we will be able to lock this mutex only when Pause() starts waiting
482 wxMutexLocker lock(m_mutexSuspend);
483 m_condSuspend.Signal();
484
485 SetState(STATE_RUNNING);
486 }
487
488 // -----------------------------------------------------------------------------
489 // static functions
490 // -----------------------------------------------------------------------------
491
492 wxThread *wxThread::This()
493 {
494 return (wxThread *)pthread_getspecific(gs_keySelf);
495 }
496
497 bool wxThread::IsMain()
498 {
499 return (bool)pthread_equal(pthread_self(), gs_tidMain);
500 }
501
502 void wxThread::Yield()
503 {
504 sched_yield();
505 }
506
507 void wxThread::Sleep(unsigned long milliseconds)
508 {
509 wxUsleep(milliseconds);
510 }
511
512 // -----------------------------------------------------------------------------
513 // creating thread
514 // -----------------------------------------------------------------------------
515
516 wxThread::wxThread()
517 {
518 // add this thread to the global list of all threads
519 gs_allThreads.Add(this);
520
521 p_internal = new wxThreadInternal();
522 }
523
524 wxThreadError wxThread::Create()
525 {
526 if (p_internal->GetState() != STATE_NEW)
527 return wxTHREAD_RUNNING;
528
529 // set up the thread attribute: right now, we only set thread priority
530 pthread_attr_t attr;
531 pthread_attr_init(&attr);
532
533 #ifdef HAVE_THREAD_PRIORITY_FUNCTIONS
534 int prio;
535 if ( pthread_attr_getschedpolicy(&attr, &prio) != 0 )
536 {
537 wxLogError(_("Cannot retrieve thread scheduling policy."));
538 }
539
540 int min_prio = sched_get_priority_min(prio),
541 max_prio = sched_get_priority_max(prio);
542
543 if ( min_prio == -1 || max_prio == -1 )
544 {
545 wxLogError(_("Cannot get priority range for scheduling policy %d."),
546 prio);
547 }
548 else
549 {
550 struct sched_param sp;
551 pthread_attr_getschedparam(&attr, &sp);
552 sp.sched_priority = min_prio +
553 (p_internal->GetPriority()*(max_prio-min_prio))/100;
554 pthread_attr_setschedparam(&attr, &sp);
555 }
556 #endif // HAVE_THREAD_PRIORITY_FUNCTIONS
557
558 #ifdef HAVE_PTHREAD_ATTR_SETSCOPE
559 // this will make the threads created by this process really concurrent
560 pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
561 #endif // HAVE_PTHREAD_ATTR_SETSCOPE
562
563 // create the new OS thread object
564 int rc = pthread_create(p_internal->GetIdPtr(), &attr,
565 wxThreadInternal::PthreadStart, (void *)this);
566 pthread_attr_destroy(&attr);
567
568 if ( rc != 0 )
569 {
570 p_internal->SetState(STATE_EXITED);
571 return wxTHREAD_NO_RESOURCE;
572 }
573
574 return wxTHREAD_NO_ERROR;
575 }
576
577 wxThreadError wxThread::Run()
578 {
579 return p_internal->Run();
580 }
581
582 // -----------------------------------------------------------------------------
583 // misc accessors
584 // -----------------------------------------------------------------------------
585
586 void wxThread::SetPriority(unsigned int prio)
587 {
588 wxCHECK_RET( ((int)WXTHREAD_MIN_PRIORITY <= (int)prio) &&
589 ((int)prio <= (int)WXTHREAD_MAX_PRIORITY),
590 _T("invalid thread priority") );
591
592 wxCriticalSectionLocker lock(m_critsect);
593
594 switch ( p_internal->GetState() )
595 {
596 case STATE_NEW:
597 // thread not yet started, priority will be set when it is
598 p_internal->SetPriority(prio);
599 break;
600
601 case STATE_RUNNING:
602 case STATE_PAUSED:
603 #ifdef HAVE_THREAD_PRIORITY_FUNCTIONS
604 {
605 struct sched_param sparam;
606 sparam.sched_priority = prio;
607
608 if ( pthread_setschedparam(p_internal->GetId(),
609 SCHED_OTHER, &sparam) != 0 )
610 {
611 wxLogError(_("Failed to set thread priority %d."), prio);
612 }
613 }
614 #endif // HAVE_THREAD_PRIORITY_FUNCTIONS
615 break;
616
617 case STATE_EXITED:
618 default:
619 wxFAIL_MSG(_T("impossible to set thread priority in this state"));
620 }
621 }
622
623 unsigned int wxThread::GetPriority() const
624 {
625 wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect);
626
627 return p_internal->GetPriority();
628 }
629
630 unsigned long wxThread::GetID() const
631 {
632 return (unsigned long)p_internal->GetId();
633 }
634
635 // -----------------------------------------------------------------------------
636 // pause/resume
637 // -----------------------------------------------------------------------------
638
639 wxThreadError wxThread::Pause()
640 {
641 wxCriticalSectionLocker lock(m_critsect);
642
643 if ( p_internal->GetState() != STATE_RUNNING )
644 {
645 wxLogDebug(_T("Can't pause thread which is not running."));
646
647 return wxTHREAD_NOT_RUNNING;
648 }
649
650 p_internal->SetState(STATE_PAUSED);
651
652 return wxTHREAD_NO_ERROR;
653 }
654
655 wxThreadError wxThread::Resume()
656 {
657 wxCriticalSectionLocker lock(m_critsect);
658
659 if ( p_internal->GetState() == STATE_PAUSED )
660 {
661 m_critsect.Leave();
662 p_internal->Resume();
663 m_critsect.Enter();
664
665 return wxTHREAD_NO_ERROR;
666 }
667 else
668 {
669 wxLogDebug(_T("Attempt to resume a thread which is not paused."));
670
671 return wxTHREAD_MISC_ERROR;
672 }
673 }
674
675 // -----------------------------------------------------------------------------
676 // exiting thread
677 // -----------------------------------------------------------------------------
678
679 wxThread::ExitCode wxThread::Delete()
680 {
681 if (IsPaused())
682 Resume();
683
684 m_critsect.Enter();
685 wxThreadState state = p_internal->GetState();
686
687 // ask the thread to stop
688 p_internal->SetCancelFlag();
689
690 m_critsect.Leave();
691
692 switch ( state )
693 {
694 case STATE_NEW:
695 case STATE_EXITED:
696 // nothing to do
697 break;
698
699 case STATE_PAUSED:
700 // resume the thread first
701 Resume();
702
703 // fall through
704
705 default:
706 // wait until the thread stops
707 p_internal->Wait();
708 }
709 //GL: As we must auto-destroy, the destruction must happen here.
710 delete this;
711
712 return NULL;
713 }
714
715 wxThreadError wxThread::Kill()
716 {
717 switch ( p_internal->GetState() )
718 {
719 case STATE_NEW:
720 case STATE_EXITED:
721 return wxTHREAD_NOT_RUNNING;
722
723 default:
724 #ifdef HAVE_PTHREAD_CANCEL
725 if ( pthread_cancel(p_internal->GetId()) != 0 )
726 #endif
727 {
728 wxLogError(_("Failed to terminate a thread."));
729
730 return wxTHREAD_MISC_ERROR;
731 }
732 //GL: As we must auto-destroy, the destruction must happen here (2).
733 delete this;
734
735 return wxTHREAD_NO_ERROR;
736 }
737 }
738
739 void wxThread::Exit(void *status)
740 {
741 // first call user-level clean up code
742 OnExit();
743
744 // next wake up the threads waiting for us (OTOH, this function won't return
745 // until someone waited for us!)
746 p_internal->SignalExit();
747
748 p_internal->SetState(STATE_EXITED);
749
750 // delete both C++ thread object and terminate the OS thread object
751 // GL: This is very ugly and buggy ...
752 // delete this;
753 pthread_exit(status);
754 }
755
756 // also test whether we were paused
757 bool wxThread::TestDestroy()
758 {
759 wxCriticalSectionLocker lock(m_critsect);
760
761 if ( p_internal->GetState() == STATE_PAUSED )
762 {
763 // leave the crit section or the other threads will stop too if they try
764 // to call any of (seemingly harmless) IsXXX() functions while we sleep
765 m_critsect.Leave();
766
767 p_internal->Pause();
768
769 // enter it back before it's finally left in lock object dtor
770 m_critsect.Enter();
771 }
772
773 return p_internal->WasCancelled();
774 }
775
776 wxThread::~wxThread()
777 {
778 m_critsect.Enter();
779 if (p_internal->GetState() != STATE_EXITED &&
780 p_internal->GetState() != STATE_NEW)
781 wxLogDebug(_T("The thread is being destroyed althought it is still running ! The application may crash."));
782
783 m_critsect.Leave();
784
785 delete p_internal;
786 // remove this thread from the global array
787 gs_allThreads.Remove(this);
788 }
789
790 // -----------------------------------------------------------------------------
791 // state tests
792 // -----------------------------------------------------------------------------
793
794 bool wxThread::IsRunning() const
795 {
796 wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect);
797
798 return p_internal->GetState() == STATE_RUNNING;
799 }
800
801 bool wxThread::IsAlive() const
802 {
803 wxCriticalSectionLocker lock((wxCriticalSection&)m_critsect);
804
805 switch ( p_internal->GetState() )
806 {
807 case STATE_RUNNING:
808 case STATE_PAUSED:
809 return TRUE;
810
811 default:
812 return FALSE;
813 }
814 }
815
816 bool wxThread::IsPaused() const
817 {
818 wxCriticalSectionLocker lock((wxCriticalSection&)m_critsect);
819
820 return (p_internal->GetState() == STATE_PAUSED);
821 }
822
823 //--------------------------------------------------------------------
824 // wxThreadModule
825 //--------------------------------------------------------------------
826
827 class wxThreadModule : public wxModule
828 {
829 public:
830 virtual bool OnInit();
831 virtual void OnExit();
832
833 private:
834 DECLARE_DYNAMIC_CLASS(wxThreadModule)
835 };
836
837 IMPLEMENT_DYNAMIC_CLASS(wxThreadModule, wxModule)
838
839 bool wxThreadModule::OnInit()
840 {
841 int rc = pthread_key_create(&gs_keySelf, NULL /* dtor function */);
842 if ( rc != 0 )
843 {
844 wxLogSysError(rc, _("Thread module initialization failed: "
845 "failed to create thread key"));
846
847 return FALSE;
848 }
849
850 gs_mutexGui = new wxMutex();
851
852 gs_tidMain = pthread_self();
853
854 gs_mutexGui->Lock();
855
856 return TRUE;
857 }
858
859 void wxThreadModule::OnExit()
860 {
861 wxASSERT_MSG( wxThread::IsMain(), _T("only main thread can be here") );
862
863 // terminate any threads left
864 size_t count = gs_allThreads.GetCount();
865 if ( count != 0u )
866 wxLogDebug(_T("Some threads were not terminated by the application."));
867
868 for ( size_t n = 0u; n < count; n++ )
869 {
870 gs_allThreads[n]->Delete();
871 }
872
873 // destroy GUI mutex
874 gs_mutexGui->Unlock();
875
876 delete gs_mutexGui;
877
878 // and free TLD slot
879 (void)pthread_key_delete(gs_keySelf);
880 }
881
882 // ----------------------------------------------------------------------------
883 // global functions
884 // ----------------------------------------------------------------------------
885
886 void wxMutexGuiEnter()
887 {
888 gs_mutexGui->Lock();
889 }
890
891 void wxMutexGuiLeave()
892 {
893 gs_mutexGui->Unlock();
894 }
895
896 #endif
897 // wxUSE_THREADS