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