[+] FutexSemaphoreWaitable
This commit is contained in:
parent
0b2abc49fb
commit
412cdfb28b
157
Include/Aurora/Threading/Waitables/FutexSemaphoreWaitable.hpp
Normal file
157
Include/Aurora/Threading/Waitables/FutexSemaphoreWaitable.hpp
Normal file
@ -0,0 +1,157 @@
|
||||
/***
|
||||
Copyright (C) 2023 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: FutexSemaphoreWaitable.hpp
|
||||
Date: 2023-08-19
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
#include "../WakeOnAddress.hpp"
|
||||
#include "../SpinTime.hpp"
|
||||
|
||||
namespace Aurora::Threading::Waitables
|
||||
{
|
||||
struct FutexSemaphoreWaitable final : IWaitable
|
||||
{
|
||||
inline constexpr FutexSemaphoreWaitable()
|
||||
{}
|
||||
|
||||
AU_NO_COPY_NO_MOVE(FutexSemaphoreWaitable);
|
||||
|
||||
inline bool TryLock() override
|
||||
{
|
||||
{
|
||||
auto uState = this->uAtomicState;
|
||||
if (uState != 0 && AuAtomicCompareExchange(&this->uAtomicState, uState - 1, uState) == uState)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(AURORA_ARCH_X86) || defined(AURORA_ARCH_X64)
|
||||
for (AU_ITERATE_N(i, AuUInt(1u) << AuUInt(Threading::GetSpinCountTimeout())))
|
||||
{
|
||||
_mm_pause();
|
||||
|
||||
auto uState = this->uAtomicState;
|
||||
if (uState != 0 && AuAtomicCompareExchange(&this->uAtomicState, uState - 1, uState) == uState)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#else
|
||||
static const AuUInt32 kRef { 0 };
|
||||
if (TryWaitOnAddress(&this->uAtomicState, &kRef, sizeof(kRef)))
|
||||
{
|
||||
auto uState = this->uAtomicState;
|
||||
if (uState != 0 && AuAtomicCompareExchange(&this->uAtomicState, uState - 1, uState) == uState)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool HasOSHandle(AuMach &mach) override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool HasLockImplementation() override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void Unlock() override
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
inline void NotifyOne()
|
||||
{
|
||||
NotifyN(1);
|
||||
}
|
||||
|
||||
inline void NotifyN(AuUInt8 uThreads)
|
||||
{
|
||||
AuAtomicAdd(&this->uAtomicState, AuUInt32(uThreads));
|
||||
|
||||
if (auto uSleeping = this->uAtomicSleeping)
|
||||
{
|
||||
WakeNOnAddress(&this->uAtomicState, uSleeping);
|
||||
}
|
||||
}
|
||||
|
||||
inline void Lock() override
|
||||
{
|
||||
static const AuUInt32 kRef { 0 };
|
||||
|
||||
while (!TryLock())
|
||||
{
|
||||
AuAtomicAdd(&this->uAtomicSleeping, 1u);
|
||||
WaitOnAddress(&this->uAtomicState, &kRef, sizeof(kRef), 0);
|
||||
AuAtomicSub(&this->uAtomicSleeping, 1u);
|
||||
}
|
||||
}
|
||||
|
||||
inline bool LockMS(AuUInt64 qwTimeout) override
|
||||
{
|
||||
return LockNS(AuMSToNS<AuUInt64>(qwTimeout));
|
||||
}
|
||||
|
||||
inline bool LockAbsMS(AuUInt64 qwTimeout) override
|
||||
{
|
||||
return LockAbsNS(AuMSToNS<AuUInt64>(qwTimeout));
|
||||
}
|
||||
|
||||
inline bool LockNS(AuUInt64 qwTimeout) override
|
||||
{
|
||||
static const AuUInt32 kRef { 0 };
|
||||
|
||||
auto qwEndTime = Time::SteadyClockNS() + qwTimeout;
|
||||
|
||||
while (!TryLock())
|
||||
{
|
||||
bool bStatus {};
|
||||
|
||||
AuAtomicAdd(&this->uAtomicSleeping, 1u);
|
||||
bStatus = WaitOnAddressSteady(&this->uAtomicState, &kRef, sizeof(kRef), qwEndTime);
|
||||
AuAtomicSub(&this->uAtomicSleeping, 1u);
|
||||
|
||||
if (!bStatus)
|
||||
{
|
||||
return TryLock();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool LockAbsNS(AuUInt64 qwTimeoutAbs) override
|
||||
{
|
||||
static const AuUInt32 kRef { 0 };
|
||||
|
||||
while (!TryLock())
|
||||
{
|
||||
bool bStatus {};
|
||||
|
||||
AuAtomicAdd(&this->uAtomicSleeping, 1u);
|
||||
bStatus = WaitOnAddressSteady(&this->uAtomicState, &kRef, sizeof(kRef), qwTimeoutAbs);
|
||||
AuAtomicSub(&this->uAtomicSleeping, 1u);
|
||||
|
||||
if (!bStatus)
|
||||
{
|
||||
return TryLock();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
AuUInt32 uAtomicState {};
|
||||
AuUInt32 uAtomicSleeping {};
|
||||
};
|
||||
}
|
@ -10,3 +10,4 @@
|
||||
#include "CBWaitable.hpp"
|
||||
#include "BooleanWaitable.hpp"
|
||||
#include "FutexWaitable.hpp"
|
||||
#include "FutexSemaphoreWaitable.hpp"
|
Loading…
Reference in New Issue
Block a user