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