X-Git-Url: https://git.piment-noir.org/?a=blobdiff_plain;f=src%2Flib%2Fplatform%2Fthreads%2Fmutex.h;h=ed60ba8724612fae369e1fd7e9e33ede7877e97e;hb=4f3d2262d4685e8b51289a1fbdbf852bbdc89667;hp=4a2ad795f86e153cc59cb3c607e443198eecc735;hpb=f00ff009cfc5dfefdf09ca241b9560e74575b3f5;p=deb_libcec.git diff --git a/src/lib/platform/threads/mutex.h b/src/lib/platform/threads/mutex.h index 4a2ad79..ed60ba8 100644 --- a/src/lib/platform/threads/mutex.h +++ b/src/lib/platform/threads/mutex.h @@ -2,7 +2,7 @@ /* * This file is part of the libCEC(R) library. * - * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited. All rights reserved. + * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited. All rights reserved. * libCEC(R) is an original work, containing original code. * * libCEC(R) is a trademark of Pulse-Eight Limited. @@ -31,6 +31,16 @@ * http://www.pulse-eight.net/ */ +#include "../os.h" + +#if defined(__WINDOWS__) +#include "../windows/os-threads.h" +#else +#include "../posix/os-threads.h" +#endif + +#include "../util/timeutils.h" + namespace PLATFORM { class PreventCopy @@ -44,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) @@ -81,8 +93,17 @@ namespace PLATFORM inline void Unlock(void) { - --m_iLockCount; - MutexUnlock(m_mutex); + if (Lock()) + { + if (m_iLockCount >= 2) + { + --m_iLockCount; + MutexUnlock(m_mutex); + } + + --m_iLockCount; + MutexUnlock(m_mutex); + } } inline bool Clear(void) @@ -99,8 +120,8 @@ namespace PLATFORM } private: - mutex_t m_mutex; - unsigned int m_iLockCount; + mutex_t m_mutex; + volatile unsigned int m_iLockCount; }; class CLockObject : public PreventCopy @@ -146,43 +167,187 @@ namespace PLATFORM bool m_bClearOnExit; }; - class CCondition : public PreventCopy + class CTryLockObject : public PreventCopy { public: - inline CCondition(void) + inline CTryLockObject(CMutex &mutex, bool bClearOnExit = false) : + m_mutex(mutex), + m_bClearOnExit(bClearOnExit), + m_bIsLocked(m_mutex.TryLock()) + { + } + + 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 { - ConditionCreate(m_condition); + return m_bIsLocked; } - inline ~CCondition(void) + private: + CMutex & m_mutex; + bool m_bClearOnExit; + volatile bool m_bIsLocked; + }; + + template + class CCondition : public PreventCopy { - Broadcast(); - ConditionDelete(m_condition); + 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 Broadcast(void) + void Signal(void) { - ConditionBroadcast(m_condition); + Set(false); + m_condition.Signal(); } - inline void Signal(void) + bool Wait(void) { - ConditionSignal(m_condition); + CLockObject lock(m_mutex); + ++m_iWaitingThreads; + + bool bReturn = m_condition.Wait(m_mutex, m_bSignaled); + return ResetAndReturn() && bReturn; } - inline bool Wait(CMutex &mutex, uint32_t iTimeout = 0) + bool Wait(uint32_t iTimeout) { - return ConditionWait(m_condition, 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: + 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; } - condition_t m_condition; + volatile bool m_bSignaled; + CCondition m_condition; + CMutex m_mutex; + volatile bool m_bBroadcast; + unsigned int m_iWaitingThreads; + bool m_bAutoReset; }; }