]> git.saurik.com Git - wxWidgets.git/blame - src/unix/threadpsx.cpp
wxThread docs updates
[wxWidgets.git] / src / unix / threadpsx.cpp
CommitLineData
518b5d2f
VZ
1/////////////////////////////////////////////////////////////////////////////
2// Name: threadpsx.cpp
3// Purpose: wxThread (Posix) Implementation
4// Author: Original from Wolfram Gloger/Guilhem Lavaux
5// Modified by:
6// Created: 04/22/98
7// RCS-ID: $Id$
8// Copyright: (c) Wolfram Gloger (1996, 1997)
9// Guilhem Lavaux (1998)
10// Vadim Zeitlin (1999)
11// Robert Roebling (1999)
12// Licence: wxWindows licence
13/////////////////////////////////////////////////////////////////////////////
14
15// ============================================================================
16// declaration
17// ============================================================================
18
19// ----------------------------------------------------------------------------
20// headers
21// ----------------------------------------------------------------------------
22
23#ifdef __GNUG__
24 #pragma implementation "thread.h"
25#endif
26
7bcb11d3
JS
27// With simple makefiles, we must ignore the file body if not using
28// threads.
29#include "wx/setup.h"
518b5d2f 30
7bcb11d3 31#if wxUSE_THREADS
518b5d2f 32
7bcb11d3 33#include "wx/thread.h"
518b5d2f
VZ
34#include "wx/module.h"
35#include "wx/utils.h"
36#include "wx/log.h"
37#include "wx/intl.h"
38#include "wx/dynarray.h"
39
40#include <stdio.h>
41#include <unistd.h>
42#include <pthread.h>
43#include <errno.h>
44#include <time.h>
45
7bcb11d3 46#if HAVE_SCHED_H
518b5d2f
VZ
47 #include <sched.h>
48#endif
49
50// ----------------------------------------------------------------------------
51// constants
52// ----------------------------------------------------------------------------
53
882eefb1
VZ
54// the possible states of the thread and transitions from them
55enum wxThreadState
518b5d2f
VZ
56{
57 STATE_NEW, // didn't start execution yet (=> RUNNING)
882eefb1
VZ
58 STATE_RUNNING, // running (=> PAUSED or EXITED)
59 STATE_PAUSED, // suspended (=> RUNNING or EXITED)
60 STATE_EXITED // thread doesn't exist any more
518b5d2f
VZ
61};
62
882eefb1
VZ
63// ----------------------------------------------------------------------------
64// types
65// ----------------------------------------------------------------------------
66
518b5d2f
VZ
67WX_DEFINE_ARRAY(wxThread *, wxArrayThread);
68
69// -----------------------------------------------------------------------------
70// global data
71// -----------------------------------------------------------------------------
72
73// we keep the list of all threads created by the application to be able to
74// terminate them on exit if there are some left - otherwise the process would
75// be left in memory
76static wxArrayThread gs_allThreads;
77
78// the id of the main thread
79static pthread_t gs_tidMain;
80
81// the key for the pointer to the associated wxThread object
82static pthread_key_t gs_keySelf;
83
84// this mutex must be acquired before any call to a GUI function
85static wxMutex *gs_mutexGui;
86
87// ============================================================================
88// implementation
89// ============================================================================
90
91//--------------------------------------------------------------------
92// wxMutex (Posix implementation)
93//--------------------------------------------------------------------
94
95class wxMutexInternal
96{
97public:
98 pthread_mutex_t p_mutex;
99};
100
101wxMutex::wxMutex()
102{
e4628635
RR
103 p_internal = new wxMutexInternal;
104
18341904
VZ
105 pthread_mutex_init(&(p_internal->p_mutex),
106 (pthread_mutexattr_t*) NULL );
518b5d2f
VZ
107 m_locked = 0;
108}
109
110wxMutex::~wxMutex()
111{
112 if (m_locked > 0)
223d09f6 113 wxLogDebug(wxT("Freeing a locked mutex (%d locks)"), m_locked);
518b5d2f
VZ
114
115 pthread_mutex_destroy( &(p_internal->p_mutex) );
116 delete p_internal;
117}
118
119wxMutexError wxMutex::Lock()
120{
121 int err = pthread_mutex_lock( &(p_internal->p_mutex) );
122 if (err == EDEADLK)
123 {
223d09f6 124 wxLogDebug(wxT("Locking this mutex would lead to deadlock!"));
518b5d2f
VZ
125
126 return wxMUTEX_DEAD_LOCK;
127 }
128
129 m_locked++;
130
131 return wxMUTEX_NO_ERROR;
132}
133
134wxMutexError wxMutex::TryLock()
135{
136 if (m_locked)
137 {
138 return wxMUTEX_BUSY;
139 }
140
141 int err = pthread_mutex_trylock( &(p_internal->p_mutex) );
142 switch (err)
143 {
144 case EBUSY: return wxMUTEX_BUSY;
145 }
146
147 m_locked++;
148
149 return wxMUTEX_NO_ERROR;
150}
151
152wxMutexError wxMutex::Unlock()
153{
154 if (m_locked > 0)
155 {
156 m_locked--;
157 }
158 else
159 {
223d09f6 160 wxLogDebug(wxT("Unlocking not locked mutex."));
518b5d2f
VZ
161
162 return wxMUTEX_UNLOCKED;
163 }
164
165 pthread_mutex_unlock( &(p_internal->p_mutex) );
166
167 return wxMUTEX_NO_ERROR;
168}
169
170//--------------------------------------------------------------------
171// wxCondition (Posix implementation)
172//--------------------------------------------------------------------
173
174class wxConditionInternal
175{
176public:
177 pthread_cond_t p_condition;
178};
179
180wxCondition::wxCondition()
181{
182 p_internal = new wxConditionInternal;
18341904
VZ
183 pthread_cond_init( &(p_internal->p_condition),
184 (pthread_condattr_t *) NULL );
518b5d2f
VZ
185}
186
187wxCondition::~wxCondition()
188{
189 pthread_cond_destroy( &(p_internal->p_condition) );
190
191 delete p_internal;
192}
193
194void wxCondition::Wait(wxMutex& mutex)
195{
196 pthread_cond_wait( &(p_internal->p_condition), &(mutex.p_internal->p_mutex) );
197}
198
199bool wxCondition::Wait(wxMutex& mutex, unsigned long sec, unsigned long nsec)
200{
201 struct timespec tspec;
202
203 tspec.tv_sec = time(0L)+sec;
204 tspec.tv_nsec = nsec;
205 return (pthread_cond_timedwait(&(p_internal->p_condition), &(mutex.p_internal->p_mutex), &tspec) != ETIMEDOUT);
206}
207
208void wxCondition::Signal()
209{
210 pthread_cond_signal( &(p_internal->p_condition) );
211}
212
213void wxCondition::Broadcast()
214{
215 pthread_cond_broadcast( &(p_internal->p_condition) );
216}
217
218//--------------------------------------------------------------------
219// wxThread (Posix implementation)
220//--------------------------------------------------------------------
221
222class wxThreadInternal
223{
224public:
225 wxThreadInternal();
226 ~wxThreadInternal();
227
228 // thread entry function
229 static void *PthreadStart(void *ptr);
230
5092b3ad
GL
231#if HAVE_THREAD_CLEANUP_FUNCTIONS
232 // thread exit function
233 static void PthreadCleanup(void *ptr);
234#endif
235
518b5d2f
VZ
236 // thread actions
237 // start the thread
238 wxThreadError Run();
239 // ask the thread to terminate
882eefb1 240 void Wait();
518b5d2f
VZ
241 // wake up threads waiting for our termination
242 void SignalExit();
243 // go to sleep until Resume() is called
244 void Pause();
245 // resume the thread
246 void Resume();
247
248 // accessors
249 // priority
250 int GetPriority() const { return m_prio; }
251 void SetPriority(int prio) { m_prio = prio; }
252 // state
882eefb1
VZ
253 wxThreadState GetState() const { return m_state; }
254 void SetState(wxThreadState state) { m_state = state; }
518b5d2f 255 // id
882eefb1
VZ
256 pthread_t GetId() const { return m_threadId; }
257 pthread_t *GetIdPtr() { return &m_threadId; }
518b5d2f 258 // "cancelled" flag
882eefb1 259 void SetCancelFlag() { m_cancelled = TRUE; }
518b5d2f
VZ
260 bool WasCancelled() const { return m_cancelled; }
261
518b5d2f 262private:
882eefb1
VZ
263 pthread_t m_threadId; // id of the thread
264 wxThreadState m_state; // see wxThreadState enum
265 int m_prio; // in wxWindows units: from 0 to 100
518b5d2f
VZ
266
267 // set when the thread should terminate
268 bool m_cancelled;
269
270 // this (mutex, cond) pair is used to synchronize the main thread and this
271 // thread in several situations:
272 // 1. The thread function blocks until condition is signaled by Run() when
862cc6f9 273 // it's initially created - this allows thread creation in "suspended"
518b5d2f
VZ
274 // state
275 // 2. The Delete() function blocks until the condition is signaled when the
276 // thread exits.
062c4861
GL
277 // GL: On Linux, this may fail because we can have a deadlock in either
278 // SignalExit() or Wait(): so we add m_end_mutex for the finalization.
0dac2f38 279 wxMutex m_mutex, m_end_mutex;
518b5d2f
VZ
280 wxCondition m_cond;
281
282 // another (mutex, cond) pair for Pause()/Resume() usage
283 //
284 // VZ: it's possible that we might reuse the mutex and condition from above
285 // for this too, but as I'm not at all sure that it won't create subtle
286 // problems with race conditions between, say, Pause() and Delete() I
287 // prefer this may be a bit less efficient but much safer solution
288 wxMutex m_mutexSuspend;
289 wxCondition m_condSuspend;
290};
291
292void *wxThreadInternal::PthreadStart(void *ptr)
293{
294 wxThread *thread = (wxThread *)ptr;
295 wxThreadInternal *pthread = thread->p_internal;
5092b3ad 296 void *status;
518b5d2f 297
862cc6f9
VZ
298 int rc = pthread_setspecific(gs_keySelf, thread);
299 if ( rc != 0 )
518b5d2f 300 {
58230fb1 301 wxLogSysError(rc, _("Cannot start thread: error writing TLS"));
518b5d2f
VZ
302
303 return (void *)-1;
304 }
5092b3ad
GL
305#if HAVE_THREAD_CLEANUP_FUNCTIONS
306 // Install the cleanup handler.
062c4861 307 pthread_cleanup_push(wxThreadInternal::PthreadCleanup, ptr);
5092b3ad 308#endif
518b5d2f
VZ
309
310 // wait for the condition to be signaled from Run()
311 // mutex state: currently locked by the thread which created us
312 pthread->m_cond.Wait(pthread->m_mutex);
518b5d2f
VZ
313 // mutex state: locked again on exit of Wait()
314
315 // call the main entry
5092b3ad
GL
316 status = thread->Entry();
317
318#if HAVE_THREAD_CLEANUP_FUNCTIONS
062c4861 319 pthread_cleanup_pop(FALSE);
5092b3ad 320#endif
518b5d2f
VZ
321
322 // terminate the thread
323 thread->Exit(status);
324
223d09f6 325 wxFAIL_MSG(wxT("wxThread::Exit() can't return."));
518b5d2f
VZ
326
327 return NULL;
328}
329
5092b3ad
GL
330#if HAVE_THREAD_CLEANUP_FUNCTIONS
331// Only called when the thread is explicitely killed.
332
333void wxThreadInternal::PthreadCleanup(void *ptr)
334{
335 wxThread *thread = (wxThread *) ptr;
336
337 // The thread is already considered as finished.
338 if (thread->p_internal->GetState() == STATE_EXITED)
339 return;
340
341 // first call user-level clean up code
342 thread->OnExit();
343
344 // next wake up the threads waiting for us (OTOH, this function won't retur
345 // until someone waited for us!)
346 thread->p_internal->SetState(STATE_EXITED);
347
348 thread->p_internal->SignalExit();
349}
350#endif
351
518b5d2f
VZ
352wxThreadInternal::wxThreadInternal()
353{
354 m_state = STATE_NEW;
355 m_cancelled = FALSE;
bbfa0322
VZ
356 m_prio = WXTHREAD_DEFAULT_PRIORITY;
357 m_threadId = 0;
518b5d2f
VZ
358
359 // this mutex is locked during almost all thread lifetime - it will only be
360 // unlocked in the very end
361 m_mutex.Lock();
0dac2f38 362
9111db68
GL
363 // this mutex is used by wxThreadInternal::Wait() and by
364 // wxThreadInternal::SignalExit(). We don't use m_mutex because of a
365 // possible deadlock in either Wait() or SignalExit().
0dac2f38 366 m_end_mutex.Lock();
518b5d2f
VZ
367
368 // this mutex is used in Pause()/Resume() and is also locked all the time
369 // unless the thread is paused
370 m_mutexSuspend.Lock();
371}
372
373wxThreadInternal::~wxThreadInternal()
374{
a737331d
GL
375 // GL: moved to SignalExit
376 // m_mutexSuspend.Unlock();
518b5d2f
VZ
377
378 // note that m_mutex will be unlocked by the thread which waits for our
379 // termination
9111db68 380
062c4861
GL
381 // In the case, we didn't start the thread, all these mutex are locked:
382 // we must unlock them.
383 if (m_mutex.IsLocked())
384 m_mutex.Unlock();
385
386 if (m_end_mutex.IsLocked())
387 m_end_mutex.Unlock();
388
389 if (m_mutexSuspend.IsLocked())
390 m_mutexSuspend.Unlock();
518b5d2f
VZ
391}
392
393wxThreadError wxThreadInternal::Run()
394{
395 wxCHECK_MSG( GetState() == STATE_NEW, wxTHREAD_RUNNING,
223d09f6 396 wxT("thread may only be started once after successful Create()") );
518b5d2f
VZ
397
398 // the mutex was locked on Create(), so we will be able to lock it again
399 // only when the thread really starts executing and enters the wait -
400 // otherwise we might signal the condition before anybody is waiting for it
401 wxMutexLocker lock(m_mutex);
402 m_cond.Signal();
403
404 m_state = STATE_RUNNING;
405
406 return wxTHREAD_NO_ERROR;
407
408 // now the mutex is unlocked back - but just to allow Wait() function to
409 // terminate by relocking it, so the net result is that the worker thread
410 // starts executing and the mutex is still locked
411}
412
882eefb1 413void wxThreadInternal::Wait()
518b5d2f 414{
223d09f6 415 wxCHECK_RET( WasCancelled(), wxT("thread should have been cancelled first") );
882eefb1 416
518b5d2f
VZ
417 // if the thread we're waiting for is waiting for the GUI mutex, we will
418 // deadlock so make sure we release it temporarily
419 if ( wxThread::IsMain() )
420 wxMutexGuiLeave();
421
518b5d2f
VZ
422 // entering Wait() releases the mutex thus allowing SignalExit() to acquire
423 // it and to signal us its termination
0dac2f38 424 m_cond.Wait(m_end_mutex);
518b5d2f
VZ
425
426 // mutex is still in the locked state - relocked on exit from Wait(), so
427 // unlock it - we don't need it any more, the thread has already terminated
0dac2f38 428 m_end_mutex.Unlock();
518b5d2f 429
9111db68
GL
430 // After that, we wait for the real end of the other thread.
431 pthread_join(GetId(), NULL);
432
518b5d2f
VZ
433 // reacquire GUI mutex
434 if ( wxThread::IsMain() )
435 wxMutexGuiEnter();
436}
437
438void wxThreadInternal::SignalExit()
439{
a737331d
GL
440 // GL: Unlock mutexSuspend here.
441 m_mutexSuspend.Unlock();
442
518b5d2f
VZ
443 // as mutex is currently locked, this will block until some other thread
444 // (normally the same which created this one) unlocks it by entering Wait()
0dac2f38 445 m_end_mutex.Lock();
518b5d2f
VZ
446
447 // wake up all the threads waiting for our termination
448 m_cond.Broadcast();
449
450 // after this call mutex will be finally unlocked
0dac2f38 451 m_end_mutex.Unlock();
518b5d2f
VZ
452}
453
454void wxThreadInternal::Pause()
455{
882eefb1
VZ
456 // the state is set from the thread which pauses us first, this function
457 // is called later so the state should have been already set
518b5d2f 458 wxCHECK_RET( m_state == STATE_PAUSED,
223d09f6 459 wxT("thread must first be paused with wxThread::Pause().") );
518b5d2f 460
862cc6f9
VZ
461 // don't pause the thread which is being terminated - this would lead to
462 // deadlock if the thread is paused after Delete() had called Resume() but
882eefb1
VZ
463 // before it had time to call Wait()
464 if ( WasCancelled() )
862cc6f9
VZ
465 return;
466
518b5d2f
VZ
467 // wait until the condition is signaled from Resume()
468 m_condSuspend.Wait(m_mutexSuspend);
469}
470
471void wxThreadInternal::Resume()
472{
473 wxCHECK_RET( m_state == STATE_PAUSED,
223d09f6 474 wxT("can't resume thread which is not suspended.") );
518b5d2f
VZ
475
476 // we will be able to lock this mutex only when Pause() starts waiting
477 wxMutexLocker lock(m_mutexSuspend);
478 m_condSuspend.Signal();
479
480 SetState(STATE_RUNNING);
481}
482
483// -----------------------------------------------------------------------------
484// static functions
485// -----------------------------------------------------------------------------
486
487wxThread *wxThread::This()
488{
489 return (wxThread *)pthread_getspecific(gs_keySelf);
490}
491
492bool wxThread::IsMain()
493{
494 return (bool)pthread_equal(pthread_self(), gs_tidMain);
495}
496
497void wxThread::Yield()
498{
499 sched_yield();
500}
501
502void wxThread::Sleep(unsigned long milliseconds)
503{
504 wxUsleep(milliseconds);
505}
506
507// -----------------------------------------------------------------------------
508// creating thread
509// -----------------------------------------------------------------------------
510
511wxThread::wxThread()
512{
513 // add this thread to the global list of all threads
514 gs_allThreads.Add(this);
515
516 p_internal = new wxThreadInternal();
517}
518
519wxThreadError wxThread::Create()
520{
a737331d 521 if (p_internal->GetState() != STATE_NEW)
518b5d2f
VZ
522 return wxTHREAD_RUNNING;
523
524 // set up the thread attribute: right now, we only set thread priority
525 pthread_attr_t attr;
526 pthread_attr_init(&attr);
527
fc9ef629 528#ifdef HAVE_THREAD_PRIORITY_FUNCTIONS
518b5d2f
VZ
529 int prio;
530 if ( pthread_attr_getschedpolicy(&attr, &prio) != 0 )
531 {
58230fb1 532 wxLogError(_("Cannot retrieve thread scheduling policy."));
518b5d2f
VZ
533 }
534
535 int min_prio = sched_get_priority_min(prio),
536 max_prio = sched_get_priority_max(prio);
537
538 if ( min_prio == -1 || max_prio == -1 )
539 {
58230fb1 540 wxLogError(_("Cannot get priority range for scheduling policy %d."),
518b5d2f
VZ
541 prio);
542 }
bbfa0322
VZ
543 else if ( max_prio == min_prio )
544 {
545 if ( p_internal->GetPriority() != WXTHREAD_DEFAULT_PRIORITY )
546 {
547 // notify the programmer that this doesn't work here
548 wxLogWarning(_("Thread priority setting is ignored."));
549 }
550 //else: we have default priority, so don't complain
551
552 // anyhow, don't do anything because priority is just ignored
553 }
518b5d2f
VZ
554 else
555 {
556 struct sched_param sp;
557 pthread_attr_getschedparam(&attr, &sp);
558 sp.sched_priority = min_prio +
559 (p_internal->GetPriority()*(max_prio-min_prio))/100;
560 pthread_attr_setschedparam(&attr, &sp);
561 }
34f8c26e 562#endif // HAVE_THREAD_PRIORITY_FUNCTIONS
518b5d2f 563
58230fb1
VZ
564#ifdef HAVE_PTHREAD_ATTR_SETSCOPE
565 // this will make the threads created by this process really concurrent
566 pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
567#endif // HAVE_PTHREAD_ATTR_SETSCOPE
568
518b5d2f 569 // create the new OS thread object
882eefb1 570 int rc = pthread_create(p_internal->GetIdPtr(), &attr,
518b5d2f
VZ
571 wxThreadInternal::PthreadStart, (void *)this);
572 pthread_attr_destroy(&attr);
573
574 if ( rc != 0 )
575 {
576 p_internal->SetState(STATE_EXITED);
577 return wxTHREAD_NO_RESOURCE;
578 }
579
580 return wxTHREAD_NO_ERROR;
581}
582
583wxThreadError wxThread::Run()
584{
bbfa0322 585 wxCHECK_MSG( p_internal->GetId(), wxTHREAD_MISC_ERROR,
223d09f6 586 wxT("must call wxThread::Create() first") );
bbfa0322 587
518b5d2f
VZ
588 return p_internal->Run();
589}
590
591// -----------------------------------------------------------------------------
592// misc accessors
593// -----------------------------------------------------------------------------
594
595void wxThread::SetPriority(unsigned int prio)
596{
34f8c26e
VZ
597 wxCHECK_RET( ((int)WXTHREAD_MIN_PRIORITY <= (int)prio) &&
598 ((int)prio <= (int)WXTHREAD_MAX_PRIORITY),
223d09f6 599 wxT("invalid thread priority") );
518b5d2f
VZ
600
601 wxCriticalSectionLocker lock(m_critsect);
602
603 switch ( p_internal->GetState() )
604 {
605 case STATE_NEW:
606 // thread not yet started, priority will be set when it is
607 p_internal->SetPriority(prio);
608 break;
609
610 case STATE_RUNNING:
611 case STATE_PAUSED:
34f8c26e 612#ifdef HAVE_THREAD_PRIORITY_FUNCTIONS
518b5d2f
VZ
613 {
614 struct sched_param sparam;
615 sparam.sched_priority = prio;
616
617 if ( pthread_setschedparam(p_internal->GetId(),
618 SCHED_OTHER, &sparam) != 0 )
619 {
620 wxLogError(_("Failed to set thread priority %d."), prio);
621 }
622 }
34f8c26e 623#endif // HAVE_THREAD_PRIORITY_FUNCTIONS
518b5d2f
VZ
624 break;
625
626 case STATE_EXITED:
627 default:
223d09f6 628 wxFAIL_MSG(wxT("impossible to set thread priority in this state"));
518b5d2f
VZ
629 }
630}
631
632unsigned int wxThread::GetPriority() const
633{
634 wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect);
635
636 return p_internal->GetPriority();
637}
638
639unsigned long wxThread::GetID() const
640{
882eefb1 641 return (unsigned long)p_internal->GetId();
518b5d2f
VZ
642}
643
644// -----------------------------------------------------------------------------
645// pause/resume
646// -----------------------------------------------------------------------------
647
648wxThreadError wxThread::Pause()
649{
650 wxCriticalSectionLocker lock(m_critsect);
651
652 if ( p_internal->GetState() != STATE_RUNNING )
653 {
223d09f6 654 wxLogDebug(wxT("Can't pause thread which is not running."));
518b5d2f
VZ
655
656 return wxTHREAD_NOT_RUNNING;
657 }
658
659 p_internal->SetState(STATE_PAUSED);
660
661 return wxTHREAD_NO_ERROR;
662}
663
664wxThreadError wxThread::Resume()
665{
666 wxCriticalSectionLocker lock(m_critsect);
667
668 if ( p_internal->GetState() == STATE_PAUSED )
669 {
a737331d 670 m_critsect.Leave();
518b5d2f 671 p_internal->Resume();
a737331d 672 m_critsect.Enter();
518b5d2f
VZ
673
674 return wxTHREAD_NO_ERROR;
675 }
676 else
677 {
223d09f6 678 wxLogDebug(wxT("Attempt to resume a thread which is not paused."));
518b5d2f
VZ
679
680 return wxTHREAD_MISC_ERROR;
681 }
682}
683
684// -----------------------------------------------------------------------------
685// exiting thread
686// -----------------------------------------------------------------------------
687
b568d04f
VZ
688wxThread::ExitCode Wait()
689{
690 wxFAIL_MSG("TODO");
691
692 return 0;
693}
694
695wxThreadError wxThread::Delete(ExitCode *rc)
518b5d2f 696{
fae05df5
GL
697 if (IsPaused())
698 Resume();
699
518b5d2f 700 m_critsect.Enter();
882eefb1 701 wxThreadState state = p_internal->GetState();
518b5d2f 702
882eefb1
VZ
703 // ask the thread to stop
704 p_internal->SetCancelFlag();
705
9111db68
GL
706 m_critsect.Leave();
707
518b5d2f
VZ
708 switch ( state )
709 {
710 case STATE_NEW:
711 case STATE_EXITED:
712 // nothing to do
713 break;
714
715 case STATE_PAUSED:
716 // resume the thread first
717 Resume();
718
719 // fall through
720
721 default:
882eefb1
VZ
722 // wait until the thread stops
723 p_internal->Wait();
518b5d2f 724 }
f439844b
GL
725 //GL: As we must auto-destroy, the destruction must happen here.
726 delete this;
518b5d2f
VZ
727
728 return NULL;
729}
730
731wxThreadError wxThread::Kill()
732{
733 switch ( p_internal->GetState() )
734 {
735 case STATE_NEW:
736 case STATE_EXITED:
737 return wxTHREAD_NOT_RUNNING;
738
739 default:
34f8c26e 740#ifdef HAVE_PTHREAD_CANCEL
518b5d2f 741 if ( pthread_cancel(p_internal->GetId()) != 0 )
34f8c26e 742#endif
518b5d2f
VZ
743 {
744 wxLogError(_("Failed to terminate a thread."));
745
746 return wxTHREAD_MISC_ERROR;
747 }
bbfa0322
VZ
748 //GL: As we must auto-destroy, the destruction must happen here (2).
749 delete this;
518b5d2f
VZ
750
751 return wxTHREAD_NO_ERROR;
752 }
753}
754
b568d04f 755void wxThread::Exit(ExitCode status)
518b5d2f
VZ
756{
757 // first call user-level clean up code
758 OnExit();
759
760 // next wake up the threads waiting for us (OTOH, this function won't return
761 // until someone waited for us!)
2a4f27f2 762 p_internal->SignalExit();
5092b3ad
GL
763
764 p_internal->SetState(STATE_EXITED);
2a4f27f2 765
518b5d2f 766 // delete both C++ thread object and terminate the OS thread object
c84fb40a
GL
767 // GL: This is very ugly and buggy ...
768// delete this;
518b5d2f
VZ
769 pthread_exit(status);
770}
771
772// also test whether we were paused
773bool wxThread::TestDestroy()
774{
882eefb1 775 wxCriticalSectionLocker lock(m_critsect);
518b5d2f
VZ
776
777 if ( p_internal->GetState() == STATE_PAUSED )
778 {
779 // leave the crit section or the other threads will stop too if they try
780 // to call any of (seemingly harmless) IsXXX() functions while we sleep
781 m_critsect.Leave();
782
783 p_internal->Pause();
784
785 // enter it back before it's finally left in lock object dtor
786 m_critsect.Enter();
787 }
788
789 return p_internal->WasCancelled();
790}
791
792wxThread::~wxThread()
793{
062c4861 794 m_critsect.Enter();
bbfa0322
VZ
795 if ( p_internal->GetState() != STATE_EXITED &&
796 p_internal->GetState() != STATE_NEW )
797 {
223d09f6 798 wxLogDebug(wxT("The thread is being destroyed although it is still "
bbfa0322
VZ
799 "running! The application may crash."));
800 }
062c4861
GL
801
802 m_critsect.Leave();
803
804 delete p_internal;
bbfa0322 805
518b5d2f
VZ
806 // remove this thread from the global array
807 gs_allThreads.Remove(this);
808}
809
810// -----------------------------------------------------------------------------
811// state tests
812// -----------------------------------------------------------------------------
813
814bool wxThread::IsRunning() const
815{
816 wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect);
817
818 return p_internal->GetState() == STATE_RUNNING;
819}
820
821bool wxThread::IsAlive() const
822{
823 wxCriticalSectionLocker lock((wxCriticalSection&)m_critsect);
824
825 switch ( p_internal->GetState() )
826 {
827 case STATE_RUNNING:
828 case STATE_PAUSED:
829 return TRUE;
830
831 default:
832 return FALSE;
833 }
834}
835
a737331d
GL
836bool wxThread::IsPaused() const
837{
838 wxCriticalSectionLocker lock((wxCriticalSection&)m_critsect);
839
840 return (p_internal->GetState() == STATE_PAUSED);
841}
842
518b5d2f
VZ
843//--------------------------------------------------------------------
844// wxThreadModule
845//--------------------------------------------------------------------
846
847class wxThreadModule : public wxModule
848{
849public:
850 virtual bool OnInit();
851 virtual void OnExit();
852
853private:
854 DECLARE_DYNAMIC_CLASS(wxThreadModule)
855};
856
857IMPLEMENT_DYNAMIC_CLASS(wxThreadModule, wxModule)
858
859bool wxThreadModule::OnInit()
860{
58230fb1
VZ
861 int rc = pthread_key_create(&gs_keySelf, NULL /* dtor function */);
862 if ( rc != 0 )
518b5d2f 863 {
58230fb1
VZ
864 wxLogSysError(rc, _("Thread module initialization failed: "
865 "failed to create thread key"));
518b5d2f
VZ
866
867 return FALSE;
868 }
869
870 gs_mutexGui = new wxMutex();
518b5d2f
VZ
871
872 gs_tidMain = pthread_self();
19da4326 873
518b5d2f
VZ
874 gs_mutexGui->Lock();
875
876 return TRUE;
877}
878
879void wxThreadModule::OnExit()
880{
223d09f6 881 wxASSERT_MSG( wxThread::IsMain(), wxT("only main thread can be here") );
518b5d2f
VZ
882
883 // terminate any threads left
884 size_t count = gs_allThreads.GetCount();
885 if ( count != 0u )
223d09f6 886 wxLogDebug(wxT("Some threads were not terminated by the application."));
518b5d2f
VZ
887
888 for ( size_t n = 0u; n < count; n++ )
889 {
bbfa0322
VZ
890 // Delete calls the destructor which removes the current entry. We
891 // should only delete the first one each time.
0ac77ef5 892 gs_allThreads[0]->Delete();
518b5d2f
VZ
893 }
894
895 // destroy GUI mutex
896 gs_mutexGui->Unlock();
897
518b5d2f
VZ
898 delete gs_mutexGui;
899
900 // and free TLD slot
901 (void)pthread_key_delete(gs_keySelf);
902}
903
904// ----------------------------------------------------------------------------
905// global functions
906// ----------------------------------------------------------------------------
907
908void wxMutexGuiEnter()
909{
910 gs_mutexGui->Lock();
911}
912
913void wxMutexGuiLeave()
914{
915 gs_mutexGui->Unlock();
916}
80cb83be 917
7bcb11d3
JS
918#endif
919 // wxUSE_THREADS