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