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