diff --git a/src/Nazara/Core/Win32/ConditionVariableImpl.cpp b/src/Nazara/Core/Win32/ConditionVariableImpl.cpp index 6a5e56d5e..696b7c755 100644 --- a/src/Nazara/Core/Win32/ConditionVariableImpl.cpp +++ b/src/Nazara/Core/Win32/ConditionVariableImpl.cpp @@ -14,16 +14,16 @@ NzConditionVariableImpl::NzConditionVariableImpl() InitializeConditionVariable(&m_cv); #else 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[SIGNAL] = CreateEvent(nullptr, false, false, nullptr); // auto-reset event #endif } #if !NAZARA_CORE_WINDOWS_VISTA NzConditionVariableImpl::~NzConditionVariableImpl() { - DeleteCriticalSection(&m_countLock); + CloseHandle(m_events[BROADCAST]); + CloseHandle(m_events[SIGNAL]); } #endif @@ -32,12 +32,7 @@ void NzConditionVariableImpl::Signal() #if NAZARA_CORE_WINDOWS_VISTA WakeConditionVariable(&m_cv); #else - // Avoid race conditions. - EnterCriticalSection(&m_countLock); - bool haveWaiters = (m_count > 0); - LeaveCriticalSection(&m_countLock); - - if (haveWaiters) + if (m_count > 0) SetEvent(m_events[SIGNAL]); #endif } @@ -47,12 +42,7 @@ void NzConditionVariableImpl::SignalAll() #if NAZARA_CORE_WINDOWS_VISTA WakeAllConditionVariable(&m_cv); #else - // Avoid race conditions. - EnterCriticalSection(&m_countLock); - bool haveWaiters = (m_count > 0); - LeaveCriticalSection (&m_countLock); - - if (haveWaiters) + if (m_count > 0) SetEvent(m_events[BROADCAST]); #endif } @@ -67,10 +57,7 @@ bool NzConditionVariableImpl::Wait(NzMutexImpl* mutex, nzUInt32 timeout) #if NAZARA_CORE_WINDOWS_VISTA return SleepConditionVariableCS(&m_cv, &mutex->m_criticalSection, timeout); #else - // Avoid race conditions. - EnterCriticalSection(&m_countLock); m_count++; - LeaveCriticalSection(&m_countLock); // It's ok to release the mutex here since Win32 // 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. 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 - 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. ResetEvent(m_events[BROADCAST]); diff --git a/src/Nazara/Core/Win32/ConditionVariableImpl.hpp b/src/Nazara/Core/Win32/ConditionVariableImpl.hpp index e77bb338c..e635cf993 100644 --- a/src/Nazara/Core/Win32/ConditionVariableImpl.hpp +++ b/src/Nazara/Core/Win32/ConditionVariableImpl.hpp @@ -10,6 +10,7 @@ #define NAZARA_CONDITIONVARIABLEIMPL_HPP #include +#include #include class NzMutexImpl; @@ -41,9 +42,8 @@ class NzConditionVariableImpl MAX_EVENTS }; - CRITICAL_SECTION m_countLock; + std::atomic_uint m_count; HANDLE m_events[MAX_EVENTS]; - unsigned int m_count; #endif };