20namespace Experimental {
23template <
typename T,
typename... Ts>
30template <
typename... Ts, std::size_t... I,
typename A>
31std::tuple<
const Ts &...,
const A &>
34 return std::tuple<
const Ts &...,
const A &>(std::get<I>(t)...,
a);
37template <
typename... Ts,
typename A>
38std::tuple<
const Ts &...,
const A &>
AppendReference(
const std::tuple<Ts...> &t,
const A &
a)
45template <std::
size_t N>
50 static void Load(
const void *ptr,
void *ret)
52 *
static_cast<char *
>(ret) = __iso_volatile_load8(
static_cast<const char *
>(ptr));
54 static void Store(
void *ptr,
void *val)
56 __iso_volatile_store8(
static_cast<char *
>(ptr), *
static_cast<char *
>(val));
58 static void Add(
void *ptr,
const void *val)
60 _InterlockedExchangeAdd8(
static_cast<char *
>(ptr), *
static_cast<const char *
>(val));
62 static bool CompareExchange(
void *ptr,
void *expected,
const void *desired)
65 const char expectedVal = *
static_cast<char *
>(expected);
66 const char desiredVal = *
static_cast<const char *
>(desired);
67 const char previous = _InterlockedCompareExchange8(
static_cast<char *
>(ptr), desiredVal, expectedVal);
68 if (previous == expectedVal) {
71 *
static_cast<char *
>(expected) = previous;
78 static void Load(
const void *ptr,
void *ret)
80 *
static_cast<short *
>(ret) = __iso_volatile_load16(
static_cast<const short *
>(ptr));
82 static void Store(
void *ptr,
void *val)
84 __iso_volatile_store16(
static_cast<short *
>(ptr), *
static_cast<short *
>(val));
86 static void Add(
void *ptr,
const void *val)
88 _InterlockedExchangeAdd16(
static_cast<short *
>(ptr), *
static_cast<const short *
>(val));
90 static bool CompareExchange(
void *ptr,
void *expected,
const void *desired)
93 const short expectedVal = *
static_cast<short *
>(expected);
94 const short desiredVal = *
static_cast<const short *
>(desired);
95 const short previous = _InterlockedCompareExchange16(
static_cast<short *
>(ptr), desiredVal, expectedVal);
96 if (previous == expectedVal) {
99 *
static_cast<short *
>(expected) = previous;
106 static void Load(
const void *ptr,
void *ret)
108 *
static_cast<int *
>(ret) = __iso_volatile_load32(
static_cast<const int *
>(ptr));
110 static void Store(
void *ptr,
void *val)
112 __iso_volatile_store32(
static_cast<int *
>(ptr), *
static_cast<int *
>(val));
114 static void Add(
void *ptr,
const void *val)
116 _InterlockedExchangeAdd(
static_cast<long *
>(ptr), *
static_cast<const long *
>(val));
118 static bool CompareExchange(
void *ptr,
void *expected,
const void *desired)
121 const long expectedVal = *
static_cast<long *
>(expected);
122 const long desiredVal = *
static_cast<const long *
>(desired);
123 const long previous = _InterlockedCompareExchange(
static_cast<long *
>(ptr), desiredVal, expectedVal);
124 if (previous == expectedVal) {
127 *
static_cast<long *
>(expected) = previous;
134 static void Load(
const void *ptr,
void *ret)
136 *
static_cast<__int64 *
>(ret) = __iso_volatile_load64(
static_cast<const __int64 *
>(ptr));
138 static void Store(
void *ptr,
void *val)
140 __iso_volatile_store64(
static_cast<__int64 *
>(ptr), *
static_cast<__int64 *
>(val));
142 static void Add(
void *ptr,
const void *val);
143 static bool CompareExchange(
void *ptr,
void *expected,
const void *desired)
146 const __int64 expectedVal = *
static_cast<__int64 *
>(expected);
147 const __int64 desiredVal = *
static_cast<const __int64 *
>(desired);
148 const __int64 previous = _InterlockedCompareExchange64(
static_cast<__int64 *
>(ptr), desiredVal, expectedVal);
149 if (previous == expectedVal) {
152 *
static_cast<__int64 *
>(expected) = previous;
160std::enable_if_t<std::is_arithmetic_v<T>>
AtomicLoad(
const T *ptr, T *ret)
163 __atomic_load(ptr, ret, __ATOMIC_RELAXED);
165 MSVC::AtomicOps<
sizeof(T)>::Load(ptr, ret);
170auto AtomicLoad(
const T *ptr, T *ret) ->
decltype(ptr->AtomicLoad(ret))
172 return ptr->AtomicLoad(ret);
179 __atomic_load(ptr, ret, __ATOMIC_ACQUIRE);
181 MSVC::AtomicOps<
sizeof(T)>::Load(ptr, ret);
183 std::atomic_thread_fence(std::memory_order_acquire);
191 __atomic_store(ptr, val, __ATOMIC_RELEASE);
194 std::atomic_thread_fence(std::memory_order_release);
195 MSVC::AtomicOps<
sizeof(T)>::Store(ptr, val);
203 return __atomic_compare_exchange(ptr, expected, desired,
false, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
205 return MSVC::AtomicOps<
sizeof(T)>::CompareExchange(ptr, expected, desired);
213 return __atomic_compare_exchange(ptr, expected, desired,
false, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED);
215 bool success = MSVC::AtomicOps<
sizeof(T)>::CompareExchange(ptr, expected, desired);
217 std::atomic_thread_fence(std::memory_order_acquire);
226 return __atomic_compare_exchange(ptr, expected, desired,
false, __ATOMIC_RELEASE, __ATOMIC_RELAXED);
229 std::atomic_thread_fence(std::memory_order_release);
230 return MSVC::AtomicOps<
sizeof(T)>::CompareExchange(ptr, expected, desired);
239 T desired = expected + val;
242 desired = expected + val;
251 T desired = expected + val;
254 desired = expected + val;
260inline void AtomicOps<8>::Add(
void *ptr,
const void *val)
263 _InterlockedExchangeAdd64(
static_cast<__int64 *
>(ptr), *
static_cast<const __int64 *
>(val));
265 AtomicAddCompareExchangeLoop(
static_cast<__int64 *
>(ptr), *
static_cast<const __int64 *
>(val));
272std::enable_if_t<std::is_integral_v<T>>
AtomicAdd(T *ptr, T val)
275 __atomic_fetch_add(ptr, val, __ATOMIC_RELAXED);
277 MSVC::AtomicOps<
sizeof(T)>
::Add(ptr, &val);
282std::enable_if_t<std::is_floating_point_v<T>>
AtomicAdd(T *ptr, T val)
291 __atomic_fetch_add(ptr, val, __ATOMIC_RELEASE);
294 std::atomic_thread_fence(std::memory_order_release);
295 MSVC::AtomicOps<
sizeof(T)>
::Add(ptr, &val);
318template <
typename T,
typename U>
319auto AtomicAdd(T *ptr,
const U &add) ->
decltype(ptr->AtomicAdd(add))
321 return ptr->AtomicAdd(add);
324template <
typename T,
typename U>
327 return ptr->AtomicAddRelease(add);
333 return ptr->AtomicIncRelease();
std::enable_if_t< std::is_arithmetic_v< T > > AtomicIncRelease(T *ptr)
std::enable_if_t< std::is_arithmetic_v< T >, bool > AtomicCompareExchangeRelease(T *ptr, T *expected, T *desired)
std::enable_if_t< std::is_arithmetic_v< T >, bool > AtomicCompareExchange(T *ptr, T *expected, T *desired)
std::enable_if_t< std::is_arithmetic_v< T > > AtomicAddCompareExchangeLoop(T *ptr, T val)
std::enable_if_t< std::is_arithmetic_v< T > > AtomicAddCompareExchangeReleaseLoop(T *ptr, T val)
std::tuple< const Ts &..., const A & > AppendReference(const std::tuple< Ts... > &t, const A &a)
std::enable_if_t< std::is_arithmetic_v< T >, bool > AtomicCompareExchangeAcquire(T *ptr, T *expected, T *desired)
std::enable_if_t< std::is_arithmetic_v< T > > AtomicLoadAcquire(const T *ptr, T *ret)
std::enable_if_t< std::is_arithmetic_v< T > > AtomicStoreRelease(T *ptr, T *val)
std::enable_if_t< std::is_arithmetic_v< T > > AtomicLoad(const T *ptr, T *ret)
std::tuple< const Ts &..., const A & > AppendReferenceImpl(const std::tuple< Ts... > &t, std::index_sequence< I... >, const A &a)
std::enable_if_t< std::is_integral_v< T > > AtomicAdd(T *ptr, T val)
std::enable_if_t< std::is_integral_v< T > > AtomicAddRelease(T *ptr, T val)
TMatrixT< Element > & Add(TMatrixT< Element > &target, Element scalar, const TMatrixT< Element > &source)
Modify addition: target += scalar * source.