[+] AuInitOnce
This commit is contained in:
parent
0de153dfe3
commit
afa2cb5944
@ -130,8 +130,8 @@ using AuMemoryViewStreamWrite = AuMemory::MemoryViewStreamWrite;
|
||||
|
||||
using AuMutex = AuThreadPrimitives::Mutex;
|
||||
using AuSemaphore = AuThreadPrimitives::Semaphore;
|
||||
using AuRWRenterableLock = AuThreadPrimitives::RWRenterableLock;
|
||||
using AuRenterableMutex = AuThreadPrimitives::CriticalSection;
|
||||
using AuRWRenterableLock = AuThreadPrimitives::RWRenterableLock;
|
||||
using AuRWLock = AuThreadPrimitives::RWLock;
|
||||
using AuCond = AuThreadPrimitives::ConditionVariable;
|
||||
using AuCondMutex = AuThreadPrimitives::ConditionMutex;
|
||||
@ -143,6 +143,8 @@ using AuFutexMutex = AuThreading::Waitables::FutexWaitable;
|
||||
using AuFutexSemaphore = AuThreading::Waitables::FutexSemaphoreWaitable;
|
||||
using AuFutexCond = AuThreading::Waitables::FutexCondWaitable;
|
||||
|
||||
using AuInitOnce = AuThreading::InitOnce;
|
||||
|
||||
template<typename T, bool bIsStatic = false>
|
||||
using AuTLSVariable = AuThreads::TLSVariable<T, bIsStatic>;
|
||||
|
||||
|
157
Include/Aurora/Threading/InitOnce.hpp
Normal file
157
Include/Aurora/Threading/InitOnce.hpp
Normal file
@ -0,0 +1,157 @@
|
||||
/***
|
||||
Copyright (C) 2023 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: InitOnce.hpp
|
||||
Date: 2023-09-17
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::Threading
|
||||
{
|
||||
struct InitOnce :
|
||||
private IWaitable
|
||||
{
|
||||
inline bool IsUninitialized()
|
||||
{
|
||||
return (AuAtomicLoad(&this->uToken_) & 1) == 0;
|
||||
}
|
||||
|
||||
inline bool IsReady()
|
||||
{
|
||||
return (AuAtomicLoad(&this->uToken_) & 2) != 0;
|
||||
}
|
||||
|
||||
inline bool TrySet()
|
||||
{
|
||||
if (AuAtomicTestAndSet(&this->uToken_, 0) == 0)
|
||||
{
|
||||
this->Finish();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Callable>
|
||||
bool TryInit(const Callable &callback)
|
||||
{
|
||||
if (AuAtomicTestAndSet(&this->uToken_, 0) == 0)
|
||||
{
|
||||
callback();
|
||||
this->Finish();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Callable>
|
||||
void Call(const Callable &callback)
|
||||
{
|
||||
if (this->TryInit(callback))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (this->IsReady())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this->Lock();
|
||||
}
|
||||
|
||||
inline void Wait()
|
||||
{
|
||||
this->Lock();
|
||||
}
|
||||
|
||||
inline IWaitable *ToBarrier()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
inline void Finish()
|
||||
{
|
||||
AuAtomicSet(&this->uToken_, 1);
|
||||
this->Wakeup();
|
||||
}
|
||||
|
||||
// barrier impl:
|
||||
|
||||
inline void Wakeup()
|
||||
{
|
||||
if (auto uSleepers = AuAtomicLoad(&this->uSleepers_))
|
||||
{
|
||||
WakeNOnAddress((const void *)&this->uToken_, uSleepers);
|
||||
}
|
||||
}
|
||||
|
||||
inline bool HasOSHandle(AuMach &mach)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool HasLockImplementation()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void Lock()
|
||||
{
|
||||
this->LockAbsNS(0);
|
||||
}
|
||||
|
||||
inline bool LockNS(AuUInt64 qwTimeoutInNs)
|
||||
{
|
||||
if (this->IsReady())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return IWaitable::LockNS(qwTimeoutInNs);
|
||||
}
|
||||
|
||||
inline bool LockAbsNS(AuUInt64 qwAbsTimeoutInNs /* = 0, infinity*/)
|
||||
{
|
||||
auto uCurrent = AuAtomicLoad(&this->uToken_);
|
||||
|
||||
while ((uCurrent & 2) == 0)
|
||||
{
|
||||
AuAtomicAdd(&this->uSleepers_, 1u);
|
||||
bool bRet = WaitOnAddressSteady((const void *)&this->uToken_, &uCurrent, sizeof(uCurrent), qwAbsTimeoutInNs);
|
||||
AuAtomicSub(&this->uSleepers_, 1u);
|
||||
|
||||
if (!bRet)
|
||||
{
|
||||
return this->IsReady();
|
||||
}
|
||||
|
||||
uCurrent = AuAtomicLoad(&this->uToken_);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool TryLock()
|
||||
{
|
||||
return this->IsReady();
|
||||
}
|
||||
|
||||
inline void Unlock()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private:
|
||||
AuAUInt32 uToken_ {};
|
||||
AuAUInt32 uSleepers_ {};
|
||||
};
|
||||
}
|
@ -26,4 +26,6 @@ namespace Aurora::Threading
|
||||
|
||||
#include "SpinTime.hpp"
|
||||
|
||||
#include "Threads/Threads.hpp"
|
||||
#include "Threads/Threads.hpp"
|
||||
|
||||
#include "InitOnce.hpp"
|
Loading…
Reference in New Issue
Block a user