[+] AuAtomicStore

[+] AuAtomicLoad
[+] AuAtomicClearU8Lock
This commit is contained in:
Reece Wilson 2023-08-23 20:02:09 +01:00 committed by J Reece Wilson
parent d7d2a576b2
commit 2e93ca7e32

View File

@ -7,6 +7,10 @@
***/
#pragma once
#if defined(AURORA_COMPILER_CLANG)
#include <stdatomic.h>
#endif
template <class T>
struct AuAtomicUtils
{
@ -64,6 +68,15 @@ struct AuAtomicUtils
* @warning T is bound by platform and compiler constraints
*/
static bool TestAndSet(T *in, const AuUInt8 offset);
//
static T Load(T *in);
//
static void Store(T *in, T value);
//
static void ClearU8Lock(T *in);
};
#if defined(AURORA_COMPILER_MSVC)
@ -327,6 +340,117 @@ inline auline T AuAtomicUtils<T>::And(T *in, T value)
#endif
#if defined(AURORA_COMPILER_CLANG)
#define ATOMIC_PREFIX_HAX(name) __c11_ ## name
#else
#define ATOMIC_PREFIX_HAX(name) __ ## name ## _explicit
#endif
template <class T>
inline auline T AuAtomicUtils<T>::Load(T *in)
{
#if defined(AURORA_COMPILER_MSVC) && (defined(AURORA_ARCH_X64) || defined(AURORA_ARCH_X86))
::_ReadWriteBarrier();
return *in;
#elif defined(AURORA_COMPILER_MSVC)
return *in;
#else
if constexpr (AuIsSame_v<AuUInt8, T>)
{
return ATOMIC_PREFIX_HAX(atomic_load)((atomic_uint_fast8_t *)in, __ATOMIC_ACQUIRE);
}
else if constexpr (AuIsSame_v<AuInt8, T>)
{
return ATOMIC_PREFIX_HAX(atomic_load)((atomic_int_fast8_t *)in, __ATOMIC_ACQUIRE);
}
else if constexpr (AuIsSame_v<AuUInt16, T>)
{
return ATOMIC_PREFIX_HAX(atomic_load)((atomic_uint_fast16_t *)in, __ATOMIC_ACQUIRE);
}
else if constexpr (AuIsSame_v<AuInt16, T>)
{
return ATOMIC_PREFIX_HAX(atomic_load)((atomic_int_fast16_t *)in, __ATOMIC_ACQUIRE);
}
else if constexpr (AuIsSame_v<AuUInt32, T>)
{
return ATOMIC_PREFIX_HAX(atomic_load)((atomic_uint_fast32_t *)in, __ATOMIC_ACQUIRE);
}
else if constexpr (AuIsSame_v<AuInt32, T>)
{
return ATOMIC_PREFIX_HAX(atomic_load)((atomic_int_fast32_t *)in, __ATOMIC_ACQUIRE);
}
else
{
static_assert(AuIsVoid_v<T>, "T");
}
#endif
}
template <class T>
inline auline void AuAtomicUtils<T>::Store(T *in, T val)
{
#if defined(AURORA_COMPILER_MSVC) && (defined(AURORA_ARCH_X64) || defined(AURORA_ARCH_X86))
*in = val;
::_ReadWriteBarrier();
#elif defined(AURORA_COMPILER_MSVC)
*in = val;
#else
if constexpr (AuIsSame_v<AuUInt8, T>)
{
ATOMIC_PREFIX_HAX(atomic_store)((atomic_uint_fast8_t *)in, val, __ATOMIC_RELEASE);
}
else if constexpr (AuIsSame_v<AuInt8, T>)
{
ATOMIC_PREFIX_HAX(atomic_store)((atomic_int_fast8_t *)in, val, __ATOMIC_RELEASE);
}
else if constexpr (AuIsSame_v<AuUInt16, T>)
{
ATOMIC_PREFIX_HAX(atomic_store)((atomic_uint_fast16_t *)in, val, __ATOMIC_RELEASE);
}
else if constexpr (AuIsSame_v<AuInt16, T>)
{
ATOMIC_PREFIX_HAX(atomic_store)((atomic_int_fast16_t *)in, val, __ATOMIC_RELEASE);
}
else if constexpr (AuIsSame_v<AuUInt32, T>)
{
ATOMIC_PREFIX_HAX(atomic_store)((atomic_uint_fast32_t *)in, val, __ATOMIC_RELEASE);
}
else if constexpr (AuIsSame_v<AuInt32, T>)
{
ATOMIC_PREFIX_HAX(atomic_store)((atomic_int_fast32_t *)in, val, __ATOMIC_RELEASE);
}
else
{
static_assert(AuIsVoid_v<T>, "T");
}
#endif
}
template <>
inline auline
void AuAtomicUtils<AuUInt8>::ClearU8Lock(AuUInt8 *in)
{
#if defined(AURORA_COMPILER_MSVC) && (defined(AURORA_ARCH_X64) || defined(AURORA_ARCH_X86))
*in = 0;
::_ReadWriteBarrier();
#elif defined(AURORA_COMPILER_MSVC)
InterlockedAndRelease((volatile LONG *)in, ~0xFF);
#else
ATOMIC_PREFIX_HAX(atomic_store)((atomic_uint_fast8_t *)in, 0, __ATOMIC_RELEASE);
#endif
}
template <>
inline auline
void AuAtomicUtils<AuUInt32>::ClearU8Lock(AuUInt32 *in)
{
#if defined(AU_CPU_ENDIAN_LITTLE)
AuAtomicUtils<AuUInt8>::ClearU8Lock((AuUInt8 *)in);
#else
AuAtomicUtils<AuUInt8>::ClearU8Lock(((AuUInt8 *)in) + 3);
#endif
}
template <class T>
inline auline bool AuAtomicUtils<T>::TestAndSet(T *in, const AuUInt8 offset)
{
@ -375,6 +499,27 @@ inline auline bool AuAtomicUtils<AuInt64>::TestAndSet(AuInt64 *in, const AuUInt8
#endif
template <class T>
auline
void AuAtomicStore(T *in, T value)
{
AuAtomicUtils<T>::Store(in, value);
}
template <class T>
auline
T AuAtomicLoad(T *in)
{
return AuAtomicUtils<T>::Load(in);
}
template <class T>
auline
void AuAtomicClearU8Lock(T *in)
{
AuAtomicUtils<T>::ClearU8Lock(in);
}
template <class T>
auline
T AuAtomicOrSetBit(T *in, AuUInt8 offset)
@ -446,6 +591,27 @@ bool AuAtomicTestAndSet(T *in, AuUInt8 offset)
return AuAtomicUtils<T>::TestAndSet(in, offset);
}
template <class T>
auline
void AuAtomicStore(volatile T *in, T value)
{
AuAtomicUtils<T>::Store((T *)in, value);
}
template <class T>
auline
T AuAtomicLoad(volatile T *in)
{
return AuAtomicUtils<T>::Load((T *)in);
}
template <class T>
auline
void AuAtomicClearU8Lock(volatile T *in)
{
AuAtomicUtils<T>::ClearU8Lock((T *)in);
}
template <class T>
auline
T AuAtomicOrSetBit(volatile T *in, AuUInt8 offset)