X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/a6b0bd49c72e577a218bfe10fc1526cf2ad6293d..aae24d21a33faa2a23fccde24255365ca845c46f:/include/wx/thread.h diff --git a/include/wx/thread.h b/include/wx/thread.h index b02df5244f..906a4eb517 100644 --- a/include/wx/thread.h +++ b/include/wx/thread.h @@ -19,14 +19,17 @@ // ---------------------------------------------------------------------------- // headers // ---------------------------------------------------------------------------- -#include "wx/object.h" #include "wx/setup.h" +#if wxUSE_THREADS +#include "wx/module.h" + // ---------------------------------------------------------------------------- // constants // ---------------------------------------------------------------------------- -typedef enum { +typedef enum +{ wxMUTEX_NO_ERROR = 0, wxMUTEX_DEAD_LOCK, // Mutex has been already locked by THE CALLING thread wxMUTEX_BUSY, // Mutex has been already locked by ONE thread @@ -34,7 +37,8 @@ typedef enum { wxMUTEX_MISC_ERROR } wxMutexError; -typedef enum { +typedef enum +{ wxTHREAD_NO_ERROR = 0, // No error wxTHREAD_NO_RESOURCE, // No resource left to create a new thread wxTHREAD_RUNNING, // The thread is already running @@ -42,43 +46,133 @@ typedef enum { wxTHREAD_MISC_ERROR // Some other error } wxThreadError; -// defines the interval of priority. +/* defines the interval of priority. */ #define WXTHREAD_MIN_PRIORITY 0 #define WXTHREAD_DEFAULT_PRIORITY 50 #define WXTHREAD_MAX_PRIORITY 100 // ---------------------------------------------------------------------------- -// Mutex handler +// A mutex object is a synchronization object whose state is set to signaled +// when it is not owned by any thread, and nonsignaled when it is owned. Its +// name comes from its usefulness in coordinating mutually-exclusive access to +// a shared resource. Only one thread at a time can own a mutex object. // ---------------------------------------------------------------------------- + +// you should consider wxMutexLocker whenever possible instead of directly +// working with wxMutex class - it is safer class WXDLLEXPORT wxMutexInternal; -class WXDLLEXPORT wxMutex { +class WXDLLEXPORT wxMutex +{ public: - // constructor & destructor - wxMutex(); - ~wxMutex(); + // constructor & destructor + wxMutex(); + ~wxMutex(); - // Lock the mutex. - wxMutexError Lock(); - // Try to lock the mutex: if it can't, returns immediately with an error. - wxMutexError TryLock(); - // Unlock the mutex. - wxMutexError Unlock(); + // Lock the mutex. + wxMutexError Lock(); + // Try to lock the mutex: if it can't, returns immediately with an error. + wxMutexError TryLock(); + // Unlock the mutex. + wxMutexError Unlock(); - // Returns true if the mutex is locked. - bool IsLocked() const { return (m_locked > 0); } + // Returns true if the mutex is locked. + bool IsLocked() const { return (m_locked > 0); } protected: - friend class wxCondition; + friend class wxCondition; + + // no assignment operator nor copy ctor + wxMutex(const wxMutex&); + wxMutex& operator=(const wxMutex&); + + int m_locked; + wxMutexInternal *p_internal; +}; + +// a helper class which locks the mutex in the ctor and unlocks it in the dtor: +// this ensures that mutex is always unlocked, even if the function returns or +// throws an exception before it reaches the end +class WXDLLEXPORT wxMutexLocker +{ +public: + // lock the mutex in the ctor + wxMutexLocker(wxMutex *mutex) + { m_isOk = mutex && ((m_mutex = mutex)->Lock() == wxMUTEX_NO_ERROR); } + + // returns TRUE if mutex was successfully locked in ctor + bool IsOk() const { return m_isOk; } + + // unlock the mutex in dtor + ~wxMutexLocker() { if ( IsOk() ) m_mutex->Unlock(); } + +private: + // no assignment operator nor copy ctor + wxMutexLocker(const wxMutexLocker&); + wxMutexLocker& operator=(const wxMutexLocker&); + + bool m_isOk; + wxMutex *m_mutex; +}; + +#ifdef __WXMSW__ + +// ---------------------------------------------------------------------------- +// Critical section: this is the same as mutex but is only visible to the +// threads of the same process. For the platforms which don't have native +// support for critical sections, they're implemented entirely in terms of +// mutexes +// ---------------------------------------------------------------------------- + +// you should consider wxCriticalSectionLocker whenever possible instead of +// directly working with wxCriticalSection class - it is safer +class WXDLLEXPORT wxCriticalSectionInternal; +class WXDLLEXPORT wxCriticalSection +{ +public: + // ctor & dtor + wxCriticalSection(); + ~wxCriticalSection(); + + // enter the section (the same as locking a mutex) + void Enter(); + // leave the critical section (same as unlocking a mutex) + void Leave(); + +private: + // no assignment operator nor copy ctor + wxCriticalSection(const wxCriticalSection&); + wxCriticalSection& operator=(const wxCriticalSection&); - int m_locked; - wxMutexInternal *p_internal; + wxCriticalSectionInternal *m_critsect; }; +// wxCriticalSectionLocker is the same to critical sections as wxMutexLocker is +// to th mutexes +class WXDLLEXPORT wxCriticalSectionLocker +{ +public: + wxCriticalSectionLocker(wxCriticalSection& critsect) : m_critsect(critsect) + { m_critsect.Enter(); } + ~wxCriticalSectionLocker() + { m_critsect.Leave(); } + +private: + // no assignment operator nor copy ctor + wxCriticalSectionLocker(const wxCriticalSectionLocker&); + wxCriticalSectionLocker& operator=(const wxCriticalSectionLocker&); + + wxCriticalSection& m_critsect; +}; + +#endif + // ---------------------------------------------------------------------------- // Condition handler. // ---------------------------------------------------------------------------- + class wxConditionInternal; -class WXDLLEXPORT wxCondition { +class WXDLLEXPORT wxCondition +{ public: // constructor & destructor wxCondition(); @@ -100,8 +194,10 @@ private: // ---------------------------------------------------------------------------- // Thread management class // ---------------------------------------------------------------------------- + class wxThreadInternal; -class WXDLLEXPORT wxThread { +class WXDLLEXPORT wxThread +{ public: // constructor & destructor. wxThread(); @@ -142,15 +238,16 @@ public: // Returns true if the thread is suspended bool IsPaused() const { return IsAlive() && !IsRunning(); } - // Returns true if the thread is the main thread (aka the GUI thread). + // Returns true if current thread is the main thread (aka the GUI thread) static bool IsMain(); // Called when thread exits. virtual void OnExit(); protected: - // In case, the DIFFER flag is true, enables another thread to kill this one. - void TestDestroy(); + // Returns TRUE if the thread was asked to terminate + bool TestDestroy(); + // Exits from the current thread. void Exit(void *status = NULL); @@ -165,11 +262,41 @@ private: }; // ---------------------------------------------------------------------------- -// Global functions and variables +// Automatic initialization // ---------------------------------------------------------------------------- // GUI mutex handling. void WXDLLEXPORT wxMutexGuiEnter(); void WXDLLEXPORT wxMutexGuiLeave(); +// implementation only +#ifdef __WXMSW__ + // unlock GUI if there are threads waiting for and lock it back when + // there are no more of them - should be called periodically by the main + // thread + void WXDLLEXPORT wxMutexGuiLeaveOrEnter(); + + // returns TRUE if the main thread has GUI lock + inline bool WXDLLEXPORT wxGuiOwnedByMainThread(); + + // wakes up the main thread if it's sleeping inside ::GetMessage() + inline void WXDLLEXPORT wxWakeUpMainThread(); +#endif // MSW + +#else // !wxUSE_THREADS + +// no thread support +inline void WXDLLEXPORT wxMutexGuiEnter() { } +inline void WXDLLEXPORT wxMutexGuiLeave() { } + +#endif // wxUSE_THREADS + +// automatically unlock GUI mutex in dtor +class WXDLLEXPORT wxMutexGuiLocker +{ +public: + wxMutexGuiLocker() { wxMutexGuiEnter(); } + ~wxMutexGuiLocker() { wxMutexGuiLeave(); } +}; + #endif // __THREADH__