From 2e93ca7e322140d7da16b43d6263e2512d8c6f0c Mon Sep 17 00:00:00 2001 From: Jamie Reece Wilson Date: Wed, 23 Aug 2023 20:02:09 +0100 Subject: [PATCH] [+] AuAtomicStore [+] AuAtomicLoad [+] AuAtomicClearU8Lock --- Include/auROXTL/auAtomic.hpp | 166 +++++++++++++++++++++++++++++++++++ 1 file changed, 166 insertions(+) diff --git a/Include/auROXTL/auAtomic.hpp b/Include/auROXTL/auAtomic.hpp index eb99733..440472c 100644 --- a/Include/auROXTL/auAtomic.hpp +++ b/Include/auROXTL/auAtomic.hpp @@ -7,6 +7,10 @@ ***/ #pragma once +#if defined(AURORA_COMPILER_CLANG) + #include +#endif + template 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::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 +inline auline T AuAtomicUtils::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) + { + return ATOMIC_PREFIX_HAX(atomic_load)((atomic_uint_fast8_t *)in, __ATOMIC_ACQUIRE); + } + else if constexpr (AuIsSame_v) + { + return ATOMIC_PREFIX_HAX(atomic_load)((atomic_int_fast8_t *)in, __ATOMIC_ACQUIRE); + } + else if constexpr (AuIsSame_v) + { + return ATOMIC_PREFIX_HAX(atomic_load)((atomic_uint_fast16_t *)in, __ATOMIC_ACQUIRE); + } + else if constexpr (AuIsSame_v) + { + return ATOMIC_PREFIX_HAX(atomic_load)((atomic_int_fast16_t *)in, __ATOMIC_ACQUIRE); + } + else if constexpr (AuIsSame_v) + { + return ATOMIC_PREFIX_HAX(atomic_load)((atomic_uint_fast32_t *)in, __ATOMIC_ACQUIRE); + } + else if constexpr (AuIsSame_v) + { + return ATOMIC_PREFIX_HAX(atomic_load)((atomic_int_fast32_t *)in, __ATOMIC_ACQUIRE); + } + else + { + static_assert(AuIsVoid_v, "T"); + } + #endif +} + +template +inline auline void AuAtomicUtils::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) + { + ATOMIC_PREFIX_HAX(atomic_store)((atomic_uint_fast8_t *)in, val, __ATOMIC_RELEASE); + } + else if constexpr (AuIsSame_v) + { + ATOMIC_PREFIX_HAX(atomic_store)((atomic_int_fast8_t *)in, val, __ATOMIC_RELEASE); + } + else if constexpr (AuIsSame_v) + { + ATOMIC_PREFIX_HAX(atomic_store)((atomic_uint_fast16_t *)in, val, __ATOMIC_RELEASE); + } + else if constexpr (AuIsSame_v) + { + ATOMIC_PREFIX_HAX(atomic_store)((atomic_int_fast16_t *)in, val, __ATOMIC_RELEASE); + } + else if constexpr (AuIsSame_v) + { + ATOMIC_PREFIX_HAX(atomic_store)((atomic_uint_fast32_t *)in, val, __ATOMIC_RELEASE); + } + else if constexpr (AuIsSame_v) + { + ATOMIC_PREFIX_HAX(atomic_store)((atomic_int_fast32_t *)in, val, __ATOMIC_RELEASE); + } + else + { + static_assert(AuIsVoid_v, "T"); + } +#endif +} + +template <> +inline auline +void AuAtomicUtils::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::ClearU8Lock(AuUInt32 *in) +{ +#if defined(AU_CPU_ENDIAN_LITTLE) + AuAtomicUtils::ClearU8Lock((AuUInt8 *)in); +#else + AuAtomicUtils::ClearU8Lock(((AuUInt8 *)in) + 3); +#endif +} + template inline auline bool AuAtomicUtils::TestAndSet(T *in, const AuUInt8 offset) { @@ -375,6 +499,27 @@ inline auline bool AuAtomicUtils::TestAndSet(AuInt64 *in, const AuUInt8 #endif +template +auline +void AuAtomicStore(T *in, T value) +{ + AuAtomicUtils::Store(in, value); +} + +template +auline +T AuAtomicLoad(T *in) +{ + return AuAtomicUtils::Load(in); +} + +template +auline +void AuAtomicClearU8Lock(T *in) +{ + AuAtomicUtils::ClearU8Lock(in); +} + template auline T AuAtomicOrSetBit(T *in, AuUInt8 offset) @@ -446,6 +591,27 @@ bool AuAtomicTestAndSet(T *in, AuUInt8 offset) return AuAtomicUtils::TestAndSet(in, offset); } +template +auline +void AuAtomicStore(volatile T *in, T value) +{ + AuAtomicUtils::Store((T *)in, value); +} + +template +auline +T AuAtomicLoad(volatile T *in) +{ + return AuAtomicUtils::Load((T *)in); +} + +template +auline +void AuAtomicClearU8Lock(volatile T *in) +{ + AuAtomicUtils::ClearU8Lock((T *)in); +} + template auline T AuAtomicOrSetBit(volatile T *in, AuUInt8 offset)