Optimized ConditionVariable Windows implementation

Former-commit-id: 4f2e582d64e8f3a1f83cea2bd0f7220987aa4332
This commit is contained in:
Lynix 2013-11-30 12:29:39 +01:00
parent 3026d8b9ac
commit 3c337c0191
2 changed files with 8 additions and 26 deletions

View File

@ -14,16 +14,16 @@ NzConditionVariableImpl::NzConditionVariableImpl()
InitializeConditionVariable(&m_cv); InitializeConditionVariable(&m_cv);
#else #else
m_count = 0; m_count = 0;
InitializeCriticalSection(&m_countLock);
m_events[SIGNAL] = CreateEvent(nullptr, false, false, nullptr); // auto-reset event
m_events[BROADCAST] = CreateEvent(nullptr, true, false, nullptr); // manual-reset event m_events[BROADCAST] = CreateEvent(nullptr, true, false, nullptr); // manual-reset event
m_events[SIGNAL] = CreateEvent(nullptr, false, false, nullptr); // auto-reset event
#endif #endif
} }
#if !NAZARA_CORE_WINDOWS_VISTA #if !NAZARA_CORE_WINDOWS_VISTA
NzConditionVariableImpl::~NzConditionVariableImpl() NzConditionVariableImpl::~NzConditionVariableImpl()
{ {
DeleteCriticalSection(&m_countLock); CloseHandle(m_events[BROADCAST]);
CloseHandle(m_events[SIGNAL]);
} }
#endif #endif
@ -32,12 +32,7 @@ void NzConditionVariableImpl::Signal()
#if NAZARA_CORE_WINDOWS_VISTA #if NAZARA_CORE_WINDOWS_VISTA
WakeConditionVariable(&m_cv); WakeConditionVariable(&m_cv);
#else #else
// Avoid race conditions. if (m_count > 0)
EnterCriticalSection(&m_countLock);
bool haveWaiters = (m_count > 0);
LeaveCriticalSection(&m_countLock);
if (haveWaiters)
SetEvent(m_events[SIGNAL]); SetEvent(m_events[SIGNAL]);
#endif #endif
} }
@ -47,12 +42,7 @@ void NzConditionVariableImpl::SignalAll()
#if NAZARA_CORE_WINDOWS_VISTA #if NAZARA_CORE_WINDOWS_VISTA
WakeAllConditionVariable(&m_cv); WakeAllConditionVariable(&m_cv);
#else #else
// Avoid race conditions. if (m_count > 0)
EnterCriticalSection(&m_countLock);
bool haveWaiters = (m_count > 0);
LeaveCriticalSection (&m_countLock);
if (haveWaiters)
SetEvent(m_events[BROADCAST]); SetEvent(m_events[BROADCAST]);
#endif #endif
} }
@ -67,10 +57,7 @@ bool NzConditionVariableImpl::Wait(NzMutexImpl* mutex, nzUInt32 timeout)
#if NAZARA_CORE_WINDOWS_VISTA #if NAZARA_CORE_WINDOWS_VISTA
return SleepConditionVariableCS(&m_cv, &mutex->m_criticalSection, timeout); return SleepConditionVariableCS(&m_cv, &mutex->m_criticalSection, timeout);
#else #else
// Avoid race conditions.
EnterCriticalSection(&m_countLock);
m_count++; m_count++;
LeaveCriticalSection(&m_countLock);
// It's ok to release the mutex here since Win32 // It's ok to release the mutex here since Win32
// manual-reset events maintain state when used with SetEvent. // manual-reset events maintain state when used with SetEvent.
@ -80,13 +67,8 @@ bool NzConditionVariableImpl::Wait(NzMutexImpl* mutex, nzUInt32 timeout)
// Wait for either event to become signaled due to Signal being called or SignalAll being called. // Wait for either event to become signaled due to Signal being called or SignalAll being called.
int result = WaitForMultipleObjects(2, m_events, false, timeout); int result = WaitForMultipleObjects(2, m_events, false, timeout);
EnterCriticalSection(&m_countLock);
m_count--;
bool lastWaiter = (result == WAIT_OBJECT_0 + BROADCAST && m_count == 0);
LeaveCriticalSection(&m_countLock);
// Some thread called SignalAll // Some thread called SignalAll
if (lastWaiter) if (--m_count == 0 && result == WAIT_OBJECT_0 + BROADCAST)
// We're the last waiter to be notified or to stop waiting, so reset the manual event. // We're the last waiter to be notified or to stop waiting, so reset the manual event.
ResetEvent(m_events[BROADCAST]); ResetEvent(m_events[BROADCAST]);

View File

@ -10,6 +10,7 @@
#define NAZARA_CONDITIONVARIABLEIMPL_HPP #define NAZARA_CONDITIONVARIABLEIMPL_HPP
#include <Nazara/Prerequesites.hpp> #include <Nazara/Prerequesites.hpp>
#include <atomic>
#include <windows.h> #include <windows.h>
class NzMutexImpl; class NzMutexImpl;
@ -41,9 +42,8 @@ class NzConditionVariableImpl
MAX_EVENTS MAX_EVENTS
}; };
CRITICAL_SECTION m_countLock; std::atomic_uint m_count;
HANDLE m_events[MAX_EVENTS]; HANDLE m_events[MAX_EVENTS];
unsigned int m_count;
#endif #endif
}; };