[+] AuInitOnce::TryCall
This commit is contained in:
parent
9e1655d579
commit
42a8218916
@ -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,25 +186,53 @@ namespace Aurora::Threading
|
||||
|
||||
struct InitOnceLocker
|
||||
{
|
||||
cstatic bool TryLock(InitOnce *pInitOnce)
|
||||
cstatic bool TryLock(InitOnce *pInitOnce, bool bFailable = false)
|
||||
{
|
||||
if (bFailable)
|
||||
{
|
||||
return pInitOnce->_TryAcquireFailable();
|
||||
}
|
||||
else
|
||||
{
|
||||
return pInitOnce->_TryAcquire();
|
||||
}
|
||||
}
|
||||
|
||||
cstatic void Finish(InitOnce *pInitOnce)
|
||||
cstatic void Finish(InitOnce *pInitOnce, bool bFailed = false)
|
||||
{
|
||||
if (bFailed)
|
||||
{
|
||||
pInitOnce->_FinishFailed();
|
||||
}
|
||||
else
|
||||
{
|
||||
pInitOnce->_Finish();
|
||||
}
|
||||
}
|
||||
|
||||
cstatic bool TryLock(__audetail::InitOnceABI *pInitOnce)
|
||||
cstatic bool TryLock(__audetail::InitOnceABI *pInitOnce, bool bFailable = false)
|
||||
{
|
||||
if (bFailable)
|
||||
{
|
||||
return pInitOnce->_TryAcquireFailable();
|
||||
}
|
||||
else
|
||||
{
|
||||
return pInitOnce->_TryAcquire();
|
||||
}
|
||||
}
|
||||
|
||||
cstatic void Finish(__audetail::InitOnceABI *pInitOnce)
|
||||
cstatic void Finish(__audetail::InitOnceABI *pInitOnce, bool bFailed = false)
|
||||
{
|
||||
if (bFailed)
|
||||
{
|
||||
pInitOnce->_FinishFailed();
|
||||
}
|
||||
else
|
||||
{
|
||||
pInitOnce->_Finish();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Example usage:
|
||||
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user