]> git.saurik.com Git - wxWidgets.git/blame - include/wx/thread.h
Only link with libwxscintilla if using Scintilla is enabled.
[wxWidgets.git] / include / wx / thread.h
CommitLineData
10b959e3 1/////////////////////////////////////////////////////////////////////////////
9e84b847 2// Name: wx/thread.h
10b959e3
JS
3// Purpose: Thread API
4// Author: Guilhem Lavaux
bf1852e1
VZ
5// Modified by: Vadim Zeitlin (modifications partly inspired by omnithreads
6// package from Olivetti & Oracle Research Laboratory)
10b959e3
JS
7// Created: 04/13/98
8// RCS-ID: $Id$
9// Copyright: (c) Guilhem Lavaux
65571936 10// Licence: wxWindows licence
10b959e3
JS
11/////////////////////////////////////////////////////////////////////////////
12
9e84b847
VZ
13#ifndef _WX_THREAD_H_
14#define _WX_THREAD_H_
10b959e3 15
9d133d87
VZ
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
bf1852e1
VZ
19
20// get the value of wxUSE_THREADS configuration flag
9e84b847 21#include "wx/defs.h"
9d133d87
VZ
22
23#if wxUSE_THREADS
6d167489 24
a6b0bd49
VZ
25// ----------------------------------------------------------------------------
26// constants
27// ----------------------------------------------------------------------------
28
6d167489 29enum wxMutexError
d524867f 30{
9e84b847
VZ
31 wxMUTEX_NO_ERROR = 0, // operation completed successfully
32 wxMUTEX_INVALID, // mutex hasn't been initialized
33 wxMUTEX_DEAD_LOCK, // mutex is already locked by the calling thread
34 wxMUTEX_BUSY, // mutex is already locked by another thread
35 wxMUTEX_UNLOCKED, // attempt to unlock a mutex which is not locked
696d13ee 36 wxMUTEX_TIMEOUT, // LockTimeout() has timed out
9e84b847
VZ
37 wxMUTEX_MISC_ERROR // any other error
38};
39
40enum wxCondError
41{
42 wxCOND_NO_ERROR = 0,
43 wxCOND_INVALID,
44 wxCOND_TIMEOUT, // WaitTimeout() has timed out
45 wxCOND_MISC_ERROR
46};
47
48enum wxSemaError
49{
50 wxSEMA_NO_ERROR = 0,
51 wxSEMA_INVALID, // semaphore hasn't been initialized successfully
52 wxSEMA_BUSY, // returned by TryWait() if Wait() would block
53 wxSEMA_TIMEOUT, // returned by WaitTimeout()
54 wxSEMA_OVERFLOW, // Post() would increase counter past the max
55 wxSEMA_MISC_ERROR
6d167489 56};
10b959e3 57
6d167489 58enum wxThreadError
d524867f 59{
9fc3ad34
VZ
60 wxTHREAD_NO_ERROR = 0, // No error
61 wxTHREAD_NO_RESOURCE, // No resource left to create a new thread
62 wxTHREAD_RUNNING, // The thread is already running
63 wxTHREAD_NOT_RUNNING, // The thread isn't running
64 wxTHREAD_KILLED, // Thread we waited for had to be killed
65 wxTHREAD_MISC_ERROR // Some other error
6d167489 66};
10b959e3 67
b568d04f
VZ
68enum wxThreadKind
69{
70 wxTHREAD_DETACHED,
71 wxTHREAD_JOINABLE
72};
73
b95a7c31
VZ
74enum wxThreadWait
75{
76 wxTHREAD_WAIT_BLOCK,
77 wxTHREAD_WAIT_YIELD, // process events while waiting; MSW only
78
79 // For compatibility reasons we use wxTHREAD_WAIT_YIELD by default as this
80 // was the default behaviour of wxMSW 2.8 but it should be avoided as it's
81 // dangerous and not portable.
82#if WXWIN_COMPATIBILITY_2_8
83 wxTHREAD_WAIT_DEFAULT = wxTHREAD_WAIT_YIELD
84#else
85 wxTHREAD_WAIT_DEFAULT = wxTHREAD_WAIT_BLOCK
86#endif
87};
88
90e95e61 89// Obsolete synonyms for wxPRIORITY_XXX for backwards compatibility-only
6d167489
VZ
90enum
91{
90e95e61
VZ
92 WXTHREAD_MIN_PRIORITY = wxPRIORITY_MIN,
93 WXTHREAD_DEFAULT_PRIORITY = wxPRIORITY_DEFAULT,
94 WXTHREAD_MAX_PRIORITY = wxPRIORITY_MAX
6d167489 95};
10b959e3 96
9e84b847
VZ
97// There are 2 types of mutexes: normal mutexes and recursive ones. The attempt
98// to lock a normal mutex by a thread which already owns it results in
99// undefined behaviour (it always works under Windows, it will almost always
100// result in a deadlock under Unix). Locking a recursive mutex in such
101// situation always succeeds and it must be unlocked as many times as it has
102// been locked.
103//
104// However recursive mutexes have several important drawbacks: first, in the
105// POSIX implementation, they're less efficient. Second, and more importantly,
106// they CAN NOT BE USED WITH CONDITION VARIABLES under Unix! Using them with
107// wxCondition will work under Windows and some Unices (notably Linux) but will
108// deadlock under other Unix versions (e.g. Solaris). As it might be difficult
109// to ensure that a recursive mutex is not used with wxCondition, it is a good
110// idea to avoid using recursive mutexes at all. Also, the last problem with
111// them is that some (older) Unix versions don't support this at all -- which
112// results in a configure warning when building and a deadlock when using them.
113enum wxMutexType
114{
115 // normal mutex: try to always use this one
116 wxMUTEX_DEFAULT,
117
118 // recursive mutex: don't use these ones with wxCondition
119 wxMUTEX_RECURSIVE
120};
121
122// forward declarations
b5dbe15d
VS
123class WXDLLIMPEXP_FWD_BASE wxThreadHelper;
124class WXDLLIMPEXP_FWD_BASE wxConditionInternal;
125class WXDLLIMPEXP_FWD_BASE wxMutexInternal;
126class WXDLLIMPEXP_FWD_BASE wxSemaphoreInternal;
127class WXDLLIMPEXP_FWD_BASE wxThreadInternal;
9e84b847 128
d524867f 129// ----------------------------------------------------------------------------
9d133d87
VZ
130// A mutex object is a synchronization object whose state is set to signaled
131// when it is not owned by any thread, and nonsignaled when it is owned. Its
132// name comes from its usefulness in coordinating mutually-exclusive access to
133// a shared resource. Only one thread at a time can own a mutex object.
a6b0bd49 134// ----------------------------------------------------------------------------
d524867f 135
9d133d87
VZ
136// you should consider wxMutexLocker whenever possible instead of directly
137// working with wxMutex class - it is safer
bb24c68f 138class WXDLLIMPEXP_BASE wxMutex
d524867f 139{
10b959e3 140public:
bf1852e1 141 // constructor & destructor
9e84b847
VZ
142 // ------------------------
143
144 // create either default (always safe) or recursive mutex
145 wxMutex(wxMutexType mutexType = wxMUTEX_DEFAULT);
146
147 // destroys the mutex kernel object
cb4f1ca4 148 ~wxMutex();
10b959e3 149
9e84b847
VZ
150 // test if the mutex has been created successfully
151 bool IsOk() const;
152
153 // mutex operations
154 // ----------------
155
156 // Lock the mutex, blocking on it until it is unlocked by the other thread.
157 // The result of locking a mutex already locked by the current thread
158 // depend on the mutex type.
159 //
160 // The caller must call Unlock() later if Lock() returned wxMUTEX_NO_ERROR.
cb4f1ca4 161 wxMutexError Lock();
9e84b847 162
696d13ee
VZ
163 // Same as Lock() but return wxMUTEX_TIMEOUT if the mutex can't be locked
164 // during the given number of milliseconds
165 wxMutexError LockTimeout(unsigned long ms);
166
9e84b847
VZ
167 // Try to lock the mutex: if it is currently locked, return immediately
168 // with an error. Otherwise the caller must call Unlock().
cb4f1ca4 169 wxMutexError TryLock();
10b959e3 170
9e84b847
VZ
171 // Unlock the mutex. It is an error to unlock an already unlocked mutex
172 wxMutexError Unlock();
a6b0bd49 173
10b959e3 174protected:
9fc3ad34 175 wxMutexInternal *m_internal;
be809868
VZ
176
177 friend class wxConditionInternal;
9e84b847 178
c0c133e1 179 wxDECLARE_NO_COPY_CLASS(wxMutex);
10b959e3
JS
180};
181
9d133d87
VZ
182// a helper class which locks the mutex in the ctor and unlocks it in the dtor:
183// this ensures that mutex is always unlocked, even if the function returns or
184// throws an exception before it reaches the end
bb24c68f 185class WXDLLIMPEXP_BASE wxMutexLocker
9d133d87
VZ
186{
187public:
188 // lock the mutex in the ctor
be52b341 189 wxMutexLocker(wxMutex& mutex)
c096f614 190 : m_isOk(false), m_mutex(mutex)
be52b341 191 { m_isOk = ( m_mutex.Lock() == wxMUTEX_NO_ERROR ); }
9d133d87 192
c096f614 193 // returns true if mutex was successfully locked in ctor
7c3d7e2d
VZ
194 bool IsOk() const
195 { return m_isOk; }
9d133d87
VZ
196
197 // unlock the mutex in dtor
7c3d7e2d
VZ
198 ~wxMutexLocker()
199 { if ( IsOk() ) m_mutex.Unlock(); }
9d133d87
VZ
200
201private:
cb4f1ca4
VZ
202 // no assignment operator nor copy ctor
203 wxMutexLocker(const wxMutexLocker&);
204 wxMutexLocker& operator=(const wxMutexLocker&);
205
9d133d87 206 bool m_isOk;
7c3d7e2d 207 wxMutex& m_mutex;
9d133d87
VZ
208};
209
210// ----------------------------------------------------------------------------
211// Critical section: this is the same as mutex but is only visible to the
212// threads of the same process. For the platforms which don't have native
213// support for critical sections, they're implemented entirely in terms of
6d167489
VZ
214// mutexes.
215//
216// NB: wxCriticalSection object does not allocate any memory in its ctor
217// which makes it possible to have static globals of this class
9d133d87
VZ
218// ----------------------------------------------------------------------------
219
6d167489
VZ
220// in order to avoid any overhead under platforms where critical sections are
221// just mutexes make all wxCriticalSection class functions inline
d98a58c5 222#if !defined(__WINDOWS__)
6d167489 223 #define wxCRITSECT_IS_MUTEX 1
d42e3d59 224
e317bd3f 225 #define wxCRITSECT_INLINE WXEXPORT inline
d1bab566 226#else // MSW
6d167489 227 #define wxCRITSECT_IS_MUTEX 0
d42e3d59
VZ
228
229 #define wxCRITSECT_INLINE
f6ddc54a 230#endif // MSW/!MSW
bf1852e1 231
3ad41c28
RR
232enum wxCriticalSectionType
233{
234 // recursive critical section
235 wxCRITSEC_DEFAULT,
236
237 // non-recursive critical section
238 wxCRITSEC_NON_RECURSIVE
239};
240
bf1852e1
VZ
241// you should consider wxCriticalSectionLocker whenever possible instead of
242// directly working with wxCriticalSection class - it is safer
bb24c68f 243class WXDLLIMPEXP_BASE wxCriticalSection
9d133d87
VZ
244{
245public:
246 // ctor & dtor
3ad41c28 247 wxCRITSECT_INLINE wxCriticalSection( wxCriticalSectionType critSecType = wxCRITSEC_DEFAULT );
d42e3d59 248 wxCRITSECT_INLINE ~wxCriticalSection();
9d133d87 249 // enter the section (the same as locking a mutex)
d42e3d59 250 wxCRITSECT_INLINE void Enter();
9e84b847 251
b9697cb4
VZ
252 // try to enter the section (the same as trying to lock a mutex)
253 wxCRITSECT_INLINE bool TryEnter();
254
9d133d87 255 // leave the critical section (same as unlocking a mutex)
d42e3d59 256 wxCRITSECT_INLINE void Leave();
9d133d87
VZ
257
258private:
6d167489 259#if wxCRITSECT_IS_MUTEX
f6ddc54a 260 wxMutex m_mutex;
d98a58c5 261#elif defined(__WINDOWS__)
6d167489
VZ
262 // we can't allocate any memory in the ctor, so use placement new -
263 // unfortunately, we have to hardcode the sizeof() here because we can't
dac348b9
VZ
264 // include windows.h from this public header and we also have to use the
265 // union to force the correct (i.e. maximal) alignment
9e84b847 266 //
1c6f2414
WS
267 // if CRITICAL_SECTION size changes in Windows, you'll get an assert from
268 // thread.cpp and will need to increase the buffer size
975b6bcf
VZ
269#ifdef __WIN64__
270 typedef char wxCritSectBuffer[40];
271#else // __WIN32__
dac348b9 272 typedef char wxCritSectBuffer[24];
975b6bcf 273#endif
dac348b9
VZ
274 union
275 {
276 unsigned long m_dummy1;
277 void *m_dummy2;
278
279 wxCritSectBuffer m_buffer;
280 };
d1bab566 281#endif // Unix&OS2/Win32
9e84b847 282
c0c133e1 283 wxDECLARE_NO_COPY_CLASS(wxCriticalSection);
9d133d87
VZ
284};
285
e317bd3f 286#if wxCRITSECT_IS_MUTEX
9e84b847 287 // implement wxCriticalSection using mutexes
a5cc517f 288 inline wxCriticalSection::wxCriticalSection( wxCriticalSectionType critSecType )
3ad41c28 289 : m_mutex( critSecType == wxCRITSEC_DEFAULT ? wxMUTEX_RECURSIVE : wxMUTEX_DEFAULT ) { }
d42e3d59 290 inline wxCriticalSection::~wxCriticalSection() { }
9e84b847 291
d42e3d59 292 inline void wxCriticalSection::Enter() { (void)m_mutex.Lock(); }
b9697cb4 293 inline bool wxCriticalSection::TryEnter() { return m_mutex.TryLock() == wxMUTEX_NO_ERROR; }
d42e3d59 294 inline void wxCriticalSection::Leave() { (void)m_mutex.Unlock(); }
9e84b847 295#endif // wxCRITSECT_IS_MUTEX
bf1852e1 296
d42e3d59
VZ
297#undef wxCRITSECT_INLINE
298#undef wxCRITSECT_IS_MUTEX
299
9d133d87 300// wxCriticalSectionLocker is the same to critical sections as wxMutexLocker is
87b6002d 301// to mutexes
bb24c68f 302class WXDLLIMPEXP_BASE wxCriticalSectionLocker
9d133d87
VZ
303{
304public:
9e84b847
VZ
305 wxCriticalSectionLocker(wxCriticalSection& cs)
306 : m_critsect(cs)
307 {
308 m_critsect.Enter();
309 }
9d133d87 310
9e84b847
VZ
311 ~wxCriticalSectionLocker()
312 {
313 m_critsect.Leave();
314 }
cb4f1ca4 315
9e84b847 316private:
bee503b0 317 wxCriticalSection& m_critsect;
9e84b847 318
c0c133e1 319 wxDECLARE_NO_COPY_CLASS(wxCriticalSectionLocker);
9d133d87
VZ
320};
321
a6b0bd49 322// ----------------------------------------------------------------------------
be809868
VZ
323// wxCondition models a POSIX condition variable which allows one (or more)
324// thread(s) to wait until some condition is fulfilled
a6b0bd49 325// ----------------------------------------------------------------------------
d524867f 326
bb24c68f 327class WXDLLIMPEXP_BASE wxCondition
d524867f 328{
10b959e3 329public:
9e84b847
VZ
330 // Each wxCondition object is associated with a (single) wxMutex object.
331 // The mutex object MUST be locked before calling Wait()
c112e100 332 wxCondition(wxMutex& mutex);
be809868
VZ
333
334 // dtor is not virtual, don't use this class polymorphically
9fc3ad34
VZ
335 ~wxCondition();
336
c096f614 337 // return true if the condition has been created successfully
9e84b847
VZ
338 bool IsOk() const;
339
be809868 340 // NB: the associated mutex MUST be locked beforehand by the calling thread
cb719f2e 341 //
be809868
VZ
342 // it atomically releases the lock on the associated mutex
343 // and starts waiting to be woken up by a Signal()/Broadcast()
344 // once its signaled, then it will wait until it can reacquire
345 // the lock on the associated mutex object, before returning.
9e84b847 346 wxCondError Wait();
9fc3ad34 347
be809868 348 // exactly as Wait() except that it may also return if the specified
90e572f1 349 // timeout elapses even if the condition hasn't been signalled: in this
c096f614
VZ
350 // case, the return value is false, otherwise (i.e. in case of a normal
351 // return) it is true
cb719f2e 352 //
90e572f1
MR
353 // the timeout parameter specifies an interval that needs to be waited for
354 // in milliseconds
9e84b847 355 wxCondError WaitTimeout(unsigned long milliseconds);
be809868
VZ
356
357 // NB: the associated mutex may or may not be locked by the calling thread
358 //
359 // this method unblocks one thread if any are blocking on the condition.
360 // if no thread is blocking in Wait(), then the signal is NOT remembered
90e572f1 361 // The thread which was blocking on Wait() will then reacquire the lock
be809868 362 // on the associated mutex object before returning
9e84b847 363 wxCondError Signal();
a6b0bd49 364
be809868
VZ
365 // NB: the associated mutex may or may not be locked by the calling thread
366 //
367 // this method unblocks all threads if any are blocking on the condition.
368 // if no thread is blocking in Wait(), then the signal is NOT remembered
90e572f1 369 // The threads which were blocking on Wait() will then reacquire the lock
be809868 370 // on the associated mutex object before returning.
9e84b847
VZ
371 wxCondError Broadcast();
372
373
40ff126a 374#if WXWIN_COMPATIBILITY_2_6
9e84b847 375 // deprecated version, don't use
40ff126a
WS
376 wxDEPRECATED( bool Wait(unsigned long milliseconds) );
377#endif // WXWIN_COMPATIBILITY_2_6
8d5eff60 378
10b959e3 379private:
9fc3ad34 380 wxConditionInternal *m_internal;
9e84b847 381
c0c133e1 382 wxDECLARE_NO_COPY_CLASS(wxCondition);
10b959e3
JS
383};
384
40ff126a
WS
385#if WXWIN_COMPATIBILITY_2_6
386 inline bool wxCondition::Wait(unsigned long milliseconds)
387 { return WaitTimeout(milliseconds) == wxCOND_NO_ERROR; }
388#endif // WXWIN_COMPATIBILITY_2_6
389
a6b0bd49 390// ----------------------------------------------------------------------------
be809868
VZ
391// wxSemaphore: a counter limiting the number of threads concurrently accessing
392// a shared resource
393// ----------------------------------------------------------------------------
394
bb24c68f 395class WXDLLIMPEXP_BASE wxSemaphore
be809868
VZ
396{
397public:
398 // specifying a maxcount of 0 actually makes wxSemaphore behave as if there
399 // is no upper limit, if maxcount is 1 the semaphore behaves as a mutex
400 wxSemaphore( int initialcount = 0, int maxcount = 0 );
401
402 // dtor is not virtual, don't use this class polymorphically
403 ~wxSemaphore();
404
c096f614 405 // return true if the semaphore has been created successfully
9e84b847
VZ
406 bool IsOk() const;
407
be809868
VZ
408 // wait indefinitely, until the semaphore count goes beyond 0
409 // and then decrement it and return (this method might have been called
410 // Acquire())
9e84b847 411 wxSemaError Wait();
be809868 412
9e84b847
VZ
413 // same as Wait(), but does not block, returns wxSEMA_NO_ERROR if
414 // successful and wxSEMA_BUSY if the count is currently zero
415 wxSemaError TryWait();
be809868 416
9e84b847 417 // same as Wait(), but as a timeout limit, returns wxSEMA_NO_ERROR if the
90e572f1 418 // semaphore was acquired and wxSEMA_TIMEOUT if the timeout has elapsed
9e84b847 419 wxSemaError WaitTimeout(unsigned long milliseconds);
be809868
VZ
420
421 // increments the semaphore count and signals one of the waiting threads
9e84b847 422 wxSemaError Post();
be809868
VZ
423
424private:
425 wxSemaphoreInternal *m_internal;
9e84b847 426
c0c133e1 427 wxDECLARE_NO_COPY_CLASS(wxSemaphore);
be809868
VZ
428};
429
430// ----------------------------------------------------------------------------
87b6002d 431// wxThread: class encapsulating a thread of execution
a6b0bd49 432// ----------------------------------------------------------------------------
d524867f 433
b568d04f
VZ
434// there are two different kinds of threads: joinable and detached (default)
435// ones. Only joinable threads can return a return code and only detached
436// threads auto-delete themselves - the user should delete the joinable
437// threads manually.
bf1852e1
VZ
438
439// NB: in the function descriptions the words "this thread" mean the thread
440// created by the wxThread object while "main thread" is the thread created
441// during the process initialization (a.k.a. the GUI thread)
b568d04f 442
547b93ab
VZ
443// On VMS thread pointers are 64 bits (also needed for other systems???
444#ifdef __VMS
445 typedef unsigned long long wxThreadIdType;
446#else
447 typedef unsigned long wxThreadIdType;
448#endif
449
bb24c68f 450class WXDLLIMPEXP_BASE wxThread
d524867f 451{
10b959e3 452public:
bf1852e1
VZ
453 // the return type for the thread function
454 typedef void *ExitCode;
455
456 // static functions
457 // Returns the wxThread object for the calling thread. NULL is returned
458 // if the caller is the main thread (but it's recommended to use
459 // IsMain() and only call This() for threads other than the main one
460 // because NULL is also returned on error). If the thread wasn't
461 // created with wxThread class, the returned value is undefined.
462 static wxThread *This();
463
464 // Returns true if current thread is the main thread.
f9226383
VZ
465 //
466 // Notice that it also returns true if main thread id hadn't been
467 // initialized yet on the assumption that it's too early in wx startup
468 // process for any other threads to have been created in this case.
469 static bool IsMain()
470 {
471 return !ms_idMainThread || GetCurrentId() == ms_idMainThread;
472 }
473
474 // Return the main thread id
475 static wxThreadIdType GetMainId() { return ms_idMainThread; }
bf1852e1 476
90e572f1 477 // Release the rest of our time slice letting the other threads run
bf1852e1
VZ
478 static void Yield();
479
480 // Sleep during the specified period of time in milliseconds
481 //
8cd8a7fe 482 // This is the same as wxMilliSleep().
bf1852e1
VZ
483 static void Sleep(unsigned long milliseconds);
484
ef8d96c2
VZ
485 // get the number of system CPUs - useful with SetConcurrency()
486 // (the "best" value for it is usually number of CPUs + 1)
487 //
488 // Returns -1 if unknown, number of CPUs otherwise
489 static int GetCPUCount();
490
4958ea8f
RD
491 // Get the platform specific thread ID and return as a long. This
492 // can be used to uniquely identify threads, even if they are not
493 // wxThreads. This is used by wxPython.
f9226383 494 static wxThreadIdType GetCurrentId();
547b93ab 495
ef8d96c2
VZ
496 // sets the concurrency level: this is, roughly, the number of threads
497 // the system tries to schedule to run in parallel. 0 means the
498 // default value (usually acceptable, but may not yield the best
499 // performance for this process)
500 //
c096f614 501 // Returns true on success, false otherwise (if not implemented, for
ef8d96c2
VZ
502 // example)
503 static bool SetConcurrency(size_t level);
504
b568d04f
VZ
505 // constructor only creates the C++ thread object and doesn't create (or
506 // start) the real thread
507 wxThread(wxThreadKind kind = wxTHREAD_DETACHED);
508
509 // functions that change the thread state: all these can only be called
510 // from _another_ thread (typically the thread that created this one, e.g.
511 // the main thread), not from the thread itself
bf1852e1 512
6fe73788
RL
513 // create a new thread and optionally set the stack size on
514 // platforms that support that - call Run() to start it
515 // (special cased for watcom which won't accept 0 default)
516
6fe73788 517 wxThreadError Create(unsigned int stackSize = 0);
bf1852e1 518
b568d04f
VZ
519 // starts execution of the thread - from the moment Run() is called
520 // the execution of wxThread::Entry() may start at any moment, caller
bf1852e1
VZ
521 // shouldn't suppose that it starts after (or before) Run() returns.
522 wxThreadError Run();
523
b568d04f
VZ
524 // stops the thread if it's running and deletes the wxThread object if
525 // this is a detached thread freeing its memory - otherwise (for
526 // joinable threads) you still need to delete wxThread object
527 // yourself.
528 //
529 // this function only works if the thread calls TestDestroy()
530 // periodically - the thread will only be deleted the next time it
531 // does it!
532 //
533 // will fill the rc pointer with the thread exit code if it's !NULL
b95a7c31
VZ
534 wxThreadError Delete(ExitCode *rc = NULL,
535 wxThreadWait waitMode = wxTHREAD_WAIT_DEFAULT);
b568d04f
VZ
536
537 // waits for a joinable thread to finish and returns its exit code
538 //
539 // Returns (ExitCode)-1 on error (for example, if the thread is not
540 // joinable)
b95a7c31 541 ExitCode Wait(wxThreadWait waitMode = wxTHREAD_WAIT_DEFAULT);
bf1852e1
VZ
542
543 // kills the thread without giving it any chance to clean up - should
90e572f1
MR
544 // not be used under normal circumstances, use Delete() instead.
545 // It is a dangerous function that should only be used in the most
546 // extreme cases!
b568d04f
VZ
547 //
548 // The wxThread object is deleted by Kill() if the thread is
549 // detachable, but you still have to delete it manually for joinable
550 // threads.
bf1852e1
VZ
551 wxThreadError Kill();
552
b568d04f
VZ
553 // pause a running thread: as Delete(), this only works if the thread
554 // calls TestDestroy() regularly
bf1852e1
VZ
555 wxThreadError Pause();
556
557 // resume a paused thread
558 wxThreadError Resume();
559
560 // priority
90e95e61
VZ
561 // Sets the priority to "prio" which must be in 0..100 range (see
562 // also wxPRIORITY_XXX constants).
bf1852e1
VZ
563 //
564 // NB: the priority can only be set before the thread is created
565 void SetPriority(unsigned int prio);
566
567 // Get the current priority.
568 unsigned int GetPriority() const;
569
bf1852e1
VZ
570 // thread status inquiries
571 // Returns true if the thread is alive: i.e. running or suspended
572 bool IsAlive() const;
573 // Returns true if the thread is running (not paused, not killed).
574 bool IsRunning() const;
575 // Returns true if the thread is suspended
a737331d 576 bool IsPaused() const;
bf1852e1 577
b568d04f
VZ
578 // is the thread of detached kind?
579 bool IsDetached() const { return m_isDetached; }
580
581 // Get the thread ID - a platform dependent number which uniquely
582 // identifies a thread inside a process
547b93ab 583 wxThreadIdType GetId() const;
4958ea8f 584
5159e014
FM
585 wxThreadKind GetKind() const
586 { return m_isDetached ? wxTHREAD_DETACHED : wxTHREAD_JOINABLE; }
587
c096f614
VZ
588 // Returns true if the thread was asked to terminate: this function should
589 // be called by the thread from time to time, otherwise the main thread
590 // will be left forever in Delete()!
591 virtual bool TestDestroy();
592
b568d04f
VZ
593 // dtor is public, but the detached threads should never be deleted - use
594 // Delete() instead (or leave the thread terminate by itself)
595 virtual ~wxThread();
596
bf1852e1 597protected:
bf1852e1 598 // exits from the current thread - can be called only from this thread
b568d04f 599 void Exit(ExitCode exitcode = 0);
9d133d87 600
bf1852e1
VZ
601 // entry point for the thread - called by Run() and executes in the context
602 // of this thread.
603 virtual void *Entry() = 0;
a6b0bd49 604
df191bfe
VZ
605
606 // Callbacks which may be overridden by the derived class to perform some
607 // specific actions when the thread is deleted or killed. By default they
608 // do nothing.
609
610 // This one is called by Delete() before actually deleting the thread and
611 // is executed in the context of the thread that called Delete().
612 virtual void OnDelete() {}
613
614 // This one is called by Kill() before killing the thread and is executed
615 // in the context of the thread that called Kill().
616 virtual void OnKill() {}
617
10b959e3 618private:
bf1852e1
VZ
619 // no copy ctor/assignment operator
620 wxThread(const wxThread&);
621 wxThread& operator=(const wxThread&);
10b959e3 622
a5cc517f
FM
623 // called when the thread exits - in the context of this thread
624 //
625 // NB: this function will not be called if the thread is Kill()ed
626 virtual void OnExit() { }
627
bf1852e1 628 friend class wxThreadInternal;
f9226383
VZ
629 friend class wxThreadModule;
630
631
632 // the main thread identifier, should be set on startup
633 static wxThreadIdType ms_idMainThread;
bf1852e1
VZ
634
635 // the (platform-dependent) thread class implementation
9fc3ad34 636 wxThreadInternal *m_internal;
10b959e3 637
bf1852e1
VZ
638 // protects access to any methods of wxThreadInternal object
639 wxCriticalSection m_critsect;
b568d04f
VZ
640
641 // true if the thread is detached, false if it is joinable
642 bool m_isDetached;
10b959e3
JS
643};
644
78ee6a47
VZ
645// wxThreadHelperThread class
646// --------------------------
647
648class WXDLLIMPEXP_BASE wxThreadHelperThread : public wxThread
649{
650public:
651 // constructor only creates the C++ thread object and doesn't create (or
652 // start) the real thread
c4b64a94
VZ
653 wxThreadHelperThread(wxThreadHelper& owner, wxThreadKind kind)
654 : wxThread(kind), m_owner(owner)
78ee6a47
VZ
655 { }
656
657protected:
658 // entry point for the thread -- calls Entry() in owner.
659 virtual void *Entry();
660
661private:
662 // the owner of the thread
663 wxThreadHelper& m_owner;
664
665 // no copy ctor/assignment operator
666 wxThreadHelperThread(const wxThreadHelperThread&);
667 wxThreadHelperThread& operator=(const wxThreadHelperThread&);
668};
669
670// ----------------------------------------------------------------------------
671// wxThreadHelper: this class implements the threading logic to run a
672// background task in another object (such as a window). It is a mix-in: just
673// derive from it to implement a threading background task in your class.
674// ----------------------------------------------------------------------------
675
676class WXDLLIMPEXP_BASE wxThreadHelper
677{
678private:
679 void KillThread()
680 {
c763d6f0
FM
681 // If wxThreadHelperThread is detached and is about to finish, it will
682 // set m_thread to NULL so don't delete it then.
683 // But if KillThread is called before wxThreadHelperThread (in detached mode)
684 // sets it to NULL, then the thread object still exists and can be killed
c4b64a94 685 wxCriticalSectionLocker locker(m_critSection);
a5cc517f 686
78ee6a47
VZ
687 if ( m_thread )
688 {
689 m_thread->Kill();
a5cc517f 690
c4b64a94
VZ
691 if ( m_kind == wxTHREAD_JOINABLE )
692 delete m_thread;
a5cc517f 693
c4b64a94 694 m_thread = NULL;
78ee6a47
VZ
695 }
696 }
697
698public:
699 // constructor only initializes m_thread to NULL
c4b64a94
VZ
700 wxThreadHelper(wxThreadKind kind = wxTHREAD_JOINABLE)
701 : m_thread(NULL), m_kind(kind) { }
78ee6a47
VZ
702
703 // destructor deletes m_thread
704 virtual ~wxThreadHelper() { KillThread(); }
705
3d5930b5
FM
706#if WXWIN_COMPATIBILITY_2_8
707 wxDEPRECATED( wxThreadError Create(unsigned int stackSize = 0) );
708#endif
709
78ee6a47
VZ
710 // create a new thread (and optionally set the stack size on platforms that
711 // support/need that), call Run() to start it
3d5930b5
FM
712 wxThreadError CreateThread(wxThreadKind kind = wxTHREAD_JOINABLE,
713 unsigned int stackSize = 0)
78ee6a47
VZ
714 {
715 KillThread();
716
3d5930b5 717 m_kind = kind;
c4b64a94 718 m_thread = new wxThreadHelperThread(*this, m_kind);
78ee6a47
VZ
719
720 return m_thread->Create(stackSize);
721 }
722
723 // entry point for the thread - called by Run() and executes in the context
724 // of this thread.
725 virtual void *Entry() = 0;
726
727 // returns a pointer to the thread which can be used to call Run()
c4b64a94
VZ
728 wxThread *GetThread() const
729 {
730 wxCriticalSectionLocker locker((wxCriticalSection&)m_critSection);
a5cc517f 731
c4b64a94 732 wxThread* thread = m_thread;
a5cc517f 733
c4b64a94
VZ
734 return thread;
735 }
78ee6a47
VZ
736
737protected:
738 wxThread *m_thread;
c4b64a94
VZ
739 wxThreadKind m_kind;
740 wxCriticalSection m_critSection; // To guard the m_thread variable
a5cc517f 741
c4b64a94 742 friend class wxThreadHelperThread;
78ee6a47
VZ
743};
744
3d5930b5
FM
745#if WXWIN_COMPATIBILITY_2_8
746inline wxThreadError wxThreadHelper::Create(unsigned int stackSize)
747{ return CreateThread(m_kind, stackSize); }
748#endif
749
78ee6a47
VZ
750// call Entry() in owner, put it down here to avoid circular declarations
751inline void *wxThreadHelperThread::Entry()
752{
c4b64a94 753 void * const result = m_owner.Entry();
a5cc517f 754
c4b64a94 755 wxCriticalSectionLocker locker(m_owner.m_critSection);
a5cc517f 756
c4b64a94
VZ
757 // Detached thread will be deleted after returning, so make sure
758 // wxThreadHelper::GetThread will not return an invalid pointer.
759 // And that wxThreadHelper::KillThread will not try to kill
760 // an already deleted thread
761 if ( m_owner.m_kind == wxTHREAD_DETACHED )
762 m_owner.m_thread = NULL;
a5cc517f 763
c4b64a94 764 return result;
78ee6a47
VZ
765}
766
a6b0bd49 767// ----------------------------------------------------------------------------
d524867f 768// Automatic initialization
a6b0bd49 769// ----------------------------------------------------------------------------
10b959e3 770
9d133d87 771// GUI mutex handling.
bb24c68f
VS
772void WXDLLIMPEXP_BASE wxMutexGuiEnter();
773void WXDLLIMPEXP_BASE wxMutexGuiLeave();
d524867f 774
72cdf4c9
VZ
775// macros for entering/leaving critical sections which may be used without
776// having to take them inside "#if wxUSE_THREADS"
b568d04f
VZ
777#define wxENTER_CRIT_SECT(cs) (cs).Enter()
778#define wxLEAVE_CRIT_SECT(cs) (cs).Leave()
bdc72a22 779#define wxCRIT_SECT_DECLARE(cs) static wxCriticalSection cs
db882c54 780#define wxCRIT_SECT_DECLARE_MEMBER(cs) wxCriticalSection cs
b568d04f 781#define wxCRIT_SECT_LOCKER(name, cs) wxCriticalSectionLocker name(cs)
72cdf4c9 782
17dbd230
VZ
783// function for checking if we're in the main thread which may be used whether
784// wxUSE_THREADS is 0 or 1
785inline bool wxIsMainThread() { return wxThread::IsMain(); }
786
9d133d87 787#else // !wxUSE_THREADS
d524867f 788
9d133d87 789// no thread support
76de6a6e
VZ
790inline void wxMutexGuiEnter() { }
791inline void wxMutexGuiLeave() { }
d524867f 792
72cdf4c9
VZ
793// macros for entering/leaving critical sections which may be used without
794// having to take them inside "#if wxUSE_THREADS"
98fa068e
VZ
795// (the implementation uses dummy structs to force semicolon after the macro;
796// also notice that Watcom doesn't like declaring a struct as a member so we
797// need to actually define it in wxCRIT_SECT_DECLARE_MEMBER)
e8ec9749
VS
798#define wxENTER_CRIT_SECT(cs) do {} while (0)
799#define wxLEAVE_CRIT_SECT(cs) do {} while (0)
800#define wxCRIT_SECT_DECLARE(cs) struct wxDummyCS##cs
98fa068e 801#define wxCRIT_SECT_DECLARE_MEMBER(cs) struct wxDummyCSMember##cs { }
e8ec9749 802#define wxCRIT_SECT_LOCKER(name, cs) struct wxDummyCSLocker##name
72cdf4c9 803
17dbd230
VZ
804// if there is only one thread, it is always the main one
805inline bool wxIsMainThread() { return true; }
806
9e84b847 807#endif // wxUSE_THREADS/!wxUSE_THREADS
10b959e3 808
4562f685
VZ
809// mark part of code as being a critical section: this macro declares a
810// critical section with the given name and enters it immediately and leaves
811// it at the end of the current scope
812//
813// example:
814//
815// int Count()
816// {
817// static int s_counter = 0;
818//
819// wxCRITICAL_SECTION(counter);
820//
821// return ++s_counter;
822// }
823//
824// this function is MT-safe in presence of the threads but there is no
825// overhead when the library is compiled without threads
826#define wxCRITICAL_SECTION(name) \
827 wxCRIT_SECT_DECLARE(s_cs##name); \
828 wxCRIT_SECT_LOCKER(cs##name##Locker, s_cs##name)
829
9e84b847 830// automatically lock GUI mutex in ctor and unlock it in dtor
bb24c68f 831class WXDLLIMPEXP_BASE wxMutexGuiLocker
bee503b0
VZ
832{
833public:
834 wxMutexGuiLocker() { wxMutexGuiEnter(); }
835 ~wxMutexGuiLocker() { wxMutexGuiLeave(); }
836};
837
f6ddc54a
VZ
838// -----------------------------------------------------------------------------
839// implementation only until the end of file
840// -----------------------------------------------------------------------------
dcda1c71 841
9838df2c 842#if wxUSE_THREADS
dcda1c71 843
da0ee16e 844#if defined(__WINDOWS__) || defined(__OS2__) || defined(__EMX__) || defined(__DARWIN__)
f6ddc54a
VZ
845 // unlock GUI if there are threads waiting for and lock it back when
846 // there are no more of them - should be called periodically by the main
847 // thread
bb24c68f 848 extern void WXDLLIMPEXP_BASE wxMutexGuiLeaveOrEnter();
f6ddc54a 849
c096f614 850 // returns true if the main thread has GUI lock
bb24c68f 851 extern bool WXDLLIMPEXP_BASE wxGuiOwnedByMainThread();
f6ddc54a
VZ
852
853 // wakes up the main thread if it's sleeping inside ::GetMessage()
bb24c68f 854 extern void WXDLLIMPEXP_BASE wxWakeUpMainThread();
bf1852e1 855
da0ee16e 856#ifndef __DARWIN__
c096f614 857 // return true if the main thread is waiting for some other to terminate:
e7549107 858 // wxApp then should block all "dangerous" messages
bb24c68f 859 extern bool WXDLLIMPEXP_BASE wxIsWaitingForThread();
a94c4b85 860#endif
420b39aa 861#endif // MSW, OS/2
dcda1c71 862
f6ddc54a
VZ
863#endif // wxUSE_THREADS
864
9e84b847 865#endif // _WX_THREAD_H_