#define MutexTryLock(mutex) (pthread_mutex_trylock(&mutex) == 0)
#define MutexUnlock(mutex) pthread_mutex_unlock(&mutex)
- typedef pthread_cond_t condition_t;
- #define ConditionCreate(cond) pthread_cond_init(&cond, NULL)
- #define ConditionDelete(cond) pthread_cond_destroy(&cond)
- #define ConditionSignal(cond) pthread_cond_signal(&cond)
- #define ConditionBroadcast(cond) pthread_cond_broadcast(&cond)
- inline bool ConditionWait(condition_t &cond, mutex_t &mutex, uint32_t iTimeout)
+ class CConditionImpl
{
- sched_yield();
- if (iTimeout > 0)
+ public:
+ CConditionImpl(void)
{
- struct timespec timeout = GetAbsTime(iTimeout);
- return (pthread_cond_timedwait(&cond, &mutex, &timeout) == 0);
+ pthread_cond_init(&m_condition, NULL);
}
- return (pthread_cond_wait(&cond, &mutex) == 0);
- }
+
+ virtual ~CConditionImpl(void)
+ {
+ pthread_cond_destroy(&m_condition);
+ }
+
+ void Signal(void)
+ {
+ pthread_cond_signal(&m_condition);
+ }
+
+ void Broadcast(void)
+ {
+ pthread_cond_broadcast(&m_condition);
+ }
+
+ bool Wait(mutex_t &mutex, uint32_t iTimeoutMs)
+ {
+ sched_yield();
+ if (iTimeout > 0)
+ {
+ struct timespec timeout = GetAbsTime(iTimeout);
+ return (pthread_cond_timedwait(&cond, &mutex, &timeout) == 0);
+ }
+ return (pthread_cond_wait(&cond, &mutex) == 0);
+ }
+
+ pthread_cond_t m_condition;
+ };
}
class CCondition : public PreventCopy
{
public:
- inline CCondition(void)
- {
- ConditionCreate(m_condition);
- }
-
+ inline CCondition(void) {}
inline ~CCondition(void)
{
- Broadcast();
- ConditionDelete(m_condition);
+ m_condition.Broadcast();
}
inline void Broadcast(void)
{
- ConditionBroadcast(m_condition);
+ m_condition.Broadcast();
}
inline void Signal(void)
{
- ConditionSignal(m_condition);
+ m_condition.Signal();
}
inline bool Wait(CMutex &mutex, uint32_t iTimeout = 0)
{
- return ConditionWait(m_condition, mutex.m_mutex, iTimeout);
+ return m_condition.Wait(mutex.m_mutex, iTimeout);
}
static void Sleep(uint32_t iTimeout)
w.Wait(m, iTimeout);
}
- condition_t m_condition;
+ private:
+ CConditionImpl m_condition;
};
}
#define MutexTryLock(mutex) (::TryEnterCriticalSection(mutex) != 0)
#define MutexUnlock(mutex) ::LeaveCriticalSection(mutex)
- #if (_WIN32_WINNT >= _WIN32_WINNT_VISTA)
- typedef CONDITION_VARIABLE* condition_t;
- #define ConditionCreate(cond) ::InitializeConditionVariable(cond = new CONDITION_VARIABLE)
- #define ConditionDelete(cond) delete cond
- #define ConditionSignal(cond) ::WakeConditionVariable(cond)
- #define ConditionBroadcast(cond) ::WakeAllConditionVariable(cond)
- #define ConditionWait(cond, mutex, timeout) (::SleepConditionVariableCS(cond, mutex, timeout <= 0 ? INFINITE : timeout) ? true : false)
- #else
- typedef HANDLE condition_t;
- #define ConditionCreate(cond) (cond = ::CreateEvent(NULL, TRUE, FALSE, NULL))
- #define ConditionDelete(cond) ::CloseHandle(cond)
- #define ConditionSignal(cond) ::SetEvent(cond)
- #define ConditionBroadcast(cond) ::SetEvent(cond)
- inline bool ConditionWait(condition_t cond, mutex_t mutex, uint32_t iTimeoutMsg)
+ // windows vista+ conditions
+ typedef VOID (WINAPI *ConditionArg) (CONDITION_VARIABLE*);
+ typedef BOOL (WINAPI *ConditionMutexArg)(CONDITION_VARIABLE*, CRITICAL_SECTION*, DWORD);
+ static ConditionArg g_InitializeConditionVariable;
+ static ConditionArg g_WakeConditionVariable;
+ static ConditionArg g_WakeAllConditionVariable;
+ static ConditionMutexArg g_SleepConditionVariableCS;
+
+ // check whether vista+ conditions are available at runtime
+ static bool CheckVistaConditionFunctions(void)
{
- ::ResetEvent(cond);
- MutexUnlock(mutex);
- DWORD iWaitReturn = ::WaitForSingleObject(cond, iTimeoutMsg <= 0 ? 1000 : iTimeoutMsg);
- MutexLock(mutex);
- return iWaitReturn == 0;
+ static int iHasVistaConditionFunctions(-1);
+ if (iHasVistaConditionFunctions == -1)
+ {
+ HMODULE handle = GetModuleHandle("Kernel32");
+ if (handle == NULL)
+ {
+ iHasVistaConditionFunctions = 0;
+ }
+ else
+ {
+ g_InitializeConditionVariable = (ConditionArg) GetProcAddress(handle,"InitializeConditionVariable");
+ g_WakeConditionVariable = (ConditionArg) GetProcAddress(handle,"WakeConditionVariable");
+ g_WakeAllConditionVariable = (ConditionArg) GetProcAddress(handle,"WakeAllConditionVariable");
+ g_SleepConditionVariableCS = (ConditionMutexArg)GetProcAddress(handle,"SleepConditionVariableCS");
+
+ // 1 when everything is resolved, 0 otherwise
+ iHasVistaConditionFunctions = g_InitializeConditionVariable &&
+ g_WakeConditionVariable &&
+ g_WakeAllConditionVariable &&
+ g_SleepConditionVariableCS ? 1 : 0;
+ }
+ }
+ return iHasVistaConditionFunctions == 1;
}
- #endif
+
+ class CConditionImpl
+ {
+ public:
+ CConditionImpl(void)
+ {
+ m_bOnVista = CheckVistaConditionFunctions();
+ if (m_bOnVista)
+ (*g_InitializeConditionVariable)(m_conditionVista = new CONDITION_VARIABLE);
+ else
+ m_conditionPreVista = ::CreateEvent(NULL, TRUE, FALSE, NULL);
+ }
+
+ virtual ~CConditionImpl(void)
+ {
+ if (m_bOnVista)
+ delete m_conditionVista;
+ else
+ ::CloseHandle(m_conditionPreVista);
+ }
+
+ void Signal(void)
+ {
+ if (m_bOnVista)
+ (*g_WakeConditionVariable)(m_conditionVista);
+ else
+ ::SetEvent(m_conditionPreVista);
+ }
+
+ void Broadcast(void)
+ {
+ if (m_bOnVista)
+ (*g_WakeAllConditionVariable)(m_conditionVista);
+ else
+ ::SetEvent(m_conditionPreVista);
+ }
+
+ bool Wait(mutex_t &mutex, uint32_t iTimeoutMs)
+ {
+ if (m_bOnVista)
+ {
+ return ((*g_SleepConditionVariableCS)(m_conditionVista, mutex, iTimeoutMs <= 0 ? INFINITE : iTimeoutMs) ? true : false);
+ }
+ else
+ {
+ ::ResetEvent(m_conditionPreVista);
+ MutexUnlock(mutex);
+ DWORD iWaitReturn = ::WaitForSingleObject(m_conditionPreVista, iTimeoutMs <= 0 ? 1000 : iTimeoutMs);
+ MutexLock(mutex);
+ return (iWaitReturn == 0);
+ }
+ }
+
+ bool m_bOnVista;
+ CONDITION_VARIABLE *m_conditionVista;
+ HANDLE m_conditionPreVista;
+ };
}