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