62 lines
1.9 KiB
C++
62 lines
1.9 KiB
C++
#pragma once
|
|
|
|
namespace baselib
|
|
{
|
|
BASELIB_CPP_INTERFACE
|
|
{
|
|
inline void ConditionVariable::Wait()
|
|
{
|
|
m_Data.waiters.fetch_add(1, memory_order_relaxed);
|
|
m_Lock.Release();
|
|
m_Data.semaphore.Acquire();
|
|
m_Lock.Acquire();
|
|
}
|
|
|
|
inline bool ConditionVariable::TimedWait(const timeout_ms timeoutInMilliseconds)
|
|
{
|
|
m_Data.waiters.fetch_add(1, memory_order_relaxed);
|
|
m_Lock.Release();
|
|
|
|
bool acquired = m_Data.semaphore.TryTimedAcquire(timeoutInMilliseconds);
|
|
|
|
if (acquired)
|
|
{
|
|
m_Lock.Acquire();
|
|
return true;
|
|
}
|
|
|
|
do
|
|
{
|
|
uint32_t waiters = m_Data.waiters.load(memory_order_relaxed);
|
|
while (waiters > 0)
|
|
{
|
|
if (m_Data.waiters.compare_exchange_weak(waiters, waiters - 1, memory_order_relaxed, memory_order_relaxed))
|
|
{
|
|
m_Lock.Acquire();
|
|
return false;
|
|
}
|
|
}
|
|
Baselib_Thread_YieldExecution();
|
|
}
|
|
while (!m_Data.semaphore.TryAcquire());
|
|
|
|
m_Lock.Acquire();
|
|
return true;
|
|
}
|
|
|
|
inline void ConditionVariable::Notify(uint16_t count)
|
|
{
|
|
uint32_t waitingThreads, threadsToWakeup;
|
|
do
|
|
{
|
|
waitingThreads = m_Data.waiters.load(memory_order_acquire);
|
|
threadsToWakeup = count < waitingThreads ? count : waitingThreads;
|
|
if (threadsToWakeup == 0)
|
|
return;
|
|
}
|
|
while (!m_Data.waiters.compare_exchange_weak(waitingThreads, waitingThreads - threadsToWakeup, memory_order_relaxed, memory_order_relaxed));
|
|
m_Data.semaphore.Release(threadsToWakeup);
|
|
}
|
|
}
|
|
}
|