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