AuroraRuntime/Source/Threading/Primitives/AuConditionMutex.Generic.cpp
Jamie Reece Wilson 62b6fa20f8 [*] Update the copyright header of most of the primitives
[*] Fix generic mutex abs yield always returning true
2024-01-29 14:48:04 +00:00

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