[+] 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 struct AuAtomicUtils
{ {
/** /**
* @brief Sets bit offset in in * @brief Generic bitwise (1 << offset)
* @return original value * @return original value
*/ */
static T Set(T *in, AuUInt8 offset); static T Set(T *in, AuUInt8 offset);
@ -29,12 +29,20 @@ struct AuAtomicUtils
static T Sub(T *in, T minuend); 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 replace replacement value for in if in matches compare
* @param compare required reference value * @param compare required reference value
* @return original value * @return original value
*/ */
static T CompareExchange(T *in, T replace, T compare); 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) #if defined(AURORA_COMPILER_MSVC)
@ -208,6 +216,52 @@ inline auline T AuAtomicUtils<T>::Set(T *in, AuUInt8 offset)
#endif #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> template<typename T>
auline auline
T AuAtomicSet(T *in, AuUInt8 offset) T AuAtomicSet(T *in, AuUInt8 offset)
@ -234,4 +288,11 @@ auline
T AuAtomicCompareExchange(T *in, T replace, T compare) T AuAtomicCompareExchange(T *in, T replace, T compare)
{ {
return AuAtomicUtils<T>::CompareExchange(in, replace, 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_{}; const bool permitMultipleTriggers_{};
ConditionMutexUnique_t mutex_; ConditionMutexUnique_t mutex_;
ConditionVariableUnique_t condition_; ConditionVariableUnique_t condition_;
std::atomic<bool> triggered_; bool triggered_;
}; };
} }

View File

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