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