Optimized ConditionVariable Windows implementation
Former-commit-id: 4f2e582d64e8f3a1f83cea2bd0f7220987aa4332
This commit is contained in:
parent
3026d8b9ac
commit
3c337c0191
|
|
@ -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]);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue