]> git.saurik.com Git - wxWidgets.git/blame - src/gtk1/threadpsx.cpp
Another solaris fix. :-<
[wxWidgets.git] / src / gtk1 / threadpsx.cpp
CommitLineData
7c351dad
GL
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$
f3855ef0
RR
8// Copyright: (c) Wolfram Gloger (1996, 1997)
9// Guilhem Lavaux (1998)
10// Robert Roebling (1999)
7c351dad
GL
11// Licence: wxWindows licence
12/////////////////////////////////////////////////////////////////////////////
f3855ef0 13
7c351dad 14#ifdef __GNUG__
015ee844 15 #pragma implementation "thread.h"
7c351dad
GL
16#endif
17
18#include <stdio.h>
19#include <unistd.h>
7c351dad 20#include <pthread.h>
6163f5d8 21#include <errno.h>
015ee844
VZ
22
23#ifdef __linux__
24 #include <sched.h>
25#endif
26
82052aff
GL
27#include "wx/thread.h"
28#include "wx/module.h"
29#include "wx/utils.h"
3069ac4e 30#include "wx/log.h"
015ee844 31#include "wx/intl.h"
7c3d7e2d 32#include "wx/dynarray.h"
7c351dad 33
83624f79
RR
34#include "gdk/gdk.h"
35#include "gtk/gtk.h"
36
015ee844 37enum thread_state
f3855ef0 38{
015ee844
VZ
39 STATE_NEW, // didn't start execution yet (=> RUNNING)
40 STATE_RUNNING,
41 STATE_PAUSED,
42 STATE_CANCELED,
43 STATE_EXITED
7c351dad
GL
44};
45
7c3d7e2d
VZ
46WX_DEFINE_ARRAY(wxThread *, wxArrayThread);
47
48// -----------------------------------------------------------------------------
f3855ef0 49// global data
7c3d7e2d
VZ
50// -----------------------------------------------------------------------------
51
52// we keep the list of all threads created by the application to be able to
53// terminate them on exit if there are some left - otherwise the process would
54// be left in memory
55static wxArrayThread gs_allThreads;
7c351dad 56
015ee844 57// the id of the main thread
7c3d7e2d 58static pthread_t gs_tidMain;
c2dd8380 59
015ee844
VZ
60// the key for the pointer to the associated wxThread object
61static pthread_key_t gs_keySelf;
62
63// this mutex must be acquired before any call to a GUI function
64static wxMutex *gs_mutexGui;
7c351dad 65
f3855ef0
RR
66//--------------------------------------------------------------------
67// common GUI thread code
68//--------------------------------------------------------------------
69
7c351dad
GL
70#include "threadgui.inc"
71
f3855ef0
RR
72//--------------------------------------------------------------------
73// wxMutex (Posix implementation)
74//--------------------------------------------------------------------
7c351dad 75
015ee844 76class wxMutexInternal
f3855ef0 77{
7c351dad
GL
78public:
79 pthread_mutex_t p_mutex;
80};
81
ee4f8c2a 82wxMutex::wxMutex()
7c351dad 83{
f3855ef0 84 p_internal = new wxMutexInternal;
bbe0af5b 85 pthread_mutex_init( &(p_internal->p_mutex), (const pthread_mutexattr_t*) NULL );
f3855ef0 86 m_locked = 0;
7c351dad
GL
87}
88
ee4f8c2a 89wxMutex::~wxMutex()
7c351dad 90{
f3855ef0 91 if (m_locked > 0)
7c3d7e2d 92 wxLogDebug("Freeing a locked mutex (%d locks)", m_locked);
b89156b5 93
bbe0af5b 94 pthread_mutex_destroy( &(p_internal->p_mutex) );
f3855ef0 95 delete p_internal;
7c351dad
GL
96}
97
ee4f8c2a 98wxMutexError wxMutex::Lock()
7c351dad 99{
bbe0af5b 100 int err = pthread_mutex_lock( &(p_internal->p_mutex) );
f3855ef0 101 if (err == EDEADLK)
bbe0af5b 102 {
7c3d7e2d
VZ
103 wxLogDebug("Locking this mutex would lead to deadlock!");
104
b332090a 105 return wxMUTEX_DEAD_LOCK;
bbe0af5b 106 }
015ee844 107
f3855ef0 108 m_locked++;
015ee844 109
b332090a 110 return wxMUTEX_NO_ERROR;
7c351dad
GL
111}
112
ee4f8c2a 113wxMutexError wxMutex::TryLock()
7c351dad 114{
f3855ef0 115 if (m_locked)
bbe0af5b 116 {
b332090a 117 return wxMUTEX_BUSY;
bbe0af5b 118 }
015ee844 119
bbe0af5b 120 int err = pthread_mutex_trylock( &(p_internal->p_mutex) );
015ee844 121 switch (err)
f3855ef0 122 {
b332090a 123 case EBUSY: return wxMUTEX_BUSY;
f3855ef0 124 }
015ee844 125
f3855ef0 126 m_locked++;
015ee844 127
b332090a 128 return wxMUTEX_NO_ERROR;
7c351dad
GL
129}
130
ee4f8c2a 131wxMutexError wxMutex::Unlock()
7c351dad 132{
f3855ef0 133 if (m_locked > 0)
bbe0af5b 134 {
f3855ef0 135 m_locked--;
bbe0af5b 136 }
f3855ef0 137 else
bbe0af5b 138 {
7c3d7e2d
VZ
139 wxLogDebug("Unlocking not locked mutex.");
140
b332090a 141 return wxMUTEX_UNLOCKED;
bbe0af5b 142 }
015ee844 143
bbe0af5b 144 pthread_mutex_unlock( &(p_internal->p_mutex) );
015ee844 145
b332090a 146 return wxMUTEX_NO_ERROR;
7c351dad
GL
147}
148
f3855ef0
RR
149//--------------------------------------------------------------------
150// wxCondition (Posix implementation)
151//--------------------------------------------------------------------
7c351dad 152
015ee844 153class wxConditionInternal
f3855ef0 154{
7c351dad
GL
155public:
156 pthread_cond_t p_condition;
157};
158
ee4f8c2a 159wxCondition::wxCondition()
7c351dad 160{
f3855ef0 161 p_internal = new wxConditionInternal;
bbe0af5b 162 pthread_cond_init( &(p_internal->p_condition), (const pthread_condattr_t *) NULL );
7c351dad
GL
163}
164
ee4f8c2a 165wxCondition::~wxCondition()
7c351dad 166{
bbe0af5b 167 pthread_cond_destroy( &(p_internal->p_condition) );
015ee844 168
f3855ef0 169 delete p_internal;
7c351dad
GL
170}
171
172void wxCondition::Wait(wxMutex& mutex)
173{
bbe0af5b 174 pthread_cond_wait( &(p_internal->p_condition), &(mutex.p_internal->p_mutex) );
7c351dad
GL
175}
176
177bool wxCondition::Wait(wxMutex& mutex, unsigned long sec, unsigned long nsec)
178{
f3855ef0 179 struct timespec tspec;
7c351dad 180
bbe0af5b 181 tspec.tv_sec = time(0L)+sec;
f3855ef0
RR
182 tspec.tv_nsec = nsec;
183 return (pthread_cond_timedwait(&(p_internal->p_condition), &(mutex.p_internal->p_mutex), &tspec) != ETIMEDOUT);
7c351dad
GL
184}
185
ee4f8c2a 186void wxCondition::Signal()
7c351dad 187{
bbe0af5b 188 pthread_cond_signal( &(p_internal->p_condition) );
7c351dad
GL
189}
190
ee4f8c2a 191void wxCondition::Broadcast()
7c351dad 192{
bbe0af5b 193 pthread_cond_broadcast( &(p_internal->p_condition) );
7c351dad
GL
194}
195
f3855ef0
RR
196//--------------------------------------------------------------------
197// wxThread (Posix implementation)
198//--------------------------------------------------------------------
7c351dad 199
015ee844 200class wxThreadInternal
f3855ef0 201{
7c351dad 202public:
7c3d7e2d
VZ
203 wxThreadInternal();
204 ~wxThreadInternal();
015ee844
VZ
205
206 // thread entry function
207 static void *PthreadStart(void *ptr);
208
7c3d7e2d
VZ
209 // thread actions
210 // start the thread
015ee844 211 wxThreadError Run();
7c3d7e2d
VZ
212 // ask the thread to terminate
213 void Cancel();
214 // wake up threads waiting for our termination
215 void SignalExit();
216 // go to sleep until Resume() is called
217 void Pause();
218 // resume the thread
219 void Resume();
015ee844
VZ
220
221 // accessors
222 // priority
223 int GetPriority() const { return m_prio; }
224 void SetPriority(int prio) { m_prio = prio; }
225 // state
226 thread_state GetState() const { return m_state; }
227 void SetState(thread_state state) { m_state = state; }
228 // id
229 pthread_t GetId() const { return thread_id; }
230 // "cancelled" flag
015ee844
VZ
231 bool WasCancelled() const { return m_cancelled; }
232
233//private: -- should be!
234 pthread_t thread_id;
235
236private:
237 thread_state m_state; // see thread_state enum
238 int m_prio; // in wxWindows units: from 0 to 100
239
240 // set when the thread should terminate
241 bool m_cancelled;
242
7c3d7e2d
VZ
243 // this (mutex, cond) pair is used to synchronize the main thread and this
244 // thread in several situations:
245 // 1. The thread function blocks until condition is signaled by Run() when
246 // it's initially created - this allows create thread in "suspended"
247 // state
248 // 2. The Delete() function blocks until the condition is signaled when the
249 // thread exits.
250 wxMutex m_mutex;
251 wxCondition m_cond;
252
253 // another (mutex, cond) pair for Pause()/Resume() usage
254 //
255 // VZ: it's possible that we might reuse the mutex and condition from above
256 // for this too, but as I'm not at all sure that it won't create subtle
257 // problems with race conditions between, say, Pause() and Delete() I
258 // prefer this may be a bit less efficient but much safer solution
259 wxMutex m_mutexSuspend;
260 wxCondition m_condSuspend;
7c351dad
GL
261};
262
263void *wxThreadInternal::PthreadStart(void *ptr)
264{
f3855ef0 265 wxThread *thread = (wxThread *)ptr;
015ee844 266 wxThreadInternal *pthread = thread->p_internal;
c2dd8380 267
015ee844
VZ
268 if ( pthread_setspecific(gs_keySelf, thread) != 0 )
269 {
270 wxLogError(_("Can not start thread: error writing TLS."));
271
272 return (void *)-1;
273 }
274
275 // wait for the condition to be signaled from Run()
7c3d7e2d
VZ
276 // mutex state: currently locked by the thread which created us
277 pthread->m_cond.Wait(pthread->m_mutex);
278
279 // mutex state: locked again on exit of Wait()
015ee844
VZ
280
281 // call the main entry
f3855ef0 282 void* status = thread->Entry();
c2dd8380 283
015ee844 284 // terminate the thread
f3855ef0 285 thread->Exit(status);
7c351dad 286
015ee844
VZ
287 wxFAIL_MSG("wxThread::Exit() can't return.");
288
f3855ef0 289 return NULL;
7c351dad
GL
290}
291
7c3d7e2d
VZ
292wxThreadInternal::wxThreadInternal()
293{
294 m_state = STATE_NEW;
295 m_cancelled = FALSE;
296
297 // this mutex is locked during almost all thread lifetime - it will only be
298 // unlocked in the very end
299 m_mutex.Lock();
300
301 // this mutex is used in Pause()/Resume() and is also locked all the time
302 // unless the thread is paused
303 m_mutexSuspend.Lock();
304}
305
306wxThreadInternal::~wxThreadInternal()
307{
308 m_mutexSuspend.Unlock();
309
310 // note that m_mutex will be unlocked by the thread which waits for our
311 // termination
312}
313
015ee844 314wxThreadError wxThreadInternal::Run()
7c351dad 315{
015ee844
VZ
316 wxCHECK_MSG( GetState() == STATE_NEW, wxTHREAD_RUNNING,
317 "thread may only be started once after successful Create()" );
7c351dad 318
7c3d7e2d
VZ
319 // the mutex was locked on Create(), so we will be able to lock it again
320 // only when the thread really starts executing and enters the wait -
321 // otherwise we might signal the condition before anybody is waiting for it
322 wxMutexLocker lock(m_mutex);
323 m_cond.Signal();
324
325 m_state = STATE_RUNNING;
7c351dad 326
015ee844 327 return wxTHREAD_NO_ERROR;
7c3d7e2d
VZ
328
329 // now the mutex is unlocked back - but just to allow Wait() function to
330 // terminate by relocking it, so the net result is that the worker thread
331 // starts executing and the mutex is still locked
015ee844 332}
7c351dad 333
015ee844
VZ
334void wxThreadInternal::Cancel()
335{
7c3d7e2d
VZ
336 // if the thread we're waiting for is waiting for the GUI mutex, we will
337 // deadlock so make sure we release it temporarily
338 if ( wxThread::IsMain() )
339 wxMutexGuiLeave();
340
341 // nobody ever writes this variable so it's safe to not use any
342 // synchronization here
015ee844 343 m_cancelled = TRUE;
7c3d7e2d
VZ
344
345 // entering Wait() releases the mutex thus allowing SignalExit() to acquire
346 // it and to signal us its termination
347 m_cond.Wait(m_mutex);
348
349 // mutex is still in the locked state - relocked on exit from Wait(), so
350 // unlock it - we don't need it any more, the thread has already terminated
351 m_mutex.Unlock();
352
353 // reacquire GUI mutex
354 if ( wxThread::IsMain() )
355 wxMutexGuiEnter();
356}
357
358void wxThreadInternal::SignalExit()
359{
360 // as mutex is currently locked, this will block until some other thread
361 // (normally the same which created this one) unlocks it by entering Wait()
362 m_mutex.Lock();
363
364 // wake up all the threads waiting for our termination
365 m_cond.Broadcast();
366
367 // after this call mutex will be finally unlocked
368 m_mutex.Unlock();
369}
370
371void wxThreadInternal::Pause()
372{
373 wxCHECK_RET( m_state == STATE_PAUSED,
374 "thread must first be paused with wxThread::Pause()." );
375
376 // wait until the condition is signaled from Resume()
377 m_condSuspend.Wait(m_mutexSuspend);
378}
379
380void wxThreadInternal::Resume()
381{
382 wxCHECK_RET( m_state == STATE_PAUSED,
383 "can't resume thread which is not suspended." );
384
385 // we will be able to lock this mutex only when Pause() starts waiting
386 wxMutexLocker lock(m_mutexSuspend);
387 m_condSuspend.Signal();
388
389 SetState(STATE_RUNNING);
015ee844 390}
7c351dad 391
015ee844
VZ
392// -----------------------------------------------------------------------------
393// static functions
394// -----------------------------------------------------------------------------
7c351dad 395
015ee844
VZ
396wxThread *wxThread::This()
397{
398 return (wxThread *)pthread_getspecific(gs_keySelf);
399}
c2dd8380 400
015ee844
VZ
401bool wxThread::IsMain()
402{
7c3d7e2d 403 return (bool)pthread_equal(pthread_self(), gs_tidMain);
015ee844
VZ
404}
405
406void wxThread::Yield()
407{
408 sched_yield();
7c351dad
GL
409}
410
015ee844 411void wxThread::Sleep(unsigned long milliseconds)
7c351dad 412{
015ee844 413 // FIXME how to test for nanosleep() availability?
f3855ef0 414
015ee844 415 usleep(milliseconds * 1000); // usleep(3) wants microseconds
7c351dad
GL
416}
417
015ee844
VZ
418// -----------------------------------------------------------------------------
419// creating thread
420// -----------------------------------------------------------------------------
421
422wxThread::wxThread()
7c351dad 423{
7c3d7e2d
VZ
424 // add this thread to the global list of all threads
425 gs_allThreads.Add(this);
426
015ee844 427 p_internal = new wxThreadInternal();
7c351dad
GL
428}
429
015ee844 430wxThreadError wxThread::Create()
7c351dad 431{
015ee844
VZ
432 if (p_internal->GetState() != STATE_NEW)
433 return wxTHREAD_RUNNING;
434
435 // set up the thread attribute: right now, we only set thread priority
436 pthread_attr_t attr;
437 pthread_attr_init(&attr);
438
439 int prio;
440 if ( pthread_attr_getschedpolicy(&attr, &prio) != 0 )
441 {
442 wxLogError(_("Can not retrieve thread scheduling policy."));
443 }
444
445 int min_prio = sched_get_priority_min(prio),
446 max_prio = sched_get_priority_max(prio);
447
448 if ( min_prio == -1 || max_prio == -1 )
449 {
450 wxLogError(_("Can not get priority range for scheduling policy %d."),
451 prio);
452 }
f3855ef0 453 else
015ee844
VZ
454 {
455 struct sched_param sp;
456 pthread_attr_getschedparam(&attr, &sp);
457 sp.sched_priority = min_prio +
458 (p_internal->GetPriority()*(max_prio-min_prio))/100;
459 pthread_attr_setschedparam(&attr, &sp);
460 }
461
7c3d7e2d 462 // create the new OS thread object
015ee844
VZ
463 int rc = pthread_create(&p_internal->thread_id, &attr,
464 wxThreadInternal::PthreadStart, (void *)this);
465 pthread_attr_destroy(&attr);
466
467 if ( rc != 0 )
468 {
469 p_internal->SetState(STATE_EXITED);
470 return wxTHREAD_NO_RESOURCE;
471 }
472
473 return wxTHREAD_NO_ERROR;
7c351dad
GL
474}
475
015ee844 476wxThreadError wxThread::Run()
7c351dad 477{
015ee844
VZ
478 return p_internal->Run();
479}
480
481// -----------------------------------------------------------------------------
482// misc accessors
483// -----------------------------------------------------------------------------
7c351dad 484
015ee844
VZ
485void wxThread::SetPriority(unsigned int prio)
486{
487 wxCHECK_RET( (WXTHREAD_MIN_PRIORITY <= prio) &&
488 (prio <= WXTHREAD_MAX_PRIORITY), "invalid thread priority" );
489
490 wxCriticalSectionLocker lock(m_critsect);
491
492 switch ( p_internal->GetState() )
f3855ef0 493 {
015ee844
VZ
494 case STATE_NEW:
495 // thread not yet started, priority will be set when it is
496 p_internal->SetPriority(prio);
497 break;
498
499 case STATE_RUNNING:
500 case STATE_PAUSED:
501 {
502 struct sched_param sparam;
503 sparam.sched_priority = prio;
504
505 if ( pthread_setschedparam(p_internal->GetId(),
506 SCHED_OTHER, &sparam) != 0 )
507 {
508 wxLogError(_("Failed to set thread priority %d."), prio);
509 }
510 }
511 break;
512
513 case STATE_EXITED:
514 default:
515 wxFAIL_MSG("impossible to set thread priority in this state");
f3855ef0 516 }
015ee844 517}
c2dd8380 518
015ee844
VZ
519unsigned int wxThread::GetPriority() const
520{
521 wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect);
522
523 return p_internal->GetPriority();
c2dd8380
GL
524}
525
015ee844
VZ
526unsigned long wxThread::GetID() const
527{
528 return (unsigned long)p_internal->thread_id;
529}
530
531// -----------------------------------------------------------------------------
532// pause/resume
533// -----------------------------------------------------------------------------
534
c2dd8380
GL
535wxThreadError wxThread::Pause()
536{
015ee844
VZ
537 wxCriticalSectionLocker lock(m_critsect);
538
539 if ( p_internal->GetState() != STATE_RUNNING )
540 {
541 wxLogDebug("Can't pause thread which is not running.");
542
b332090a 543 return wxTHREAD_NOT_RUNNING;
015ee844 544 }
c2dd8380 545
015ee844 546 p_internal->SetState(STATE_PAUSED);
c2dd8380 547
b332090a 548 return wxTHREAD_NO_ERROR;
c2dd8380
GL
549}
550
551wxThreadError wxThread::Resume()
552{
015ee844 553 wxCriticalSectionLocker lock(m_critsect);
c2dd8380 554
015ee844
VZ
555 if ( p_internal->GetState() == STATE_PAUSED )
556 {
7c3d7e2d 557 p_internal->Resume();
015ee844
VZ
558
559 return wxTHREAD_NO_ERROR;
560 }
561 else
562 {
563 wxLogDebug("Attempt to resume a thread which is not paused.");
564
565 return wxTHREAD_MISC_ERROR;
566 }
7c351dad
GL
567}
568
015ee844
VZ
569// -----------------------------------------------------------------------------
570// exiting thread
571// -----------------------------------------------------------------------------
572
573wxThread::ExitCode wxThread::Delete()
7c351dad 574{
015ee844
VZ
575 m_critsect.Enter();
576 thread_state state = p_internal->GetState();
577 m_critsect.Leave();
7c351dad 578
015ee844 579 switch ( state )
f3855ef0 580 {
015ee844
VZ
581 case STATE_NEW:
582 case STATE_EXITED:
583 // nothing to do
584 break;
7c351dad 585
015ee844
VZ
586 case STATE_PAUSED:
587 // resume the thread first
588 Resume();
c2dd8380 589
015ee844 590 // fall through
c2dd8380 591
015ee844
VZ
592 default:
593 // set the flag telling to the thread to stop and wait
594 p_internal->Cancel();
f3855ef0 595 }
015ee844
VZ
596
597 return NULL;
7c351dad
GL
598}
599
015ee844 600wxThreadError wxThread::Kill()
7c351dad 601{
015ee844
VZ
602 switch ( p_internal->GetState() )
603 {
604 case STATE_NEW:
605 case STATE_EXITED:
606 return wxTHREAD_NOT_RUNNING;
607
608 default:
609 if ( pthread_cancel(p_internal->GetId()) != 0 )
610 {
611 wxLogError(_("Failed to terminate a thread."));
612
613 return wxTHREAD_MISC_ERROR;
614 }
615
616 return wxTHREAD_NO_ERROR;
617 }
7c351dad
GL
618}
619
620void wxThread::Exit(void *status)
621{
7c3d7e2d 622 // first call user-level clean up code
015ee844
VZ
623 OnExit();
624
7c3d7e2d
VZ
625 // next wake up the threads waiting for us (OTOH, this function won't return
626 // until someone waited for us!)
627 p_internal->SignalExit();
628
015ee844
VZ
629 p_internal->SetState(STATE_EXITED);
630
7c3d7e2d 631 // delete both C++ thread object and terminate the OS thread object
015ee844 632 delete this;
f3855ef0 633 pthread_exit(status);
7c351dad
GL
634}
635
7c3d7e2d 636// also test whether we were paused
8c10faf1 637bool wxThread::TestDestroy()
7c351dad 638{
015ee844 639 wxCriticalSectionLocker lock((wxCriticalSection&)m_critsect);
2501ce51 640
7c3d7e2d
VZ
641 if ( p_internal->GetState() == STATE_PAUSED )
642 {
643 // leave the crit section or the other threads will stop too if they try
644 // to call any of (seemingly harmless) IsXXX() functions while we sleep
645 m_critsect.Leave();
646
647 p_internal->Pause();
648
649 // enter it back before it's finally left in lock object dtor
650 m_critsect.Enter();
651 }
652
015ee844 653 return p_internal->WasCancelled();
7c351dad
GL
654}
655
015ee844 656wxThread::~wxThread()
7c351dad 657{
7c3d7e2d
VZ
658 // remove this thread from the global array
659 gs_allThreads.Remove(this);
7c351dad
GL
660}
661
015ee844
VZ
662// -----------------------------------------------------------------------------
663// state tests
664// -----------------------------------------------------------------------------
665
c2dd8380
GL
666bool wxThread::IsRunning() const
667{
015ee844
VZ
668 wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect);
669
670 return p_internal->GetState() == STATE_RUNNING;
c2dd8380
GL
671}
672
673bool wxThread::IsAlive() const
674{
015ee844 675 wxCriticalSectionLocker lock((wxCriticalSection&)m_critsect);
c2dd8380 676
015ee844
VZ
677 switch ( p_internal->GetState() )
678 {
679 case STATE_RUNNING:
680 case STATE_PAUSED:
681 return TRUE;
7c351dad 682
015ee844
VZ
683 default:
684 return FALSE;
685 }
7c351dad
GL
686}
687
f3855ef0 688//--------------------------------------------------------------------
015ee844 689// wxThreadModule
f3855ef0
RR
690//--------------------------------------------------------------------
691
06cfab17
RR
692class wxThreadModule : public wxModule
693{
694public:
695 virtual bool OnInit();
696 virtual void OnExit();
697
698private:
699 DECLARE_DYNAMIC_CLASS(wxThreadModule)
700};
701
d524867f 702IMPLEMENT_DYNAMIC_CLASS(wxThreadModule, wxModule)
f3855ef0 703
015ee844 704bool wxThreadModule::OnInit()
d524867f 705{
015ee844
VZ
706 if ( pthread_key_create(&gs_keySelf, NULL /* dtor function */) != 0 )
707 {
708 wxLogError(_("Thread module initialization failed: "
709 "failed to create pthread key."));
710
711 return FALSE;
712 }
713
714 gs_mutexGui = new wxMutex();
d524867f 715 wxThreadGuiInit();
7c3d7e2d 716 gs_tidMain = pthread_self();
015ee844
VZ
717 gs_mutexGui->Lock();
718
d524867f
RR
719 return TRUE;
720}
7c351dad 721
d524867f
RR
722void wxThreadModule::OnExit()
723{
7c3d7e2d
VZ
724 wxASSERT_MSG( wxThread::IsMain(), "only main thread can be here" );
725
726 // terminate any threads left
727 size_t count = gs_allThreads.GetCount();
728 if ( count != 0u )
729 wxLogDebug("Some threads were not terminated by the application.");
730
731 for ( size_t n = 0u; n < count; n++ )
732 {
733 gs_allThreads[n]->Delete();
734 }
735
736 // destroy GUI mutex
015ee844 737 gs_mutexGui->Unlock();
d524867f 738 wxThreadGuiExit();
015ee844 739 delete gs_mutexGui;
f3855ef0 740
7c3d7e2d 741 // and free TLD slot
015ee844
VZ
742 (void)pthread_key_delete(gs_keySelf);
743}