[+] AuAtomicTestAndSet

This commit is contained in:
Reece Wilson 2022-02-19 13:20:22 +00:00
parent b29be7b2d5
commit 2c55b722d6
3 changed files with 67 additions and 10 deletions

View File

@ -11,7 +11,7 @@ template<typename T>
struct AuAtomicUtils
{
/**
* @brief Sets bit offset in in
* @brief Generic bitwise (1 << offset)
* @return original value
*/
static T Set(T *in, AuUInt8 offset);
@ -29,12 +29,20 @@ struct AuAtomicUtils
static T Sub(T *in, T minuend);
/**
* @brief Generic bitwise compare exchange
* @brief Generic compare exchange
* @param replace replacement value for in if in matches compare
* @param compare required reference value
* @return original value
*/
static T CompareExchange(T *in, T replace, T compare);
/**
* @brief { return *in & (1 << offset); in |= (1 << offset) }
* @param in
* @param offset Bit index
* @return *in & (1 << offset)
*/
static bool TestAndSet(T *in, const AuUInt8 offset);
};
#if defined(AURORA_COMPILER_MSVC)
@ -208,6 +216,52 @@ inline auline T AuAtomicUtils<T>::Set(T *in, AuUInt8 offset)
#endif
template<typename T>
inline auline bool AuAtomicUtils<T>::TestAndSet(T *in, const AuUInt8 offset)
{
return AuAtomicSet<T>::Set(in, offset) & (1 << offset);
}
#if defined(AURORA_COMPILER_MSVC) && (defined(AURORA_ARCH_X64) || defined(AURORA_ARCH_X86))
template<>
inline auline bool AuAtomicUtils<unsigned long>::TestAndSet(unsigned long *in, const AuUInt8 offset)
{
return _interlockedbittestandset(reinterpret_cast<volatile long *>(in), offset);
}
template<>
inline auline bool AuAtomicUtils<long>::TestAndSet(long *in, const AuUInt8 offset)
{
return _interlockedbittestandset(reinterpret_cast<volatile long *>(in), offset);
}
template<>
inline auline bool AuAtomicUtils<AuUInt32>::TestAndSet(AuUInt32 *in, const AuUInt8 offset)
{
return _interlockedbittestandset(reinterpret_cast<volatile long *>(in), offset);
}
template<>
inline auline bool AuAtomicUtils<AuInt32>::TestAndSet(AuInt32 *in, const AuUInt8 offset)
{
return _interlockedbittestandset(reinterpret_cast<volatile long *>(in), offset);
}
template<>
inline auline bool AuAtomicUtils<AuUInt64>::TestAndSet(AuUInt64 *in, const AuUInt8 offset)
{
return _interlockedbittestandset64(reinterpret_cast<volatile long long *>(in), offset);
}
template<>
inline auline bool AuAtomicUtils<AuInt64>::TestAndSet(AuInt64 *in, const AuUInt8 offset)
{
return _interlockedbittestandset64(reinterpret_cast<volatile long long *>(in), offset);
}
#endif
template<typename T>
auline
T AuAtomicSet(T *in, AuUInt8 offset)
@ -235,3 +289,10 @@ T AuAtomicCompareExchange(T *in, T replace, T compare)
{
return AuAtomicUtils<T>::CompareExchange(in, replace, compare);
}
template<typename T>
auline
bool AuAtomicTestAndSet(T *in, AuUInt8 offset)
{
return AuAtomicUtils<T>::TestAndSet(in, offset);
}

View File

@ -33,6 +33,6 @@ namespace Aurora::Threading::Primitives
const bool permitMultipleTriggers_{};
ConditionMutexUnique_t mutex_;
ConditionVariableUnique_t condition_;
std::atomic<bool> triggered_;
bool triggered_;
};
}

View File

@ -36,11 +36,7 @@ namespace Aurora::Threading::Primitives
bool SpinLock::TryLock()
{
#if defined(_AU_HAS_ATOMIC_INTRINS)
return _interlockedbittestandset(&value_, 0) == 0;
#else
return value_.fetch_or(1);
#endif
return AuAtomicTestAndSet(&this->value_, 0) == 0;
}
bool SpinLock::HasLockImplementation()
@ -58,7 +54,7 @@ namespace Aurora::Threading::Primitives
{
if (timeout == 0)
{
while (AuAtomicSet(&this->value_, 0))
while (AuAtomicTestAndSet(&this->value_, 0))
{
long count = 0;
while (value_)
@ -72,7 +68,7 @@ namespace Aurora::Threading::Primitives
AuUInt64 startTime = AuTime::CurrentInternalClockMS();
AuUInt64 endTime = startTime + timeout;
while (AuAtomicSet(&this->value_, 0))
while (AuAtomicTestAndSet(&this->value_, 0))
{
long count = 0;
while (value_)