19template <
typename T,
typename... Ts>
28template <std::
size_t N>
33 static void Load(
const void *ptr,
void *
ret)
35 *
static_cast<char *
>(
ret) = __iso_volatile_load8(
static_cast<const char *
>(ptr));
37 static void Store(
void *ptr,
void *val)
39 __iso_volatile_store8(
static_cast<char *
>(ptr), *
static_cast<char *
>(val));
41 static void Add(
void *ptr,
const void *val)
43 _InterlockedExchangeAdd8(
static_cast<char *
>(ptr), *
static_cast<const char *
>(val));
45 static bool CompareExchange(
void *ptr,
void *expected,
const void *desired)
48 const char expectedVal = *
static_cast<char *
>(expected);
49 const char desiredVal = *
static_cast<const char *
>(desired);
50 const char previous = _InterlockedCompareExchange8(
static_cast<char *
>(ptr), desiredVal, expectedVal);
51 if (previous == expectedVal) {
54 *
static_cast<char *
>(expected) = previous;
61 static void Load(
const void *ptr,
void *
ret)
63 *
static_cast<short *
>(
ret) = __iso_volatile_load16(
static_cast<const short *
>(ptr));
65 static void Store(
void *ptr,
void *val)
67 __iso_volatile_store16(
static_cast<short *
>(ptr), *
static_cast<short *
>(val));
69 static void Add(
void *ptr,
const void *val)
71 _InterlockedExchangeAdd16(
static_cast<short *
>(ptr), *
static_cast<const short *
>(val));
73 static bool CompareExchange(
void *ptr,
void *expected,
const void *desired)
76 const short expectedVal = *
static_cast<short *
>(expected);
77 const short desiredVal = *
static_cast<const short *
>(desired);
78 const short previous = _InterlockedCompareExchange16(
static_cast<short *
>(ptr), desiredVal, expectedVal);
79 if (previous == expectedVal) {
82 *
static_cast<short *
>(expected) = previous;
89 static void Load(
const void *ptr,
void *
ret)
91 *
static_cast<int *
>(
ret) = __iso_volatile_load32(
static_cast<const int *
>(ptr));
93 static void Store(
void *ptr,
void *val)
95 __iso_volatile_store32(
static_cast<int *
>(ptr), *
static_cast<int *
>(val));
97 static void Add(
void *ptr,
const void *val)
99 _InterlockedExchangeAdd(
static_cast<long *
>(ptr), *
static_cast<const long *
>(val));
101 static bool CompareExchange(
void *ptr,
void *expected,
const void *desired)
104 const long expectedVal = *
static_cast<long *
>(expected);
105 const long desiredVal = *
static_cast<const long *
>(desired);
106 const long previous = _InterlockedCompareExchange(
static_cast<long *
>(ptr), desiredVal, expectedVal);
107 if (previous == expectedVal) {
110 *
static_cast<long *
>(expected) = previous;
117 static void Load(
const void *ptr,
void *
ret)
119 *
static_cast<__int64 *
>(
ret) = __iso_volatile_load64(
static_cast<const __int64 *
>(ptr));
121 static void Store(
void *ptr,
void *val)
123 __iso_volatile_store64(
static_cast<__int64 *
>(ptr), *
static_cast<__int64 *
>(val));
125 static void Add(
void *ptr,
const void *val);
126 static bool CompareExchange(
void *ptr,
void *expected,
const void *desired)
129 const __int64 expectedVal = *
static_cast<__int64 *
>(expected);
130 const __int64 desiredVal = *
static_cast<const __int64 *
>(desired);
131 const __int64 previous = _InterlockedCompareExchange64(
static_cast<__int64 *
>(ptr), desiredVal, expectedVal);
132 if (previous == expectedVal) {
135 *
static_cast<__int64 *
>(expected) = previous;
146 __atomic_load(ptr,
ret, __ATOMIC_RELAXED);
148 MSVC::AtomicOps<
sizeof(T)>::Load(ptr,
ret);
156 __atomic_store(ptr, val, __ATOMIC_RELEASE);
159 std::atomic_thread_fence(std::memory_order_release);
160 MSVC::AtomicOps<
sizeof(T)>::Store(ptr, val);
168 return __atomic_compare_exchange(ptr, expected, desired,
false, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
170 return MSVC::AtomicOps<
sizeof(T)>::CompareExchange(ptr, expected, desired);
178 return __atomic_compare_exchange(ptr, expected, desired,
false, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED);
180 bool success = MSVC::AtomicOps<
sizeof(T)>::CompareExchange(ptr, expected, desired);
182 std::atomic_thread_fence(std::memory_order_acquire);
192 T desired = expected + val;
195 desired = expected + val;
201inline void AtomicOps<8>::Add(
void *ptr,
const void *val)
204 _InterlockedExchangeAdd64(
static_cast<__int64 *
>(ptr), *
static_cast<const __int64 *
>(val));
206 AtomicAddCompareExchangeLoop(
static_cast<__int64 *
>(ptr), *
static_cast<const __int64 *
>(val));
213std::enable_if_t<std::is_integral_v<T>>
AtomicAdd(T *ptr, T val)
216 __atomic_fetch_add(ptr, val, __ATOMIC_RELAXED);
218 MSVC::AtomicOps<
sizeof(T)>
::Add(ptr, &val);
223std::enable_if_t<std::is_floating_point_v<T>>
AtomicAdd(T *ptr, T val)
236std::enable_if_t<std::is_arithmetic_v<T>>
AtomicInc(T *ptr)
241template <
typename T,
typename U>
242auto AtomicAdd(T *ptr,
const U &add) ->
decltype(ptr->AtomicAdd(add))
244 return ptr->AtomicAdd(add);
250 return ptr->AtomicInc();
std::enable_if_t< std::is_arithmetic_v< T > > AtomicInc(T *ptr)
void AtomicLoad(const T *ptr, T *ret)
void AtomicStoreRelease(T *ptr, T *val)
bool AtomicCompareExchange(T *ptr, T *expected, T *desired)
bool AtomicCompareExchangeAcquire(T *ptr, T *expected, T *desired)
void AtomicAddCompareExchangeLoop(T *ptr, T val)
std::enable_if_t< std::is_integral_v< T > > AtomicAdd(T *ptr, T val)
Namespace for ROOT features in testing.
TMatrixT< Element > & Add(TMatrixT< Element > &target, Element scalar, const TMatrixT< Element > &source)
Modify addition: target += scalar * source.