]> git.saurik.com Git - wxWidgets.git/blame - src/unix/threadpsx.cpp
add support for alpha in color dialog on OSX, see #14127
[wxWidgets.git] / src / unix / threadpsx.cpp
CommitLineData
518b5d2f 1/////////////////////////////////////////////////////////////////////////////
ad9835c9 2// Name: src/unix/threadpsx.cpp
518b5d2f
VZ
3// Purpose: wxThread (Posix) Implementation
4// Author: Original from Wolfram Gloger/Guilhem Lavaux
be809868 5// Modified by: K. S. Sreeram (2002): POSIXified wxCondition, added wxSemaphore
518b5d2f
VZ
6// Created: 04/22/98
7// RCS-ID: $Id$
8// Copyright: (c) Wolfram Gloger (1996, 1997)
9// Guilhem Lavaux (1998)
8d5eff60 10// Vadim Zeitlin (1999-2002)
518b5d2f 11// Robert Roebling (1999)
be809868 12// K. S. Sreeram (2002)
65571936 13// Licence: wxWindows licence
518b5d2f
VZ
14/////////////////////////////////////////////////////////////////////////////
15
16// ============================================================================
17// declaration
18// ============================================================================
19
20// ----------------------------------------------------------------------------
21// headers
22// ----------------------------------------------------------------------------
23
14f355c2
VS
24// for compilers that support precompilation, includes "wx.h".
25#include "wx/wxprec.h"
518b5d2f 26
7bcb11d3 27#if wxUSE_THREADS
518b5d2f 28
88a7a4e1 29#include "wx/thread.h"
79b7b95a 30#include "wx/except.h"
88a7a4e1 31
ad9835c9 32#ifndef WX_PRECOMP
79b7b95a 33 #include "wx/app.h"
ad9835c9 34 #include "wx/dynarray.h"
88a7a4e1 35 #include "wx/intl.h"
e4db172a 36 #include "wx/log.h"
de6185e2 37 #include "wx/utils.h"
c0badb70 38 #include "wx/timer.h"
bb90a3e6 39 #include "wx/stopwatch.h"
02761f6c 40 #include "wx/module.h"
ad9835c9
WS
41#endif
42
518b5d2f
VZ
43#include <stdio.h>
44#include <unistd.h>
45#include <pthread.h>
46#include <errno.h>
47#include <time.h>
feedacd8 48#include <sys/time.h> // needed for at least __QNX__
4f66d445 49#ifdef HAVE_SCHED_H
518b5d2f
VZ
50 #include <sched.h>
51#endif
52
ef8d96c2
VZ
53#ifdef HAVE_THR_SETCONCURRENCY
54 #include <thread.h>
55#endif
56
89b3361e 57#ifdef HAVE_ABI_FORCEDUNWIND
e02ea203
VZ
58 #include <cxxabi.h>
59#endif
60
eaf4bde6
VZ
61#ifdef HAVE_SETPRIORITY
62 #include <sys/resource.h> // for setpriority()
63#endif
64
ef8d96c2
VZ
65// we use wxFFile under Linux in GetCPUCount()
66#ifdef __LINUX__
67 #include "wx/ffile.h"
68#endif
69
35e9c131
VS
70#define THR_ID_CAST(id) (reinterpret_cast<void*>(id))
71#define THR_ID(thr) THR_ID_CAST((thr)->GetId())
ef4f69ec 72
518b5d2f
VZ
73// ----------------------------------------------------------------------------
74// constants
75// ----------------------------------------------------------------------------
76
882eefb1
VZ
77// the possible states of the thread and transitions from them
78enum wxThreadState
518b5d2f
VZ
79{
80 STATE_NEW, // didn't start execution yet (=> RUNNING)
882eefb1
VZ
81 STATE_RUNNING, // running (=> PAUSED or EXITED)
82 STATE_PAUSED, // suspended (=> RUNNING or EXITED)
83 STATE_EXITED // thread doesn't exist any more
518b5d2f
VZ
84};
85
9fc3ad34
VZ
86// the exit value of a thread which has been cancelled
87static const wxThread::ExitCode EXITCODE_CANCELLED = (wxThread::ExitCode)-1;
88
9e84b847 89// trace mask for wxThread operations
9a83f860 90#define TRACE_THREADS wxT("thread")
9fc3ad34 91
9e84b847 92// you can get additional debugging messages for the semaphore operations
9a83f860 93#define TRACE_SEMA wxT("semaphore")
9e84b847 94
9fc3ad34
VZ
95// ----------------------------------------------------------------------------
96// private functions
97// ----------------------------------------------------------------------------
98
99static void ScheduleThreadForDeletion();
100static void DeleteThread(wxThread *This);
101
882eefb1 102// ----------------------------------------------------------------------------
9e84b847 103// private classes
882eefb1
VZ
104// ----------------------------------------------------------------------------
105
9e84b847 106// an (non owning) array of pointers to threads
0d2c74c6 107WX_DEFINE_ARRAY_PTR(wxThread *, wxArrayThread);
518b5d2f 108
9e84b847
VZ
109// an entry for a thread we can wait for
110
518b5d2f
VZ
111// -----------------------------------------------------------------------------
112// global data
113// -----------------------------------------------------------------------------
114
115// we keep the list of all threads created by the application to be able to
116// terminate them on exit if there are some left - otherwise the process would
117// be left in memory
118static wxArrayThread gs_allThreads;
119
25b34b26
VZ
120// a mutex to protect gs_allThreads
121static wxMutex *gs_mutexAllThreads = NULL;
122
518b5d2f 123// the id of the main thread
f9226383
VZ
124//
125// we suppose that 0 is not a valid pthread_t value but in principle this might
126// be false (e.g. if it's a selector-like value), wxThread::IsMain() would need
127// to be updated in such case
128wxThreadIdType wxThread::ms_idMainThread = 0;
518b5d2f
VZ
129
130// the key for the pointer to the associated wxThread object
131static pthread_key_t gs_keySelf;
132
9fc3ad34
VZ
133// the number of threads which are being deleted - the program won't exit
134// until there are any left
135static size_t gs_nThreadsBeingDeleted = 0;
136
137// a mutex to protect gs_nThreadsBeingDeleted
d3b9f782 138static wxMutex *gs_mutexDeleteThread = NULL;
9fc3ad34
VZ
139
140// and a condition variable which will be signaled when all
141// gs_nThreadsBeingDeleted will have been deleted
d3b9f782 142static wxCondition *gs_condAllDeleted = NULL;
9fc3ad34 143
a94c4b85 144#ifndef __WXOSX__
c80217d1
VS
145// this mutex must be acquired before any call to a GUI function
146// (it's not inside #if wxUSE_GUI because this file is compiled as part
147// of wxBase)
148static wxMutex *gs_mutexGui = NULL;
a94c4b85 149#endif
518b5d2f 150
9e84b847
VZ
151// when we wait for a thread to exit, we're blocking on a condition which the
152// thread signals in its SignalExit() method -- but this condition can't be a
153// member of the thread itself as a detached thread may delete itself at any
154// moment and accessing the condition member of the thread after this would
155// result in a disaster
156//
157// so instead we maintain a global list of the structs below for the threads
158// we're interested in waiting on
159
518b5d2f 160// ============================================================================
8d5eff60 161// wxMutex implementation
518b5d2f
VZ
162// ============================================================================
163
8d5eff60
VZ
164// ----------------------------------------------------------------------------
165// wxMutexInternal
166// ----------------------------------------------------------------------------
518b5d2f 167
9e84b847
VZ
168// this is a simple wrapper around pthread_mutex_t which provides error
169// checking
518b5d2f
VZ
170class wxMutexInternal
171{
172public:
9e84b847 173 wxMutexInternal(wxMutexType mutexType);
8d5eff60
VZ
174 ~wxMutexInternal();
175
176 wxMutexError Lock();
696d13ee 177 wxMutexError Lock(unsigned long ms);
8d5eff60
VZ
178 wxMutexError TryLock();
179 wxMutexError Unlock();
180
9e84b847
VZ
181 bool IsOk() const { return m_isOk; }
182
696d13ee
VZ
183private:
184 // convert the result of pthread_mutex_[timed]lock() call to wx return code
185 wxMutexError HandleLockResult(int err);
186
8d5eff60 187private:
9fc3ad34 188 pthread_mutex_t m_mutex;
9e84b847 189 bool m_isOk;
375f364e
RR
190 wxMutexType m_type;
191 unsigned long m_owningThread;
be809868 192
9e84b847 193 // wxConditionInternal uses our m_mutex
be809868 194 friend class wxConditionInternal;
518b5d2f
VZ
195};
196
123dca7d
VZ
197#if defined(HAVE_PTHREAD_MUTEXATTR_T) && \
198 wxUSE_UNIX && !defined(HAVE_PTHREAD_MUTEXATTR_SETTYPE_DECL)
707a3782
VS
199// on some systems pthread_mutexattr_settype() is not in the headers (but it is
200// in the library, otherwise we wouldn't compile this code at all)
201extern "C" int pthread_mutexattr_settype(pthread_mutexattr_t *, int);
202#endif
203
9e84b847 204wxMutexInternal::wxMutexInternal(wxMutexType mutexType)
518b5d2f 205{
375f364e
RR
206 m_type = mutexType;
207 m_owningThread = 0;
208
9e84b847
VZ
209 int err;
210 switch ( mutexType )
211 {
212 case wxMUTEX_RECURSIVE:
213 // support recursive locks like Win32, i.e. a thread can lock a
214 // mutex which it had itself already locked
215 //
216 // unfortunately initialization of recursive mutexes is non
217 // portable, so try several methods
d9b9876f 218#ifdef HAVE_PTHREAD_MUTEXATTR_T
9e84b847
VZ
219 {
220 pthread_mutexattr_t attr;
221 pthread_mutexattr_init(&attr);
222 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
d9b9876f 223
9e84b847
VZ
224 err = pthread_mutex_init(&m_mutex, &attr);
225 }
d9b9876f 226#elif defined(HAVE_PTHREAD_RECURSIVE_MUTEX_INITIALIZER)
9e84b847
VZ
227 // we can use this only as initializer so we have to assign it
228 // first to a temp var - assigning directly to m_mutex wouldn't
229 // even compile
230 {
231 pthread_mutex_t mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
232 m_mutex = mutex;
233 }
d9b9876f 234#else // no recursive mutexes
9e84b847 235 err = EINVAL;
d9b9876f 236#endif // HAVE_PTHREAD_MUTEXATTR_T/...
9e84b847
VZ
237 break;
238
239 default:
9a83f860 240 wxFAIL_MSG( wxT("unknown mutex type") );
9e84b847
VZ
241 // fall through
242
243 case wxMUTEX_DEFAULT:
244 err = pthread_mutex_init(&m_mutex, NULL);
245 break;
246 }
247
248 m_isOk = err == 0;
249 if ( !m_isOk )
250 {
401eb3de 251 wxLogApiError( wxT("pthread_mutex_init()"), err);
9e84b847 252 }
8d5eff60
VZ
253}
254
255wxMutexInternal::~wxMutexInternal()
256{
9e84b847
VZ
257 if ( m_isOk )
258 {
259 int err = pthread_mutex_destroy(&m_mutex);
260 if ( err != 0 )
261 {
401eb3de 262 wxLogApiError( wxT("pthread_mutex_destroy()"), err);
9e84b847
VZ
263 }
264 }
8d5eff60
VZ
265}
266
267wxMutexError wxMutexInternal::Lock()
268{
375f364e
RR
269 if ((m_type == wxMUTEX_DEFAULT) && (m_owningThread != 0))
270 {
271 if (m_owningThread == wxThread::GetCurrentId())
272 return wxMUTEX_DEAD_LOCK;
273 }
122cf17b 274
696d13ee
VZ
275 return HandleLockResult(pthread_mutex_lock(&m_mutex));
276}
277
278wxMutexError wxMutexInternal::Lock(unsigned long ms)
279{
e55a667c 280#ifdef HAVE_PTHREAD_MUTEX_TIMEDLOCK
696d13ee
VZ
281 static const long MSEC_IN_SEC = 1000;
282 static const long NSEC_IN_MSEC = 1000000;
fd91cec1 283 static const long NSEC_IN_USEC = 1000;
696d13ee
VZ
284 static const long NSEC_IN_SEC = MSEC_IN_SEC * NSEC_IN_MSEC;
285
286 time_t seconds = ms/MSEC_IN_SEC;
287 long nanoseconds = (ms % MSEC_IN_SEC) * NSEC_IN_MSEC;
288 timespec ts = { 0, 0 };
289
fd91cec1
VZ
290 // normally we should use clock_gettime(CLOCK_REALTIME) here but this
291 // function is in librt and we don't link with it currently, so use
292 // gettimeofday() instead -- if it turns out that this is really too
293 // imprecise, we should modify configure to check if clock_gettime() is
294 // available and whether it requires -lrt and use it instead
295#if 0
696d13ee
VZ
296 if ( clock_gettime(CLOCK_REALTIME, &ts) == 0 )
297 {
696d13ee 298 }
fd91cec1
VZ
299#else
300 struct timeval tv;
301 if ( wxGetTimeOfDay(&tv) != -1 )
302 {
303 ts.tv_sec = tv.tv_sec;
304 ts.tv_nsec = tv.tv_usec*NSEC_IN_USEC;
305 }
306#endif
696d13ee
VZ
307 else // fall back on system timer
308 {
fd91cec1
VZ
309 ts.tv_sec = time(NULL);
310 }
311
312 ts.tv_sec += seconds;
313 ts.tv_nsec += nanoseconds;
314 if ( ts.tv_nsec > NSEC_IN_SEC )
315 {
316 ts.tv_sec += 1;
317 ts.tv_nsec -= NSEC_IN_SEC;
696d13ee
VZ
318 }
319
320 return HandleLockResult(pthread_mutex_timedlock(&m_mutex, &ts));
e55a667c
VZ
321#else // !HAVE_PTHREAD_MUTEX_TIMEDLOCK
322 wxUnusedVar(ms);
323
324 return wxMUTEX_MISC_ERROR;
325#endif // HAVE_PTHREAD_MUTEX_TIMEDLOCK/!HAVE_PTHREAD_MUTEX_TIMEDLOCK
696d13ee
VZ
326}
327
328wxMutexError wxMutexInternal::HandleLockResult(int err)
329{
375f364e
RR
330 // wxPrintf( "err %d\n", err );
331
8d5eff60
VZ
332 switch ( err )
333 {
334 case EDEADLK:
9e84b847
VZ
335 // only error checking mutexes return this value and so it's an
336 // unexpected situation -- hence use assert, not wxLogDebug
9a83f860 337 wxFAIL_MSG( wxT("mutex deadlock prevented") );
8d5eff60
VZ
338 return wxMUTEX_DEAD_LOCK;
339
8d5eff60 340 case EINVAL:
9a83f860 341 wxLogDebug(wxT("pthread_mutex_[timed]lock(): mutex not initialized"));
9e84b847 342 break;
8d5eff60 343
696d13ee
VZ
344 case ETIMEDOUT:
345 return wxMUTEX_TIMEOUT;
346
8d5eff60 347 case 0:
375f364e
RR
348 if (m_type == wxMUTEX_DEFAULT)
349 m_owningThread = wxThread::GetCurrentId();
8d5eff60 350 return wxMUTEX_NO_ERROR;
9e84b847
VZ
351
352 default:
9a83f860 353 wxLogApiError(wxT("pthread_mutex_[timed]lock()"), err);
8d5eff60 354 }
9e84b847
VZ
355
356 return wxMUTEX_MISC_ERROR;
8d5eff60
VZ
357}
358
696d13ee 359
8d5eff60
VZ
360wxMutexError wxMutexInternal::TryLock()
361{
362 int err = pthread_mutex_trylock(&m_mutex);
363 switch ( err )
364 {
365 case EBUSY:
9e84b847
VZ
366 // not an error: mutex is already locked, but we're prepared for
367 // this
8d5eff60
VZ
368 return wxMUTEX_BUSY;
369
8d5eff60 370 case EINVAL:
9a83f860 371 wxLogDebug(wxT("pthread_mutex_trylock(): mutex not initialized."));
9e84b847 372 break;
8d5eff60
VZ
373
374 case 0:
375f364e
RR
375 if (m_type == wxMUTEX_DEFAULT)
376 m_owningThread = wxThread::GetCurrentId();
8d5eff60 377 return wxMUTEX_NO_ERROR;
9e84b847
VZ
378
379 default:
9a83f860 380 wxLogApiError(wxT("pthread_mutex_trylock()"), err);
8d5eff60 381 }
9e84b847
VZ
382
383 return wxMUTEX_MISC_ERROR;
8d5eff60
VZ
384}
385
386wxMutexError wxMutexInternal::Unlock()
387{
375f364e 388 m_owningThread = 0;
122cf17b 389
8d5eff60
VZ
390 int err = pthread_mutex_unlock(&m_mutex);
391 switch ( err )
392 {
393 case EPERM:
394 // we don't own the mutex
395 return wxMUTEX_UNLOCKED;
396
8d5eff60 397 case EINVAL:
9a83f860 398 wxLogDebug(wxT("pthread_mutex_unlock(): mutex not initialized."));
9e84b847 399 break;
8d5eff60
VZ
400
401 case 0:
402 return wxMUTEX_NO_ERROR;
518b5d2f 403
9e84b847 404 default:
9a83f860 405 wxLogApiError(wxT("pthread_mutex_unlock()"), err);
518b5d2f
VZ
406 }
407
9e84b847 408 return wxMUTEX_MISC_ERROR;
518b5d2f
VZ
409}
410
be809868 411// ===========================================================================
8d5eff60 412// wxCondition implementation
be809868 413// ===========================================================================
8d5eff60 414
be809868 415// ---------------------------------------------------------------------------
8d5eff60 416// wxConditionInternal
be809868 417// ---------------------------------------------------------------------------
518b5d2f 418
9e84b847
VZ
419// this is a wrapper around pthread_cond_t associated with a wxMutex (and hence
420// with a pthread_mutex_t)
518b5d2f
VZ
421class wxConditionInternal
422{
423public:
c112e100 424 wxConditionInternal(wxMutex& mutex);
9fc3ad34
VZ
425 ~wxConditionInternal();
426
9e84b847 427 bool IsOk() const { return m_isOk && m_mutex.IsOk(); }
4c460b34 428
9e84b847
VZ
429 wxCondError Wait();
430 wxCondError WaitTimeout(unsigned long milliseconds);
547b93ab 431
9e84b847
VZ
432 wxCondError Signal();
433 wxCondError Broadcast();
4c460b34 434
be809868 435private:
c112e100 436 // get the POSIX mutex associated with us
9e84b847 437 pthread_mutex_t *GetPMutex() const { return &m_mutex.m_internal->m_mutex; }
518b5d2f 438
c112e100 439 wxMutex& m_mutex;
be809868 440 pthread_cond_t m_cond;
9e84b847
VZ
441
442 bool m_isOk;
8d5eff60 443};
547b93ab 444
c112e100
VZ
445wxConditionInternal::wxConditionInternal(wxMutex& mutex)
446 : m_mutex(mutex)
9fc3ad34 447{
9e84b847 448 int err = pthread_cond_init(&m_cond, NULL /* default attributes */);
9fc3ad34 449
9e84b847 450 m_isOk = err == 0;
9fc3ad34 451
9e84b847 452 if ( !m_isOk )
9fc3ad34 453 {
9a83f860 454 wxLogApiError(wxT("pthread_cond_init()"), err);
9fc3ad34
VZ
455 }
456}
457
9e84b847 458wxConditionInternal::~wxConditionInternal()
4c460b34 459{
9e84b847 460 if ( m_isOk )
c112e100 461 {
9e84b847
VZ
462 int err = pthread_cond_destroy(&m_cond);
463 if ( err != 0 )
464 {
9a83f860 465 wxLogApiError(wxT("pthread_cond_destroy()"), err);
9e84b847 466 }
c112e100 467 }
be809868 468}
4c460b34 469
9e84b847 470wxCondError wxConditionInternal::Wait()
be809868 471{
9e84b847
VZ
472 int err = pthread_cond_wait(&m_cond, GetPMutex());
473 if ( err != 0 )
474 {
9a83f860 475 wxLogApiError(wxT("pthread_cond_wait()"), err);
4c460b34 476
9e84b847 477 return wxCOND_MISC_ERROR;
be809868 478 }
4c460b34 479
9e84b847 480 return wxCOND_NO_ERROR;
be809868 481}
60ce696e 482
9e84b847 483wxCondError wxConditionInternal::WaitTimeout(unsigned long milliseconds)
be809868 484{
e60defcb 485 wxLongLong curtime = wxGetUTCTimeMillis();
9e84b847 486 curtime += milliseconds;
be809868
VZ
487 wxLongLong temp = curtime / 1000;
488 int sec = temp.GetLo();
9e84b847 489 temp *= 1000;
be809868
VZ
490 temp = curtime - temp;
491 int millis = temp.GetLo();
492
493 timespec tspec;
494
495 tspec.tv_sec = sec;
496 tspec.tv_nsec = millis * 1000L * 1000L;
4c460b34 497
9e84b847
VZ
498 int err = pthread_cond_timedwait( &m_cond, GetPMutex(), &tspec );
499 switch ( err )
500 {
501 case ETIMEDOUT:
502 return wxCOND_TIMEOUT;
503
504 case 0:
505 return wxCOND_NO_ERROR;
506
507 default:
9a83f860 508 wxLogApiError(wxT("pthread_cond_timedwait()"), err);
9e84b847
VZ
509 }
510
511 return wxCOND_MISC_ERROR;
9fc3ad34
VZ
512}
513
9e84b847 514wxCondError wxConditionInternal::Signal()
9fc3ad34 515{
9e84b847
VZ
516 int err = pthread_cond_signal(&m_cond);
517 if ( err != 0 )
518 {
9a83f860 519 wxLogApiError(wxT("pthread_cond_signal()"), err);
9e84b847
VZ
520
521 return wxCOND_MISC_ERROR;
522 }
523
524 return wxCOND_NO_ERROR;
be809868 525}
547b93ab 526
9e84b847 527wxCondError wxConditionInternal::Broadcast()
be809868 528{
9e84b847
VZ
529 int err = pthread_cond_broadcast(&m_cond);
530 if ( err != 0 )
531 {
9a83f860 532 wxLogApiError(wxT("pthread_cond_broadcast()"), err);
9e84b847
VZ
533
534 return wxCOND_MISC_ERROR;
535 }
536
537 return wxCOND_NO_ERROR;
be809868
VZ
538}
539
540// ===========================================================================
541// wxSemaphore implementation
542// ===========================================================================
9fc3ad34 543
be809868
VZ
544// ---------------------------------------------------------------------------
545// wxSemaphoreInternal
546// ---------------------------------------------------------------------------
547
9e84b847
VZ
548// we implement the semaphores using mutexes and conditions instead of using
549// the sem_xxx() POSIX functions because they're not widely available and also
550// because it's impossible to implement WaitTimeout() using them
be809868
VZ
551class wxSemaphoreInternal
552{
553public:
9e84b847 554 wxSemaphoreInternal(int initialcount, int maxcount);
be809868 555
9e84b847 556 bool IsOk() const { return m_isOk; }
be809868 557
9e84b847
VZ
558 wxSemaError Wait();
559 wxSemaError TryWait();
560 wxSemaError WaitTimeout(unsigned long milliseconds);
be809868 561
9e84b847 562 wxSemaError Post();
be809868
VZ
563
564private:
565 wxMutex m_mutex;
566 wxCondition m_cond;
567
9e84b847
VZ
568 size_t m_count,
569 m_maxcount;
570
571 bool m_isOk;
be809868
VZ
572};
573
9e84b847 574wxSemaphoreInternal::wxSemaphoreInternal(int initialcount, int maxcount)
c112e100 575 : m_cond(m_mutex)
be809868
VZ
576{
577
9e84b847
VZ
578 if ( (initialcount < 0 || maxcount < 0) ||
579 ((maxcount > 0) && (initialcount > maxcount)) )
580 {
9a83f860 581 wxFAIL_MSG( wxT("wxSemaphore: invalid initial or maximal count") );
9e84b847 582
ad9835c9 583 m_isOk = false;
9e84b847
VZ
584 }
585 else
be809868 586 {
9e84b847
VZ
587 m_maxcount = (size_t)maxcount;
588 m_count = (size_t)initialcount;
547b93ab 589 }
547b93ab 590
9e84b847 591 m_isOk = m_mutex.IsOk() && m_cond.IsOk();
be809868 592}
547b93ab 593
9e84b847 594wxSemaError wxSemaphoreInternal::Wait()
be809868 595{
cd10339a 596 wxMutexLocker locker(m_mutex);
60ce696e 597
9e84b847 598 while ( m_count == 0 )
9fc3ad34 599 {
9e84b847 600 wxLogTrace(TRACE_SEMA,
9a83f860 601 wxT("Thread %p waiting for semaphore to become signalled"),
35e9c131 602 THR_ID_CAST(wxThread::GetCurrentId()));
9e84b847
VZ
603
604 if ( m_cond.Wait() != wxCOND_NO_ERROR )
605 return wxSEMA_MISC_ERROR;
606
607 wxLogTrace(TRACE_SEMA,
9a83f860 608 wxT("Thread %p finished waiting for semaphore, count = %lu"),
35e9c131 609 THR_ID_CAST(wxThread::GetCurrentId()), (unsigned long)m_count);
9fc3ad34 610 }
be809868 611
9e84b847
VZ
612 m_count--;
613
614 return wxSEMA_NO_ERROR;
be809868
VZ
615}
616
9e84b847 617wxSemaError wxSemaphoreInternal::TryWait()
be809868 618{
cd10339a 619 wxMutexLocker locker(m_mutex);
be809868 620
9e84b847
VZ
621 if ( m_count == 0 )
622 return wxSEMA_BUSY;
be809868 623
9e84b847 624 m_count--;
be809868 625
9e84b847 626 return wxSEMA_NO_ERROR;
be809868
VZ
627}
628
9e84b847 629wxSemaError wxSemaphoreInternal::WaitTimeout(unsigned long milliseconds)
be809868 630{
cd10339a 631 wxMutexLocker locker(m_mutex);
be809868
VZ
632
633 wxLongLong startTime = wxGetLocalTimeMillis();
634
9e84b847 635 while ( m_count == 0 )
9fc3ad34 636 {
be809868 637 wxLongLong elapsed = wxGetLocalTimeMillis() - startTime;
9e84b847 638 long remainingTime = (long)milliseconds - (long)elapsed.GetLo();
be809868 639 if ( remainingTime <= 0 )
9e84b847
VZ
640 {
641 // timeout
642 return wxSEMA_TIMEOUT;
643 }
be809868 644
918dc519
VZ
645 switch ( m_cond.WaitTimeout(remainingTime) )
646 {
647 case wxCOND_TIMEOUT:
648 return wxSEMA_TIMEOUT;
649
650 default:
651 return wxSEMA_MISC_ERROR;
652
653 case wxCOND_NO_ERROR:
654 ;
655 }
9fc3ad34 656 }
8d5eff60 657
9e84b847 658 m_count--;
be809868 659
9e84b847 660 return wxSEMA_NO_ERROR;
be809868
VZ
661}
662
9e84b847 663wxSemaError wxSemaphoreInternal::Post()
be809868 664{
cd10339a 665 wxMutexLocker locker(m_mutex);
be809868 666
9e84b847 667 if ( m_maxcount > 0 && m_count == m_maxcount )
60ce696e 668 {
9e84b847 669 return wxSEMA_OVERFLOW;
60ce696e 670 }
be809868 671
9e84b847 672 m_count++;
518b5d2f 673
9e84b847 674 wxLogTrace(TRACE_SEMA,
9a83f860 675 wxT("Thread %p about to signal semaphore, count = %lu"),
35e9c131 676 THR_ID_CAST(wxThread::GetCurrentId()), (unsigned long)m_count);
2b5f62a0 677
9e84b847
VZ
678 return m_cond.Signal() == wxCOND_NO_ERROR ? wxSEMA_NO_ERROR
679 : wxSEMA_MISC_ERROR;
518b5d2f
VZ
680}
681
be809868 682// ===========================================================================
8d5eff60 683// wxThread implementation
be809868 684// ===========================================================================
518b5d2f 685
295272bd
VZ
686// the thread callback functions must have the C linkage
687extern "C"
688{
689
816a7358 690#ifdef wxHAVE_PTHREAD_CLEANUP
295272bd
VZ
691 // thread exit function
692 void wxPthreadCleanup(void *ptr);
816a7358 693#endif // wxHAVE_PTHREAD_CLEANUP
90350682 694
295272bd 695void *wxPthreadStart(void *ptr);
90350682 696
295272bd 697} // extern "C"
90350682 698
8d5eff60
VZ
699// ----------------------------------------------------------------------------
700// wxThreadInternal
701// ----------------------------------------------------------------------------
702
518b5d2f
VZ
703class wxThreadInternal
704{
705public:
706 wxThreadInternal();
707 ~wxThreadInternal();
708
709 // thread entry function
295272bd 710 static void *PthreadStart(wxThread *thread);
518b5d2f
VZ
711
712 // thread actions
713 // start the thread
714 wxThreadError Run();
9e84b847
VZ
715 // unblock the thread allowing it to run
716 void SignalRun() { m_semRun.Post(); }
518b5d2f 717 // ask the thread to terminate
882eefb1 718 void Wait();
518b5d2f
VZ
719 // go to sleep until Resume() is called
720 void Pause();
721 // resume the thread
722 void Resume();
723
724 // accessors
725 // priority
726 int GetPriority() const { return m_prio; }
727 void SetPriority(int prio) { m_prio = prio; }
728 // state
882eefb1 729 wxThreadState GetState() const { return m_state; }
9e84b847
VZ
730 void SetState(wxThreadState state)
731 {
711f12ef 732#if wxUSE_LOG_TRACE
a243da29 733 static const wxChar *const stateNames[] =
9e84b847 734 {
9a83f860
VZ
735 wxT("NEW"),
736 wxT("RUNNING"),
737 wxT("PAUSED"),
738 wxT("EXITED"),
9e84b847
VZ
739 };
740
9a83f860 741 wxLogTrace(TRACE_THREADS, wxT("Thread %p: %s => %s."),
35e9c131 742 THR_ID(this), stateNames[m_state], stateNames[state]);
711f12ef 743#endif // wxUSE_LOG_TRACE
9e84b847
VZ
744
745 m_state = state;
746 }
518b5d2f 747 // id
882eefb1
VZ
748 pthread_t GetId() const { return m_threadId; }
749 pthread_t *GetIdPtr() { return &m_threadId; }
518b5d2f 750 // "cancelled" flag
ad9835c9 751 void SetCancelFlag() { m_cancelled = true; }
518b5d2f 752 bool WasCancelled() const { return m_cancelled; }
9fc3ad34
VZ
753 // exit code
754 void SetExitCode(wxThread::ExitCode exitcode) { m_exitcode = exitcode; }
755 wxThread::ExitCode GetExitCode() const { return m_exitcode; }
756
4c460b34
VZ
757 // the pause flag
758 void SetReallyPaused(bool paused) { m_isPaused = paused; }
759 bool IsReallyPaused() const { return m_isPaused; }
760
9fc3ad34 761 // tell the thread that it is a detached one
4c460b34
VZ
762 void Detach()
763 {
9e84b847
VZ
764 wxCriticalSectionLocker lock(m_csJoinFlag);
765
ad9835c9
WS
766 m_shouldBeJoined = false;
767 m_isDetached = true;
4c460b34 768 }
518b5d2f 769
816a7358 770#ifdef wxHAVE_PTHREAD_CLEANUP
90350682
VZ
771 // this is used by wxPthreadCleanup() only
772 static void Cleanup(wxThread *thread);
816a7358 773#endif // wxHAVE_PTHREAD_CLEANUP
90350682 774
518b5d2f 775private:
882eefb1
VZ
776 pthread_t m_threadId; // id of the thread
777 wxThreadState m_state; // see wxThreadState enum
77ffb593 778 int m_prio; // in wxWidgets units: from 0 to 100
518b5d2f 779
9fc3ad34 780 // this flag is set when the thread should terminate
518b5d2f
VZ
781 bool m_cancelled;
782
be809868 783 // this flag is set when the thread is blocking on m_semSuspend
4c460b34
VZ
784 bool m_isPaused;
785
9fc3ad34
VZ
786 // the thread exit code - only used for joinable (!detached) threads and
787 // is only valid after the thread termination
788 wxThread::ExitCode m_exitcode;
789
790 // many threads may call Wait(), but only one of them should call
791 // pthread_join(), so we have to keep track of this
792 wxCriticalSection m_csJoinFlag;
793 bool m_shouldBeJoined;
4c460b34 794 bool m_isDetached;
9fc3ad34 795
be809868 796 // this semaphore is posted by Run() and the threads Entry() is not
9fc3ad34 797 // called before it is done
be809868 798 wxSemaphore m_semRun;
9fc3ad34
VZ
799
800 // this one is signaled when the thread should resume after having been
801 // Pause()d
be809868 802 wxSemaphore m_semSuspend;
518b5d2f
VZ
803};
804
9fc3ad34
VZ
805// ----------------------------------------------------------------------------
806// thread startup and exit functions
807// ----------------------------------------------------------------------------
808
295272bd
VZ
809void *wxPthreadStart(void *ptr)
810{
811 return wxThreadInternal::PthreadStart((wxThread *)ptr);
812}
813
814void *wxThreadInternal::PthreadStart(wxThread *thread)
518b5d2f 815{
9fc3ad34 816 wxThreadInternal *pthread = thread->m_internal;
518b5d2f 817
9a83f860 818 wxLogTrace(TRACE_THREADS, wxT("Thread %p started."), THR_ID(pthread));
ef4f69ec 819
9fc3ad34
VZ
820 // associate the thread pointer with the newly created thread so that
821 // wxThread::This() will work
862cc6f9
VZ
822 int rc = pthread_setspecific(gs_keySelf, thread);
823 if ( rc != 0 )
518b5d2f 824 {
b82f92a8 825 wxLogSysError(rc, _("Cannot start thread: error writing TLS."));
518b5d2f
VZ
826
827 return (void *)-1;
828 }
9fc3ad34 829
4c460b34
VZ
830 // have to declare this before pthread_cleanup_push() which defines a
831 // block!
832 bool dontRunAtAll;
833
816a7358 834#ifdef wxHAVE_PTHREAD_CLEANUP
9fc3ad34
VZ
835 // install the cleanup handler which will be called if the thread is
836 // cancelled
295272bd 837 pthread_cleanup_push(wxPthreadCleanup, thread);
816a7358 838#endif // wxHAVE_PTHREAD_CLEANUP
518b5d2f 839
be809868
VZ
840 // wait for the semaphore to be posted from Run()
841 pthread->m_semRun.Wait();
518b5d2f 842
4c460b34
VZ
843 // test whether we should run the run at all - may be it was deleted
844 // before it started to Run()?
845 {
846 wxCriticalSectionLocker lock(thread->m_critsect);
9fc3ad34 847
4c460b34
VZ
848 dontRunAtAll = pthread->GetState() == STATE_NEW &&
849 pthread->WasCancelled();
850 }
9fc3ad34 851
4c460b34 852 if ( !dontRunAtAll )
9fc3ad34 853 {
4c460b34 854 // call the main entry
ef4f69ec 855 wxLogTrace(TRACE_THREADS,
9a83f860 856 wxT("Thread %p about to enter its Entry()."),
ef4f69ec
VZ
857 THR_ID(pthread));
858
79b7b95a
VS
859 wxTRY
860 {
861 pthread->m_exitcode = thread->Entry();
5092b3ad 862
79b7b95a 863 wxLogTrace(TRACE_THREADS,
9a83f860 864 wxT("Thread %p Entry() returned %lu."),
79b7b95a
VS
865 THR_ID(pthread), wxPtrToUInt(pthread->m_exitcode));
866 }
89b3361e 867#ifdef HAVE_ABI_FORCEDUNWIND
e02ea203
VZ
868 // When using common C++ ABI under Linux we must always rethrow this
869 // special exception used to unwind the stack when the thread was
870 // cancelled, otherwise the thread library would simply terminate the
871 // program, see http://udrepper.livejournal.com/21541.html
872 catch ( abi::__forced_unwind& )
873 {
874 wxCriticalSectionLocker lock(thread->m_critsect);
875 pthread->SetState(STATE_EXITED);
876 throw;
877 }
89b3361e 878#endif // HAVE_ABI_FORCEDUNWIND
79b7b95a 879 wxCATCH_ALL( wxTheApp->OnUnhandledException(); )
ef4f69ec 880
4c460b34
VZ
881 {
882 wxCriticalSectionLocker lock(thread->m_critsect);
883
4c460b34 884 // change the state of the thread to "exited" so that
90350682 885 // wxPthreadCleanup handler won't do anything from now (if it's
4c460b34
VZ
886 // called before we do pthread_cleanup_pop below)
887 pthread->SetState(STATE_EXITED);
888 }
9fc3ad34
VZ
889 }
890
741d91c5
VZ
891 // NB: pthread_cleanup_push/pop() are macros and pop contains the matching
892 // '}' for the '{' in push, so they must be used in the same block!
816a7358 893#ifdef wxHAVE_PTHREAD_CLEANUP
741d91c5
VZ
894 #ifdef __DECCXX
895 // under Tru64 we get a warning from macro expansion
896 #pragma message save
897 #pragma message disable(declbutnotref)
898 #endif
899
9fc3ad34 900 // remove the cleanup handler without executing it
062c4861 901 pthread_cleanup_pop(FALSE);
741d91c5
VZ
902
903 #ifdef __DECCXX
904 #pragma message restore
905 #endif
816a7358 906#endif // wxHAVE_PTHREAD_CLEANUP
518b5d2f 907
4c460b34
VZ
908 if ( dontRunAtAll )
909 {
9e84b847 910 // FIXME: deleting a possibly joinable thread here???
4c460b34 911 delete thread;
518b5d2f 912
4c460b34
VZ
913 return EXITCODE_CANCELLED;
914 }
915 else
916 {
917 // terminate the thread
918 thread->Exit(pthread->m_exitcode);
919
920 wxFAIL_MSG(wxT("wxThread::Exit() can't return."));
518b5d2f 921
4c460b34
VZ
922 return NULL;
923 }
518b5d2f
VZ
924}
925
816a7358 926#ifdef wxHAVE_PTHREAD_CLEANUP
5092b3ad 927
9fc3ad34 928// this handler is called when the thread is cancelled
90350682 929extern "C" void wxPthreadCleanup(void *ptr)
5092b3ad 930{
90350682
VZ
931 wxThreadInternal::Cleanup((wxThread *)ptr);
932}
5092b3ad 933
90350682
VZ
934void wxThreadInternal::Cleanup(wxThread *thread)
935{
b4866582 936 if (pthread_getspecific(gs_keySelf) == 0) return;
9fc3ad34
VZ
937 {
938 wxCriticalSectionLocker lock(thread->m_critsect);
939 if ( thread->m_internal->GetState() == STATE_EXITED )
940 {
941 // thread is already considered as finished.
942 return;
943 }
944 }
5092b3ad 945
9fc3ad34
VZ
946 // exit the thread gracefully
947 thread->Exit(EXITCODE_CANCELLED);
948}
5092b3ad 949
816a7358 950#endif // wxHAVE_PTHREAD_CLEANUP
5092b3ad 951
9fc3ad34
VZ
952// ----------------------------------------------------------------------------
953// wxThreadInternal
954// ----------------------------------------------------------------------------
5092b3ad 955
518b5d2f
VZ
956wxThreadInternal::wxThreadInternal()
957{
958 m_state = STATE_NEW;
ad9835c9 959 m_cancelled = false;
90e95e61 960 m_prio = wxPRIORITY_DEFAULT;
bbfa0322 961 m_threadId = 0;
9fc3ad34 962 m_exitcode = 0;
518b5d2f 963
ad9835c9
WS
964 // set to true only when the thread starts waiting on m_semSuspend
965 m_isPaused = false;
4c460b34 966
9fc3ad34 967 // defaults for joinable threads
ad9835c9
WS
968 m_shouldBeJoined = true;
969 m_isDetached = false;
518b5d2f
VZ
970}
971
972wxThreadInternal::~wxThreadInternal()
973{
518b5d2f
VZ
974}
975
976wxThreadError wxThreadInternal::Run()
977{
978 wxCHECK_MSG( GetState() == STATE_NEW, wxTHREAD_RUNNING,
9fc3ad34 979 wxT("thread may only be started once after Create()") );
518b5d2f 980
9fc3ad34 981 SetState(STATE_RUNNING);
518b5d2f 982
9e84b847
VZ
983 // wake up threads waiting for our start
984 SignalRun();
985
518b5d2f 986 return wxTHREAD_NO_ERROR;
518b5d2f
VZ
987}
988
882eefb1 989void wxThreadInternal::Wait()
518b5d2f 990{
9a83f860 991 wxCHECK_RET( !m_isDetached, wxT("can't wait for a detached thread") );
9e84b847 992
518b5d2f
VZ
993 // if the thread we're waiting for is waiting for the GUI mutex, we will
994 // deadlock so make sure we release it temporarily
995 if ( wxThread::IsMain() )
827833e2
SC
996 {
997#ifdef __WXOSX__
998 // give the thread we're waiting for chance to do the GUI call
999 // it might be in, we don't do this conditionally as the to be waited on
1000 // thread might have to acquire the mutex later but before terminating
1001 if ( wxGuiOwnedByMainThread() )
1002 wxMutexGuiLeave();
1003#else
518b5d2f 1004 wxMutexGuiLeave();
827833e2
SC
1005#endif
1006 }
518b5d2f 1007
547b93ab 1008 wxLogTrace(TRACE_THREADS,
9a83f860 1009 wxT("Starting to wait for thread %p to exit."),
ef4f69ec
VZ
1010 THR_ID(this));
1011
9e84b847
VZ
1012 // to avoid memory leaks we should call pthread_join(), but it must only be
1013 // done once so use a critical section to serialize the code below
9fc3ad34 1014 {
4c460b34
VZ
1015 wxCriticalSectionLocker lock(m_csJoinFlag);
1016
1017 if ( m_shouldBeJoined )
9fc3ad34 1018 {
4c460b34
VZ
1019 // FIXME shouldn't we set cancellation type to DISABLED here? If
1020 // we're cancelled inside pthread_join(), things will almost
1021 // certainly break - but if we disable the cancellation, we
1022 // might deadlock
2b5f62a0 1023 if ( pthread_join(GetId(), &m_exitcode) != 0 )
4c460b34 1024 {
9e84b847
VZ
1025 // this is a serious problem, so use wxLogError and not
1026 // wxLogDebug: it is possible to bring the system to its knees
1027 // by creating too many threads and not joining them quite
1028 // easily
76a6e803 1029 wxLogError(_("Failed to join a thread, potential memory leak detected - please restart the program"));
4c460b34 1030 }
9fc3ad34 1031
ad9835c9 1032 m_shouldBeJoined = false;
4c460b34 1033 }
9fc3ad34 1034 }
9111db68 1035
827833e2 1036#ifndef __WXOSX__
518b5d2f
VZ
1037 // reacquire GUI mutex
1038 if ( wxThread::IsMain() )
1039 wxMutexGuiEnter();
827833e2 1040#endif
518b5d2f
VZ
1041}
1042
518b5d2f
VZ
1043void wxThreadInternal::Pause()
1044{
882eefb1
VZ
1045 // the state is set from the thread which pauses us first, this function
1046 // is called later so the state should have been already set
518b5d2f 1047 wxCHECK_RET( m_state == STATE_PAUSED,
223d09f6 1048 wxT("thread must first be paused with wxThread::Pause().") );
518b5d2f 1049
ef4f69ec 1050 wxLogTrace(TRACE_THREADS,
9a83f860 1051 wxT("Thread %p goes to sleep."), THR_ID(this));
ef4f69ec 1052
be809868
VZ
1053 // wait until the semaphore is Post()ed from Resume()
1054 m_semSuspend.Wait();
518b5d2f
VZ
1055}
1056
1057void wxThreadInternal::Resume()
1058{
1059 wxCHECK_RET( m_state == STATE_PAUSED,
223d09f6 1060 wxT("can't resume thread which is not suspended.") );
518b5d2f 1061
4c460b34
VZ
1062 // the thread might be not actually paused yet - if there were no call to
1063 // TestDestroy() since the last call to Pause() for example
1064 if ( IsReallyPaused() )
1065 {
ef4f69ec 1066 wxLogTrace(TRACE_THREADS,
9a83f860 1067 wxT("Waking up thread %p"), THR_ID(this));
ef4f69ec 1068
4c460b34 1069 // wake up Pause()
be809868 1070 m_semSuspend.Post();
4c460b34
VZ
1071
1072 // reset the flag
ad9835c9 1073 SetReallyPaused(false);
4c460b34
VZ
1074 }
1075 else
1076 {
ef4f69ec 1077 wxLogTrace(TRACE_THREADS,
9a83f860 1078 wxT("Thread %p is not yet really paused"), THR_ID(this));
4c460b34 1079 }
518b5d2f
VZ
1080
1081 SetState(STATE_RUNNING);
1082}
1083
1084// -----------------------------------------------------------------------------
9fc3ad34 1085// wxThread static functions
518b5d2f
VZ
1086// -----------------------------------------------------------------------------
1087
1088wxThread *wxThread::This()
1089{
1090 return (wxThread *)pthread_getspecific(gs_keySelf);
1091}
1092
518b5d2f
VZ
1093void wxThread::Yield()
1094{
6f837e5c 1095#ifdef HAVE_SCHED_YIELD
518b5d2f 1096 sched_yield();
6f837e5c 1097#endif
518b5d2f
VZ
1098}
1099
ef8d96c2
VZ
1100int wxThread::GetCPUCount()
1101{
85bf679a
VZ
1102#if defined(_SC_NPROCESSORS_ONLN)
1103 // this works for Solaris and Linux 2.6
1104 int rc = sysconf(_SC_NPROCESSORS_ONLN);
1105 if ( rc != -1 )
1106 {
1107 return rc;
1108 }
1109#elif defined(__LINUX__) && wxUSE_FFILE
ef8d96c2
VZ
1110 // read from proc (can't use wxTextFile here because it's a special file:
1111 // it has 0 size but still can be read from)
1112 wxLogNull nolog;
1113
9a83f860 1114 wxFFile file(wxT("/proc/cpuinfo"));
ef8d96c2
VZ
1115 if ( file.IsOpened() )
1116 {
1117 // slurp the whole file
1118 wxString s;
1119 if ( file.ReadAll(&s) )
1120 {
9ec1ed2a 1121 // (ab)use Replace() to find the number of "processor: num" strings
9a83f860 1122 size_t count = s.Replace(wxT("processor\t:"), wxT(""));
ef8d96c2
VZ
1123 if ( count > 0 )
1124 {
1125 return count;
1126 }
1127
9a83f860 1128 wxLogDebug(wxT("failed to parse /proc/cpuinfo"));
ef8d96c2
VZ
1129 }
1130 else
1131 {
9a83f860 1132 wxLogDebug(wxT("failed to read /proc/cpuinfo"));
ef8d96c2
VZ
1133 }
1134 }
ef8d96c2
VZ
1135#endif // different ways to get number of CPUs
1136
1137 // unknown
1138 return -1;
1139}
1140
f9226383 1141wxThreadIdType wxThread::GetCurrentId()
1fcfb40d 1142{
f9226383 1143 return (wxThreadIdType)pthread_self();
1fcfb40d
RD
1144}
1145
ef4f69ec 1146
ef8d96c2
VZ
1147bool wxThread::SetConcurrency(size_t level)
1148{
32632baf
VZ
1149#ifdef HAVE_PTHREAD_SET_CONCURRENCY
1150 int rc = pthread_setconcurrency( level );
1151#elif defined(HAVE_THR_SETCONCURRENCY)
ef8d96c2 1152 int rc = thr_setconcurrency(level);
32632baf
VZ
1153#else // !HAVE_THR_SETCONCURRENCY
1154 // ok only for the default value
1155 int rc = level == 0 ? 0 : -1;
1156#endif // HAVE_THR_SETCONCURRENCY/!HAVE_THR_SETCONCURRENCY
1157
ef8d96c2
VZ
1158 if ( rc != 0 )
1159 {
32632baf
VZ
1160 wxLogSysError(rc, _("Failed to set thread concurrency level to %lu"),
1161 static_cast<unsigned long>(level));
1162 return false;
ef8d96c2
VZ
1163 }
1164
32632baf 1165 return true;
ef8d96c2
VZ
1166}
1167
518b5d2f
VZ
1168// -----------------------------------------------------------------------------
1169// creating thread
1170// -----------------------------------------------------------------------------
1171
acb8423c 1172wxThread::wxThread(wxThreadKind kind)
518b5d2f
VZ
1173{
1174 // add this thread to the global list of all threads
25b34b26
VZ
1175 {
1176 wxMutexLocker lock(*gs_mutexAllThreads);
1177
1178 gs_allThreads.Add(this);
1179 }
518b5d2f 1180
9fc3ad34 1181 m_internal = new wxThreadInternal();
acb8423c
VZ
1182
1183 m_isDetached = kind == wxTHREAD_DETACHED;
518b5d2f
VZ
1184}
1185
8a077f28
SN
1186#ifdef HAVE_PTHREAD_ATTR_SETSTACKSIZE
1187 #define WXUNUSED_STACKSIZE(identifier) identifier
1188#else
1189 #define WXUNUSED_STACKSIZE(identifier) WXUNUSED(identifier)
1190#endif
1191
1192wxThreadError wxThread::Create(unsigned int WXUNUSED_STACKSIZE(stackSize))
518b5d2f 1193{
9fc3ad34
VZ
1194 if ( m_internal->GetState() != STATE_NEW )
1195 {
1196 // don't recreate thread
518b5d2f 1197 return wxTHREAD_RUNNING;
9fc3ad34 1198 }
518b5d2f
VZ
1199
1200 // set up the thread attribute: right now, we only set thread priority
1201 pthread_attr_t attr;
1202 pthread_attr_init(&attr);
1203
8a077f28
SN
1204#ifdef HAVE_PTHREAD_ATTR_SETSTACKSIZE
1205 if (stackSize)
1206 pthread_attr_setstacksize(&attr, stackSize);
1207#endif
1208
fc9ef629 1209#ifdef HAVE_THREAD_PRIORITY_FUNCTIONS
9fc3ad34
VZ
1210 int policy;
1211 if ( pthread_attr_getschedpolicy(&attr, &policy) != 0 )
518b5d2f 1212 {
58230fb1 1213 wxLogError(_("Cannot retrieve thread scheduling policy."));
518b5d2f
VZ
1214 }
1215
fb10f04c
JJ
1216#ifdef __VMS__
1217 /* the pthread.h contains too many spaces. This is a work-around */
1218# undef sched_get_priority_max
1219#undef sched_get_priority_min
1220#define sched_get_priority_max(_pol_) \
1221 (_pol_ == SCHED_OTHER ? PRI_FG_MAX_NP : PRI_FIFO_MAX)
1222#define sched_get_priority_min(_pol_) \
1223 (_pol_ == SCHED_OTHER ? PRI_FG_MIN_NP : PRI_FIFO_MIN)
1224#endif
1fcfb40d 1225
fb10f04c
JJ
1226 int max_prio = sched_get_priority_max(policy),
1227 min_prio = sched_get_priority_min(policy),
9fc3ad34 1228 prio = m_internal->GetPriority();
518b5d2f
VZ
1229
1230 if ( min_prio == -1 || max_prio == -1 )
1231 {
58230fb1 1232 wxLogError(_("Cannot get priority range for scheduling policy %d."),
9fc3ad34 1233 policy);
518b5d2f 1234 }
bbfa0322
VZ
1235 else if ( max_prio == min_prio )
1236 {
90e95e61 1237 if ( prio != wxPRIORITY_DEFAULT )
bbfa0322
VZ
1238 {
1239 // notify the programmer that this doesn't work here
1240 wxLogWarning(_("Thread priority setting is ignored."));
1241 }
1242 //else: we have default priority, so don't complain
1243
1244 // anyhow, don't do anything because priority is just ignored
1245 }
518b5d2f
VZ
1246 else
1247 {
1248 struct sched_param sp;
9fc3ad34
VZ
1249 if ( pthread_attr_getschedparam(&attr, &sp) != 0 )
1250 {
9a83f860 1251 wxFAIL_MSG(wxT("pthread_attr_getschedparam() failed"));
9fc3ad34
VZ
1252 }
1253
1254 sp.sched_priority = min_prio + (prio*(max_prio - min_prio))/100;
1255
1256 if ( pthread_attr_setschedparam(&attr, &sp) != 0 )
1257 {
9a83f860 1258 wxFAIL_MSG(wxT("pthread_attr_setschedparam(priority) failed"));
9fc3ad34 1259 }
518b5d2f 1260 }
34f8c26e 1261#endif // HAVE_THREAD_PRIORITY_FUNCTIONS
518b5d2f 1262
58230fb1
VZ
1263#ifdef HAVE_PTHREAD_ATTR_SETSCOPE
1264 // this will make the threads created by this process really concurrent
9fc3ad34
VZ
1265 if ( pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM) != 0 )
1266 {
9a83f860 1267 wxFAIL_MSG(wxT("pthread_attr_setscope(PTHREAD_SCOPE_SYSTEM) failed"));
9fc3ad34 1268 }
58230fb1
VZ
1269#endif // HAVE_PTHREAD_ATTR_SETSCOPE
1270
9fc3ad34
VZ
1271 // VZ: assume that this one is always available (it's rather fundamental),
1272 // if this function is ever missing we should try to use
1273 // pthread_detach() instead (after thread creation)
1274 if ( m_isDetached )
1275 {
1276 if ( pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) != 0 )
1277 {
9a83f860 1278 wxFAIL_MSG(wxT("pthread_attr_setdetachstate(DETACHED) failed"));
9fc3ad34
VZ
1279 }
1280
1281 // never try to join detached threads
1282 m_internal->Detach();
1283 }
1284 //else: threads are created joinable by default, it's ok
1285
518b5d2f 1286 // create the new OS thread object
9fc3ad34
VZ
1287 int rc = pthread_create
1288 (
1289 m_internal->GetIdPtr(),
1290 &attr,
295272bd 1291 wxPthreadStart,
9fc3ad34
VZ
1292 (void *)this
1293 );
1294
1295 if ( pthread_attr_destroy(&attr) != 0 )
1296 {
9a83f860 1297 wxFAIL_MSG(wxT("pthread_attr_destroy() failed"));
9fc3ad34 1298 }
518b5d2f
VZ
1299
1300 if ( rc != 0 )
1301 {
9fc3ad34
VZ
1302 m_internal->SetState(STATE_EXITED);
1303
518b5d2f
VZ
1304 return wxTHREAD_NO_RESOURCE;
1305 }
1306
1307 return wxTHREAD_NO_ERROR;
1308}
1309
1310wxThreadError wxThread::Run()
1311{
9fc3ad34
VZ
1312 wxCriticalSectionLocker lock(m_critsect);
1313
1314 wxCHECK_MSG( m_internal->GetId(), wxTHREAD_MISC_ERROR,
223d09f6 1315 wxT("must call wxThread::Create() first") );
bbfa0322 1316
9fc3ad34 1317 return m_internal->Run();
518b5d2f
VZ
1318}
1319
1320// -----------------------------------------------------------------------------
1321// misc accessors
1322// -----------------------------------------------------------------------------
1323
1324void wxThread::SetPriority(unsigned int prio)
1325{
90e95e61 1326 wxCHECK_RET( wxPRIORITY_MIN <= prio && prio <= wxPRIORITY_MAX,
223d09f6 1327 wxT("invalid thread priority") );
518b5d2f
VZ
1328
1329 wxCriticalSectionLocker lock(m_critsect);
1330
9fc3ad34 1331 switch ( m_internal->GetState() )
518b5d2f
VZ
1332 {
1333 case STATE_NEW:
1334 // thread not yet started, priority will be set when it is
9fc3ad34 1335 m_internal->SetPriority(prio);
518b5d2f
VZ
1336 break;
1337
1338 case STATE_RUNNING:
1339 case STATE_PAUSED:
34f8c26e 1340#ifdef HAVE_THREAD_PRIORITY_FUNCTIONS
7bfe6a32 1341#if defined(__LINUX__)
17a1ebd1
VZ
1342 // On Linux, pthread_setschedparam with SCHED_OTHER does not allow
1343 // a priority other than 0. Instead, we use the BSD setpriority
1344 // which alllows us to set a 'nice' value between 20 to -20. Only
1345 // super user can set a value less than zero (more negative yields
1346 // higher priority). setpriority set the static priority of a
1347 // process, but this is OK since Linux is configured as a thread
1348 // per process.
1349 //
1350 // FIXME this is not true for 2.6!!
7bfe6a32 1351
90e95e61 1352 // map wx priorites 0..100 to Unix priorities 20..-20
a07bf2d0 1353 if ( setpriority(PRIO_PROCESS, 0, -(2*(int)prio)/5 + 20) == -1 )
17a1ebd1
VZ
1354 {
1355 wxLogError(_("Failed to set thread priority %d."), prio);
7bfe6a32
JS
1356 }
1357#else // __LINUX__
518b5d2f
VZ
1358 {
1359 struct sched_param sparam;
1360 sparam.sched_priority = prio;
1361
9fc3ad34 1362 if ( pthread_setschedparam(m_internal->GetId(),
518b5d2f
VZ
1363 SCHED_OTHER, &sparam) != 0 )
1364 {
1365 wxLogError(_("Failed to set thread priority %d."), prio);
1366 }
1367 }
7bfe6a32 1368#endif // __LINUX__
34f8c26e 1369#endif // HAVE_THREAD_PRIORITY_FUNCTIONS
518b5d2f
VZ
1370 break;
1371
1372 case STATE_EXITED:
1373 default:
223d09f6 1374 wxFAIL_MSG(wxT("impossible to set thread priority in this state"));
518b5d2f
VZ
1375 }
1376}
1377
1378unsigned int wxThread::GetPriority() const
1379{
1380 wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect);
1381
9fc3ad34 1382 return m_internal->GetPriority();
518b5d2f
VZ
1383}
1384
547b93ab 1385wxThreadIdType wxThread::GetId() const
13d068d9 1386{
df744f4d 1387 return (wxThreadIdType) m_internal->GetId();
518b5d2f
VZ
1388}
1389
1390// -----------------------------------------------------------------------------
1391// pause/resume
1392// -----------------------------------------------------------------------------
1393
1394wxThreadError wxThread::Pause()
1395{
4c460b34 1396 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR,
9a83f860 1397 wxT("a thread can't pause itself") );
4c460b34 1398
518b5d2f
VZ
1399 wxCriticalSectionLocker lock(m_critsect);
1400
9fc3ad34 1401 if ( m_internal->GetState() != STATE_RUNNING )
518b5d2f 1402 {
223d09f6 1403 wxLogDebug(wxT("Can't pause thread which is not running."));
518b5d2f
VZ
1404
1405 return wxTHREAD_NOT_RUNNING;
1406 }
1407
9fc3ad34
VZ
1408 // just set a flag, the thread will be really paused only during the next
1409 // call to TestDestroy()
1410 m_internal->SetState(STATE_PAUSED);
518b5d2f
VZ
1411
1412 return wxTHREAD_NO_ERROR;
1413}
1414
1415wxThreadError wxThread::Resume()
1416{
4c460b34 1417 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR,
9a83f860 1418 wxT("a thread can't resume itself") );
518b5d2f 1419
4c460b34 1420 wxCriticalSectionLocker lock(m_critsect);
518b5d2f 1421
4c460b34 1422 wxThreadState state = m_internal->GetState();
9fc3ad34
VZ
1423
1424 switch ( state )
518b5d2f 1425 {
9fc3ad34 1426 case STATE_PAUSED:
9a83f860 1427 wxLogTrace(TRACE_THREADS, wxT("Thread %p suspended, resuming."),
35e9c131 1428 THR_ID(this));
9fc3ad34
VZ
1429
1430 m_internal->Resume();
1431
1432 return wxTHREAD_NO_ERROR;
1433
1434 case STATE_EXITED:
9a83f860 1435 wxLogTrace(TRACE_THREADS, wxT("Thread %p exited, won't resume."),
35e9c131 1436 THR_ID(this));
9fc3ad34 1437 return wxTHREAD_NO_ERROR;
518b5d2f 1438
9fc3ad34 1439 default:
9a83f860 1440 wxLogDebug(wxT("Attempt to resume a thread which is not paused."));
9fc3ad34
VZ
1441
1442 return wxTHREAD_MISC_ERROR;
518b5d2f
VZ
1443 }
1444}
1445
1446// -----------------------------------------------------------------------------
1447// exiting thread
1448// -----------------------------------------------------------------------------
1449
b95a7c31 1450wxThread::ExitCode wxThread::Wait(wxThreadWait WXUNUSED(waitMode))
b568d04f 1451{
9fc3ad34 1452 wxCHECK_MSG( This() != this, (ExitCode)-1,
9a83f860 1453 wxT("a thread can't wait for itself") );
9fc3ad34
VZ
1454
1455 wxCHECK_MSG( !m_isDetached, (ExitCode)-1,
9a83f860 1456 wxT("can't wait for detached thread") );
9fc3ad34
VZ
1457
1458 m_internal->Wait();
b568d04f 1459
9fc3ad34 1460 return m_internal->GetExitCode();
b568d04f
VZ
1461}
1462
b95a7c31 1463wxThreadError wxThread::Delete(ExitCode *rc, wxThreadWait WXUNUSED(waitMode))
518b5d2f 1464{
4c460b34 1465 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR,
9a83f860 1466 wxT("a thread can't delete itself") );
4c460b34 1467
9e84b847
VZ
1468 bool isDetached = m_isDetached;
1469
518b5d2f 1470 m_critsect.Enter();
9fc3ad34 1471 wxThreadState state = m_internal->GetState();
518b5d2f 1472
882eefb1 1473 // ask the thread to stop
9fc3ad34
VZ
1474 m_internal->SetCancelFlag();
1475
9111db68
GL
1476 m_critsect.Leave();
1477
df191bfe
VZ
1478 OnDelete();
1479
518b5d2f
VZ
1480 switch ( state )
1481 {
1482 case STATE_NEW:
4c460b34 1483 // we need to wake up the thread so that PthreadStart() will
9e84b847
VZ
1484 // terminate - right now it's blocking on run semaphore in
1485 // PthreadStart()
4c460b34
VZ
1486 m_internal->SignalRun();
1487
1488 // fall through
1489
518b5d2f
VZ
1490 case STATE_EXITED:
1491 // nothing to do
1492 break;
1493
1494 case STATE_PAUSED:
9e84b847 1495 // resume the thread first
9fc3ad34 1496 m_internal->Resume();
518b5d2f
VZ
1497
1498 // fall through
1499
1500 default:
9e84b847 1501 if ( !isDetached )
9fc3ad34 1502 {
9e84b847
VZ
1503 // wait until the thread stops
1504 m_internal->Wait();
9fc3ad34 1505
9e84b847
VZ
1506 if ( rc )
1507 {
1508 // return the exit code of the thread
1509 *rc = m_internal->GetExitCode();
1510 }
9fc3ad34 1511 }
9e84b847 1512 //else: can't wait for detached threads
518b5d2f 1513 }
ce00f59b 1514
363daf0b
FM
1515 if (state == STATE_NEW)
1516 return wxTHREAD_MISC_ERROR;
ce00f59b 1517 // for coherency with the MSW implementation, signal the user that
363daf0b 1518 // Delete() was called on a thread which didn't start to run yet.
518b5d2f 1519
acb8423c 1520 return wxTHREAD_NO_ERROR;
518b5d2f
VZ
1521}
1522
1523wxThreadError wxThread::Kill()
1524{
9fc3ad34 1525 wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR,
9a83f860 1526 wxT("a thread can't kill itself") );
9fc3ad34 1527
df191bfe
VZ
1528 OnKill();
1529
9fc3ad34 1530 switch ( m_internal->GetState() )
518b5d2f
VZ
1531 {
1532 case STATE_NEW:
1533 case STATE_EXITED:
1534 return wxTHREAD_NOT_RUNNING;
1535
9fc3ad34
VZ
1536 case STATE_PAUSED:
1537 // resume the thread first
1538 Resume();
1539
1540 // fall through
1541
518b5d2f 1542 default:
9fc3ad34
VZ
1543#ifdef HAVE_PTHREAD_CANCEL
1544 if ( pthread_cancel(m_internal->GetId()) != 0 )
741d91c5 1545#endif // HAVE_PTHREAD_CANCEL
518b5d2f
VZ
1546 {
1547 wxLogError(_("Failed to terminate a thread."));
1548
1549 return wxTHREAD_MISC_ERROR;
1550 }
9fc3ad34 1551
741d91c5 1552#ifdef HAVE_PTHREAD_CANCEL
9fc3ad34
VZ
1553 if ( m_isDetached )
1554 {
1555 // if we use cleanup function, this will be done from
90350682 1556 // wxPthreadCleanup()
816a7358 1557#ifndef wxHAVE_PTHREAD_CLEANUP
9fc3ad34
VZ
1558 ScheduleThreadForDeletion();
1559
b18cfdd9
VZ
1560 // don't call OnExit() here, it can only be called in the
1561 // threads context and we're in the context of another thread
9fc3ad34
VZ
1562
1563 DeleteThread(this);
816a7358 1564#endif // wxHAVE_PTHREAD_CLEANUP
9fc3ad34
VZ
1565 }
1566 else
1567 {
1568 m_internal->SetExitCode(EXITCODE_CANCELLED);
1569 }
518b5d2f
VZ
1570
1571 return wxTHREAD_NO_ERROR;
741d91c5 1572#endif // HAVE_PTHREAD_CANCEL
518b5d2f
VZ
1573 }
1574}
1575
b568d04f 1576void wxThread::Exit(ExitCode status)
518b5d2f 1577{
4c460b34 1578 wxASSERT_MSG( This() == this,
9a83f860 1579 wxT("wxThread::Exit() can only be called in the context of the same thread") );
4c460b34 1580
9e84b847
VZ
1581 if ( m_isDetached )
1582 {
1583 // from the moment we call OnExit(), the main program may terminate at
1584 // any moment, so mark this thread as being already in process of being
1585 // deleted or wxThreadModule::OnExit() will try to delete it again
1586 ScheduleThreadForDeletion();
1587 }
9fc3ad34
VZ
1588
1589 // don't enter m_critsect before calling OnExit() because the user code
1590 // might deadlock if, for example, it signals a condition in OnExit() (a
1591 // common case) while the main thread calls any of functions entering
1592 // m_critsect on us (almost all of them do)
79b7b95a
VS
1593 wxTRY
1594 {
1595 OnExit();
1596 }
1597 wxCATCH_ALL( wxTheApp->OnUnhandledException(); )
518b5d2f 1598
9fc3ad34
VZ
1599 // delete C++ thread object if this is a detached thread - user is
1600 // responsible for doing this for joinable ones
1601 if ( m_isDetached )
1602 {
1603 // FIXME I'm feeling bad about it - what if another thread function is
1604 // called (in another thread context) now? It will try to access
1605 // half destroyed object which will probably result in something
1606 // very bad - but we can't protect this by a crit section unless
1607 // we make it a global object, but this would mean that we can
1608 // only call one thread function at a time :-(
1609 DeleteThread(this);
b4866582 1610 pthread_setspecific(gs_keySelf, 0);
9fc3ad34 1611 }
343b1669
RR
1612 else
1613 {
1614 m_critsect.Enter();
1615 m_internal->SetState(STATE_EXITED);
1616 m_critsect.Leave();
1617 }
9fc3ad34
VZ
1618
1619 // terminate the thread (pthread_exit() never returns)
518b5d2f 1620 pthread_exit(status);
9fc3ad34 1621
9a83f860 1622 wxFAIL_MSG(wxT("pthread_exit() failed"));
518b5d2f
VZ
1623}
1624
1625// also test whether we were paused
1626bool wxThread::TestDestroy()
1627{
4c460b34 1628 wxASSERT_MSG( This() == this,
9a83f860 1629 wxT("wxThread::TestDestroy() can only be called in the context of the same thread") );
4c460b34 1630
9fc3ad34 1631 m_critsect.Enter();
518b5d2f 1632
9fc3ad34 1633 if ( m_internal->GetState() == STATE_PAUSED )
518b5d2f 1634 {
ad9835c9 1635 m_internal->SetReallyPaused(true);
4c460b34 1636
9fc3ad34
VZ
1637 // leave the crit section or the other threads will stop too if they
1638 // try to call any of (seemingly harmless) IsXXX() functions while we
1639 // sleep
518b5d2f
VZ
1640 m_critsect.Leave();
1641
9fc3ad34
VZ
1642 m_internal->Pause();
1643 }
1644 else
1645 {
1646 // thread wasn't requested to pause, nothing to do
1647 m_critsect.Leave();
518b5d2f
VZ
1648 }
1649
9fc3ad34 1650 return m_internal->WasCancelled();
518b5d2f
VZ
1651}
1652
1653wxThread::~wxThread()
1654{
062c4861 1655 m_critsect.Enter();
9fc3ad34
VZ
1656
1657 // check that the thread either exited or couldn't be created
1658 if ( m_internal->GetState() != STATE_EXITED &&
1659 m_internal->GetState() != STATE_NEW )
bbfa0322 1660 {
35e9c131
VS
1661 wxLogDebug(wxT("The thread %p is being destroyed although it is still running! The application may crash."),
1662 THR_ID(this));
bbfa0322 1663 }
062c4861
GL
1664
1665 m_critsect.Leave();
1666
9fc3ad34 1667 delete m_internal;
bbfa0322 1668
518b5d2f 1669 // remove this thread from the global array
25b34b26
VZ
1670 {
1671 wxMutexLocker lock(*gs_mutexAllThreads);
1672
1673 gs_allThreads.Remove(this);
1674 }
518b5d2f
VZ
1675}
1676
1677// -----------------------------------------------------------------------------
1678// state tests
1679// -----------------------------------------------------------------------------
1680
1681bool wxThread::IsRunning() const
1682{
1683 wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect);
1684
9fc3ad34 1685 return m_internal->GetState() == STATE_RUNNING;
518b5d2f
VZ
1686}
1687
1688bool wxThread::IsAlive() const
1689{
1690 wxCriticalSectionLocker lock((wxCriticalSection&)m_critsect);
1691
9fc3ad34 1692 switch ( m_internal->GetState() )
518b5d2f
VZ
1693 {
1694 case STATE_RUNNING:
1695 case STATE_PAUSED:
ad9835c9 1696 return true;
518b5d2f
VZ
1697
1698 default:
ad9835c9 1699 return false;
518b5d2f
VZ
1700 }
1701}
1702
a737331d
GL
1703bool wxThread::IsPaused() const
1704{
1705 wxCriticalSectionLocker lock((wxCriticalSection&)m_critsect);
1706
9fc3ad34 1707 return (m_internal->GetState() == STATE_PAUSED);
a737331d
GL
1708}
1709
518b5d2f
VZ
1710//--------------------------------------------------------------------
1711// wxThreadModule
1712//--------------------------------------------------------------------
1713
a94c4b85
SC
1714#ifdef __WXOSX__
1715void wxOSXThreadModuleOnInit();
1716void wxOSXThreadModuleOnExit();
1717#endif
1718
518b5d2f
VZ
1719class wxThreadModule : public wxModule
1720{
1721public:
1722 virtual bool OnInit();
1723 virtual void OnExit();
1724
1725private:
1726 DECLARE_DYNAMIC_CLASS(wxThreadModule)
1727};
1728
1729IMPLEMENT_DYNAMIC_CLASS(wxThreadModule, wxModule)
1730
1731bool wxThreadModule::OnInit()
1732{
58230fb1
VZ
1733 int rc = pthread_key_create(&gs_keySelf, NULL /* dtor function */);
1734 if ( rc != 0 )
518b5d2f 1735 {
76a6e803 1736 wxLogSysError(rc, _("Thread module initialization failed: failed to create thread key"));
518b5d2f 1737
ad9835c9 1738 return false;
518b5d2f
VZ
1739 }
1740
f9226383 1741 wxThread::ms_idMainThread = wxThread::GetCurrentId();
19da4326 1742
25b34b26
VZ
1743 gs_mutexAllThreads = new wxMutex();
1744
a94c4b85
SC
1745#ifdef __WXOSX__
1746 wxOSXThreadModuleOnInit();
1747#else
9fc3ad34 1748 gs_mutexGui = new wxMutex();
518b5d2f 1749 gs_mutexGui->Lock();
a94c4b85 1750#endif
518b5d2f 1751
be809868 1752 gs_mutexDeleteThread = new wxMutex();
25b34b26 1753 gs_condAllDeleted = new wxCondition(*gs_mutexDeleteThread);
88e243b2 1754
ad9835c9 1755 return true;
518b5d2f
VZ
1756}
1757
1758void wxThreadModule::OnExit()
1759{
223d09f6 1760 wxASSERT_MSG( wxThread::IsMain(), wxT("only main thread can be here") );
518b5d2f 1761
9fc3ad34
VZ
1762 // are there any threads left which are being deleted right now?
1763 size_t nThreadsBeingDeleted;
be809868 1764
9fc3ad34 1765 {
be809868 1766 wxMutexLocker lock( *gs_mutexDeleteThread );
9fc3ad34 1767 nThreadsBeingDeleted = gs_nThreadsBeingDeleted;
9fc3ad34 1768
be809868 1769 if ( nThreadsBeingDeleted > 0 )
9e84b847 1770 {
2b5f62a0 1771 wxLogTrace(TRACE_THREADS,
9a83f860 1772 wxT("Waiting for %lu threads to disappear"),
2b5f62a0 1773 (unsigned long)nThreadsBeingDeleted);
9fc3ad34 1774
be809868
VZ
1775 // have to wait until all of them disappear
1776 gs_condAllDeleted->Wait();
1777 }
9fc3ad34
VZ
1778 }
1779
25b34b26
VZ
1780 size_t count;
1781
4c460b34 1782 {
25b34b26
VZ
1783 wxMutexLocker lock(*gs_mutexAllThreads);
1784
1785 // terminate any threads left
1786 count = gs_allThreads.GetCount();
1787 if ( count != 0u )
1788 {
1789 wxLogDebug(wxT("%lu threads were not terminated by the application."),
1790 (unsigned long)count);
1791 }
1792 } // unlock mutex before deleting the threads as they lock it in their dtor
518b5d2f
VZ
1793
1794 for ( size_t n = 0u; n < count; n++ )
1795 {
bbfa0322
VZ
1796 // Delete calls the destructor which removes the current entry. We
1797 // should only delete the first one each time.
0ac77ef5 1798 gs_allThreads[0]->Delete();
518b5d2f
VZ
1799 }
1800
25b34b26
VZ
1801 delete gs_mutexAllThreads;
1802
a94c4b85
SC
1803#ifdef __WXOSX__
1804 wxOSXThreadModuleOnExit();
1805#else
518b5d2f
VZ
1806 // destroy GUI mutex
1807 gs_mutexGui->Unlock();
518b5d2f 1808 delete gs_mutexGui;
a94c4b85 1809#endif
518b5d2f
VZ
1810
1811 // and free TLD slot
1812 (void)pthread_key_delete(gs_keySelf);
be809868
VZ
1813
1814 delete gs_condAllDeleted;
1815 delete gs_mutexDeleteThread;
518b5d2f
VZ
1816}
1817
1818// ----------------------------------------------------------------------------
1819// global functions
1820// ----------------------------------------------------------------------------
1821
9fc3ad34
VZ
1822static void ScheduleThreadForDeletion()
1823{
be809868 1824 wxMutexLocker lock( *gs_mutexDeleteThread );
9fc3ad34
VZ
1825
1826 gs_nThreadsBeingDeleted++;
1827
9a83f860 1828 wxLogTrace(TRACE_THREADS, wxT("%lu thread%s waiting to be deleted"),
2b5f62a0 1829 (unsigned long)gs_nThreadsBeingDeleted,
9a83f860 1830 gs_nThreadsBeingDeleted == 1 ? wxT("") : wxT("s"));
9fc3ad34
VZ
1831}
1832
1833static void DeleteThread(wxThread *This)
1834{
35e9c131 1835 wxLogTrace(TRACE_THREADS, wxT("Thread %p auto deletes."), THR_ID(This));
9fc3ad34 1836
be809868 1837 delete This;
9fc3ad34 1838
2450225e
VZ
1839 // only lock gs_mutexDeleteThread after deleting the thread to avoid
1840 // calling out into user code with it locked as this may result in
1841 // deadlocks if the thread dtor deletes another thread (see #11501)
1842 wxMutexLocker locker( *gs_mutexDeleteThread );
1843
be809868 1844 wxCHECK_RET( gs_nThreadsBeingDeleted > 0,
9a83f860 1845 wxT("no threads scheduled for deletion, yet we delete one?") );
9fc3ad34 1846
9a83f860 1847 wxLogTrace(TRACE_THREADS, wxT("%lu threads remain scheduled for deletion."),
2b5f62a0 1848 (unsigned long)gs_nThreadsBeingDeleted - 1);
4c460b34 1849
9fc3ad34
VZ
1850 if ( !--gs_nThreadsBeingDeleted )
1851 {
1852 // no more threads left, signal it
1853 gs_condAllDeleted->Signal();
9fc3ad34
VZ
1854 }
1855}
1856
da0ee16e 1857#ifndef __DARWIN__
a94c4b85 1858
d254213e 1859void wxMutexGuiEnterImpl()
518b5d2f 1860{
9fc3ad34 1861 gs_mutexGui->Lock();
518b5d2f
VZ
1862}
1863
d254213e 1864void wxMutexGuiLeaveImpl()
518b5d2f 1865{
9fc3ad34 1866 gs_mutexGui->Unlock();
518b5d2f 1867}
80cb83be 1868
a94c4b85
SC
1869#endif
1870
9e84b847
VZ
1871// ----------------------------------------------------------------------------
1872// include common implementation code
1873// ----------------------------------------------------------------------------
1874
1875#include "wx/thrimpl.cpp"
1876
1877#endif // wxUSE_THREADS