]> git.saurik.com Git - wxWidgets.git/blame - src/unix/threadpsx.cpp
Fix for wxPython segvs
[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
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.
275 wxMutex m_mutex;
276 wxCondition m_cond;
277
278 // another (mutex, cond) pair for Pause()/Resume() usage
279 //
280 // VZ: it's possible that we might reuse the mutex and condition from above
281 // for this too, but as I'm not at all sure that it won't create subtle
282 // problems with race conditions between, say, Pause() and Delete() I
283 // prefer this may be a bit less efficient but much safer solution
284 wxMutex m_mutexSuspend;
285 wxCondition m_condSuspend;
286};
287
288void *wxThreadInternal::PthreadStart(void *ptr)
289{
290 wxThread *thread = (wxThread *)ptr;
291 wxThreadInternal *pthread = thread->p_internal;
292
862cc6f9
VZ
293 int rc = pthread_setspecific(gs_keySelf, thread);
294 if ( rc != 0 )
518b5d2f 295 {
58230fb1 296 wxLogSysError(rc, _("Cannot start thread: error writing TLS"));
518b5d2f
VZ
297
298 return (void *)-1;
299 }
300
301 // wait for the condition to be signaled from Run()
302 // mutex state: currently locked by the thread which created us
303 pthread->m_cond.Wait(pthread->m_mutex);
304
305 // mutex state: locked again on exit of Wait()
306
307 // call the main entry
308 void* status = thread->Entry();
309
310 // terminate the thread
311 thread->Exit(status);
312
d207efe1 313 wxFAIL_MSG(_T("wxThread::Exit() can't return."));
518b5d2f
VZ
314
315 return NULL;
316}
317
318wxThreadInternal::wxThreadInternal()
319{
320 m_state = STATE_NEW;
321 m_cancelled = FALSE;
322
323 // this mutex is locked during almost all thread lifetime - it will only be
324 // unlocked in the very end
325 m_mutex.Lock();
326
327 // this mutex is used in Pause()/Resume() and is also locked all the time
328 // unless the thread is paused
329 m_mutexSuspend.Lock();
330}
331
332wxThreadInternal::~wxThreadInternal()
333{
a737331d
GL
334 // GL: moved to SignalExit
335 // m_mutexSuspend.Unlock();
518b5d2f
VZ
336
337 // note that m_mutex will be unlocked by the thread which waits for our
338 // termination
339}
340
341wxThreadError wxThreadInternal::Run()
342{
343 wxCHECK_MSG( GetState() == STATE_NEW, wxTHREAD_RUNNING,
d207efe1 344 _T("thread may only be started once after successful Create()") );
518b5d2f
VZ
345
346 // the mutex was locked on Create(), so we will be able to lock it again
347 // only when the thread really starts executing and enters the wait -
348 // otherwise we might signal the condition before anybody is waiting for it
349 wxMutexLocker lock(m_mutex);
350 m_cond.Signal();
351
352 m_state = STATE_RUNNING;
353
354 return wxTHREAD_NO_ERROR;
355
356 // now the mutex is unlocked back - but just to allow Wait() function to
357 // terminate by relocking it, so the net result is that the worker thread
358 // starts executing and the mutex is still locked
359}
360
882eefb1 361void wxThreadInternal::Wait()
518b5d2f 362{
d207efe1 363 wxCHECK_RET( WasCancelled(), _T("thread should have been cancelled first") );
882eefb1 364
518b5d2f
VZ
365 // if the thread we're waiting for is waiting for the GUI mutex, we will
366 // deadlock so make sure we release it temporarily
367 if ( wxThread::IsMain() )
368 wxMutexGuiLeave();
369
518b5d2f
VZ
370 // entering Wait() releases the mutex thus allowing SignalExit() to acquire
371 // it and to signal us its termination
372 m_cond.Wait(m_mutex);
373
374 // mutex is still in the locked state - relocked on exit from Wait(), so
375 // unlock it - we don't need it any more, the thread has already terminated
376 m_mutex.Unlock();
377
378 // reacquire GUI mutex
379 if ( wxThread::IsMain() )
380 wxMutexGuiEnter();
381}
382
383void wxThreadInternal::SignalExit()
384{
a737331d
GL
385 // GL: Unlock mutexSuspend here.
386 m_mutexSuspend.Unlock();
387
518b5d2f
VZ
388 // as mutex is currently locked, this will block until some other thread
389 // (normally the same which created this one) unlocks it by entering Wait()
390 m_mutex.Lock();
391
392 // wake up all the threads waiting for our termination
393 m_cond.Broadcast();
394
395 // after this call mutex will be finally unlocked
396 m_mutex.Unlock();
397}
398
399void wxThreadInternal::Pause()
400{
882eefb1
VZ
401 // the state is set from the thread which pauses us first, this function
402 // is called later so the state should have been already set
518b5d2f 403 wxCHECK_RET( m_state == STATE_PAUSED,
d207efe1 404 _T("thread must first be paused with wxThread::Pause().") );
518b5d2f 405
862cc6f9
VZ
406 // don't pause the thread which is being terminated - this would lead to
407 // deadlock if the thread is paused after Delete() had called Resume() but
882eefb1
VZ
408 // before it had time to call Wait()
409 if ( WasCancelled() )
862cc6f9
VZ
410 return;
411
518b5d2f
VZ
412 // wait until the condition is signaled from Resume()
413 m_condSuspend.Wait(m_mutexSuspend);
414}
415
416void wxThreadInternal::Resume()
417{
418 wxCHECK_RET( m_state == STATE_PAUSED,
d207efe1 419 _T("can't resume thread which is not suspended.") );
518b5d2f
VZ
420
421 // we will be able to lock this mutex only when Pause() starts waiting
422 wxMutexLocker lock(m_mutexSuspend);
423 m_condSuspend.Signal();
424
425 SetState(STATE_RUNNING);
426}
427
428// -----------------------------------------------------------------------------
429// static functions
430// -----------------------------------------------------------------------------
431
432wxThread *wxThread::This()
433{
434 return (wxThread *)pthread_getspecific(gs_keySelf);
435}
436
437bool wxThread::IsMain()
438{
439 return (bool)pthread_equal(pthread_self(), gs_tidMain);
440}
441
442void wxThread::Yield()
443{
444 sched_yield();
445}
446
447void wxThread::Sleep(unsigned long milliseconds)
448{
449 wxUsleep(milliseconds);
450}
451
452// -----------------------------------------------------------------------------
453// creating thread
454// -----------------------------------------------------------------------------
455
456wxThread::wxThread()
457{
458 // add this thread to the global list of all threads
459 gs_allThreads.Add(this);
460
461 p_internal = new wxThreadInternal();
462}
463
464wxThreadError wxThread::Create()
465{
a737331d 466 if (p_internal->GetState() != STATE_NEW)
518b5d2f
VZ
467 return wxTHREAD_RUNNING;
468
469 // set up the thread attribute: right now, we only set thread priority
470 pthread_attr_t attr;
471 pthread_attr_init(&attr);
472
fc9ef629 473#ifdef HAVE_THREAD_PRIORITY_FUNCTIONS
518b5d2f
VZ
474 int prio;
475 if ( pthread_attr_getschedpolicy(&attr, &prio) != 0 )
476 {
58230fb1 477 wxLogError(_("Cannot retrieve thread scheduling policy."));
518b5d2f
VZ
478 }
479
480 int min_prio = sched_get_priority_min(prio),
481 max_prio = sched_get_priority_max(prio);
482
483 if ( min_prio == -1 || max_prio == -1 )
484 {
58230fb1 485 wxLogError(_("Cannot get priority range for scheduling policy %d."),
518b5d2f
VZ
486 prio);
487 }
488 else
489 {
490 struct sched_param sp;
491 pthread_attr_getschedparam(&attr, &sp);
492 sp.sched_priority = min_prio +
493 (p_internal->GetPriority()*(max_prio-min_prio))/100;
494 pthread_attr_setschedparam(&attr, &sp);
495 }
34f8c26e 496#endif // HAVE_THREAD_PRIORITY_FUNCTIONS
518b5d2f 497
58230fb1
VZ
498#ifdef HAVE_PTHREAD_ATTR_SETSCOPE
499 // this will make the threads created by this process really concurrent
500 pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
501#endif // HAVE_PTHREAD_ATTR_SETSCOPE
502
518b5d2f 503 // create the new OS thread object
882eefb1 504 int rc = pthread_create(p_internal->GetIdPtr(), &attr,
518b5d2f
VZ
505 wxThreadInternal::PthreadStart, (void *)this);
506 pthread_attr_destroy(&attr);
507
508 if ( rc != 0 )
509 {
510 p_internal->SetState(STATE_EXITED);
511 return wxTHREAD_NO_RESOURCE;
512 }
513
514 return wxTHREAD_NO_ERROR;
515}
516
517wxThreadError wxThread::Run()
518{
519 return p_internal->Run();
520}
521
522// -----------------------------------------------------------------------------
523// misc accessors
524// -----------------------------------------------------------------------------
525
526void wxThread::SetPriority(unsigned int prio)
527{
34f8c26e
VZ
528 wxCHECK_RET( ((int)WXTHREAD_MIN_PRIORITY <= (int)prio) &&
529 ((int)prio <= (int)WXTHREAD_MAX_PRIORITY),
d207efe1 530 _T("invalid thread priority") );
518b5d2f
VZ
531
532 wxCriticalSectionLocker lock(m_critsect);
533
534 switch ( p_internal->GetState() )
535 {
536 case STATE_NEW:
537 // thread not yet started, priority will be set when it is
538 p_internal->SetPriority(prio);
539 break;
540
541 case STATE_RUNNING:
542 case STATE_PAUSED:
34f8c26e 543#ifdef HAVE_THREAD_PRIORITY_FUNCTIONS
518b5d2f
VZ
544 {
545 struct sched_param sparam;
546 sparam.sched_priority = prio;
547
548 if ( pthread_setschedparam(p_internal->GetId(),
549 SCHED_OTHER, &sparam) != 0 )
550 {
551 wxLogError(_("Failed to set thread priority %d."), prio);
552 }
553 }
34f8c26e 554#endif // HAVE_THREAD_PRIORITY_FUNCTIONS
518b5d2f
VZ
555 break;
556
557 case STATE_EXITED:
558 default:
d207efe1 559 wxFAIL_MSG(_T("impossible to set thread priority in this state"));
518b5d2f
VZ
560 }
561}
562
563unsigned int wxThread::GetPriority() const
564{
565 wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect);
566
567 return p_internal->GetPriority();
568}
569
570unsigned long wxThread::GetID() const
571{
882eefb1 572 return (unsigned long)p_internal->GetId();
518b5d2f
VZ
573}
574
575// -----------------------------------------------------------------------------
576// pause/resume
577// -----------------------------------------------------------------------------
578
579wxThreadError wxThread::Pause()
580{
581 wxCriticalSectionLocker lock(m_critsect);
582
583 if ( p_internal->GetState() != STATE_RUNNING )
584 {
d207efe1 585 wxLogDebug(_T("Can't pause thread which is not running."));
518b5d2f
VZ
586
587 return wxTHREAD_NOT_RUNNING;
588 }
589
590 p_internal->SetState(STATE_PAUSED);
591
592 return wxTHREAD_NO_ERROR;
593}
594
595wxThreadError wxThread::Resume()
596{
597 wxCriticalSectionLocker lock(m_critsect);
598
599 if ( p_internal->GetState() == STATE_PAUSED )
600 {
a737331d 601 m_critsect.Leave();
518b5d2f 602 p_internal->Resume();
a737331d 603 m_critsect.Enter();
518b5d2f
VZ
604
605 return wxTHREAD_NO_ERROR;
606 }
607 else
608 {
d207efe1 609 wxLogDebug(_T("Attempt to resume a thread which is not paused."));
518b5d2f
VZ
610
611 return wxTHREAD_MISC_ERROR;
612 }
613}
614
615// -----------------------------------------------------------------------------
616// exiting thread
617// -----------------------------------------------------------------------------
618
619wxThread::ExitCode wxThread::Delete()
620{
621 m_critsect.Enter();
882eefb1 622 wxThreadState state = p_internal->GetState();
518b5d2f
VZ
623 m_critsect.Leave();
624
882eefb1
VZ
625 // ask the thread to stop
626 p_internal->SetCancelFlag();
627
518b5d2f
VZ
628 switch ( state )
629 {
630 case STATE_NEW:
631 case STATE_EXITED:
632 // nothing to do
633 break;
634
635 case STATE_PAUSED:
636 // resume the thread first
637 Resume();
638
639 // fall through
640
641 default:
882eefb1
VZ
642 // wait until the thread stops
643 p_internal->Wait();
518b5d2f
VZ
644 }
645
646 return NULL;
647}
648
649wxThreadError wxThread::Kill()
650{
651 switch ( p_internal->GetState() )
652 {
653 case STATE_NEW:
654 case STATE_EXITED:
655 return wxTHREAD_NOT_RUNNING;
656
657 default:
34f8c26e 658#ifdef HAVE_PTHREAD_CANCEL
518b5d2f 659 if ( pthread_cancel(p_internal->GetId()) != 0 )
34f8c26e 660#endif
518b5d2f
VZ
661 {
662 wxLogError(_("Failed to terminate a thread."));
663
664 return wxTHREAD_MISC_ERROR;
665 }
666
667 return wxTHREAD_NO_ERROR;
668 }
669}
670
671void wxThread::Exit(void *status)
672{
673 // first call user-level clean up code
674 OnExit();
675
676 // next wake up the threads waiting for us (OTOH, this function won't return
677 // until someone waited for us!)
678 p_internal->SignalExit();
679
680 p_internal->SetState(STATE_EXITED);
681
682 // delete both C++ thread object and terminate the OS thread object
c84fb40a
GL
683 // GL: This is very ugly and buggy ...
684// delete this;
518b5d2f
VZ
685 pthread_exit(status);
686}
687
688// also test whether we were paused
689bool wxThread::TestDestroy()
690{
882eefb1 691 wxCriticalSectionLocker lock(m_critsect);
518b5d2f
VZ
692
693 if ( p_internal->GetState() == STATE_PAUSED )
694 {
695 // leave the crit section or the other threads will stop too if they try
696 // to call any of (seemingly harmless) IsXXX() functions while we sleep
697 m_critsect.Leave();
698
699 p_internal->Pause();
700
701 // enter it back before it's finally left in lock object dtor
702 m_critsect.Enter();
703 }
704
705 return p_internal->WasCancelled();
706}
707
708wxThread::~wxThread()
709{
710 // remove this thread from the global array
711 gs_allThreads.Remove(this);
712}
713
714// -----------------------------------------------------------------------------
715// state tests
716// -----------------------------------------------------------------------------
717
718bool wxThread::IsRunning() const
719{
720 wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect);
721
722 return p_internal->GetState() == STATE_RUNNING;
723}
724
725bool wxThread::IsAlive() const
726{
727 wxCriticalSectionLocker lock((wxCriticalSection&)m_critsect);
728
729 switch ( p_internal->GetState() )
730 {
731 case STATE_RUNNING:
732 case STATE_PAUSED:
733 return TRUE;
734
735 default:
736 return FALSE;
737 }
738}
739
a737331d
GL
740bool wxThread::IsPaused() const
741{
742 wxCriticalSectionLocker lock((wxCriticalSection&)m_critsect);
743
744 return (p_internal->GetState() == STATE_PAUSED);
745}
746
518b5d2f
VZ
747//--------------------------------------------------------------------
748// wxThreadModule
749//--------------------------------------------------------------------
750
751class wxThreadModule : public wxModule
752{
753public:
754 virtual bool OnInit();
755 virtual void OnExit();
756
757private:
758 DECLARE_DYNAMIC_CLASS(wxThreadModule)
759};
760
761IMPLEMENT_DYNAMIC_CLASS(wxThreadModule, wxModule)
762
763bool wxThreadModule::OnInit()
764{
58230fb1
VZ
765 int rc = pthread_key_create(&gs_keySelf, NULL /* dtor function */);
766 if ( rc != 0 )
518b5d2f 767 {
58230fb1
VZ
768 wxLogSysError(rc, _("Thread module initialization failed: "
769 "failed to create thread key"));
518b5d2f
VZ
770
771 return FALSE;
772 }
773
19da4326 774#ifndef __WXGTK12__
518b5d2f 775 gs_mutexGui = new wxMutex();
19da4326 776#endif
518b5d2f
VZ
777
778 gs_tidMain = pthread_self();
19da4326
RR
779
780#ifndef __WXGTK12__
518b5d2f 781 gs_mutexGui->Lock();
19da4326 782#endif
518b5d2f
VZ
783
784 return TRUE;
785}
786
787void wxThreadModule::OnExit()
788{
d207efe1 789 wxASSERT_MSG( wxThread::IsMain(), _T("only main thread can be here") );
518b5d2f
VZ
790
791 // terminate any threads left
792 size_t count = gs_allThreads.GetCount();
793 if ( count != 0u )
d207efe1 794 wxLogDebug(_T("Some threads were not terminated by the application."));
518b5d2f
VZ
795
796 for ( size_t n = 0u; n < count; n++ )
797 {
798 gs_allThreads[n]->Delete();
799 }
800
19da4326 801#ifndef __WXGTK12__
518b5d2f
VZ
802 // destroy GUI mutex
803 gs_mutexGui->Unlock();
804
518b5d2f 805 delete gs_mutexGui;
19da4326 806#endif
518b5d2f
VZ
807
808 // and free TLD slot
809 (void)pthread_key_delete(gs_keySelf);
810}
811
812// ----------------------------------------------------------------------------
813// global functions
814// ----------------------------------------------------------------------------
815
816void wxMutexGuiEnter()
817{
19da4326
RR
818#ifdef __WXGTK12__
819 gdk_threads_enter();
820#else
518b5d2f 821 gs_mutexGui->Lock();
19da4326 822#endif
518b5d2f
VZ
823}
824
825void wxMutexGuiLeave()
826{
19da4326
RR
827#ifdef __WXGTK12__
828 gdk_threads_leave();
829#else
518b5d2f 830 gs_mutexGui->Unlock();
19da4326 831#endif
518b5d2f 832}
80cb83be 833
7bcb11d3
JS
834#endif
835 // wxUSE_THREADS