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