X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/d524867f4cd44178f8e6d22f37ade851918de628..aae24d21a33faa2a23fccde24255365ca845c46f:/include/wx/thread.h diff --git a/include/wx/thread.h b/include/wx/thread.h index aa43599256..906a4eb517 100644 --- a/include/wx/thread.h +++ b/include/wx/thread.h @@ -16,8 +16,12 @@ #pragma interface "thread.h" #endif -#include "wx/object.h" +// ---------------------------------------------------------------------------- +// headers +// ---------------------------------------------------------------------------- #include "wx/setup.h" + +#if wxUSE_THREADS #include "wx/module.h" // ---------------------------------------------------------------------------- @@ -48,41 +52,120 @@ typedef enum #define WXTHREAD_MAX_PRIORITY 100 // ---------------------------------------------------------------------------- -// GUI mutex handling. +// 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. // ---------------------------------------------------------------------------- -void WXDLLEXPORT wxMutexGuiEnter(); -void WXDLLEXPORT wxMutexGuiLeave(); +// you should consider wxMutexLocker whenever possible instead of directly +// working with wxMutex class - it is safer +class WXDLLEXPORT wxMutexInternal; +class WXDLLEXPORT wxMutex +{ +public: + // 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(); + + // Returns true if the mutex is locked. + bool IsLocked() const { return (m_locked > 0); } + +protected: + 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__ // ---------------------------------------------------------------------------- -// Mutex handler +// 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 // ---------------------------------------------------------------------------- -class WXDLLEXPORT wxMutexInternal; -class WXDLLEXPORT wxMutex +// you should consider wxCriticalSectionLocker whenever possible instead of +// directly working with wxCriticalSection class - it is safer +class WXDLLEXPORT wxCriticalSectionInternal; +class WXDLLEXPORT wxCriticalSection { public: - // constructor & destructor - wxMutex(); - ~wxMutex(); + // ctor & dtor + wxCriticalSection(); + ~wxCriticalSection(); - // 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(); + // enter the section (the same as locking a mutex) + void Enter(); + // leave the critical section (same as unlocking a mutex) + void Leave(); - // Returns true if the mutex is locked. - bool IsLocked() const { return (m_locked > 0); } +private: + // no assignment operator nor copy ctor + wxCriticalSection(const wxCriticalSection&); + wxCriticalSection& operator=(const wxCriticalSection&); -protected: - friend class wxCondition; + 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&); - int m_locked; - wxMutexInternal *p_internal; + wxCriticalSection& m_critsect; }; +#endif + // ---------------------------------------------------------------------------- // Condition handler. // ---------------------------------------------------------------------------- @@ -155,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); @@ -181,17 +265,38 @@ private: // Automatic initialization // ---------------------------------------------------------------------------- -class wxThreadModule : public wxModule -{ - DECLARE_DYNAMIC_CLASS(wxThreadModule) - -public: - wxThreadModule() {} +// GUI mutex handling. +void WXDLLEXPORT wxMutexGuiEnter(); +void WXDLLEXPORT wxMutexGuiLeave(); - virtual bool OnInit(); - virtual void OnExit(); -}; +// 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__