[+] FlexibleConditionVariable::WaitForSignalRelativeNanoseconds(AuUInt64 uRelativeNanoseconds)

[+] FlexibleConditionVariable::WaitForSignalRelativeNanoseconds(Threading::IWaitable *pWaitable, AuUInt64 uRelativeNanoseconds)
[+] FlexibleConditionVariable::WaitForSignalRelativeNanoseconds(AuUInt64 uRelativeNanoseconds)
[*] Refactor FlexibleConditionVariable
This commit is contained in:
Reece Wilson 2023-07-25 12:38:49 +01:00
parent dab6e9caee
commit 66cfbb5351
2 changed files with 69 additions and 15 deletions

View File

@ -18,8 +18,13 @@ namespace Aurora::Threading::Primitives
struct ConditionEx
{
virtual void WaitForSignal() = 0;
virtual void WaitForSignal(Threading::IWaitable *waitable) = 0;
virtual void WaitForSignal(const AuSPtr<Threading::IWaitable> &waitable) = 0;
virtual void WaitForSignal(IWaitable *pWaitable) = 0;
virtual void WaitForSignal(const AuSPtr<IWaitable> &pWaitable) = 0;
virtual void WaitForSignalRelativeNanoseconds(AuUInt64 uRelativeNanoseconds) = 0;
virtual void WaitForSignalRelativeNanoseconds(IWaitable *pWaitable, AuUInt64 uRelativeNanoseconds) = 0;
virtual void WaitForSignalRelativeNanoseconds(const AuSPtr<IWaitable> &pWaitable, AuUInt64 uRelativeNanoseconds) = 0;
virtual void Broadcast() = 0;
virtual void Signal() = 0;
};

View File

@ -15,32 +15,81 @@ namespace Aurora::Threading::Primitives
{
SemaphoreConditionVariableImpl();
void WaitForSignal(Aurora::Threading::IWaitable *pWaitable) override;
void WaitForSignal(const AuSPtr<Threading::IWaitable> &pWaitable) override;
void WaitForSignal(IWaitable *pWaitable) override;
void WaitForSignal(const AuSPtr<IWaitable> &pWaitable) override;
void WaitForSignal() override;
void WaitForSignalRelativeNanoseconds(AuUInt64 uRelativeNanoseconds) override;
void WaitForSignalRelativeNanoseconds(IWaitable *waitable, AuUInt64 uRelativeNanoseconds) override;
void WaitForSignalRelativeNanoseconds(const AuSPtr<IWaitable> &waitable, AuUInt64 uRelativeNanoseconds) override;
void Signal() override;
void Broadcast() override;
private:
SemaphoreImpl s_;
AuUInt32 waiters_;
AuUInt32 uWaiters_;
};
SemaphoreConditionVariableImpl::SemaphoreConditionVariableImpl() :
s_(0),
waiters_(0)
uWaiters_(0)
{
}
void SemaphoreConditionVariableImpl::WaitForSignal(Aurora::Threading::IWaitable *pWaitable)
void SemaphoreConditionVariableImpl::WaitForSignalRelativeNanoseconds(AuUInt64 uRelativeNanoseconds)
{
WaitForSignalRelativeNanoseconds(nullptr, uRelativeNanoseconds);
}
void SemaphoreConditionVariableImpl::WaitForSignalRelativeNanoseconds(IWaitable *pWaitable, AuUInt64 uRelativeNanoseconds)
{
return WaitForSignalRelativeNanoseconds(pWaitable ? AuUnsafeRaiiToShared(pWaitable) : AuSPtr<IWaitable> {},
uRelativeNanoseconds);
}
void SemaphoreConditionVariableImpl::WaitForSignalRelativeNanoseconds(const AuSPtr<IWaitable> &pWaitable,
AuUInt64 uRelativeNanoseconds)
{
AuAtomicAdd(&this->uWaiters_, 1u);
if (pWaitable)
{
pWaitable->Unlock();
}
auto bSuccess = this->s_.LockNS(uRelativeNanoseconds);
if (!bSuccess)
{
auto uWaiters = this->uWaiters_;
auto uWaitCount = 1;
while (AuAtomicCompareExchange(&this->uWaiters_, uWaiters - uWaitCount, uWaiters) != uWaiters)
{
uWaiters = this->uWaiters_;
if (uWaiters == 0)
{
break;
}
}
}
if (pWaitable)
{
pWaitable->Lock();
}
}
void SemaphoreConditionVariableImpl::WaitForSignal(IWaitable *pWaitable)
{
return WaitForSignal(AuUnsafeRaiiToShared(pWaitable));
}
void SemaphoreConditionVariableImpl::WaitForSignal(const AuSPtr<Threading::IWaitable> &pWaitable)
void SemaphoreConditionVariableImpl::WaitForSignal(const AuSPtr<IWaitable> &pWaitable)
{
AuAtomicAdd(&this->waiters_, 1u);
AuAtomicAdd(&this->uWaiters_, 1u);
if (pWaitable)
{
@ -65,16 +114,16 @@ namespace Aurora::Threading::Primitives
AuUInt32 uWaitCount {};
AuUInt32 uWaiters {};
uWaiters = this->waiters_;
uWaiters = this->uWaiters_;
if (uWaiters > 0)
{
this->s_.Unlock();
uWaitCount = 1;
}
while (AuAtomicCompareExchange(&this->waiters_, uWaiters - uWaitCount, uWaiters) != uWaiters)
while (AuAtomicCompareExchange(&this->uWaiters_, uWaiters - uWaitCount, uWaiters) != uWaiters)
{
uWaiters = this->waiters_;
uWaiters = this->uWaiters_;
if (uWaiters == 0)
{
@ -88,16 +137,16 @@ namespace Aurora::Threading::Primitives
AuUInt32 uWaitCount {};
AuUInt32 uWaiters {};
uWaiters = this->waiters_;
uWaiters = this->uWaiters_;
if (uWaiters > 0)
{
this->s_.Unlock(uWaiters);
uWaitCount = uWaiters;
}
while (AuAtomicCompareExchange(&this->waiters_, uWaiters - uWaitCount, uWaiters) != uWaiters)
while (AuAtomicCompareExchange(&this->uWaiters_, uWaiters - uWaitCount, uWaiters) != uWaiters)
{
uWaiters = this->waiters_;
uWaiters = this->uWaiters_;
if (uWaiters <= uWaitCount)
{