AuroraRuntime/Source/Threading/Primitives/AuConditionEx.cpp
2023-07-25 12:27:08 +01:00

120 lines
2.9 KiB
C++

/***
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: AuConditionEx.cpp
Date: 2021-6-12
Author: Reece
***/
#include <Source/RuntimeInternal.hpp>
#include "AuConditionEx.hpp"
#include "AuSemaphore.Generic.hpp"
namespace Aurora::Threading::Primitives
{
struct SemaphoreConditionVariableImpl : ConditionEx
{
SemaphoreConditionVariableImpl();
void WaitForSignal(Aurora::Threading::IWaitable *pWaitable) override;
void WaitForSignal(const AuSPtr<Threading::IWaitable> &pWaitable) override;
void WaitForSignal() override;
void Signal() override;
void Broadcast() override;
private:
SemaphoreImpl s_;
AuUInt32 waiters_;
};
SemaphoreConditionVariableImpl::SemaphoreConditionVariableImpl() :
s_(0),
waiters_(0)
{
}
void SemaphoreConditionVariableImpl::WaitForSignal(Aurora::Threading::IWaitable *pWaitable)
{
return WaitForSignal(AuUnsafeRaiiToShared(pWaitable));
}
void SemaphoreConditionVariableImpl::WaitForSignal(const AuSPtr<Threading::IWaitable> &pWaitable)
{
AuAtomicAdd(&this->waiters_, 1u);
if (pWaitable)
{
pWaitable->Unlock();
}
this->s_.Lock();
if (pWaitable)
{
pWaitable->Lock();
}
}
void SemaphoreConditionVariableImpl::WaitForSignal()
{
WaitForSignal(nullptr);
}
void SemaphoreConditionVariableImpl::Signal()
{
AuUInt32 uWaitCount {};
AuUInt32 uWaiters {};
uWaiters = this->waiters_;
if (uWaiters > 0)
{
this->s_.Unlock();
uWaitCount = 1;
}
while (AuAtomicCompareExchange(&this->waiters_, uWaiters - uWaitCount, uWaiters) != uWaiters)
{
uWaiters = this->waiters_;
if (uWaiters == 0)
{
return;
}
}
}
void SemaphoreConditionVariableImpl::Broadcast()
{
AuUInt32 uWaitCount {};
AuUInt32 uWaiters {};
uWaiters = this->waiters_;
if (uWaiters > 0)
{
this->s_.Unlock(uWaiters);
uWaitCount = uWaiters;
}
while (AuAtomicCompareExchange(&this->waiters_, uWaiters - uWaitCount, uWaiters) != uWaiters)
{
uWaiters = this->waiters_;
if (uWaiters <= uWaitCount)
{
uWaitCount = uWaiters;
}
}
}
AUKN_SYM ConditionEx *FlexibleConditionVariableNew()
{
return _new SemaphoreConditionVariableImpl();
}
AUKN_SYM void FlexibleConditionVariableRelease(ConditionEx *pCVEx)
{
AuSafeDelete<SemaphoreConditionVariableImpl *>(pCVEx);
}
AUROXTL_INTERFACE_SOO_SRC_EX(AURORA_SYMBOL_EXPORT, FlexibleConditionVariable, SemaphoreConditionVariableImpl)
}