1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxThread (Posix) Implementation
4 // Author: Original from Wolfram Gloger/Guilhem Lavaux
8 // Copyright: (c) Wolfram Gloger (1996, 1997)
9 // Guilhem Lavaux (1998)
10 // Vadim Zeitlin (1999)
11 // Robert Roebling (1999)
12 // Licence: wxWindows licence
13 /////////////////////////////////////////////////////////////////////////////
15 // ============================================================================
17 // ============================================================================
19 // ----------------------------------------------------------------------------
21 // ----------------------------------------------------------------------------
24 #pragma implementation "thread.h"
31 #include "wx/thread.h"
32 #include "wx/module.h"
36 #include "wx/dynarray.h"
48 // ----------------------------------------------------------------------------
50 // ----------------------------------------------------------------------------
52 // the possible states of the thread and transitions from them
55 STATE_NEW
, // didn't start execution yet (=> RUNNING)
56 STATE_RUNNING
, // running (=> PAUSED or EXITED)
57 STATE_PAUSED
, // suspended (=> RUNNING or EXITED)
58 STATE_EXITED
// thread doesn't exist any more
61 // the exit value of a thread which has been cancelled
62 static const wxThread::ExitCode EXITCODE_CANCELLED
= (wxThread::ExitCode
)-1;
65 #define TRACE_THREADS _T("thread")
67 // ----------------------------------------------------------------------------
69 // ----------------------------------------------------------------------------
71 static void ScheduleThreadForDeletion();
72 static void DeleteThread(wxThread
*This
);
74 // ----------------------------------------------------------------------------
76 // ----------------------------------------------------------------------------
78 // same as wxMutexLocker but for "native" mutex
82 MutexLock(pthread_mutex_t
& mutex
)
85 if ( pthread_mutex_lock(m_mutex
) != 0 )
87 wxLogDebug(_T("pthread_mutex_lock() failed"));
93 if ( pthread_mutex_unlock(m_mutex
) != 0 )
95 wxLogDebug(_T("pthread_mutex_unlock() failed"));
100 pthread_mutex_t
*m_mutex
;
103 // ----------------------------------------------------------------------------
105 // ----------------------------------------------------------------------------
107 WX_DEFINE_ARRAY(wxThread
*, wxArrayThread
);
109 // -----------------------------------------------------------------------------
111 // -----------------------------------------------------------------------------
113 // we keep the list of all threads created by the application to be able to
114 // terminate them on exit if there are some left - otherwise the process would
116 static wxArrayThread gs_allThreads
;
118 // the id of the main thread
119 static pthread_t gs_tidMain
;
121 // the key for the pointer to the associated wxThread object
122 static pthread_key_t gs_keySelf
;
124 // the number of threads which are being deleted - the program won't exit
125 // until there are any left
126 static size_t gs_nThreadsBeingDeleted
= 0;
128 // a mutex to protect gs_nThreadsBeingDeleted
129 static pthread_mutex_t gs_mutexDeleteThread
= PTHREAD_MUTEX_INITIALIZER
;
131 // and a condition variable which will be signaled when all
132 // gs_nThreadsBeingDeleted will have been deleted
133 static wxCondition
*gs_condAllDeleted
= (wxCondition
*)NULL
;
136 // this mutex must be acquired before any call to a GUI function
137 static wxMutex
*gs_mutexGui
;
140 // ============================================================================
142 // ============================================================================
144 //--------------------------------------------------------------------
145 // wxMutex (Posix implementation)
146 //--------------------------------------------------------------------
148 class wxMutexInternal
151 pthread_mutex_t m_mutex
;
156 m_internal
= new wxMutexInternal
;
158 pthread_mutex_init(&(m_internal
->m_mutex
),
159 (pthread_mutexattr_t
*) NULL
);
166 wxLogDebug(wxT("Freeing a locked mutex (%d locks)"), m_locked
);
168 pthread_mutex_destroy( &(m_internal
->m_mutex
) );
172 wxMutexError
wxMutex::Lock()
174 int err
= pthread_mutex_lock( &(m_internal
->m_mutex
) );
177 wxLogDebug(wxT("Locking this mutex would lead to deadlock!"));
179 return wxMUTEX_DEAD_LOCK
;
184 return wxMUTEX_NO_ERROR
;
187 wxMutexError
wxMutex::TryLock()
194 int err
= pthread_mutex_trylock( &(m_internal
->m_mutex
) );
197 case EBUSY
: return wxMUTEX_BUSY
;
202 return wxMUTEX_NO_ERROR
;
205 wxMutexError
wxMutex::Unlock()
213 wxLogDebug(wxT("Unlocking not locked mutex."));
215 return wxMUTEX_UNLOCKED
;
218 pthread_mutex_unlock( &(m_internal
->m_mutex
) );
220 return wxMUTEX_NO_ERROR
;
223 //--------------------------------------------------------------------
224 // wxCondition (Posix implementation)
225 //--------------------------------------------------------------------
227 // The native POSIX condition variables are dumb: if the condition is signaled
228 // before another thread starts to wait on it, the signal is lost and so this
229 // other thread will be never woken up. It's much more convenient to us to
230 // remember that the condition was signaled and to return from Wait()
231 // immediately in this case (this is more like Win32 automatic event objects)
233 class wxConditionInternal
236 wxConditionInternal();
237 ~wxConditionInternal();
240 bool WaitWithTimeout(const timespec
* ts
);
250 bool m_wasSignaled
; // TRUE if condition was signaled while
251 // nobody waited for it
252 size_t m_nWaiters
; // TRUE if someone already waits for us
254 pthread_mutex_t m_mutexProtect
; // protects access to vars above
256 pthread_mutex_t m_mutex
; // the mutex used with the condition
257 pthread_cond_t m_condition
; // the condition itself
260 wxConditionInternal::wxConditionInternal()
262 m_wasSignaled
= FALSE
;
265 if ( pthread_cond_init(&m_condition
, (pthread_condattr_t
*)NULL
) != 0 )
267 // this is supposed to never happen
268 wxFAIL_MSG( _T("pthread_cond_init() failed") );
271 if ( pthread_mutex_init(&m_mutex
, (pthread_mutexattr_t
*)NULL
) != 0 ||
272 pthread_mutex_init(&m_mutexProtect
, NULL
) != 0 )
275 wxFAIL_MSG( _T("wxCondition: pthread_mutex_init() failed") );
278 // initially the mutex is locked, so no thread can Signal() or Broadcast()
279 // until another thread starts to Wait()
280 if ( pthread_mutex_lock(&m_mutex
) != 0 )
282 wxFAIL_MSG( _T("wxCondition: pthread_mutex_lock() failed") );
286 wxConditionInternal::~wxConditionInternal()
288 if ( pthread_cond_destroy( &m_condition
) != 0 )
290 wxLogDebug(_T("Failed to destroy condition variable (some "
291 "threads are probably still waiting on it?)"));
294 if ( pthread_mutex_unlock( &m_mutex
) != 0 )
296 wxLogDebug(_T("wxCondition: failed to unlock the mutex"));
299 if ( pthread_mutex_destroy( &m_mutex
) != 0 ||
300 pthread_mutex_destroy( &m_mutexProtect
) != 0 )
302 wxLogDebug(_T("Failed to destroy mutex (it is probably locked)"));
306 void wxConditionInternal::WaitDone()
308 MutexLock
lock(m_mutexProtect
);
310 m_wasSignaled
= FALSE
;
314 bool wxConditionInternal::ShouldWait()
316 MutexLock
lock(m_mutexProtect
);
320 // the condition was signaled before we started to wait, reset the
322 m_wasSignaled
= FALSE
;
327 // we start to wait for it
333 bool wxConditionInternal::HasWaiters()
335 MutexLock
lock(m_mutexProtect
);
339 // someone waits for us, signal the condition normally
343 // nobody waits for us and may be never will - so just remember that the
344 // condition was signaled and don't do anything else
345 m_wasSignaled
= TRUE
;
350 void wxConditionInternal::Wait()
354 if ( pthread_cond_wait( &m_condition
, &m_mutex
) != 0 )
356 // not supposed to ever happen
357 wxFAIL_MSG( _T("pthread_cond_wait() failed") );
364 bool wxConditionInternal::WaitWithTimeout(const timespec
* ts
)
370 switch ( pthread_cond_timedwait( &m_condition
, &m_mutex
, ts
) )
373 // condition signaled
378 wxLogDebug(_T("pthread_cond_timedwait() failed"));
384 // wait interrupted or timeout elapsed
390 // the condition had already been signaled before
399 void wxConditionInternal::Signal()
403 MutexLock
lock(m_mutex
);
405 if ( pthread_cond_signal( &m_condition
) != 0 )
407 // shouldn't ever happen
408 wxFAIL_MSG(_T("pthread_cond_signal() failed"));
413 void wxConditionInternal::Broadcast()
417 MutexLock
lock(m_mutex
);
419 if ( pthread_cond_broadcast( &m_condition
) != 0 )
421 // shouldn't ever happen
422 wxFAIL_MSG(_T("pthread_cond_broadcast() failed"));
427 wxCondition::wxCondition()
429 m_internal
= new wxConditionInternal
;
432 wxCondition::~wxCondition()
437 void wxCondition::Wait()
442 bool wxCondition::Wait(unsigned long sec
, unsigned long nsec
)
446 tspec
.tv_sec
= time(0L) + sec
; // FIXME is time(0) correct here?
447 tspec
.tv_nsec
= nsec
;
449 return m_internal
->WaitWithTimeout(&tspec
);
452 void wxCondition::Signal()
454 m_internal
->Signal();
457 void wxCondition::Broadcast()
459 m_internal
->Broadcast();
462 //--------------------------------------------------------------------
463 // wxThread (Posix implementation)
464 //--------------------------------------------------------------------
466 class wxThreadInternal
472 // thread entry function
473 static void *PthreadStart(void *ptr
);
475 #if HAVE_THREAD_CLEANUP_FUNCTIONS
476 // thread exit function
477 static void PthreadCleanup(void *ptr
);
483 // ask the thread to terminate
485 // wake up threads waiting for our termination
487 // wake up threads waiting for our start
488 void SignalRun() { m_condRun
.Signal(); }
489 // go to sleep until Resume() is called
496 int GetPriority() const { return m_prio
; }
497 void SetPriority(int prio
) { m_prio
= prio
; }
499 wxThreadState
GetState() const { return m_state
; }
500 void SetState(wxThreadState state
) { m_state
= state
; }
502 pthread_t
GetId() const { return m_threadId
; }
503 pthread_t
*GetIdPtr() { return &m_threadId
; }
505 void SetCancelFlag() { m_cancelled
= TRUE
; }
506 bool WasCancelled() const { return m_cancelled
; }
508 void SetExitCode(wxThread::ExitCode exitcode
) { m_exitcode
= exitcode
; }
509 wxThread::ExitCode
GetExitCode() const { return m_exitcode
; }
512 void SetReallyPaused(bool paused
) { m_isPaused
= paused
; }
513 bool IsReallyPaused() const { return m_isPaused
; }
515 // tell the thread that it is a detached one
518 m_shouldBeJoined
= m_shouldBroadcast
= FALSE
;
521 // but even detached threads need to notifyus about their termination
522 // sometimes - tell the thread that it should do it
523 void Notify() { m_shouldBroadcast
= TRUE
; }
526 pthread_t m_threadId
; // id of the thread
527 wxThreadState m_state
; // see wxThreadState enum
528 int m_prio
; // in wxWindows units: from 0 to 100
530 // this flag is set when the thread should terminate
533 // this flag is set when the thread is blocking on m_condSuspend
536 // the thread exit code - only used for joinable (!detached) threads and
537 // is only valid after the thread termination
538 wxThread::ExitCode m_exitcode
;
540 // many threads may call Wait(), but only one of them should call
541 // pthread_join(), so we have to keep track of this
542 wxCriticalSection m_csJoinFlag
;
543 bool m_shouldBeJoined
;
544 bool m_shouldBroadcast
;
547 // VZ: it's possible that we might do with less than three different
548 // condition objects - for example, m_condRun and m_condEnd a priori
549 // won't be used in the same time. But for now I prefer this may be a
550 // bit less efficient but safer solution of having distinct condition
551 // variables for each purpose.
553 // this condition is signaled by Run() and the threads Entry() is not
554 // called before it is done
555 wxCondition m_condRun
;
557 // this one is signaled when the thread should resume after having been
559 wxCondition m_condSuspend
;
561 // finally this one is signalled when the thread exits
562 wxCondition m_condEnd
;
565 // ----------------------------------------------------------------------------
566 // thread startup and exit functions
567 // ----------------------------------------------------------------------------
569 void *wxThreadInternal::PthreadStart(void *ptr
)
571 wxThread
*thread
= (wxThread
*)ptr
;
572 wxThreadInternal
*pthread
= thread
->m_internal
;
574 // associate the thread pointer with the newly created thread so that
575 // wxThread::This() will work
576 int rc
= pthread_setspecific(gs_keySelf
, thread
);
579 wxLogSysError(rc
, _("Cannot start thread: error writing TLS"));
584 // have to declare this before pthread_cleanup_push() which defines a
588 #if HAVE_THREAD_CLEANUP_FUNCTIONS
589 // install the cleanup handler which will be called if the thread is
591 pthread_cleanup_push(wxThreadInternal::PthreadCleanup
, ptr
);
592 #endif // HAVE_THREAD_CLEANUP_FUNCTIONS
594 // wait for the condition to be signaled from Run()
595 pthread
->m_condRun
.Wait();
597 // test whether we should run the run at all - may be it was deleted
598 // before it started to Run()?
600 wxCriticalSectionLocker
lock(thread
->m_critsect
);
602 dontRunAtAll
= pthread
->GetState() == STATE_NEW
&&
603 pthread
->WasCancelled();
608 // call the main entry
609 pthread
->m_exitcode
= thread
->Entry();
611 wxLogTrace(TRACE_THREADS
, _T("Thread %ld left its Entry()."),
615 wxCriticalSectionLocker
lock(thread
->m_critsect
);
617 wxLogTrace(TRACE_THREADS
, _T("Thread %ld changes state to EXITED."),
620 // change the state of the thread to "exited" so that
621 // PthreadCleanup handler won't do anything from now (if it's
622 // called before we do pthread_cleanup_pop below)
623 pthread
->SetState(STATE_EXITED
);
627 // NB: at least under Linux, pthread_cleanup_push/pop are macros and pop
628 // contains the matching '}' for the '{' in push, so they must be used
629 // in the same block!
630 #if HAVE_THREAD_CLEANUP_FUNCTIONS
631 // remove the cleanup handler without executing it
632 pthread_cleanup_pop(FALSE
);
633 #endif // HAVE_THREAD_CLEANUP_FUNCTIONS
639 return EXITCODE_CANCELLED
;
643 // terminate the thread
644 thread
->Exit(pthread
->m_exitcode
);
646 wxFAIL_MSG(wxT("wxThread::Exit() can't return."));
652 #if HAVE_THREAD_CLEANUP_FUNCTIONS
654 // this handler is called when the thread is cancelled
655 void wxThreadInternal::PthreadCleanup(void *ptr
)
657 wxThread
*thread
= (wxThread
*) ptr
;
660 wxCriticalSectionLocker
lock(thread
->m_critsect
);
661 if ( thread
->m_internal
->GetState() == STATE_EXITED
)
663 // thread is already considered as finished.
668 // exit the thread gracefully
669 thread
->Exit(EXITCODE_CANCELLED
);
672 #endif // HAVE_THREAD_CLEANUP_FUNCTIONS
674 // ----------------------------------------------------------------------------
676 // ----------------------------------------------------------------------------
678 wxThreadInternal::wxThreadInternal()
682 m_prio
= WXTHREAD_DEFAULT_PRIORITY
;
686 // set to TRUE only when the thread starts waiting on m_condSuspend
689 // defaults for joinable threads
690 m_shouldBeJoined
= TRUE
;
691 m_shouldBroadcast
= TRUE
;
692 m_isDetached
= FALSE
;
695 wxThreadInternal::~wxThreadInternal()
699 wxThreadError
wxThreadInternal::Run()
701 wxCHECK_MSG( GetState() == STATE_NEW
, wxTHREAD_RUNNING
,
702 wxT("thread may only be started once after Create()") );
706 SetState(STATE_RUNNING
);
708 return wxTHREAD_NO_ERROR
;
711 void wxThreadInternal::Wait()
713 // if the thread we're waiting for is waiting for the GUI mutex, we will
714 // deadlock so make sure we release it temporarily
715 if ( wxThread::IsMain() )
718 bool isDetached
= m_isDetached
;
720 wxLogTrace(TRACE_THREADS
, _T("Starting to wait for thread %ld to exit."),
723 // wait until the thread terminates (we're blocking in _another_ thread,
727 wxLogTrace(TRACE_THREADS
, _T("Finished waiting for thread %ld."), id
);
729 // we can't use any member variables any more if the thread is detached
730 // because it could be already deleted
733 // to avoid memory leaks we should call pthread_join(), but it must
735 wxCriticalSectionLocker
lock(m_csJoinFlag
);
737 if ( m_shouldBeJoined
)
739 // FIXME shouldn't we set cancellation type to DISABLED here? If
740 // we're cancelled inside pthread_join(), things will almost
741 // certainly break - but if we disable the cancellation, we
743 if ( pthread_join(id
, &m_exitcode
) != 0 )
745 wxLogError(_("Failed to join a thread, potential memory leak "
746 "detected - please restart the program"));
749 m_shouldBeJoined
= FALSE
;
753 // reacquire GUI mutex
754 if ( wxThread::IsMain() )
758 void wxThreadInternal::SignalExit()
760 wxLogTrace(TRACE_THREADS
, _T("Thread %ld about to exit."), GetId());
762 SetState(STATE_EXITED
);
764 // wake up all the threads waiting for our termination - if there are any
765 if ( m_shouldBroadcast
)
767 wxLogTrace(TRACE_THREADS
, _T("Thread %ld signals end condition."),
770 m_condEnd
.Broadcast();
774 void wxThreadInternal::Pause()
776 // the state is set from the thread which pauses us first, this function
777 // is called later so the state should have been already set
778 wxCHECK_RET( m_state
== STATE_PAUSED
,
779 wxT("thread must first be paused with wxThread::Pause().") );
781 wxLogTrace(TRACE_THREADS
, _T("Thread %ld goes to sleep."), GetId());
783 // wait until the condition is signaled from Resume()
784 m_condSuspend
.Wait();
787 void wxThreadInternal::Resume()
789 wxCHECK_RET( m_state
== STATE_PAUSED
,
790 wxT("can't resume thread which is not suspended.") );
792 // the thread might be not actually paused yet - if there were no call to
793 // TestDestroy() since the last call to Pause() for example
794 if ( IsReallyPaused() )
796 wxLogTrace(TRACE_THREADS
, _T("Waking up thread %ld"), GetId());
799 m_condSuspend
.Signal();
802 SetReallyPaused(FALSE
);
806 wxLogTrace(TRACE_THREADS
, _T("Thread %ld is not yet really paused"),
810 SetState(STATE_RUNNING
);
813 // -----------------------------------------------------------------------------
814 // wxThread static functions
815 // -----------------------------------------------------------------------------
817 wxThread
*wxThread::This()
819 return (wxThread
*)pthread_getspecific(gs_keySelf
);
822 bool wxThread::IsMain()
824 return (bool)pthread_equal(pthread_self(), gs_tidMain
);
827 void wxThread::Yield()
832 void wxThread::Sleep(unsigned long milliseconds
)
834 wxUsleep(milliseconds
);
837 // -----------------------------------------------------------------------------
839 // -----------------------------------------------------------------------------
841 wxThread::wxThread(wxThreadKind kind
)
843 // add this thread to the global list of all threads
844 gs_allThreads
.Add(this);
846 m_internal
= new wxThreadInternal();
848 m_isDetached
= kind
== wxTHREAD_DETACHED
;
851 wxThreadError
wxThread::Create()
853 if ( m_internal
->GetState() != STATE_NEW
)
855 // don't recreate thread
856 return wxTHREAD_RUNNING
;
859 // set up the thread attribute: right now, we only set thread priority
861 pthread_attr_init(&attr
);
863 #ifdef HAVE_THREAD_PRIORITY_FUNCTIONS
865 if ( pthread_attr_getschedpolicy(&attr
, &policy
) != 0 )
867 wxLogError(_("Cannot retrieve thread scheduling policy."));
870 int min_prio
= sched_get_priority_min(policy
),
871 max_prio
= sched_get_priority_max(policy
),
872 prio
= m_internal
->GetPriority();
874 if ( min_prio
== -1 || max_prio
== -1 )
876 wxLogError(_("Cannot get priority range for scheduling policy %d."),
879 else if ( max_prio
== min_prio
)
881 if ( prio
!= WXTHREAD_DEFAULT_PRIORITY
)
883 // notify the programmer that this doesn't work here
884 wxLogWarning(_("Thread priority setting is ignored."));
886 //else: we have default priority, so don't complain
888 // anyhow, don't do anything because priority is just ignored
892 struct sched_param sp
;
893 if ( pthread_attr_getschedparam(&attr
, &sp
) != 0 )
895 wxFAIL_MSG(_T("pthread_attr_getschedparam() failed"));
898 sp
.sched_priority
= min_prio
+ (prio
*(max_prio
- min_prio
))/100;
900 if ( pthread_attr_setschedparam(&attr
, &sp
) != 0 )
902 wxFAIL_MSG(_T("pthread_attr_setschedparam(priority) failed"));
905 #endif // HAVE_THREAD_PRIORITY_FUNCTIONS
907 #ifdef HAVE_PTHREAD_ATTR_SETSCOPE
908 // this will make the threads created by this process really concurrent
909 if ( pthread_attr_setscope(&attr
, PTHREAD_SCOPE_SYSTEM
) != 0 )
911 wxFAIL_MSG(_T("pthread_attr_setscope(PTHREAD_SCOPE_SYSTEM) failed"));
913 #endif // HAVE_PTHREAD_ATTR_SETSCOPE
915 // VZ: assume that this one is always available (it's rather fundamental),
916 // if this function is ever missing we should try to use
917 // pthread_detach() instead (after thread creation)
920 if ( pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_DETACHED
) != 0 )
922 wxFAIL_MSG(_T("pthread_attr_setdetachstate(DETACHED) failed"));
925 // never try to join detached threads
926 m_internal
->Detach();
928 //else: threads are created joinable by default, it's ok
930 // create the new OS thread object
931 int rc
= pthread_create
933 m_internal
->GetIdPtr(),
935 wxThreadInternal::PthreadStart
,
939 if ( pthread_attr_destroy(&attr
) != 0 )
941 wxFAIL_MSG(_T("pthread_attr_destroy() failed"));
946 m_internal
->SetState(STATE_EXITED
);
948 return wxTHREAD_NO_RESOURCE
;
951 return wxTHREAD_NO_ERROR
;
954 wxThreadError
wxThread::Run()
956 wxCriticalSectionLocker
lock(m_critsect
);
958 wxCHECK_MSG( m_internal
->GetId(), wxTHREAD_MISC_ERROR
,
959 wxT("must call wxThread::Create() first") );
961 return m_internal
->Run();
964 // -----------------------------------------------------------------------------
966 // -----------------------------------------------------------------------------
968 void wxThread::SetPriority(unsigned int prio
)
970 wxCHECK_RET( ((int)WXTHREAD_MIN_PRIORITY
<= (int)prio
) &&
971 ((int)prio
<= (int)WXTHREAD_MAX_PRIORITY
),
972 wxT("invalid thread priority") );
974 wxCriticalSectionLocker
lock(m_critsect
);
976 switch ( m_internal
->GetState() )
979 // thread not yet started, priority will be set when it is
980 m_internal
->SetPriority(prio
);
985 #ifdef HAVE_THREAD_PRIORITY_FUNCTIONS
987 struct sched_param sparam
;
988 sparam
.sched_priority
= prio
;
990 if ( pthread_setschedparam(m_internal
->GetId(),
991 SCHED_OTHER
, &sparam
) != 0 )
993 wxLogError(_("Failed to set thread priority %d."), prio
);
996 #endif // HAVE_THREAD_PRIORITY_FUNCTIONS
1001 wxFAIL_MSG(wxT("impossible to set thread priority in this state"));
1005 unsigned int wxThread::GetPriority() const
1007 wxCriticalSectionLocker
lock((wxCriticalSection
&)m_critsect
);
1009 return m_internal
->GetPriority();
1012 unsigned long wxThread::GetId() const
1014 return (unsigned long)m_internal
->GetId();
1017 // -----------------------------------------------------------------------------
1019 // -----------------------------------------------------------------------------
1021 wxThreadError
wxThread::Pause()
1023 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
,
1024 _T("a thread can't pause itself") );
1026 wxCriticalSectionLocker
lock(m_critsect
);
1028 if ( m_internal
->GetState() != STATE_RUNNING
)
1030 wxLogDebug(wxT("Can't pause thread which is not running."));
1032 return wxTHREAD_NOT_RUNNING
;
1035 wxLogTrace(TRACE_THREADS
, _T("Asking thread %ld to pause."),
1038 // just set a flag, the thread will be really paused only during the next
1039 // call to TestDestroy()
1040 m_internal
->SetState(STATE_PAUSED
);
1042 return wxTHREAD_NO_ERROR
;
1045 wxThreadError
wxThread::Resume()
1047 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
,
1048 _T("a thread can't resume itself") );
1050 wxCriticalSectionLocker
lock(m_critsect
);
1052 wxThreadState state
= m_internal
->GetState();
1057 wxLogTrace(TRACE_THREADS
, _T("Thread %ld suspended, resuming."),
1060 m_internal
->Resume();
1062 return wxTHREAD_NO_ERROR
;
1065 wxLogTrace(TRACE_THREADS
, _T("Thread %ld exited, won't resume."),
1067 return wxTHREAD_NO_ERROR
;
1070 wxLogDebug(_T("Attempt to resume a thread which is not paused."));
1072 return wxTHREAD_MISC_ERROR
;
1076 // -----------------------------------------------------------------------------
1078 // -----------------------------------------------------------------------------
1080 wxThread::ExitCode
wxThread::Wait()
1082 wxCHECK_MSG( This() != this, (ExitCode
)-1,
1083 _T("a thread can't wait for itself") );
1085 wxCHECK_MSG( !m_isDetached
, (ExitCode
)-1,
1086 _T("can't wait for detached thread") );
1090 return m_internal
->GetExitCode();
1093 wxThreadError
wxThread::Delete(ExitCode
*rc
)
1095 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
,
1096 _T("a thread can't delete itself") );
1099 wxThreadState state
= m_internal
->GetState();
1101 // ask the thread to stop
1102 m_internal
->SetCancelFlag();
1106 // detached threads won't broadcast about their termination by default
1107 // because usually nobody waits for them - but here we do, so ask the
1108 // thread to notify us
1109 m_internal
->Notify();
1117 // we need to wake up the thread so that PthreadStart() will
1118 // terminate - right now it's blocking on m_condRun
1119 m_internal
->SignalRun();
1128 // resume the thread first (don't call our Resume() because this
1129 // would dead lock when it tries to enter m_critsect)
1130 m_internal
->Resume();
1135 // wait until the thread stops
1140 wxASSERT_MSG( !m_isDetached
,
1141 _T("no return code for detached threads") );
1143 // if it's a joinable thread, it's not deleted yet
1144 *rc
= m_internal
->GetExitCode();
1148 return wxTHREAD_NO_ERROR
;
1151 wxThreadError
wxThread::Kill()
1153 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
,
1154 _T("a thread can't kill itself") );
1156 switch ( m_internal
->GetState() )
1160 return wxTHREAD_NOT_RUNNING
;
1163 // resume the thread first
1169 #ifdef HAVE_PTHREAD_CANCEL
1170 if ( pthread_cancel(m_internal
->GetId()) != 0 )
1173 wxLogError(_("Failed to terminate a thread."));
1175 return wxTHREAD_MISC_ERROR
;
1180 // if we use cleanup function, this will be done from
1182 #if !HAVE_THREAD_CLEANUP_FUNCTIONS
1183 ScheduleThreadForDeletion();
1188 #endif // HAVE_THREAD_CLEANUP_FUNCTIONS
1192 m_internal
->SetExitCode(EXITCODE_CANCELLED
);
1195 return wxTHREAD_NO_ERROR
;
1199 void wxThread::Exit(ExitCode status
)
1201 wxASSERT_MSG( This() == this,
1202 _T("wxThread::Exit() can only be called in the "
1203 "context of the same thread") );
1205 // from the moment we call OnExit(), the main program may terminate at any
1206 // moment, so mark this thread as being already in process of being
1207 // deleted or wxThreadModule::OnExit() will try to delete it again
1208 ScheduleThreadForDeletion();
1210 // don't enter m_critsect before calling OnExit() because the user code
1211 // might deadlock if, for example, it signals a condition in OnExit() (a
1212 // common case) while the main thread calls any of functions entering
1213 // m_critsect on us (almost all of them do)
1216 // now do enter it because SignalExit() will change our state
1219 // next wake up the threads waiting for us (OTOH, this function won't return
1220 // until someone waited for us!)
1221 m_internal
->SignalExit();
1223 // leave the critical section before entering the dtor which tries to
1227 // delete C++ thread object if this is a detached thread - user is
1228 // responsible for doing this for joinable ones
1231 // FIXME I'm feeling bad about it - what if another thread function is
1232 // called (in another thread context) now? It will try to access
1233 // half destroyed object which will probably result in something
1234 // very bad - but we can't protect this by a crit section unless
1235 // we make it a global object, but this would mean that we can
1236 // only call one thread function at a time :-(
1240 // terminate the thread (pthread_exit() never returns)
1241 pthread_exit(status
);
1243 wxFAIL_MSG(_T("pthread_exit() failed"));
1246 // also test whether we were paused
1247 bool wxThread::TestDestroy()
1249 wxASSERT_MSG( This() == this,
1250 _T("wxThread::TestDestroy() can only be called in the "
1251 "context of the same thread") );
1255 if ( m_internal
->GetState() == STATE_PAUSED
)
1257 m_internal
->SetReallyPaused(TRUE
);
1259 // leave the crit section or the other threads will stop too if they
1260 // try to call any of (seemingly harmless) IsXXX() functions while we
1264 m_internal
->Pause();
1268 // thread wasn't requested to pause, nothing to do
1272 return m_internal
->WasCancelled();
1275 wxThread::~wxThread()
1280 // check that the thread either exited or couldn't be created
1281 if ( m_internal
->GetState() != STATE_EXITED
&&
1282 m_internal
->GetState() != STATE_NEW
)
1284 wxLogDebug(_T("The thread %ld is being destroyed although it is still "
1285 "running! The application may crash."), GetId());
1289 #endif // __WXDEBUG__
1293 // remove this thread from the global array
1294 gs_allThreads
.Remove(this);
1296 // detached thread will decrement this counter in DeleteThread(), but it
1297 // is not called for the joinable threads, so do it here
1298 if ( !m_isDetached
)
1300 MutexLock
lock(gs_mutexDeleteThread
);
1301 gs_nThreadsBeingDeleted
--;
1303 wxLogTrace(TRACE_THREADS
, _T("%u scheduled for deletion threads left."),
1304 gs_nThreadsBeingDeleted
- 1);
1308 // -----------------------------------------------------------------------------
1310 // -----------------------------------------------------------------------------
1312 bool wxThread::IsRunning() const
1314 wxCriticalSectionLocker
lock((wxCriticalSection
&)m_critsect
);
1316 return m_internal
->GetState() == STATE_RUNNING
;
1319 bool wxThread::IsAlive() const
1321 wxCriticalSectionLocker
lock((wxCriticalSection
&)m_critsect
);
1323 switch ( m_internal
->GetState() )
1334 bool wxThread::IsPaused() const
1336 wxCriticalSectionLocker
lock((wxCriticalSection
&)m_critsect
);
1338 return (m_internal
->GetState() == STATE_PAUSED
);
1341 //--------------------------------------------------------------------
1343 //--------------------------------------------------------------------
1345 class wxThreadModule
: public wxModule
1348 virtual bool OnInit();
1349 virtual void OnExit();
1352 DECLARE_DYNAMIC_CLASS(wxThreadModule
)
1355 IMPLEMENT_DYNAMIC_CLASS(wxThreadModule
, wxModule
)
1357 bool wxThreadModule::OnInit()
1359 int rc
= pthread_key_create(&gs_keySelf
, NULL
/* dtor function */);
1362 wxLogSysError(rc
, _("Thread module initialization failed: "
1363 "failed to create thread key"));
1368 gs_tidMain
= pthread_self();
1371 gs_mutexGui
= new wxMutex();
1373 gs_mutexGui
->Lock();
1379 void wxThreadModule::OnExit()
1381 wxASSERT_MSG( wxThread::IsMain(), wxT("only main thread can be here") );
1383 // are there any threads left which are being deleted right now?
1384 size_t nThreadsBeingDeleted
;
1386 MutexLock
lock(gs_mutexDeleteThread
);
1387 nThreadsBeingDeleted
= gs_nThreadsBeingDeleted
;
1390 if ( nThreadsBeingDeleted
> 0 )
1392 wxLogTrace(TRACE_THREADS
, _T("Waiting for %u threads to disappear"),
1393 nThreadsBeingDeleted
);
1395 // have to wait until all of them disappear
1396 gs_condAllDeleted
->Wait();
1399 // terminate any threads left
1400 size_t count
= gs_allThreads
.GetCount();
1403 wxLogDebug(wxT("%u threads were not terminated by the application."),
1407 for ( size_t n
= 0u; n
< count
; n
++ )
1409 // Delete calls the destructor which removes the current entry. We
1410 // should only delete the first one each time.
1411 gs_allThreads
[0]->Delete();
1415 // destroy GUI mutex
1416 gs_mutexGui
->Unlock();
1421 // and free TLD slot
1422 (void)pthread_key_delete(gs_keySelf
);
1425 // ----------------------------------------------------------------------------
1427 // ----------------------------------------------------------------------------
1429 static void ScheduleThreadForDeletion()
1431 MutexLock
lock(gs_mutexDeleteThread
);
1433 if ( gs_nThreadsBeingDeleted
== 0 )
1435 gs_condAllDeleted
= new wxCondition
;
1438 gs_nThreadsBeingDeleted
++;
1440 wxLogTrace(TRACE_THREADS
, _T("%u thread%s waiting to be deleted"),
1441 gs_nThreadsBeingDeleted
,
1442 gs_nThreadsBeingDeleted
== 1 ? "" : "s");
1445 static void DeleteThread(wxThread
*This
)
1447 // gs_mutexDeleteThread should be unlocked before signalling the condition
1448 // or wxThreadModule::OnExit() would deadlock
1450 MutexLock
lock(gs_mutexDeleteThread
);
1452 wxLogTrace(TRACE_THREADS
, _T("Thread %ld auto deletes."), This
->GetId());
1456 wxCHECK_RET( gs_nThreadsBeingDeleted
> 0,
1457 _T("no threads scheduled for deletion, yet we delete "
1461 wxLogTrace(TRACE_THREADS
, _T("%u scheduled for deletion threads left."),
1462 gs_nThreadsBeingDeleted
- 1);
1464 if ( !--gs_nThreadsBeingDeleted
)
1466 // no more threads left, signal it
1467 gs_condAllDeleted
->Signal();
1469 delete gs_condAllDeleted
;
1470 gs_condAllDeleted
= (wxCondition
*)NULL
;
1474 void wxMutexGuiEnter()
1477 gs_mutexGui
->Lock();
1481 void wxMutexGuiLeave()
1484 gs_mutexGui
->Unlock();