[+] AuInitOnce::TryCall

This commit is contained in:
Reece Wilson 2023-09-20 02:57:40 +01:00
parent 9e1655d579
commit 42a8218916

View File

@ -28,10 +28,14 @@ namespace __audetail
inline bool _TryAcquire();
inline bool _TryAcquireFailable();
inline void _Finish();
inline void _Wakeup();
inline void _FinishFailed();
inline bool _LockAbsNS(AuUInt64 qwAbsTimeoutInNs /* = 0, infinity*/);
protected:
@ -67,10 +71,10 @@ namespace Aurora::Threading
template <typename Callable>
bool TryInit(const Callable &callback)
{
if (this->_TryAcquire())
if (InitOnceABI::_TryAcquire())
{
callback();
this->_Finish();
InitOnceABI::_Finish();
return true;
}
else
@ -95,6 +99,35 @@ namespace Aurora::Threading
this->Wait();
}
template <typename Callable>
bool TryCall(const Callable &callback, bool bWait = true)
{
bool bRet {};
if (InitOnceABI::_TryAcquireFailable())
{
if (callback())
{
InitOnceABI::_Finish();
return true;
}
else
{
InitOnceABI::_FinishFailed();
return false;
}
}
if ((!(bRet = this->IsReady())) &&
(bWait))
{
this->Wait();
bRet = this->IsReady();
}
return bRet;
}
inline void Wait()
{
InitOnceABI::Wait();
@ -153,24 +186,52 @@ namespace Aurora::Threading
struct InitOnceLocker
{
cstatic bool TryLock(InitOnce *pInitOnce)
cstatic bool TryLock(InitOnce *pInitOnce, bool bFailable = false)
{
return pInitOnce->_TryAcquire();
if (bFailable)
{
return pInitOnce->_TryAcquireFailable();
}
else
{
return pInitOnce->_TryAcquire();
}
}
cstatic void Finish(InitOnce *pInitOnce)
cstatic void Finish(InitOnce *pInitOnce, bool bFailed = false)
{
pInitOnce->_Finish();
if (bFailed)
{
pInitOnce->_FinishFailed();
}
else
{
pInitOnce->_Finish();
}
}
cstatic bool TryLock(__audetail::InitOnceABI *pInitOnce)
cstatic bool TryLock(__audetail::InitOnceABI *pInitOnce, bool bFailable = false)
{
return pInitOnce->_TryAcquire();
if (bFailable)
{
return pInitOnce->_TryAcquireFailable();
}
else
{
return pInitOnce->_TryAcquire();
}
}
cstatic void Finish(__audetail::InitOnceABI *pInitOnce)
cstatic void Finish(__audetail::InitOnceABI *pInitOnce, bool bFailed = false)
{
pInitOnce->_Finish();
if (bFailed)
{
pInitOnce->_FinishFailed();
}
else
{
pInitOnce->_Finish();
}
}
/**
@ -227,6 +288,19 @@ namespace __audetail
return AuAtomicTestAndSet(&this->uToken_, 0) == 0;
}
bool InitOnceABI::_TryAcquireFailable()
{
if (AuAtomicTestAndSet(&this->uToken_, 0) == 0)
{
AuAtomicUnset(&this->uToken_, 2);
return true;
}
else
{
return false;
}
}
void InitOnceABI::_Finish()
{
AuAtomicSet(&this->uToken_, 1);
@ -241,11 +315,18 @@ namespace __audetail
}
}
void InitOnceABI::_FinishFailed()
{
AuAtomicUnset(&this->uToken_, 0);
AuAtomicSet(&this->uToken_, 2);
InitOnceABI::_Wakeup();
}
bool InitOnceABI::_LockAbsNS(AuUInt64 qwAbsTimeoutInNs /* = 0, infinity*/)
{
auto uCurrent = AuAtomicLoad(&this->uToken_);
while ((uCurrent & 2) == 0)
while ((uCurrent & (2 | 4)) == 0)
{
AuAtomicAdd(&this->uSleepers_, 1u);
bool bRet = Aurora::Threading::WaitOnAddressSteady((const void *)&this->uToken_, &uCurrent, sizeof(uCurrent), qwAbsTimeoutInNs);