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