* http://www.pulse-eight.net/
*/
-#include "../os.h"
+#include "lib/platform/os.h"
#if defined(__WINDOWS__)
-#include "../windows/os-threads.h"
+#include "lib/platform/windows/os-threads.h"
#else
-#include "../posix/os-threads.h"
+#include "lib/platform/posix/os-threads.h"
#endif
+#include "lib/platform/util/timeutils.h"
+
namespace PLATFORM
{
class PreventCopy
private:
inline PreventCopy(const PreventCopy &c) { *this = c; }
- inline PreventCopy &operator=(const PreventCopy &c){ *this = c; return *this; }
+ inline PreventCopy &operator=(const PreventCopy & UNUSED(c)){ return *this; }
};
- class CCondition;
+ template <typename _Predicate>
+ class CCondition;
class CMutex : public PreventCopy
{
- friend class CCondition;
+ template <typename _Predicate>
+ friend class CCondition;
public:
inline CMutex(void) :
m_iLockCount(0)
inline bool Lock(void)
{
- MutexLock(m_mutex);
- ++m_iLockCount;
- return true;
+ if (MutexLock(m_mutex))
+ {
+ ++m_iLockCount;
+ return true;
+ }
+ return false;
}
inline void Unlock(void)
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 <typename _Predicate>
+ 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)
{
- return m_condition.Wait(mutex.m_mutex, iTimeout);
+ CLockObject lock(m_mutex);
+ ++m_iWaitingThreads;
+
+ bool bReturn = m_condition.Wait(m_mutex, m_bSignaled);
+ return ResetAndReturn() && bReturn;
+ }
+
+ bool Wait(uint32_t 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<volatile bool> m_condition;
+ CMutex m_mutex;
+ volatile bool m_bBroadcast;
+ unsigned int m_iWaitingThreads;
+ bool m_bAutoReset;
};
}