196 lines
4.3 KiB
C++
196 lines
4.3 KiB
C++
/***
|
|
Copyright (C) 2021-2024 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
|
|
|
File: AuConditionMutex.Generic.cpp
|
|
Date: 2021-6-14
|
|
Author: Reece
|
|
***/
|
|
#include <Source/RuntimeInternal.hpp>
|
|
#include "AuConditionMutex.Generic.hpp"
|
|
#include "../AuWakeInternal.hpp"
|
|
#include "SMTYield.hpp"
|
|
|
|
#if defined(_AURUNTIME_GENERICCM)
|
|
|
|
namespace Aurora::Threading::Primitives
|
|
{
|
|
GenericConditionMutex::GenericConditionMutex()
|
|
{
|
|
}
|
|
|
|
GenericConditionMutex::~GenericConditionMutex()
|
|
{
|
|
}
|
|
|
|
bool GenericConditionMutex::TryLock()
|
|
{
|
|
if (ThrdCfg::gPreferLinuxCondMutexSpinTryLock)
|
|
{
|
|
return this->TryLockHeavy();
|
|
}
|
|
else
|
|
{
|
|
return this->TryLockNoSpin();
|
|
}
|
|
}
|
|
|
|
void GenericConditionMutex::Lock()
|
|
{
|
|
if (ThrdCfg::gPreferUnixPrimitivesNoSpin)
|
|
{
|
|
if (this->TryLockNoSpin())
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (this->TryLockHeavy())
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
AuAtomicAdd(&this->uSleeping_, 1u);
|
|
|
|
while (!this->TryLockNoSpin())
|
|
{
|
|
static const AuUInt32 kRef { 1 };
|
|
(void)InternalLTSWaitOnAddressHighRes(&this->uState_, &kRef, 4, 0);
|
|
}
|
|
|
|
AuAtomicSub(&this->uSleeping_, 1u);
|
|
}
|
|
|
|
void GenericConditionMutex::Unlock()
|
|
{
|
|
AuAtomicClearU8Lock(&this->uState_);
|
|
|
|
if (AuAtomicLoad(&this->uSleeping_))
|
|
{
|
|
InternalLTSWakeOne(&this->uState_);
|
|
}
|
|
}
|
|
|
|
bool GenericConditionMutex::TryLockNoSpin()
|
|
{
|
|
return AuAtomicTestAndSet(&this->uState_, 0) == 0;
|
|
}
|
|
|
|
bool GenericConditionMutex::TryLockHeavy()
|
|
{
|
|
return DoTryIf([=]()
|
|
{
|
|
return this->TryLockNoSpin();
|
|
});
|
|
}
|
|
|
|
bool GenericConditionMutex::LockAbsNS(AuUInt64 uEndTime)
|
|
{
|
|
bool bStatus { true };
|
|
|
|
if (this->TryLock())
|
|
{
|
|
return true;
|
|
}
|
|
|
|
AuAtomicAdd(&this->uSleeping_, 1u);
|
|
|
|
while (!this->TryLockNoSpin())
|
|
{
|
|
static const AuUInt32 kRef { 1 };
|
|
|
|
if (uEndTime != 0)
|
|
{
|
|
if (!InternalLTSWaitOnAddressHighRes(&this->uState_, &kRef, 4, uEndTime))
|
|
{
|
|
bStatus = false;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
(void)InternalLTSWaitOnAddressHighRes(&this->uState_, &kRef, 4, uEndTime);
|
|
}
|
|
}
|
|
|
|
AuAtomicSub(&this->uSleeping_, 1u);
|
|
return bStatus;
|
|
}
|
|
|
|
bool GenericConditionMutex::LockNS(AuUInt64 uTimeout)
|
|
{
|
|
AuUInt64 uEndTime {};
|
|
bool bStatus { true };
|
|
|
|
if (this->TryLock())
|
|
{
|
|
return true;
|
|
}
|
|
|
|
if (uTimeout != 0)
|
|
{
|
|
uEndTime = AuTime::SteadyClockNS() + uTimeout;
|
|
}
|
|
|
|
if (!ThrdCfg::gPreferUnixPrimitivesNoSpin)
|
|
{
|
|
if (this->TryLockHeavy())
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
AuAtomicAdd(&this->uSleeping_, 1u);
|
|
|
|
while (!this->TryLockNoSpin())
|
|
{
|
|
static const AuUInt32 kRef { 1 };
|
|
|
|
if (uTimeout != 0)
|
|
{
|
|
if (!InternalLTSWaitOnAddressHighRes(&this->uState_, &kRef, 4, uEndTime))
|
|
{
|
|
bStatus = false;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
(void)InternalLTSWaitOnAddressHighRes(&this->uState_, &kRef, 4, uEndTime);
|
|
}
|
|
}
|
|
|
|
AuAtomicSub(&this->uSleeping_, 1u);
|
|
return bStatus;
|
|
}
|
|
|
|
bool GenericConditionMutex::LockAbsMS(AuUInt64 timeout)
|
|
{
|
|
return this->LockAbsNS(AuMSToNS<AuUInt64>(timeout));
|
|
}
|
|
|
|
bool GenericConditionMutex::LockMS(AuUInt64 timeout)
|
|
{
|
|
return this->LockNS(AuMSToNS<AuUInt64>(timeout));
|
|
}
|
|
|
|
AuUInt GenericConditionMutex::GetOSHandle()
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
AUKN_SYM IConditionMutex *ConditionMutexNew()
|
|
{
|
|
return _new ConditionMutexGenericImpl();
|
|
}
|
|
|
|
AUKN_SYM void ConditionMutexRelease(IConditionMutex *pMutex)
|
|
{
|
|
AuSafeDelete<ConditionMutexGenericImpl *>(pMutex);
|
|
}
|
|
|
|
AUROXTL_INTERFACE_SOO_SRC_EX(AURORA_SYMBOL_EXPORT, ConditionMutex, ConditionMutexGenericImpl)
|
|
}
|
|
|
|
#endif |