X-Git-Url: https://git.piment-noir.org/?a=blobdiff_plain;f=src%2Flib%2Fplatform%2Fthreads%2Fmutex.h;h=ed60ba8724612fae369e1fd7e9e33ede7877e97e;hb=4f3d2262d4685e8b51289a1fbdbf852bbdc89667;hp=d44c0f1953b532da1cfd81a22eaac01bf0fe4048;hpb=3a590d6a4652d1c47026446dcdc44ac9852f8af3;p=deb_libcec.git diff --git a/src/lib/platform/threads/mutex.h b/src/lib/platform/threads/mutex.h index d44c0f1..ed60ba8 100644 --- a/src/lib/platform/threads/mutex.h +++ b/src/lib/platform/threads/mutex.h @@ -39,6 +39,8 @@ #include "../posix/os-threads.h" #endif +#include "../util/timeutils.h" + namespace PLATFORM { class PreventCopy @@ -52,11 +54,13 @@ namespace PLATFORM inline PreventCopy &operator=(const PreventCopy &c){ *this = c; return *this; } }; - class CCondition; + template + class CCondition; class CMutex : public PreventCopy { - friend class CCondition; + template + friend class CCondition; public: inline CMutex(void) : m_iLockCount(0) @@ -163,39 +167,187 @@ namespace PLATFORM bool m_bClearOnExit; }; - class CCondition : public PreventCopy + class CTryLockObject : public PreventCopy { public: - inline CCondition(void) {} - inline ~CCondition(void) + inline CTryLockObject(CMutex &mutex, bool bClearOnExit = false) : + m_mutex(mutex), + m_bClearOnExit(bClearOnExit), + m_bIsLocked(m_mutex.TryLock()) { - m_condition.Broadcast(); } - inline void Broadcast(void) + inline ~CTryLockObject(void) + { + if (m_bClearOnExit) + Clear(); + else if (m_bIsLocked) + Unlock(); + } + + inline bool TryLock(void) + { + bool bReturn = m_mutex.TryLock(); + m_bIsLocked |= bReturn; + return bReturn; + } + + inline void Unlock(void) + { + if (m_bIsLocked) + { + m_bIsLocked = false; + m_mutex.Unlock(); + } + } + + inline bool Clear(void) + { + m_bIsLocked = false; + return m_mutex.Clear(); + } + + inline bool Lock(void) + { + bool bReturn = m_mutex.Lock(); + m_bIsLocked |= bReturn; + return bReturn; + } + + inline bool IsLocked(void) const + { + return m_bIsLocked; + } + + private: + CMutex & m_mutex; + bool m_bClearOnExit; + volatile bool m_bIsLocked; + }; + + template + class CCondition : public PreventCopy + { + public: + inline CCondition(void) {} + inline ~CCondition(void) + { + m_condition.Broadcast(); + } + + inline void Broadcast(void) + { + m_condition.Broadcast(); + } + + inline void Signal(void) + { + m_condition.Signal(); + } + + inline bool Wait(CMutex &mutex, _Predicate &predicate) + { + while(!predicate) + m_condition.Wait(mutex.m_mutex); + return true; + } + + inline bool Wait(CMutex &mutex, _Predicate &predicate, uint32_t iTimeout) + { + if (iTimeout == 0) + return Wait(mutex, predicate); + + if (predicate) + return true; + + bool bReturn(false); + bool bBreak(false); + CTimeout timeout(iTimeout); + uint32_t iMsLeft(0); + + while (!bReturn && !bBreak) + { + iMsLeft = timeout.TimeLeft(); + if ((bReturn = predicate) == false && (bBreak = iMsLeft == 0) == false) + m_condition.Wait(mutex.m_mutex, iMsLeft); + } + return bReturn; + } + + private: + CConditionImpl m_condition; + }; + + class CEvent + { + public: + CEvent(bool bAutoReset = true) : + m_bSignaled(false), + m_bBroadcast(false), + m_iWaitingThreads(0), + m_bAutoReset(bAutoReset) {} + virtual ~CEvent(void) {} + + void Broadcast(void) { + Set(true); m_condition.Broadcast(); } - inline void Signal(void) + void Signal(void) { + Set(false); m_condition.Signal(); } - inline bool Wait(CMutex &mutex, uint32_t iTimeout = 0) + bool Wait(void) + { + CLockObject lock(m_mutex); + ++m_iWaitingThreads; + + bool bReturn = m_condition.Wait(m_mutex, m_bSignaled); + return ResetAndReturn() && bReturn; + } + + bool Wait(uint32_t iTimeout) { - return m_condition.Wait(mutex.m_mutex, iTimeout); + if (iTimeout == 0) + return Wait(); + + CLockObject lock(m_mutex); + ++m_iWaitingThreads; + bool bReturn = m_condition.Wait(m_mutex, m_bSignaled, iTimeout); + return ResetAndReturn() && bReturn; } static void Sleep(uint32_t iTimeout) { - CCondition w; - CMutex m; - CLockObject lock(m); - w.Wait(m, iTimeout); + CEvent event; + event.Wait(iTimeout); } private: - CConditionImpl m_condition; + void Set(bool bBroadcast = false) + { + CLockObject lock(m_mutex); + m_bSignaled = true; + m_bBroadcast = bBroadcast; + } + + bool ResetAndReturn(void) + { + CLockObject lock(m_mutex); + bool bReturn(m_bSignaled); + if (bReturn && (--m_iWaitingThreads == 0 || !m_bBroadcast) && m_bAutoReset) + m_bSignaled = false; + return bReturn; + } + + volatile bool m_bSignaled; + CCondition m_condition; + CMutex m_mutex; + volatile bool m_bBroadcast; + unsigned int m_iWaitingThreads; + bool m_bAutoReset; }; }