]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/unix/threadpsx.cpp
Workaround for #15404: wxRichTextCtrl: caret does not disappear when focus is lost...
[wxWidgets.git] / src / unix / threadpsx.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: src/unix/threadpsx.cpp
3// Purpose: wxThread (Posix) Implementation
4// Author: Original from Wolfram Gloger/Guilhem Lavaux
5// Modified by: K. S. Sreeram (2002): POSIXified wxCondition, added wxSemaphore
6// Created: 04/22/98
7// Copyright: (c) Wolfram Gloger (1996, 1997)
8// Guilhem Lavaux (1998)
9// Vadim Zeitlin (1999-2002)
10// Robert Roebling (1999)
11// K. S. Sreeram (2002)
12// Licence: wxWindows licence
13/////////////////////////////////////////////////////////////////////////////
14
15// ============================================================================
16// declaration
17// ============================================================================
18
19// ----------------------------------------------------------------------------
20// headers
21// ----------------------------------------------------------------------------
22
23// for compilers that support precompilation, includes "wx.h".
24#include "wx/wxprec.h"
25
26#if wxUSE_THREADS
27
28#include "wx/thread.h"
29#include "wx/except.h"
30
31#ifndef WX_PRECOMP
32 #include "wx/app.h"
33 #include "wx/dynarray.h"
34 #include "wx/intl.h"
35 #include "wx/log.h"
36 #include "wx/utils.h"
37 #include "wx/timer.h"
38 #include "wx/stopwatch.h"
39 #include "wx/module.h"
40#endif
41
42#include <stdio.h>
43#include <unistd.h>
44#include <pthread.h>
45#include <errno.h>
46#include <time.h>
47#include <sys/time.h> // needed for at least __QNX__
48#ifdef HAVE_SCHED_H
49 #include <sched.h>
50#endif
51
52#ifdef HAVE_THR_SETCONCURRENCY
53 #include <thread.h>
54#endif
55
56#ifdef HAVE_ABI_FORCEDUNWIND
57 #include <cxxabi.h>
58#endif
59
60#ifdef HAVE_SETPRIORITY
61 #include <sys/resource.h> // for setpriority()
62#endif
63
64// we use wxFFile under Linux in GetCPUCount()
65#ifdef __LINUX__
66 #include "wx/ffile.h"
67#endif
68
69#define THR_ID_CAST(id) (reinterpret_cast<void*>(id))
70#define THR_ID(thr) THR_ID_CAST((thr)->GetId())
71
72// ----------------------------------------------------------------------------
73// constants
74// ----------------------------------------------------------------------------
75
76// the possible states of the thread and transitions from them
77enum wxThreadState
78{
79 STATE_NEW, // didn't start execution yet (=> RUNNING)
80 STATE_RUNNING, // running (=> PAUSED or EXITED)
81 STATE_PAUSED, // suspended (=> RUNNING or EXITED)
82 STATE_EXITED // thread doesn't exist any more
83};
84
85// the exit value of a thread which has been cancelled
86static const wxThread::ExitCode EXITCODE_CANCELLED = (wxThread::ExitCode)-1;
87
88// trace mask for wxThread operations
89#define TRACE_THREADS wxT("thread")
90
91// you can get additional debugging messages for the semaphore operations
92#define TRACE_SEMA wxT("semaphore")
93
94// ----------------------------------------------------------------------------
95// private functions
96// ----------------------------------------------------------------------------
97
98static void ScheduleThreadForDeletion();
99static void DeleteThread(wxThread *This);
100
101// ----------------------------------------------------------------------------
102// private classes
103// ----------------------------------------------------------------------------
104
105// an (non owning) array of pointers to threads
106WX_DEFINE_ARRAY_PTR(wxThread *, wxArrayThread);
107
108// an entry for a thread we can wait for
109
110// -----------------------------------------------------------------------------
111// global data
112// -----------------------------------------------------------------------------
113
114// we keep the list of all threads created by the application to be able to
115// terminate them on exit if there are some left - otherwise the process would
116// be left in memory
117static wxArrayThread gs_allThreads;
118
119// a mutex to protect gs_allThreads
120static wxMutex *gs_mutexAllThreads = NULL;
121
122// the id of the main thread
123//
124// we suppose that 0 is not a valid pthread_t value but in principle this might
125// be false (e.g. if it's a selector-like value), wxThread::IsMain() would need
126// to be updated in such case
127wxThreadIdType wxThread::ms_idMainThread = 0;
128
129// the key for the pointer to the associated wxThread object
130static pthread_key_t gs_keySelf;
131
132// the number of threads which are being deleted - the program won't exit
133// until there are any left
134static size_t gs_nThreadsBeingDeleted = 0;
135
136// a mutex to protect gs_nThreadsBeingDeleted
137static wxMutex *gs_mutexDeleteThread = NULL;
138
139// and a condition variable which will be signaled when all
140// gs_nThreadsBeingDeleted will have been deleted
141static wxCondition *gs_condAllDeleted = NULL;
142
143#ifndef __WXOSX__
144// this mutex must be acquired before any call to a GUI function
145// (it's not inside #if wxUSE_GUI because this file is compiled as part
146// of wxBase)
147static wxMutex *gs_mutexGui = NULL;
148#endif
149
150// when we wait for a thread to exit, we're blocking on a condition which the
151// thread signals in its SignalExit() method -- but this condition can't be a
152// member of the thread itself as a detached thread may delete itself at any
153// moment and accessing the condition member of the thread after this would
154// result in a disaster
155//
156// so instead we maintain a global list of the structs below for the threads
157// we're interested in waiting on
158
159// ============================================================================
160// wxMutex implementation
161// ============================================================================
162
163// ----------------------------------------------------------------------------
164// wxMutexInternal
165// ----------------------------------------------------------------------------
166
167// this is a simple wrapper around pthread_mutex_t which provides error
168// checking
169class wxMutexInternal
170{
171public:
172 wxMutexInternal(wxMutexType mutexType);
173 ~wxMutexInternal();
174
175 wxMutexError Lock();
176 wxMutexError Lock(unsigned long ms);
177 wxMutexError TryLock();
178 wxMutexError Unlock();
179
180 bool IsOk() const { return m_isOk; }
181
182private:
183 // convert the result of pthread_mutex_[timed]lock() call to wx return code
184 wxMutexError HandleLockResult(int err);
185
186private:
187 pthread_mutex_t m_mutex;
188 bool m_isOk;
189 wxMutexType m_type;
190 unsigned long m_owningThread;
191
192 // wxConditionInternal uses our m_mutex
193 friend class wxConditionInternal;
194};
195
196#if defined(HAVE_PTHREAD_MUTEXATTR_T) && \
197 wxUSE_UNIX && !defined(HAVE_PTHREAD_MUTEXATTR_SETTYPE_DECL)
198// on some systems pthread_mutexattr_settype() is not in the headers (but it is
199// in the library, otherwise we wouldn't compile this code at all)
200extern "C" int pthread_mutexattr_settype(pthread_mutexattr_t *, int);
201#endif
202
203wxMutexInternal::wxMutexInternal(wxMutexType mutexType)
204{
205 m_type = mutexType;
206 m_owningThread = 0;
207
208 int err;
209 switch ( mutexType )
210 {
211 case wxMUTEX_RECURSIVE:
212 // support recursive locks like Win32, i.e. a thread can lock a
213 // mutex which it had itself already locked
214 //
215 // unfortunately initialization of recursive mutexes is non
216 // portable, so try several methods
217#ifdef HAVE_PTHREAD_MUTEXATTR_T
218 {
219 pthread_mutexattr_t attr;
220 pthread_mutexattr_init(&attr);
221 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
222
223 err = pthread_mutex_init(&m_mutex, &attr);
224 }
225#elif defined(HAVE_PTHREAD_RECURSIVE_MUTEX_INITIALIZER)
226 // we can use this only as initializer so we have to assign it
227 // first to a temp var - assigning directly to m_mutex wouldn't
228 // even compile
229 {
230 pthread_mutex_t mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
231 m_mutex = mutex;
232 }
233#else // no recursive mutexes
234 err = EINVAL;
235#endif // HAVE_PTHREAD_MUTEXATTR_T/...
236 break;
237
238 default:
239 wxFAIL_MSG( wxT("unknown mutex type") );
240 // fall through
241
242 case wxMUTEX_DEFAULT:
243 err = pthread_mutex_init(&m_mutex, NULL);
244 break;
245 }
246
247 m_isOk = err == 0;
248 if ( !m_isOk )
249 {
250 wxLogApiError( wxT("pthread_mutex_init()"), err);
251 }
252}
253
254wxMutexInternal::~wxMutexInternal()
255{
256 if ( m_isOk )
257 {
258 int err = pthread_mutex_destroy(&m_mutex);
259 if ( err != 0 )
260 {
261 wxLogApiError( wxT("pthread_mutex_destroy()"), err);
262 }
263 }
264}
265
266wxMutexError wxMutexInternal::Lock()
267{
268 if ((m_type == wxMUTEX_DEFAULT) && (m_owningThread != 0))
269 {
270 if (m_owningThread == wxThread::GetCurrentId())
271 return wxMUTEX_DEAD_LOCK;
272 }
273
274 return HandleLockResult(pthread_mutex_lock(&m_mutex));
275}
276
277wxMutexError wxMutexInternal::Lock(unsigned long ms)
278{
279#ifdef HAVE_PTHREAD_MUTEX_TIMEDLOCK
280 static const long MSEC_IN_SEC = 1000;
281 static const long NSEC_IN_MSEC = 1000000;
282 static const long NSEC_IN_USEC = 1000;
283 static const long NSEC_IN_SEC = MSEC_IN_SEC * NSEC_IN_MSEC;
284
285 time_t seconds = ms/MSEC_IN_SEC;
286 long nanoseconds = (ms % MSEC_IN_SEC) * NSEC_IN_MSEC;
287 timespec ts = { 0, 0 };
288
289 // normally we should use clock_gettime(CLOCK_REALTIME) here but this
290 // function is in librt and we don't link with it currently, so use
291 // gettimeofday() instead -- if it turns out that this is really too
292 // imprecise, we should modify configure to check if clock_gettime() is
293 // available and whether it requires -lrt and use it instead
294#if 0
295 if ( clock_gettime(CLOCK_REALTIME, &ts) == 0 )
296 {
297 }
298#else
299 struct timeval tv;
300 if ( wxGetTimeOfDay(&tv) != -1 )
301 {
302 ts.tv_sec = tv.tv_sec;
303 ts.tv_nsec = tv.tv_usec*NSEC_IN_USEC;
304 }
305#endif
306 else // fall back on system timer
307 {
308 ts.tv_sec = time(NULL);
309 }
310
311 ts.tv_sec += seconds;
312 ts.tv_nsec += nanoseconds;
313 if ( ts.tv_nsec > NSEC_IN_SEC )
314 {
315 ts.tv_sec += 1;
316 ts.tv_nsec -= NSEC_IN_SEC;
317 }
318
319 return HandleLockResult(pthread_mutex_timedlock(&m_mutex, &ts));
320#else // !HAVE_PTHREAD_MUTEX_TIMEDLOCK
321 wxUnusedVar(ms);
322
323 return wxMUTEX_MISC_ERROR;
324#endif // HAVE_PTHREAD_MUTEX_TIMEDLOCK/!HAVE_PTHREAD_MUTEX_TIMEDLOCK
325}
326
327wxMutexError wxMutexInternal::HandleLockResult(int err)
328{
329 // wxPrintf( "err %d\n", err );
330
331 switch ( err )
332 {
333 case EDEADLK:
334 // only error checking mutexes return this value and so it's an
335 // unexpected situation -- hence use assert, not wxLogDebug
336 wxFAIL_MSG( wxT("mutex deadlock prevented") );
337 return wxMUTEX_DEAD_LOCK;
338
339 case EINVAL:
340 wxLogDebug(wxT("pthread_mutex_[timed]lock(): mutex not initialized"));
341 break;
342
343 case ETIMEDOUT:
344 return wxMUTEX_TIMEOUT;
345
346 case 0:
347 if (m_type == wxMUTEX_DEFAULT)
348 m_owningThread = wxThread::GetCurrentId();
349 return wxMUTEX_NO_ERROR;
350
351 default:
352 wxLogApiError(wxT("pthread_mutex_[timed]lock()"), err);
353 }
354
355 return wxMUTEX_MISC_ERROR;
356}
357
358
359wxMutexError wxMutexInternal::TryLock()
360{
361 int err = pthread_mutex_trylock(&m_mutex);
362 switch ( err )
363 {
364 case EBUSY:
365 // not an error: mutex is already locked, but we're prepared for
366 // this
367 return wxMUTEX_BUSY;
368
369 case EINVAL:
370 wxLogDebug(wxT("pthread_mutex_trylock(): mutex not initialized."));
371 break;
372
373 case 0:
374 if (m_type == wxMUTEX_DEFAULT)
375 m_owningThread = wxThread::GetCurrentId();
376 return wxMUTEX_NO_ERROR;
377
378 default:
379 wxLogApiError(wxT("pthread_mutex_trylock()"), err);
380 }
381
382 return wxMUTEX_MISC_ERROR;
383}
384
385wxMutexError wxMutexInternal::Unlock()
386{
387 m_owningThread = 0;
388
389 int err = pthread_mutex_unlock(&m_mutex);
390 switch ( err )
391 {
392 case EPERM:
393 // we don't own the mutex
394 return wxMUTEX_UNLOCKED;
395
396 case EINVAL:
397 wxLogDebug(wxT("pthread_mutex_unlock(): mutex not initialized."));
398 break;
399
400 case 0:
401 return wxMUTEX_NO_ERROR;
402
403 default:
404 wxLogApiError(wxT("pthread_mutex_unlock()"), err);
405 }
406
407 return wxMUTEX_MISC_ERROR;
408}
409
410// ===========================================================================
411// wxCondition implementation
412// ===========================================================================
413
414// ---------------------------------------------------------------------------
415// wxConditionInternal
416// ---------------------------------------------------------------------------
417
418// this is a wrapper around pthread_cond_t associated with a wxMutex (and hence
419// with a pthread_mutex_t)
420class wxConditionInternal
421{
422public:
423 wxConditionInternal(wxMutex& mutex);
424 ~wxConditionInternal();
425
426 bool IsOk() const { return m_isOk && m_mutex.IsOk(); }
427
428 wxCondError Wait();
429 wxCondError WaitTimeout(unsigned long milliseconds);
430
431 wxCondError Signal();
432 wxCondError Broadcast();
433
434private:
435 // get the POSIX mutex associated with us
436 pthread_mutex_t *GetPMutex() const { return &m_mutex.m_internal->m_mutex; }
437
438 wxMutex& m_mutex;
439 pthread_cond_t m_cond;
440
441 bool m_isOk;
442};
443
444wxConditionInternal::wxConditionInternal(wxMutex& mutex)
445 : m_mutex(mutex)
446{
447 int err = pthread_cond_init(&m_cond, NULL /* default attributes */);
448
449 m_isOk = err == 0;
450
451 if ( !m_isOk )
452 {
453 wxLogApiError(wxT("pthread_cond_init()"), err);
454 }
455}
456
457wxConditionInternal::~wxConditionInternal()
458{
459 if ( m_isOk )
460 {
461 int err = pthread_cond_destroy(&m_cond);
462 if ( err != 0 )
463 {
464 wxLogApiError(wxT("pthread_cond_destroy()"), err);
465 }
466 }
467}
468
469wxCondError wxConditionInternal::Wait()
470{
471 int err = pthread_cond_wait(&m_cond, GetPMutex());
472 if ( err != 0 )
473 {
474 wxLogApiError(wxT("pthread_cond_wait()"), err);
475
476 return wxCOND_MISC_ERROR;
477 }
478
479 return wxCOND_NO_ERROR;
480}
481
482wxCondError wxConditionInternal::WaitTimeout(unsigned long milliseconds)
483{
484 wxLongLong curtime = wxGetUTCTimeMillis();
485 curtime += milliseconds;
486 wxLongLong temp = curtime / 1000;
487 int sec = temp.GetLo();
488 temp *= 1000;
489 temp = curtime - temp;
490 int millis = temp.GetLo();
491
492 timespec tspec;
493
494 tspec.tv_sec = sec;
495 tspec.tv_nsec = millis * 1000L * 1000L;
496
497 int err = pthread_cond_timedwait( &m_cond, GetPMutex(), &tspec );
498 switch ( err )
499 {
500 case ETIMEDOUT:
501 return wxCOND_TIMEOUT;
502
503 case 0:
504 return wxCOND_NO_ERROR;
505
506 default:
507 wxLogApiError(wxT("pthread_cond_timedwait()"), err);
508 }
509
510 return wxCOND_MISC_ERROR;
511}
512
513wxCondError wxConditionInternal::Signal()
514{
515 int err = pthread_cond_signal(&m_cond);
516 if ( err != 0 )
517 {
518 wxLogApiError(wxT("pthread_cond_signal()"), err);
519
520 return wxCOND_MISC_ERROR;
521 }
522
523 return wxCOND_NO_ERROR;
524}
525
526wxCondError wxConditionInternal::Broadcast()
527{
528 int err = pthread_cond_broadcast(&m_cond);
529 if ( err != 0 )
530 {
531 wxLogApiError(wxT("pthread_cond_broadcast()"), err);
532
533 return wxCOND_MISC_ERROR;
534 }
535
536 return wxCOND_NO_ERROR;
537}
538
539// ===========================================================================
540// wxSemaphore implementation
541// ===========================================================================
542
543// ---------------------------------------------------------------------------
544// wxSemaphoreInternal
545// ---------------------------------------------------------------------------
546
547// we implement the semaphores using mutexes and conditions instead of using
548// the sem_xxx() POSIX functions because they're not widely available and also
549// because it's impossible to implement WaitTimeout() using them
550class wxSemaphoreInternal
551{
552public:
553 wxSemaphoreInternal(int initialcount, int maxcount);
554
555 bool IsOk() const { return m_isOk; }
556
557 wxSemaError Wait();
558 wxSemaError TryWait();
559 wxSemaError WaitTimeout(unsigned long milliseconds);
560
561 wxSemaError Post();
562
563private:
564 wxMutex m_mutex;
565 wxCondition m_cond;
566
567 size_t m_count,
568 m_maxcount;
569
570 bool m_isOk;
571};
572
573wxSemaphoreInternal::wxSemaphoreInternal(int initialcount, int maxcount)
574 : m_cond(m_mutex)
575{
576
577 if ( (initialcount < 0 || maxcount < 0) ||
578 ((maxcount > 0) && (initialcount > maxcount)) )
579 {
580 wxFAIL_MSG( wxT("wxSemaphore: invalid initial or maximal count") );
581
582 m_isOk = false;
583 }
584 else
585 {
586 m_maxcount = (size_t)maxcount;
587 m_count = (size_t)initialcount;
588 }
589
590 m_isOk = m_mutex.IsOk() && m_cond.IsOk();
591}
592
593wxSemaError wxSemaphoreInternal::Wait()
594{
595 wxMutexLocker locker(m_mutex);
596
597 while ( m_count == 0 )
598 {
599 wxLogTrace(TRACE_SEMA,
600 wxT("Thread %p waiting for semaphore to become signalled"),
601 THR_ID_CAST(wxThread::GetCurrentId()));
602
603 if ( m_cond.Wait() != wxCOND_NO_ERROR )
604 return wxSEMA_MISC_ERROR;
605
606 wxLogTrace(TRACE_SEMA,
607 wxT("Thread %p finished waiting for semaphore, count = %lu"),
608 THR_ID_CAST(wxThread::GetCurrentId()), (unsigned long)m_count);
609 }
610
611 m_count--;
612
613 return wxSEMA_NO_ERROR;
614}
615
616wxSemaError wxSemaphoreInternal::TryWait()
617{
618 wxMutexLocker locker(m_mutex);
619
620 if ( m_count == 0 )
621 return wxSEMA_BUSY;
622
623 m_count--;
624
625 return wxSEMA_NO_ERROR;
626}
627
628wxSemaError wxSemaphoreInternal::WaitTimeout(unsigned long milliseconds)
629{
630 wxMutexLocker locker(m_mutex);
631
632 wxLongLong startTime = wxGetLocalTimeMillis();
633
634 while ( m_count == 0 )
635 {
636 wxLongLong elapsed = wxGetLocalTimeMillis() - startTime;
637 long remainingTime = (long)milliseconds - (long)elapsed.GetLo();
638 if ( remainingTime <= 0 )
639 {
640 // timeout
641 return wxSEMA_TIMEOUT;
642 }
643
644 switch ( m_cond.WaitTimeout(remainingTime) )
645 {
646 case wxCOND_TIMEOUT:
647 return wxSEMA_TIMEOUT;
648
649 default:
650 return wxSEMA_MISC_ERROR;
651
652 case wxCOND_NO_ERROR:
653 ;
654 }
655 }
656
657 m_count--;
658
659 return wxSEMA_NO_ERROR;
660}
661
662wxSemaError wxSemaphoreInternal::Post()
663{
664 wxMutexLocker locker(m_mutex);
665
666 if ( m_maxcount > 0 && m_count == m_maxcount )
667 {
668 return wxSEMA_OVERFLOW;
669 }
670
671 m_count++;
672
673 wxLogTrace(TRACE_SEMA,
674 wxT("Thread %p about to signal semaphore, count = %lu"),
675 THR_ID_CAST(wxThread::GetCurrentId()), (unsigned long)m_count);
676
677 return m_cond.Signal() == wxCOND_NO_ERROR ? wxSEMA_NO_ERROR
678 : wxSEMA_MISC_ERROR;
679}
680
681// ===========================================================================
682// wxThread implementation
683// ===========================================================================
684
685// the thread callback functions must have the C linkage
686extern "C"
687{
688
689#ifdef wxHAVE_PTHREAD_CLEANUP
690 // thread exit function
691 void wxPthreadCleanup(void *ptr);
692#endif // wxHAVE_PTHREAD_CLEANUP
693
694void *wxPthreadStart(void *ptr);
695
696} // extern "C"
697
698// ----------------------------------------------------------------------------
699// wxThreadInternal
700// ----------------------------------------------------------------------------
701
702class wxThreadInternal
703{
704public:
705 wxThreadInternal();
706 ~wxThreadInternal();
707
708 // thread entry function
709 static void *PthreadStart(wxThread *thread);
710
711 // thread actions
712 // create the thread
713 wxThreadError Create(wxThread *thread, unsigned int stackSize);
714 // start the thread
715 wxThreadError Run();
716 // unblock the thread allowing it to run
717 void SignalRun() { m_semRun.Post(); }
718 // ask the thread to terminate
719 void Wait();
720 // go to sleep until Resume() is called
721 void Pause();
722 // resume the thread
723 void Resume();
724
725 // accessors
726 // priority
727 int GetPriority() const { return m_prio; }
728 void SetPriority(int prio) { m_prio = prio; }
729 // state
730 wxThreadState GetState() const { return m_state; }
731 void SetState(wxThreadState state)
732 {
733#if wxUSE_LOG_TRACE
734 static const wxChar *const stateNames[] =
735 {
736 wxT("NEW"),
737 wxT("RUNNING"),
738 wxT("PAUSED"),
739 wxT("EXITED"),
740 };
741
742 wxLogTrace(TRACE_THREADS, wxT("Thread %p: %s => %s."),
743 THR_ID(this), stateNames[m_state], stateNames[state]);
744#endif // wxUSE_LOG_TRACE
745
746 m_state = state;
747 }
748 // id
749 pthread_t GetId() const { return m_threadId; }
750 pthread_t *GetIdPtr() { return &m_threadId; }
751 // "created" flag
752 bool WasCreated() const { return m_created; }
753 // "cancelled" flag
754 void SetCancelFlag() { m_cancelled = true; }
755 bool WasCancelled() const { return m_cancelled; }
756 // exit code
757 void SetExitCode(wxThread::ExitCode exitcode) { m_exitcode = exitcode; }
758 wxThread::ExitCode GetExitCode() const { return m_exitcode; }
759
760 // the pause flag
761 void SetReallyPaused(bool paused) { m_isPaused = paused; }
762 bool IsReallyPaused() const { return m_isPaused; }
763
764 // tell the thread that it is a detached one
765 void Detach()
766 {
767 wxCriticalSectionLocker lock(m_csJoinFlag);
768
769 m_shouldBeJoined = false;
770 m_isDetached = true;
771 }
772
773#ifdef wxHAVE_PTHREAD_CLEANUP
774 // this is used by wxPthreadCleanup() only
775 static void Cleanup(wxThread *thread);
776#endif // wxHAVE_PTHREAD_CLEANUP
777
778private:
779 pthread_t m_threadId; // id of the thread
780 wxThreadState m_state; // see wxThreadState enum
781 int m_prio; // in wxWidgets units: from 0 to 100
782
783 // this flag is set when the thread was successfully created
784 bool m_created;
785
786 // this flag is set when the thread should terminate
787 bool m_cancelled;
788
789 // this flag is set when the thread is blocking on m_semSuspend
790 bool m_isPaused;
791
792 // the thread exit code - only used for joinable (!detached) threads and
793 // is only valid after the thread termination
794 wxThread::ExitCode m_exitcode;
795
796 // many threads may call Wait(), but only one of them should call
797 // pthread_join(), so we have to keep track of this
798 wxCriticalSection m_csJoinFlag;
799 bool m_shouldBeJoined;
800 bool m_isDetached;
801
802 // this semaphore is posted by Run() and the threads Entry() is not
803 // called before it is done
804 wxSemaphore m_semRun;
805
806 // this one is signaled when the thread should resume after having been
807 // Pause()d
808 wxSemaphore m_semSuspend;
809};
810
811// ----------------------------------------------------------------------------
812// thread startup and exit functions
813// ----------------------------------------------------------------------------
814
815void *wxPthreadStart(void *ptr)
816{
817 return wxThreadInternal::PthreadStart((wxThread *)ptr);
818}
819
820void *wxThreadInternal::PthreadStart(wxThread *thread)
821{
822 wxThreadInternal *pthread = thread->m_internal;
823
824 wxLogTrace(TRACE_THREADS, wxT("Thread %p started."), THR_ID(pthread));
825
826 // associate the thread pointer with the newly created thread so that
827 // wxThread::This() will work
828 int rc = pthread_setspecific(gs_keySelf, thread);
829 if ( rc != 0 )
830 {
831 wxLogSysError(rc, _("Cannot start thread: error writing TLS."));
832
833 return (void *)-1;
834 }
835
836 // have to declare this before pthread_cleanup_push() which defines a
837 // block!
838 bool dontRunAtAll;
839
840#ifdef wxHAVE_PTHREAD_CLEANUP
841 // install the cleanup handler which will be called if the thread is
842 // cancelled
843 pthread_cleanup_push(wxPthreadCleanup, thread);
844#endif // wxHAVE_PTHREAD_CLEANUP
845
846 // wait for the semaphore to be posted from Run()
847 pthread->m_semRun.Wait();
848
849 // test whether we should run the run at all - may be it was deleted
850 // before it started to Run()?
851 {
852 wxCriticalSectionLocker lock(thread->m_critsect);
853
854 dontRunAtAll = pthread->GetState() == STATE_NEW &&
855 pthread->WasCancelled();
856 }
857
858 if ( !dontRunAtAll )
859 {
860 // call the main entry
861 wxLogTrace(TRACE_THREADS,
862 wxT("Thread %p about to enter its Entry()."),
863 THR_ID(pthread));
864
865 wxTRY
866 {
867 pthread->m_exitcode = thread->Entry();
868
869 wxLogTrace(TRACE_THREADS,
870 wxT("Thread %p Entry() returned %lu."),
871 THR_ID(pthread), wxPtrToUInt(pthread->m_exitcode));
872 }
873#ifdef HAVE_ABI_FORCEDUNWIND
874 // When using common C++ ABI under Linux we must always rethrow this
875 // special exception used to unwind the stack when the thread was
876 // cancelled, otherwise the thread library would simply terminate the
877 // program, see http://udrepper.livejournal.com/21541.html
878 catch ( abi::__forced_unwind& )
879 {
880 wxCriticalSectionLocker lock(thread->m_critsect);
881 pthread->SetState(STATE_EXITED);
882 throw;
883 }
884#endif // HAVE_ABI_FORCEDUNWIND
885 wxCATCH_ALL( wxTheApp->OnUnhandledException(); )
886
887 {
888 wxCriticalSectionLocker lock(thread->m_critsect);
889
890 // change the state of the thread to "exited" so that
891 // wxPthreadCleanup handler won't do anything from now (if it's
892 // called before we do pthread_cleanup_pop below)
893 pthread->SetState(STATE_EXITED);
894 }
895 }
896
897 // NB: pthread_cleanup_push/pop() are macros and pop contains the matching
898 // '}' for the '{' in push, so they must be used in the same block!
899#ifdef wxHAVE_PTHREAD_CLEANUP
900 #ifdef __DECCXX
901 // under Tru64 we get a warning from macro expansion
902 #pragma message save
903 #pragma message disable(declbutnotref)
904 #endif
905
906 // remove the cleanup handler without executing it
907 pthread_cleanup_pop(FALSE);
908
909 #ifdef __DECCXX
910 #pragma message restore
911 #endif
912#endif // wxHAVE_PTHREAD_CLEANUP
913
914 if ( dontRunAtAll )
915 {
916 // FIXME: deleting a possibly joinable thread here???
917 delete thread;
918
919 return EXITCODE_CANCELLED;
920 }
921 else
922 {
923 // terminate the thread
924 thread->Exit(pthread->m_exitcode);
925
926 wxFAIL_MSG(wxT("wxThread::Exit() can't return."));
927
928 return NULL;
929 }
930}
931
932#ifdef wxHAVE_PTHREAD_CLEANUP
933
934// this handler is called when the thread is cancelled
935extern "C" void wxPthreadCleanup(void *ptr)
936{
937 wxThreadInternal::Cleanup((wxThread *)ptr);
938}
939
940void wxThreadInternal::Cleanup(wxThread *thread)
941{
942 if (pthread_getspecific(gs_keySelf) == 0) return;
943 {
944 wxCriticalSectionLocker lock(thread->m_critsect);
945 if ( thread->m_internal->GetState() == STATE_EXITED )
946 {
947 // thread is already considered as finished.
948 return;
949 }
950 }
951
952 // exit the thread gracefully
953 thread->Exit(EXITCODE_CANCELLED);
954}
955
956#endif // wxHAVE_PTHREAD_CLEANUP
957
958// ----------------------------------------------------------------------------
959// wxThreadInternal
960// ----------------------------------------------------------------------------
961
962wxThreadInternal::wxThreadInternal()
963{
964 m_state = STATE_NEW;
965 m_created = false;
966 m_cancelled = false;
967 m_prio = wxPRIORITY_DEFAULT;
968 m_threadId = 0;
969 m_exitcode = 0;
970
971 // set to true only when the thread starts waiting on m_semSuspend
972 m_isPaused = false;
973
974 // defaults for joinable threads
975 m_shouldBeJoined = true;
976 m_isDetached = false;
977}
978
979wxThreadInternal::~wxThreadInternal()
980{
981}
982
983#ifdef HAVE_PTHREAD_ATTR_SETSTACKSIZE
984 #define WXUNUSED_STACKSIZE(identifier) identifier
985#else
986 #define WXUNUSED_STACKSIZE(identifier) WXUNUSED(identifier)
987#endif
988
989wxThreadError wxThreadInternal::Create(wxThread *thread,
990 unsigned int WXUNUSED_STACKSIZE(stackSize))
991{
992 if ( GetState() != STATE_NEW )
993 {
994 // don't recreate thread
995 return wxTHREAD_RUNNING;
996 }
997
998 // set up the thread attribute: right now, we only set thread priority
999 pthread_attr_t attr;
1000 pthread_attr_init(&attr);
1001
1002#ifdef HAVE_PTHREAD_ATTR_SETSTACKSIZE
1003 if (stackSize)
1004 pthread_attr_setstacksize(&attr, stackSize);
1005#endif
1006
1007#ifdef HAVE_THREAD_PRIORITY_FUNCTIONS
1008 int policy;
1009 if ( pthread_attr_getschedpolicy(&attr, &policy) != 0 )
1010 {
1011 wxLogError(_("Cannot retrieve thread scheduling policy."));
1012 }
1013
1014#ifdef __VMS__
1015 /* the pthread.h contains too many spaces. This is a work-around */
1016# undef sched_get_priority_max
1017#undef sched_get_priority_min
1018#define sched_get_priority_max(_pol_) \
1019 (_pol_ == SCHED_OTHER ? PRI_FG_MAX_NP : PRI_FIFO_MAX)
1020#define sched_get_priority_min(_pol_) \
1021 (_pol_ == SCHED_OTHER ? PRI_FG_MIN_NP : PRI_FIFO_MIN)
1022#endif
1023
1024 int max_prio = sched_get_priority_max(policy),
1025 min_prio = sched_get_priority_min(policy),
1026 prio = GetPriority();
1027
1028 if ( min_prio == -1 || max_prio == -1 )
1029 {
1030 wxLogError(_("Cannot get priority range for scheduling policy %d."),
1031 policy);
1032 }
1033 else if ( max_prio == min_prio )
1034 {
1035 if ( prio != wxPRIORITY_DEFAULT )
1036 {
1037 // notify the programmer that this doesn't work here
1038 wxLogWarning(_("Thread priority setting is ignored."));
1039 }
1040 //else: we have default priority, so don't complain
1041
1042 // anyhow, don't do anything because priority is just ignored
1043 }
1044 else
1045 {
1046 struct sched_param sp;
1047 if ( pthread_attr_getschedparam(&attr, &sp) != 0 )
1048 {
1049 wxFAIL_MSG(wxT("pthread_attr_getschedparam() failed"));
1050 }
1051
1052 sp.sched_priority = min_prio + (prio*(max_prio - min_prio))/100;
1053
1054 if ( pthread_attr_setschedparam(&attr, &sp) != 0 )
1055 {
1056 wxFAIL_MSG(wxT("pthread_attr_setschedparam(priority) failed"));
1057 }
1058 }
1059#endif // HAVE_THREAD_PRIORITY_FUNCTIONS
1060
1061#ifdef HAVE_PTHREAD_ATTR_SETSCOPE
1062 // this will make the threads created by this process really concurrent
1063 if ( pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM) != 0 )
1064 {
1065 wxFAIL_MSG(wxT("pthread_attr_setscope(PTHREAD_SCOPE_SYSTEM) failed"));
1066 }
1067#endif // HAVE_PTHREAD_ATTR_SETSCOPE
1068
1069 // VZ: assume that this one is always available (it's rather fundamental),
1070 // if this function is ever missing we should try to use
1071 // pthread_detach() instead (after thread creation)
1072 if ( thread->IsDetached() )
1073 {
1074 if ( pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) != 0 )
1075 {
1076 wxFAIL_MSG(wxT("pthread_attr_setdetachstate(DETACHED) failed"));
1077 }
1078
1079 // never try to join detached threads
1080 Detach();
1081 }
1082 //else: threads are created joinable by default, it's ok
1083
1084 // create the new OS thread object
1085 int rc = pthread_create
1086 (
1087 GetIdPtr(),
1088 &attr,
1089 wxPthreadStart,
1090 (void *)thread
1091 );
1092
1093 if ( pthread_attr_destroy(&attr) != 0 )
1094 {
1095 wxFAIL_MSG(wxT("pthread_attr_destroy() failed"));
1096 }
1097
1098 if ( rc != 0 )
1099 {
1100 SetState(STATE_EXITED);
1101
1102 return wxTHREAD_NO_RESOURCE;
1103 }
1104
1105 m_created = true;
1106 return wxTHREAD_NO_ERROR;
1107}
1108
1109wxThreadError wxThreadInternal::Run()
1110{
1111 wxCHECK_MSG( GetState() == STATE_NEW, wxTHREAD_RUNNING,
1112 wxT("thread may only be started once after Create()") );
1113
1114 SetState(STATE_RUNNING);
1115
1116 // wake up threads waiting for our start
1117 SignalRun();
1118
1119 return wxTHREAD_NO_ERROR;
1120}
1121
1122void wxThreadInternal::Wait()
1123{
1124 wxCHECK_RET( !m_isDetached, wxT("can't wait for a detached thread") );
1125
1126 // if the thread we're waiting for is waiting for the GUI mutex, we will
1127 // deadlock so make sure we release it temporarily
1128 if ( wxThread::IsMain() )
1129 {
1130#ifdef __WXOSX__
1131 // give the thread we're waiting for chance to do the GUI call
1132 // it might be in, we don't do this conditionally as the to be waited on
1133 // thread might have to acquire the mutex later but before terminating
1134 if ( wxGuiOwnedByMainThread() )
1135 wxMutexGuiLeave();
1136#else
1137 wxMutexGuiLeave();
1138#endif
1139 }
1140
1141 wxLogTrace(TRACE_THREADS,
1142 wxT("Starting to wait for thread %p to exit."),
1143 THR_ID(this));
1144
1145 // to avoid memory leaks we should call pthread_join(), but it must only be
1146 // done once so use a critical section to serialize the code below
1147 {
1148 wxCriticalSectionLocker lock(m_csJoinFlag);
1149
1150 if ( m_shouldBeJoined )
1151 {
1152 // FIXME shouldn't we set cancellation type to DISABLED here? If
1153 // we're cancelled inside pthread_join(), things will almost
1154 // certainly break - but if we disable the cancellation, we
1155 // might deadlock
1156 if ( pthread_join(GetId(), &m_exitcode) != 0 )
1157 {
1158 // this is a serious problem, so use wxLogError and not
1159 // wxLogDebug: it is possible to bring the system to its knees
1160 // by creating too many threads and not joining them quite
1161 // easily
1162 wxLogError(_("Failed to join a thread, potential memory leak detected - please restart the program"));
1163 }
1164
1165 m_shouldBeJoined = false;
1166 }
1167 }
1168
1169#ifndef __WXOSX__
1170 // reacquire GUI mutex
1171 if ( wxThread::IsMain() )
1172 wxMutexGuiEnter();
1173#endif
1174}
1175
1176void wxThreadInternal::Pause()
1177{
1178 // the state is set from the thread which pauses us first, this function
1179 // is called later so the state should have been already set
1180 wxCHECK_RET( m_state == STATE_PAUSED,
1181 wxT("thread must first be paused with wxThread::Pause().") );
1182
1183 wxLogTrace(TRACE_THREADS,
1184 wxT("Thread %p goes to sleep."), THR_ID(this));
1185
1186 // wait until the semaphore is Post()ed from Resume()
1187 m_semSuspend.Wait();
1188}
1189
1190void wxThreadInternal::Resume()
1191{
1192 wxCHECK_RET( m_state == STATE_PAUSED,
1193 wxT("can't resume thread which is not suspended.") );
1194
1195 // the thread might be not actually paused yet - if there were no call to
1196 // TestDestroy() since the last call to Pause() for example
1197 if ( IsReallyPaused() )
1198 {
1199 wxLogTrace(TRACE_THREADS,
1200 wxT("Waking up thread %p"), THR_ID(this));
1201
1202 // wake up Pause()
1203 m_semSuspend.Post();
1204
1205 // reset the flag
1206 SetReallyPaused(false);
1207 }
1208 else
1209 {
1210 wxLogTrace(TRACE_THREADS,
1211 wxT("Thread %p is not yet really paused"), THR_ID(this));
1212 }
1213
1214 SetState(STATE_RUNNING);
1215}
1216
1217// -----------------------------------------------------------------------------
1218// wxThread static functions
1219// -----------------------------------------------------------------------------
1220
1221wxThread *wxThread::This()
1222{
1223 return (wxThread *)pthread_getspecific(gs_keySelf);
1224}
1225
1226void wxThread::Yield()
1227{
1228#ifdef HAVE_SCHED_YIELD
1229 sched_yield();
1230#endif
1231}
1232
1233int wxThread::GetCPUCount()
1234{
1235#if defined(_SC_NPROCESSORS_ONLN)
1236 // this works for Solaris and Linux 2.6
1237 int rc = sysconf(_SC_NPROCESSORS_ONLN);
1238 if ( rc != -1 )
1239 {
1240 return rc;
1241 }
1242#elif defined(__LINUX__) && wxUSE_FFILE
1243 // read from proc (can't use wxTextFile here because it's a special file:
1244 // it has 0 size but still can be read from)
1245 wxLogNull nolog;
1246
1247 wxFFile file(wxT("/proc/cpuinfo"));
1248 if ( file.IsOpened() )
1249 {
1250 // slurp the whole file
1251 wxString s;
1252 if ( file.ReadAll(&s) )
1253 {
1254 // (ab)use Replace() to find the number of "processor: num" strings
1255 size_t count = s.Replace(wxT("processor\t:"), wxT(""));
1256 if ( count > 0 )
1257 {
1258 return count;
1259 }
1260
1261 wxLogDebug(wxT("failed to parse /proc/cpuinfo"));
1262 }
1263 else
1264 {
1265 wxLogDebug(wxT("failed to read /proc/cpuinfo"));
1266 }
1267 }
1268#endif // different ways to get number of CPUs
1269
1270 // unknown
1271 return -1;
1272}
1273
1274wxThreadIdType wxThread::GetCurrentId()
1275{
1276 return (wxThreadIdType)pthread_self();
1277}
1278
1279
1280bool wxThread::SetConcurrency(size_t level)
1281{
1282#ifdef HAVE_PTHREAD_SET_CONCURRENCY
1283 int rc = pthread_setconcurrency( level );
1284#elif defined(HAVE_THR_SETCONCURRENCY)
1285 int rc = thr_setconcurrency(level);
1286#else // !HAVE_THR_SETCONCURRENCY
1287 // ok only for the default value
1288 int rc = level == 0 ? 0 : -1;
1289#endif // HAVE_THR_SETCONCURRENCY/!HAVE_THR_SETCONCURRENCY
1290
1291 if ( rc != 0 )
1292 {
1293 wxLogSysError(rc, _("Failed to set thread concurrency level to %lu"),
1294 static_cast<unsigned long>(level));
1295 return false;
1296 }
1297
1298 return true;
1299}
1300
1301// -----------------------------------------------------------------------------
1302// creating thread
1303// -----------------------------------------------------------------------------
1304
1305wxThread::wxThread(wxThreadKind kind)
1306{
1307 // add this thread to the global list of all threads
1308 {
1309 wxMutexLocker lock(*gs_mutexAllThreads);
1310
1311 gs_allThreads.Add(this);
1312 }
1313
1314 m_internal = new wxThreadInternal();
1315
1316 m_isDetached = kind == wxTHREAD_DETACHED;
1317}
1318
1319wxThreadError wxThread::Create(unsigned int stackSize)
1320{
1321 wxCriticalSectionLocker lock(m_critsect);
1322
1323 return m_internal->Create(this, stackSize);
1324}
1325
1326wxThreadError wxThread::Run()
1327{
1328 wxCriticalSectionLocker lock(m_critsect);
1329
1330 // Create the thread if it wasn't created yet with an explicit
1331 // Create() call:
1332 if ( !m_internal->WasCreated() )
1333 {
1334 wxThreadError rv = m_internal->Create(this, 0);
1335 if ( rv != wxTHREAD_NO_ERROR )
1336 return rv;
1337 }
1338
1339 return m_internal->Run();
1340}
1341
1342// -----------------------------------------------------------------------------
1343// misc accessors
1344// -----------------------------------------------------------------------------
1345
1346void wxThread::SetPriority(unsigned int prio)
1347{
1348 wxCHECK_RET( wxPRIORITY_MIN <= prio && prio <= wxPRIORITY_MAX,
1349 wxT("invalid thread priority") );
1350
1351 wxCriticalSectionLocker lock(m_critsect);
1352
1353 switch ( m_internal->GetState() )
1354 {
1355 case STATE_NEW:
1356 // thread not yet started, priority will be set when it is
1357 m_internal->SetPriority(prio);
1358 break;
1359
1360 case STATE_RUNNING:
1361 case STATE_PAUSED:
1362#ifdef HAVE_THREAD_PRIORITY_FUNCTIONS
1363#if defined(__LINUX__)
1364 // On Linux, pthread_setschedparam with SCHED_OTHER does not allow
1365 // a priority other than 0. Instead, we use the BSD setpriority
1366 // which alllows us to set a 'nice' value between 20 to -20. Only
1367 // super user can set a value less than zero (more negative yields
1368 // higher priority). setpriority set the static priority of a
1369 // process, but this is OK since Linux is configured as a thread
1370 // per process.
1371 //
1372 // FIXME this is not true for 2.6!!
1373
1374 // map wx priorites 0..100 to Unix priorities 20..-20
1375 if ( setpriority(PRIO_PROCESS, 0, -(2*(int)prio)/5 + 20) == -1 )
1376 {
1377 wxLogError(_("Failed to set thread priority %d."), prio);
1378 }
1379#else // __LINUX__
1380 {
1381 struct sched_param sparam;
1382 sparam.sched_priority = prio;
1383
1384 if ( pthread_setschedparam(m_internal->GetId(),
1385 SCHED_OTHER, &sparam) != 0 )
1386 {
1387 wxLogError(_("Failed to set thread priority %d."), prio);
1388 }
1389 }
1390#endif // __LINUX__
1391#endif // HAVE_THREAD_PRIORITY_FUNCTIONS
1392 break;
1393
1394 case STATE_EXITED:
1395 default:
1396 wxFAIL_MSG(wxT("impossible to set thread priority in this state"));
1397 }
1398}
1399
1400unsigned int wxThread::GetPriority() const
1401{
1402 wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect);
1403
1404 return m_internal->GetPriority();
1405}
1406
1407wxThreadIdType wxThread::GetId() const
1408{
1409 return (wxThreadIdType) m_internal->GetId();
1410}
1411
1412// -----------------------------------------------------------------------------
1413// pause/resume
1414// -----------------------------------------------------------------------------
1415
1416wxThreadError wxThread::Pause()
1417{
1418 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR,
1419 wxT("a thread can't pause itself") );
1420
1421 wxCriticalSectionLocker lock(m_critsect);
1422
1423 if ( m_internal->GetState() != STATE_RUNNING )
1424 {
1425 wxLogDebug(wxT("Can't pause thread which is not running."));
1426
1427 return wxTHREAD_NOT_RUNNING;
1428 }
1429
1430 // just set a flag, the thread will be really paused only during the next
1431 // call to TestDestroy()
1432 m_internal->SetState(STATE_PAUSED);
1433
1434 return wxTHREAD_NO_ERROR;
1435}
1436
1437wxThreadError wxThread::Resume()
1438{
1439 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR,
1440 wxT("a thread can't resume itself") );
1441
1442 wxCriticalSectionLocker lock(m_critsect);
1443
1444 wxThreadState state = m_internal->GetState();
1445
1446 switch ( state )
1447 {
1448 case STATE_PAUSED:
1449 wxLogTrace(TRACE_THREADS, wxT("Thread %p suspended, resuming."),
1450 THR_ID(this));
1451
1452 m_internal->Resume();
1453
1454 return wxTHREAD_NO_ERROR;
1455
1456 case STATE_EXITED:
1457 wxLogTrace(TRACE_THREADS, wxT("Thread %p exited, won't resume."),
1458 THR_ID(this));
1459 return wxTHREAD_NO_ERROR;
1460
1461 default:
1462 wxLogDebug(wxT("Attempt to resume a thread which is not paused."));
1463
1464 return wxTHREAD_MISC_ERROR;
1465 }
1466}
1467
1468// -----------------------------------------------------------------------------
1469// exiting thread
1470// -----------------------------------------------------------------------------
1471
1472wxThread::ExitCode wxThread::Wait(wxThreadWait WXUNUSED(waitMode))
1473{
1474 wxCHECK_MSG( This() != this, (ExitCode)-1,
1475 wxT("a thread can't wait for itself") );
1476
1477 wxCHECK_MSG( !m_isDetached, (ExitCode)-1,
1478 wxT("can't wait for detached thread") );
1479
1480 m_internal->Wait();
1481
1482 return m_internal->GetExitCode();
1483}
1484
1485wxThreadError wxThread::Delete(ExitCode *rc, wxThreadWait WXUNUSED(waitMode))
1486{
1487 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR,
1488 wxT("a thread can't delete itself") );
1489
1490 bool isDetached = m_isDetached;
1491
1492 m_critsect.Enter();
1493 wxThreadState state = m_internal->GetState();
1494
1495 // ask the thread to stop
1496 m_internal->SetCancelFlag();
1497
1498 m_critsect.Leave();
1499
1500 OnDelete();
1501
1502 switch ( state )
1503 {
1504 case STATE_NEW:
1505 // we need to wake up the thread so that PthreadStart() will
1506 // terminate - right now it's blocking on run semaphore in
1507 // PthreadStart()
1508 m_internal->SignalRun();
1509
1510 // fall through
1511
1512 case STATE_EXITED:
1513 // nothing to do
1514 break;
1515
1516 case STATE_PAUSED:
1517 // resume the thread first
1518 m_internal->Resume();
1519
1520 // fall through
1521
1522 default:
1523 if ( !isDetached )
1524 {
1525 // wait until the thread stops
1526 m_internal->Wait();
1527
1528 if ( rc )
1529 {
1530 // return the exit code of the thread
1531 *rc = m_internal->GetExitCode();
1532 }
1533 }
1534 //else: can't wait for detached threads
1535 }
1536
1537 if (state == STATE_NEW)
1538 return wxTHREAD_MISC_ERROR;
1539 // for coherency with the MSW implementation, signal the user that
1540 // Delete() was called on a thread which didn't start to run yet.
1541
1542 return wxTHREAD_NO_ERROR;
1543}
1544
1545wxThreadError wxThread::Kill()
1546{
1547 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR,
1548 wxT("a thread can't kill itself") );
1549
1550 OnKill();
1551
1552 switch ( m_internal->GetState() )
1553 {
1554 case STATE_NEW:
1555 case STATE_EXITED:
1556 return wxTHREAD_NOT_RUNNING;
1557
1558 case STATE_PAUSED:
1559 // resume the thread first
1560 Resume();
1561
1562 // fall through
1563
1564 default:
1565#ifdef HAVE_PTHREAD_CANCEL
1566 if ( pthread_cancel(m_internal->GetId()) != 0 )
1567#endif // HAVE_PTHREAD_CANCEL
1568 {
1569 wxLogError(_("Failed to terminate a thread."));
1570
1571 return wxTHREAD_MISC_ERROR;
1572 }
1573
1574#ifdef HAVE_PTHREAD_CANCEL
1575 if ( m_isDetached )
1576 {
1577 // if we use cleanup function, this will be done from
1578 // wxPthreadCleanup()
1579#ifndef wxHAVE_PTHREAD_CLEANUP
1580 ScheduleThreadForDeletion();
1581
1582 // don't call OnExit() here, it can only be called in the
1583 // threads context and we're in the context of another thread
1584
1585 DeleteThread(this);
1586#endif // wxHAVE_PTHREAD_CLEANUP
1587 }
1588 else
1589 {
1590 m_internal->SetExitCode(EXITCODE_CANCELLED);
1591 }
1592
1593 return wxTHREAD_NO_ERROR;
1594#endif // HAVE_PTHREAD_CANCEL
1595 }
1596}
1597
1598void wxThread::Exit(ExitCode status)
1599{
1600 wxASSERT_MSG( This() == this,
1601 wxT("wxThread::Exit() can only be called in the context of the same thread") );
1602
1603 if ( m_isDetached )
1604 {
1605 // from the moment we call OnExit(), the main program may terminate at
1606 // any moment, so mark this thread as being already in process of being
1607 // deleted or wxThreadModule::OnExit() will try to delete it again
1608 ScheduleThreadForDeletion();
1609 }
1610
1611 // don't enter m_critsect before calling OnExit() because the user code
1612 // might deadlock if, for example, it signals a condition in OnExit() (a
1613 // common case) while the main thread calls any of functions entering
1614 // m_critsect on us (almost all of them do)
1615 wxTRY
1616 {
1617 OnExit();
1618 }
1619 wxCATCH_ALL( wxTheApp->OnUnhandledException(); )
1620
1621 // delete C++ thread object if this is a detached thread - user is
1622 // responsible for doing this for joinable ones
1623 if ( m_isDetached )
1624 {
1625 // FIXME I'm feeling bad about it - what if another thread function is
1626 // called (in another thread context) now? It will try to access
1627 // half destroyed object which will probably result in something
1628 // very bad - but we can't protect this by a crit section unless
1629 // we make it a global object, but this would mean that we can
1630 // only call one thread function at a time :-(
1631 DeleteThread(this);
1632 pthread_setspecific(gs_keySelf, 0);
1633 }
1634 else
1635 {
1636 m_critsect.Enter();
1637 m_internal->SetState(STATE_EXITED);
1638 m_critsect.Leave();
1639 }
1640
1641 // terminate the thread (pthread_exit() never returns)
1642 pthread_exit(status);
1643
1644 wxFAIL_MSG(wxT("pthread_exit() failed"));
1645}
1646
1647// also test whether we were paused
1648bool wxThread::TestDestroy()
1649{
1650 wxASSERT_MSG( This() == this,
1651 wxT("wxThread::TestDestroy() can only be called in the context of the same thread") );
1652
1653 m_critsect.Enter();
1654
1655 if ( m_internal->GetState() == STATE_PAUSED )
1656 {
1657 m_internal->SetReallyPaused(true);
1658
1659 // leave the crit section or the other threads will stop too if they
1660 // try to call any of (seemingly harmless) IsXXX() functions while we
1661 // sleep
1662 m_critsect.Leave();
1663
1664 m_internal->Pause();
1665 }
1666 else
1667 {
1668 // thread wasn't requested to pause, nothing to do
1669 m_critsect.Leave();
1670 }
1671
1672 return m_internal->WasCancelled();
1673}
1674
1675wxThread::~wxThread()
1676{
1677 m_critsect.Enter();
1678
1679 // check that the thread either exited or couldn't be created
1680 if ( m_internal->GetState() != STATE_EXITED &&
1681 m_internal->GetState() != STATE_NEW )
1682 {
1683 wxLogDebug(wxT("The thread %p is being destroyed although it is still running! The application may crash."),
1684 THR_ID(this));
1685 }
1686
1687 m_critsect.Leave();
1688
1689 delete m_internal;
1690
1691 // remove this thread from the global array
1692 {
1693 wxMutexLocker lock(*gs_mutexAllThreads);
1694
1695 gs_allThreads.Remove(this);
1696 }
1697}
1698
1699// -----------------------------------------------------------------------------
1700// state tests
1701// -----------------------------------------------------------------------------
1702
1703bool wxThread::IsRunning() const
1704{
1705 wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect);
1706
1707 return m_internal->GetState() == STATE_RUNNING;
1708}
1709
1710bool wxThread::IsAlive() const
1711{
1712 wxCriticalSectionLocker lock((wxCriticalSection&)m_critsect);
1713
1714 switch ( m_internal->GetState() )
1715 {
1716 case STATE_RUNNING:
1717 case STATE_PAUSED:
1718 return true;
1719
1720 default:
1721 return false;
1722 }
1723}
1724
1725bool wxThread::IsPaused() const
1726{
1727 wxCriticalSectionLocker lock((wxCriticalSection&)m_critsect);
1728
1729 return (m_internal->GetState() == STATE_PAUSED);
1730}
1731
1732//--------------------------------------------------------------------
1733// wxThreadModule
1734//--------------------------------------------------------------------
1735
1736#ifdef __WXOSX__
1737void wxOSXThreadModuleOnInit();
1738void wxOSXThreadModuleOnExit();
1739#endif
1740
1741class wxThreadModule : public wxModule
1742{
1743public:
1744 virtual bool OnInit();
1745 virtual void OnExit();
1746
1747private:
1748 DECLARE_DYNAMIC_CLASS(wxThreadModule)
1749};
1750
1751IMPLEMENT_DYNAMIC_CLASS(wxThreadModule, wxModule)
1752
1753bool wxThreadModule::OnInit()
1754{
1755 int rc = pthread_key_create(&gs_keySelf, NULL /* dtor function */);
1756 if ( rc != 0 )
1757 {
1758 wxLogSysError(rc, _("Thread module initialization failed: failed to create thread key"));
1759
1760 return false;
1761 }
1762
1763 wxThread::ms_idMainThread = wxThread::GetCurrentId();
1764
1765 gs_mutexAllThreads = new wxMutex();
1766
1767#ifdef __WXOSX__
1768 wxOSXThreadModuleOnInit();
1769#else
1770 gs_mutexGui = new wxMutex();
1771 gs_mutexGui->Lock();
1772#endif
1773
1774 gs_mutexDeleteThread = new wxMutex();
1775 gs_condAllDeleted = new wxCondition(*gs_mutexDeleteThread);
1776
1777 return true;
1778}
1779
1780void wxThreadModule::OnExit()
1781{
1782 wxASSERT_MSG( wxThread::IsMain(), wxT("only main thread can be here") );
1783
1784 // are there any threads left which are being deleted right now?
1785 size_t nThreadsBeingDeleted;
1786
1787 {
1788 wxMutexLocker lock( *gs_mutexDeleteThread );
1789 nThreadsBeingDeleted = gs_nThreadsBeingDeleted;
1790
1791 if ( nThreadsBeingDeleted > 0 )
1792 {
1793 wxLogTrace(TRACE_THREADS,
1794 wxT("Waiting for %lu threads to disappear"),
1795 (unsigned long)nThreadsBeingDeleted);
1796
1797 // have to wait until all of them disappear
1798 gs_condAllDeleted->Wait();
1799 }
1800 }
1801
1802 size_t count;
1803
1804 {
1805 wxMutexLocker lock(*gs_mutexAllThreads);
1806
1807 // terminate any threads left
1808 count = gs_allThreads.GetCount();
1809 if ( count != 0u )
1810 {
1811 wxLogDebug(wxT("%lu threads were not terminated by the application."),
1812 (unsigned long)count);
1813 }
1814 } // unlock mutex before deleting the threads as they lock it in their dtor
1815
1816 for ( size_t n = 0u; n < count; n++ )
1817 {
1818 // Delete calls the destructor which removes the current entry. We
1819 // should only delete the first one each time.
1820 gs_allThreads[0]->Delete();
1821 }
1822
1823 delete gs_mutexAllThreads;
1824
1825#ifdef __WXOSX__
1826 wxOSXThreadModuleOnExit();
1827#else
1828 // destroy GUI mutex
1829 gs_mutexGui->Unlock();
1830 delete gs_mutexGui;
1831#endif
1832
1833 // and free TLD slot
1834 (void)pthread_key_delete(gs_keySelf);
1835
1836 delete gs_condAllDeleted;
1837 delete gs_mutexDeleteThread;
1838}
1839
1840// ----------------------------------------------------------------------------
1841// global functions
1842// ----------------------------------------------------------------------------
1843
1844static void ScheduleThreadForDeletion()
1845{
1846 wxMutexLocker lock( *gs_mutexDeleteThread );
1847
1848 gs_nThreadsBeingDeleted++;
1849
1850 wxLogTrace(TRACE_THREADS, wxT("%lu thread%s waiting to be deleted"),
1851 (unsigned long)gs_nThreadsBeingDeleted,
1852 gs_nThreadsBeingDeleted == 1 ? wxT("") : wxT("s"));
1853}
1854
1855static void DeleteThread(wxThread *This)
1856{
1857 wxLogTrace(TRACE_THREADS, wxT("Thread %p auto deletes."), THR_ID(This));
1858
1859 delete This;
1860
1861 // only lock gs_mutexDeleteThread after deleting the thread to avoid
1862 // calling out into user code with it locked as this may result in
1863 // deadlocks if the thread dtor deletes another thread (see #11501)
1864 wxMutexLocker locker( *gs_mutexDeleteThread );
1865
1866 wxCHECK_RET( gs_nThreadsBeingDeleted > 0,
1867 wxT("no threads scheduled for deletion, yet we delete one?") );
1868
1869 wxLogTrace(TRACE_THREADS, wxT("%lu threads remain scheduled for deletion."),
1870 (unsigned long)gs_nThreadsBeingDeleted - 1);
1871
1872 if ( !--gs_nThreadsBeingDeleted )
1873 {
1874 // no more threads left, signal it
1875 gs_condAllDeleted->Signal();
1876 }
1877}
1878
1879#ifndef __DARWIN__
1880
1881void wxMutexGuiEnterImpl()
1882{
1883 gs_mutexGui->Lock();
1884}
1885
1886void wxMutexGuiLeaveImpl()
1887{
1888 gs_mutexGui->Unlock();
1889}
1890
1891#endif
1892
1893// ----------------------------------------------------------------------------
1894// include common implementation code
1895// ----------------------------------------------------------------------------
1896
1897#include "wx/thrimpl.cpp"
1898
1899#endif // wxUSE_THREADS