NexusForce 1.0.0
A rigorously engineered full-stack C++ backend library.
载入中...
搜索中...
未找到
atomic_base.hpp
浏览该文件的文档.
1#ifndef NEFORCE_CORE_ASYNC_ATOMIC_BASE_HPP__
2#define NEFORCE_CORE_ASYNC_ATOMIC_BASE_HPP__
3
10
14#ifdef NEFORCE_COMPILER_MSVC
15# include <intrin.h>
16#endif
17#ifdef NEFORCE_COMPILER_CLANG_CL
18# include <intrin0.inl.h>
19#endif
20NEFORCE_BEGIN_NAMESPACE__
21
27
33
34#ifdef NEFORCE_COMPILER_MSVC
35# pragma warning(push)
36# pragma warning(disable : 6001)
37#endif
38
45NEFORCE_ALWAYS_INLINE_INLINE void atomic_thread_fence(const memory_order mo) noexcept {
46#ifdef NEFORCE_COMPILER_MSVC
47 if (mo == memory_order_relaxed) {
48 return;
49 }
50# ifdef NEFORCE_ARCH_ARM
51 if (mo == memory_order_acquire || mo == memory_order_consume) {
52 ::__dmb(::_ARM64_BARRIER_ISHLD);
53 } else {
54 ::__dmb(::_ARM64_BARRIER_ISH);
55 }
56# else
57 ::_ReadWriteBarrier();
58 if (mo == memory_order_seq_cst) {
59 // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
60 volatile long guard; // The value of guard is not important, we only use the fence in _InterlockedIncrement
61
62 // According to the MSVC library comments, _mm_mfence is slower on some CPUs.
63 // The memory fence in interlocked operations have some exceptions, but it`s enough for atomic_thread_fence.
64 ::_InterlockedIncrement(&guard);
65 ::_ReadWriteBarrier();
66 }
67# endif
68#else
69 __atomic_thread_fence(static_cast<int32_t>(mo));
70#endif
71}
72
73#ifdef NEFORCE_COMPILER_MSVC
74# pragma warning(pop)
75#endif
76
83NEFORCE_ALWAYS_INLINE_INLINE void atomic_signal_fence(const memory_order mo) noexcept {
84#ifdef NEFORCE_COMPILER_MSVC
85 if (mo != memory_order_relaxed) {
86 ::_ReadWriteBarrier();
87 }
88#else
89 __atomic_signal_fence(static_cast<int32_t>(mo));
90#endif
91}
92
93
95NEFORCE_BEGIN_INNER__
96
97template <size_t Size>
98struct atomic_load_verifier {
99 template <typename T>
100 static void verify(const volatile T* /*unused*/, remove_volatile_t<T>& /*unused*/) noexcept {}
101};
102
103#ifdef NEFORCE_COMPILER_MSVC
104
105template <size_t Size>
106struct interlocked_exchange_impl;
107
108template <>
109struct interlocked_exchange_impl<1> {
110 template <typename T>
111 static T call(volatile T* target, T value) {
112 return static_cast<T>(
113 ::_InterlockedExchange8(reinterpret_cast<volatile char*>(target), static_cast<char>(value)));
114 }
115};
116template <>
117struct interlocked_exchange_impl<2> {
118 template <typename T>
119 static T call(volatile T* target, T value) {
120 return static_cast<T>(
121 ::_InterlockedExchange16(reinterpret_cast<volatile short*>(target), static_cast<short>(value)));
122 }
123};
124template <>
125struct interlocked_exchange_impl<4> {
126 template <typename T>
127 static T call(volatile T* target, T value) {
128 return static_cast<T>(
129 ::_InterlockedExchange(reinterpret_cast<volatile long*>(target), static_cast<long>(value)));
130 }
131};
132template <>
133struct interlocked_exchange_impl<8> {
134 template <typename T>
135 static T call(volatile T* target, T value) {
136# if defined(NEFORCE_ARCH_BITS_64) || defined(NEFORCE_COMPILER_CLANG_CL)
137 return static_cast<T>(
138 ::_InterlockedExchange64(reinterpret_cast<volatile long long*>(target), static_cast<long long>(value)));
139# else
140 return static_cast<T>(
141 ::_interlockedexchange64(reinterpret_cast<volatile long long*>(target), static_cast<long long>(value)));
142# endif
143 }
144};
145
146template <size_t Size>
147struct interlocked_compare_exchange_impl;
148
149template <>
150struct interlocked_compare_exchange_impl<1> {
151 template <typename T>
152 static bool call(volatile T* target, T* expected, T desired) {
153 const char old =
154 ::_InterlockedCompareExchange8(reinterpret_cast<volatile char*>(target),
155 *reinterpret_cast<char*>(&desired), *reinterpret_cast<char*>(expected));
156 if (old == *reinterpret_cast<char*>(expected)) {
157 return true;
158 }
159 *reinterpret_cast<char*>(expected) = old;
160 return false;
161 }
162};
163template <>
164struct interlocked_compare_exchange_impl<2> {
165 template <typename T>
166 static bool call(volatile T* target, T* expected, T desired) {
167 const short old = ::_InterlockedCompareExchange16(reinterpret_cast<volatile short*>(target),
168 *reinterpret_cast<short*>(&desired),
169 *reinterpret_cast<short*>(expected));
170 if (old == *reinterpret_cast<short*>(expected)) {
171 return true;
172 }
173 *reinterpret_cast<short*>(expected) = old;
174 return false;
175 }
176};
177template <>
178struct interlocked_compare_exchange_impl<4> {
179 template <typename T>
180 static bool call(volatile T* target, T* expected, T desired) {
181 const long old =
182 ::_InterlockedCompareExchange(reinterpret_cast<volatile long*>(target),
183 *reinterpret_cast<long*>(&desired), *reinterpret_cast<long*>(expected));
184 if (old == *reinterpret_cast<long*>(expected)) {
185 return true;
186 }
187 *reinterpret_cast<long*>(expected) = old;
188 return false;
189 }
190};
191template <>
192struct interlocked_compare_exchange_impl<8> {
193 template <typename T>
194 static bool call(volatile T* target, T* expected, T desired) {
195 const long long old = ::_InterlockedCompareExchange64(reinterpret_cast<volatile long long*>(target),
196 *reinterpret_cast<long long*>(&desired),
197 *reinterpret_cast<long long*>(expected));
198 if (old == *reinterpret_cast<long long*>(expected)) {
199 return true;
200 }
201 *reinterpret_cast<long long*>(expected) = old;
202 return false;
203 }
204};
205template <>
206struct interlocked_compare_exchange_impl<16> {
207# if !(defined(NEFORCE_ARCH_BITS_64) || defined(NEFORCE_ARCH_AARCH64))
208private:
209 struct futex_lock_128 {
210 alignas(64) volatile platform_wait_t state_ = 0;
211
212 static futex_lock_128& for_addr(const void* addr) noexcept {
213 constexpr uintptr_t pool_size = 64;
214 static futex_lock_128 pool[pool_size];
215 return pool[(reinterpret_cast<uintptr_t>(addr) >> 4) % pool_size];
216 }
217
218 void lock(const void* /*addr*/) noexcept {
219 for (;;) {
220 if (::_InterlockedCompareExchange(&state_, 1, 0) == 0) {
221 return;
222 }
223 _NEFORCE atomic_wait_address_v(const_cast<platform_wait_t*>(&state_), static_cast<platform_wait_t>(1),
224 [this] { return ::_InterlockedExchangeAdd(&state_, 0); });
225 }
226 }
227
228 void unlock(const void* /*addr*/) noexcept {
229 ::_InterlockedExchange(&state_, 0);
230 _NEFORCE atomic_notify_address(const_cast<platform_wait_t*>(&state_), false);
231 }
232 };
233# endif
234
235 template <typename T>
236 static bool call(volatile T* target, T* expected, T desired) {
237 alignas(16) long long exp_arr[2];
238 alignas(16) long long des_arr[2];
239 _NEFORCE memory_copy(exp_arr, expected, 16);
240 _NEFORCE memory_copy(des_arr, &desired, 16);
241 bool result = false;
242
243# if defined(NEFORCE_ARCH_BITS_64) || defined(NEFORCE_ARCH_AARCH64)
244 result = ::_InterlockedCompareExchange128(reinterpret_cast<volatile long long*>(target), des_arr[1], des_arr[0],
245 exp_arr) != 0;
246# else
247 auto& flock = futex_lock_128::for_addr(target);
248 flock.lock(target);
249 if (_NEFORCE memory_compare(const_cast<T*>(target), exp_arr, 16) == 0) {
250 _NEFORCE memory_copy(const_cast<T*>(target), des_arr, 16);
251 flock.unlock(target);
252 result = true;
253 } else {
254 _NEFORCE memory_copy(exp_arr, const_cast<T*>(target), 16);
255 flock.unlock(target);
256 result = false;
257 }
258# endif
259
260 if (!result) {
261 _NEFORCE memory_copy(expected, exp_arr, 16);
262 }
263 return result;
264 }
265};
266
267template <size_t Size>
268struct interlocked_fetch_add_impl;
269
270template <>
271struct interlocked_fetch_add_impl<1> {
272 template <typename T>
273 static T call(volatile T* target, T value) {
274 return static_cast<T>(
275 ::_InterlockedExchangeAdd8(reinterpret_cast<volatile char*>(target), static_cast<char>(value)));
276 }
277};
278template <>
279struct interlocked_fetch_add_impl<2> {
280 template <typename T>
281 static T call(volatile T* target, T value) {
282 return static_cast<T>(
283 ::_InterlockedExchangeAdd16(reinterpret_cast<volatile short*>(target), static_cast<short>(value)));
284 }
285};
286template <>
287struct interlocked_fetch_add_impl<4> {
288 template <typename T>
289 static T call(volatile T* target, T value) {
290 return static_cast<T>(
291 ::_InterlockedExchangeAdd(reinterpret_cast<volatile long*>(target), static_cast<long>(value)));
292 }
293};
294template <>
295struct interlocked_fetch_add_impl<8> {
296 template <typename T>
297 static T call(volatile T* target, T value) {
298# if defined(NEFORCE_ARCH_BITS_64) || defined(NEFORCE_COMPILER_CLANG_CL)
299 return static_cast<T>(::_InterlockedExchangeAdd64(reinterpret_cast<volatile long long*>(target),
300 static_cast<long long>(value)));
301# else
302 return static_cast<T>(::_interlockedexchangeadd64(reinterpret_cast<volatile long long*>(target),
303 static_cast<long long>(value)));
304# endif
305 }
306};
307
308template <size_t Size>
309struct interlocked_fetch_and_impl;
310
311template <>
312struct interlocked_fetch_and_impl<1> {
313 template <typename T>
314 static T call(volatile T* target, T value) {
315 return static_cast<T>(::_InterlockedAnd8(reinterpret_cast<volatile char*>(target), static_cast<char>(value)));
316 }
317};
318template <>
319struct interlocked_fetch_and_impl<2> {
320 template <typename T>
321 static T call(volatile T* target, T value) {
322 return static_cast<T>(
323 ::_InterlockedAnd16(reinterpret_cast<volatile short*>(target), static_cast<short>(value)));
324 }
325};
326template <>
327struct interlocked_fetch_and_impl<4> {
328 template <typename T>
329 static T call(volatile T* target, T value) {
330 return static_cast<T>(::_InterlockedAnd(reinterpret_cast<volatile long*>(target), static_cast<long>(value)));
331 }
332};
333template <>
334struct interlocked_fetch_and_impl<8> {
335 template <typename T>
336 static T call(volatile T* target, T value) {
337# if defined(NEFORCE_ARCH_BITS_64) || defined(NEFORCE_COMPILER_CLANG_CL)
338 return static_cast<T>(
339 ::_InterlockedAnd64(reinterpret_cast<volatile long long*>(target), static_cast<long long>(value)));
340# else
341 return static_cast<T>(
342 ::_interlockedadd64(reinterpret_cast<volatile long long*>(target), static_cast<long long>(value)));
343# endif
344 }
345};
346
347template <size_t Size>
348struct interlocked_fetch_or_impl;
349
350template <>
351struct interlocked_fetch_or_impl<1> {
352 template <typename T>
353 static T call(volatile T* target, T value) {
354 return static_cast<T>(::_InterlockedOr8(reinterpret_cast<volatile char*>(target), static_cast<char>(value)));
355 }
356};
357template <>
358struct interlocked_fetch_or_impl<2> {
359 template <typename T>
360 static T call(volatile T* target, T value) {
361 return static_cast<T>(::_InterlockedOr16(reinterpret_cast<volatile short*>(target), static_cast<short>(value)));
362 }
363};
364template <>
365struct interlocked_fetch_or_impl<4> {
366 template <typename T>
367 static T call(volatile T* target, T value) {
368 return static_cast<T>(::_InterlockedOr(reinterpret_cast<volatile long*>(target), static_cast<long>(value)));
369 }
370};
371template <>
372struct interlocked_fetch_or_impl<8> {
373 template <typename T>
374 static T call(volatile T* target, T value) {
375# if defined(NEFORCE_ARCH_BITS_64) || defined(NEFORCE_COMPILER_CLANG_CL)
376 return static_cast<T>(
377 ::_InterlockedOr64(reinterpret_cast<volatile long long*>(target), static_cast<long long>(value)));
378# else
379 return static_cast<T>(
380 ::_interlockedor64(reinterpret_cast<volatile long long*>(target), static_cast<long long>(value)));
381# endif
382 }
383};
384
385template <size_t Size>
386struct interlocked_fetch_xor_impl;
387
388template <>
389struct interlocked_fetch_xor_impl<1> {
390 template <typename T>
391 static T call(volatile T* target, T value) {
392 return static_cast<T>(::_InterlockedXor8(reinterpret_cast<volatile char*>(target), static_cast<char>(value)));
393 }
394};
395template <>
396struct interlocked_fetch_xor_impl<2> {
397 template <typename T>
398 static T call(volatile T* target, T value) {
399 return static_cast<T>(
400 ::_InterlockedXor16(reinterpret_cast<volatile short*>(target), static_cast<short>(value)));
401 }
402};
403template <>
404struct interlocked_fetch_xor_impl<4> {
405 template <typename T>
406 static T call(volatile T* target, T value) {
407 return static_cast<T>(::_InterlockedXor(reinterpret_cast<volatile long*>(target), static_cast<long>(value)));
408 }
409};
410template <>
411struct interlocked_fetch_xor_impl<8> {
412 template <typename T>
413 static T call(volatile T* target, T value) {
414# if defined(NEFORCE_ARCH_BITS_64) || defined(NEFORCE_COMPILER_CLANG_CL)
415 return static_cast<T>(
416 ::_InterlockedXor64(reinterpret_cast<volatile long long*>(target), static_cast<long long>(value)));
417# else
418 return static_cast<T>(
419 ::_interlockedxor64(reinterpret_cast<volatile long long*>(target), static_cast<long long>(value)));
420# endif
421 }
422};
423
424template <size_t Size>
425struct atomic_is_always_lock_free_impl {
426 static constexpr bool value = false;
427};
428template <>
429struct atomic_is_always_lock_free_impl<1> {
430 static constexpr bool value = true;
431};
432template <>
433struct atomic_is_always_lock_free_impl<2> {
434 static constexpr bool value = true;
435};
436template <>
437struct atomic_is_always_lock_free_impl<4> {
438 static constexpr bool value = true;
439};
440template <>
441struct atomic_is_always_lock_free_impl<8> {
442 static constexpr bool value = true;
443};
444template <>
445struct atomic_is_always_lock_free_impl<16> {
446# if defined(NEFORCE_ARCH_X86_64) || defined(NEFORCE_ARCH_AARCH64)
447 static constexpr bool value = true;
448# else
449 static constexpr bool value = false;
450# endif
451};
452
453template <>
454struct atomic_load_verifier<16> {
455 template <typename T>
456 static void verify(const volatile T* target, remove_volatile_t<T>& result) noexcept {
457 _NEFORCE memory_copy(&result, const_cast<const T*>(target), 16);
458 auto* mutable_target = const_cast<volatile T*>(target);
459 interlocked_compare_exchange_impl<16>::call(mutable_target, &result, result);
460 }
461};
462#endif
463
464NEFORCE_END_INNER__
466
467
472template <typename T>
474
475
484template <typename T>
485NEFORCE_ALWAYS_INLINE_INLINE void atomic_store(volatile T* ptr, remove_volatile_t<T> value,
486 const memory_order mo) noexcept {
487 static_assert(is_integral_v<T>, "T must be integral type");
488#ifdef NEFORCE_COMPILER_GNUC
489 __atomic_store_n(ptr, value, static_cast<int32_t>(mo));
490#else
491 inner::interlocked_exchange_impl<sizeof(T)>::call(ptr, value);
492 if (mo == memory_order_seq_cst || mo == memory_order_release) {
493 ::_ReadWriteBarrier();
494 }
495#endif
496}
497
506template <typename T>
507NEFORCE_ALWAYS_INLINE_INLINE remove_volatile_t<T> atomic_load(const volatile T* ptr, const memory_order mo) noexcept {
508 static_assert(is_integral_v<T>, "T must be integral type");
509#ifdef NEFORCE_COMPILER_GNUC
510 return __atomic_load_n(ptr, static_cast<int32_t>(mo));
511#else
512 remove_volatile_t<T> result = *ptr;
513 if (mo == memory_order_seq_cst || mo == memory_order_acquire) {
514 ::_ReadWriteBarrier();
515 }
516 return result;
517#endif
518}
519
529template <typename T>
530NEFORCE_ALWAYS_INLINE_INLINE remove_volatile_t<T> atomic_exchange(volatile T* ptr, remove_volatile_t<T> value,
531 const memory_order mo) noexcept {
532 static_assert(is_integral_v<T>, "T must be integral type");
533#ifdef NEFORCE_COMPILER_GNUC
534 return __atomic_exchange_n(ptr, value, static_cast<int32_t>(mo));
535#else
536 remove_volatile_t<T> old = inner::interlocked_exchange_impl<sizeof(T)>::call(ptr, value);
537 if (mo == memory_order_seq_cst) {
538 ::_ReadWriteBarrier();
539 }
540 return old;
541#endif
542}
543
556template <typename T>
557NEFORCE_ALWAYS_INLINE_INLINE bool atomic_cmpexch_weak(volatile T* ptr, remove_volatile_t<T>* expected,
558 remove_volatile_t<T> desired, const memory_order success,
559 const memory_order failure) noexcept {
560 static_assert(is_integral_v<T>, "T must be integral type");
562#ifdef NEFORCE_COMPILER_GNUC
563 return __atomic_compare_exchange_n(ptr, expected, desired, true, static_cast<int32_t>(success),
564 static_cast<int32_t>(failure));
565#else
566# if defined(NEFORCE_ARCH_X86) || defined(NEFORCE_ARCH_AARCH64)
567 const bool result = inner::interlocked_compare_exchange_impl<sizeof(T)>::call(ptr, expected, desired);
569 ::_ReadWriteBarrier();
570 }
571 return result;
572# else
573 remove_volatile_t<T> old_val = *expected;
575 bool success_flag;
576# if defined(NEFORCE_ARCH_ARM)
577 NEFORCE_IF_CONSTEXPR(sizeof(T) == 1) {
578 asm volatile("ldrexb %[loaded], [%[ptr]]\n\t"
579 "cmp %[loaded], %[old_val]\n\t"
580 "bne 1f\n\t"
581 "strexb %w[success], %w[desired], [%[ptr]]\n\t"
582 "1:"
583 : [loaded] "=&r"(loaded), [success] "=&r"(success_flag)
584 : [ptr] "r"(ptr), [old_val] "r"(old_val), [desired] "r"(desired)
585 : "cc", "memory");
586 }
587 else NEFORCE_IF_CONSTEXPR(sizeof(T) == 2) {
588 asm volatile("ldrexh %[loaded], [%[ptr]]\n\t"
589 "cmp %[loaded], %[old_val]\n\t"
590 "bne 1f\n\t"
591 "strexh %w[success], %w[desired], [%[ptr]]\n\t"
592 "1:"
593 : [loaded] "=&r"(loaded), [success] "=&r"(success_flag)
594 : [ptr] "r"(ptr), [old_val] "r"(old_val), [desired] "r"(desired)
595 : "cc", "memory");
596 }
597 else NEFORCE_IF_CONSTEXPR(sizeof(T) == 4) {
598 asm volatile("ldrex %[loaded], [%[ptr]]\n\t"
599 "cmp %[loaded], %[old_val]\n\t"
600 "bne 1f\n\t"
601 "strex %w[success], %w[desired], [%[ptr]]\n\t"
602 "1:"
603 : [loaded] "=&r"(loaded), [success] "=&r"(success_flag)
604 : [ptr] "r"(ptr), [old_val] "r"(old_val), [desired] "r"(desired)
605 : "cc", "memory");
606 }
607 else NEFORCE_IF_CONSTEXPR(sizeof(T) == 8) {
608 uint32_t loaded_lo, loaded_hi;
609 uint32_t old_lo = static_cast<uint32_t>(old_val);
610 uint32_t old_hi = static_cast<uint32_t>(static_cast<uint64_t>(old_val) >> 32);
611 uint32_t des_lo = static_cast<uint32_t>(static_cast<uint64_t>(desired));
612 uint32_t des_hi = static_cast<uint32_t>(static_cast<uint64_t>(desired) >> 32);
613 uint32_t tmp_success = 0;
614 asm volatile(
615 "ldrexd %[lo], %[hi], [%[ptr]]\n\t"
616 "cmp %[lo], %[old_lo]\n\t"
617 "cmpeq %[hi], %[old_hi]\n\t"
618 "bne 1f\n\t"
619 "strexd %[success], %[des_lo], %[des_hi], [%[ptr]]\n\t"
620 "1:"
621 : [lo] "=&r"(loaded_lo), [hi] "=&r"(loaded_hi), [success] "=&r"(tmp_success)
622 : [ptr] "r"(ptr), [old_lo] "r"(old_lo), [old_hi] "r"(old_hi), [des_lo] "r"(des_lo), [des_hi] "r"(des_hi)
623 : "cc", "memory");
624 loaded = static_cast<T>(static_cast<uint64_t>(loaded_lo) | (static_cast<uint64_t>(loaded_hi) << 32));
625 success_flag = (tmp_success == 0);
626 if (loaded != old_val) {
627 *expected = loaded;
628 return false;
629 }
630 return success_flag;
631 }
632# elif defined(NEFORCE_ARCH_RISCV)
633 NEFORCE_IF_CONSTEXPR(sizeof(T) == 4) {
634 asm volatile("lr.w %[loaded], (%[ptr])\n\t"
635 "bne %[loaded], %[old_val], 1f\n\t"
636 "sc.w %[success], %[desired], (%[ptr])\n\t"
637 "1:"
638 : [loaded] "=&r"(loaded), [success] "=&r"(success_flag)
639 : [ptr] "r"(ptr), [old_val] "r"(old_val), [desired] "r"(desired)
640 : "memory");
641 }
642 else NEFORCE_IF_CONSTEXPR(sizeof(T) == 8) {
643 asm volatile("lr.d %[loaded], (%[ptr])\n\t"
644 "bne %[loaded], %[old_val], 1f\n\t"
645 "sc.d %[success], %[desired], (%[ptr])\n\t"
646 "1:"
647 : [loaded] "=&r"(loaded), [success] "=&r"(success_flag)
648 : [ptr] "r"(ptr), [old_val] "r"(old_val), [desired] "r"(desired)
649 : "memory");
650 }
651# elif defined(NEFORCE_ARCH_LOONGARCH)
652 NEFORCE_IF_CONSTEXPR(sizeof(T) == 4) {
653 uint32_t sc_result;
654 uint32_t des_copy = static_cast<uint32_t>(desired);
655 asm volatile("ll.w %[loaded], %[ptr]\n\t"
656 "bne %[loaded], %[old_val], 1f\n\t"
657 "sc.w %[des_copy], %[ptr]\n\t"
658 "1:\n\t"
659 "move %[success], %[des_copy]\n\t"
660 : [loaded] "=&r"(loaded), [des_copy] "+r"(des_copy), [success] "=r"(sc_result)
661 : [ptr] "m"(*ptr), [old_val] "r"(old_val)
662 : "memory");
663 success_flag = (sc_result == 0);
664 }
665 else NEFORCE_IF_CONSTEXPR(sizeof(T) == 8) {
666 asm volatile("ll.d %[loaded], %[ptr]\n\t"
667 "bne %[loaded], %[old_val], 1f\n\t"
668 "sc.d %[desired], %[ptr]\n\t"
669 "move %[success], %[desired]\n\t"
670 "1:"
671 : [loaded] "=&r"(loaded), [success] "=&r"(success_flag)
672 : [ptr] "m"(*ptr), [old_val] "r"(old_val), [desired] "r"(desired)
673 : "memory");
674 }
675# endif
676 if (loaded != old_val) {
677 *expected = loaded;
678 return false;
679 }
680 return success_flag == 0;
681# endif
682#endif
683}
684
697template <typename T>
698NEFORCE_ALWAYS_INLINE_INLINE bool atomic_cmpexch_strong(volatile T* ptr, remove_volatile_t<T>* expected,
699 remove_volatile_t<T> desired, const memory_order success,
700 const memory_order failure) noexcept {
701 static_assert(is_integral_v<T>, "T must be integral type");
703#ifdef NEFORCE_COMPILER_GNUC
704 return __atomic_compare_exchange_n(ptr, expected, desired, false, static_cast<int32_t>(success),
705 static_cast<int32_t>(failure));
706#else
707# if defined(NEFORCE_ARCH_X86) || defined(NEFORCE_ARCH_AARCH64)
708 return _NEFORCE atomic_cmpexch_weak(ptr, expected, desired, success, failure);
709# else
710 remove_volatile_t<T> old_val = *expected;
711 while (true) {
712 if (_NEFORCE atomic_cmpexch_weak(ptr, expected, desired, success, failure)) {
713 return true;
714 }
715 if (*expected != old_val) {
716 return false;
717 }
718 }
719# endif
720#endif
721}
722
732template <typename T>
733NEFORCE_ALWAYS_INLINE_INLINE remove_volatile_t<T> atomic_fetch_add(volatile T* ptr, atomic_diff_t<T> value,
734 const memory_order mo) noexcept {
735 static_assert(is_integral_v<T>, "T must be integral type");
736#ifdef NEFORCE_COMPILER_GNUC
737 return __atomic_fetch_add(ptr, value, static_cast<int32_t>(mo));
738#else
739 remove_volatile_t<T> old = inner::interlocked_fetch_add_impl<sizeof(T)>::call(ptr, value);
740 if (mo == memory_order_seq_cst) {
741 ::_ReadWriteBarrier();
742 }
743 return old;
744#endif
745}
746
756template <typename T>
757NEFORCE_ALWAYS_INLINE_INLINE remove_volatile_t<T> atomic_fetch_sub(volatile T* ptr, atomic_diff_t<T> value,
758 const memory_order mo) noexcept {
759 static_assert(is_integral_v<T>, "T must be integral type");
760#ifdef NEFORCE_COMPILER_GNUC
761 return __atomic_fetch_sub(ptr, value, static_cast<int32_t>(mo));
762#else
763 return _NEFORCE atomic_fetch_add(ptr, static_cast<atomic_diff_t<T>>(-value), mo);
764#endif
765}
766
776template <typename T>
777NEFORCE_ALWAYS_INLINE_INLINE remove_volatile_t<T> atomic_fetch_and(volatile T* ptr, remove_volatile_t<T> value,
778 const memory_order mo) noexcept {
779 static_assert(is_integral_v<T>, "T must be integral type");
780#ifdef NEFORCE_COMPILER_GNUC
781 return __atomic_fetch_and(ptr, value, static_cast<int32_t>(mo));
782#else
783 remove_volatile_t<T> old = inner::interlocked_fetch_and_impl<sizeof(T)>::call(ptr, value);
784 if (mo == memory_order_seq_cst) {
785 ::_ReadWriteBarrier();
786 }
787 return old;
788#endif
789}
790
800template <typename T>
801NEFORCE_ALWAYS_INLINE_INLINE remove_volatile_t<T> atomic_fetch_or(volatile T* ptr, remove_volatile_t<T> value,
802 const memory_order mo) noexcept {
803 static_assert(is_integral_v<T>, "T must be integral type");
804#ifdef NEFORCE_COMPILER_GNUC
805 return __atomic_fetch_or(ptr, value, static_cast<int32_t>(mo));
806#else
807 remove_volatile_t<T> old = inner::interlocked_fetch_or_impl<sizeof(T)>::call(ptr, value);
808 if (mo == memory_order_seq_cst) {
809 ::_ReadWriteBarrier();
810 }
811 return old;
812#endif
813}
814
824template <typename T>
825NEFORCE_ALWAYS_INLINE_INLINE remove_volatile_t<T> atomic_fetch_xor(volatile T* ptr, remove_volatile_t<T> value,
826 const memory_order mo) noexcept {
827 static_assert(is_integral_v<T>, "T must be integral type");
828#ifdef NEFORCE_COMPILER_GNUC
829 return __atomic_fetch_xor(ptr, value, static_cast<int32_t>(mo));
830#else
831 remove_volatile_t<T> old = inner::interlocked_fetch_xor_impl<sizeof(T)>::call(ptr, value);
832 if (mo == memory_order_seq_cst) {
833 ::_ReadWriteBarrier();
834 }
835 return old;
836#endif
837}
838
848template <typename T>
849NEFORCE_ALWAYS_INLINE_INLINE remove_volatile_t<T> atomic_add_fetch(volatile T* ptr, atomic_diff_t<T> value,
850 memory_order mo) noexcept {
851 static_assert(is_integral_v<T>, "T must be integral type");
852#ifdef NEFORCE_COMPILER_GNUC
853 return __atomic_add_fetch(ptr, value, static_cast<int32_t>(mo));
854#else
855 return _NEFORCE atomic_fetch_add(ptr, value, mo) + value;
856#endif
857}
858
868template <typename T>
869NEFORCE_ALWAYS_INLINE_INLINE remove_volatile_t<T> atomic_sub_fetch(volatile T* ptr, atomic_diff_t<T> value,
870 memory_order mo) noexcept {
871 static_assert(is_integral_v<T>, "T must be integral type");
872#ifdef NEFORCE_COMPILER_GNUC
873 return __atomic_sub_fetch(ptr, value, static_cast<int32_t>(mo));
874#else
875 return _NEFORCE atomic_fetch_sub(ptr, value, mo) - value;
876#endif
877}
878
888template <typename T>
889NEFORCE_ALWAYS_INLINE_INLINE remove_volatile_t<T> atomic_and_fetch(volatile T* ptr, remove_volatile_t<T> value,
890 memory_order mo) noexcept {
891 static_assert(is_integral_v<T>, "T must be integral type");
892#ifdef NEFORCE_COMPILER_GNUC
893 return __atomic_and_fetch(ptr, value, static_cast<int32_t>(mo));
894#else
895 return _NEFORCE atomic_fetch_and(ptr, value, mo) & value;
896#endif
897}
898
908template <typename T>
909NEFORCE_ALWAYS_INLINE_INLINE remove_volatile_t<T> atomic_or_fetch(volatile T* ptr, remove_volatile_t<T> value,
910 memory_order mo) noexcept {
911 static_assert(is_integral_v<T>, "T must be integral type");
912#ifdef NEFORCE_COMPILER_GNUC
913 return __atomic_or_fetch(ptr, value, static_cast<int32_t>(mo));
914#else
915 return _NEFORCE atomic_fetch_or(ptr, value, mo) | value;
916#endif
917}
918
928template <typename T>
929NEFORCE_ALWAYS_INLINE_INLINE remove_volatile_t<T> atomic_xor_fetch(volatile T* ptr, remove_volatile_t<T> value,
930 memory_order mo) noexcept {
931 static_assert(is_integral_v<T>, "T must be integral type");
932#ifdef NEFORCE_COMPILER_GNUC
933 return __atomic_xor_fetch(ptr, value, static_cast<int32_t>(mo));
934#else
935 return _NEFORCE atomic_fetch_xor(ptr, value, mo) ^ value;
936#endif
937}
938
939
951template <typename T>
952NEFORCE_ALWAYS_INLINE_INLINE bool atomic_cmpexch_weak_any(volatile T* ptr, remove_volatile_t<T>* expected,
953 remove_volatile_t<T>* desired, const memory_order success,
954 const memory_order failure) noexcept {
956#ifdef NEFORCE_COMPILER_GNUC
957 return __atomic_compare_exchange(ptr, expected, desired, true, static_cast<int32_t>(success),
958 static_cast<int32_t>(failure));
959#else
960# if defined(NEFORCE_ARCH_X86) || defined(NEFORCE_ARCH_AARCH64)
961 const bool result = inner::interlocked_compare_exchange_impl<sizeof(T)>::call(ptr, expected, *desired);
963 ::_ReadWriteBarrier();
964 }
965 return result;
966# else
967 remove_volatile_t<T> old_val = *expected;
969 bool success_flag;
970# if defined(NEFORCE_ARCH_ARM)
971 NEFORCE_IF_CONSTEXPR(sizeof(T) == 1) {
972 asm volatile("ldrexb %[loaded], [%[ptr]]\n\t"
973 "cmp %[loaded], %[old_val]\n\t"
974 "bne 1f\n\t"
975 "strexb %w[success], %w[desired], [%[ptr]]\n\t"
976 "1:"
977 : [loaded] "=&r"(loaded), [success] "=&r"(success_flag)
978 : [ptr] "r"(ptr), [old_val] "r"(old_val), [desired] "r"(desired)
979 : "cc", "memory");
980 }
981 else NEFORCE_IF_CONSTEXPR(sizeof(T) == 2) {
982 asm volatile("ldrexh %[loaded], [%[ptr]]\n\t"
983 "cmp %[loaded], %[old_val]\n\t"
984 "bne 1f\n\t"
985 "strexh %w[success], %w[desired], [%[ptr]]\n\t"
986 "1:"
987 : [loaded] "=&r"(loaded), [success] "=&r"(success_flag)
988 : [ptr] "r"(ptr), [old_val] "r"(old_val), [desired] "r"(desired)
989 : "cc", "memory");
990 }
991 else NEFORCE_IF_CONSTEXPR(sizeof(T) == 4) {
992 asm volatile("ldrex %[loaded], [%[ptr]]\n\t"
993 "cmp %[loaded], %[old_val]\n\t"
994 "bne 1f\n\t"
995 "strex %w[success], %w[desired], [%[ptr]]\n\t"
996 "1:"
997 : [loaded] "=&r"(loaded), [success] "=&r"(success_flag)
998 : [ptr] "r"(ptr), [old_val] "r"(old_val), [desired] "r"(desired)
999 : "cc", "memory");
1000 }
1001 else NEFORCE_IF_CONSTEXPR(sizeof(T) == 8) {
1002 asm volatile("ldrexd %[loaded], [%[ptr]]\n\t"
1003 "cmp %[loaded], %[old_val]\n\t"
1004 "bne 1f\n\t"
1005 "strexd %w[success], %[desired], [%[ptr]]\n\t"
1006 "1:"
1007 : [loaded] "=&r"(loaded), [success] "=&r"(success_flag)
1008 : [ptr] "r"(ptr), [old_val] "r"(old_val), [desired] "r"(desired)
1009 : "cc", "memory");
1010 }
1011# elif defined(NEFORCE_ARCH_RISCV)
1012 NEFORCE_IF_CONSTEXPR(sizeof(T) == 4) {
1013 asm volatile("lr.w %[loaded], (%[ptr])\n\t"
1014 "bne %[loaded], %[old_val], 1f\n\t"
1015 "sc.w %[success], %[desired], (%[ptr])\n\t"
1016 "1:"
1017 : [loaded] "=&r"(loaded), [success] "=&r"(success_flag)
1018 : [ptr] "r"(ptr), [old_val] "r"(old_val), [desired] "r"(desired)
1019 : "memory");
1020 }
1021 else NEFORCE_IF_CONSTEXPR(sizeof(T) == 8) {
1022 asm volatile("lr.d %[loaded], (%[ptr])\n\t"
1023 "bne %[loaded], %[old_val], 1f\n\t"
1024 "sc.d %[success], %[desired], (%[ptr])\n\t"
1025 "1:"
1026 : [loaded] "=&r"(loaded), [success] "=&r"(success_flag)
1027 : [ptr] "r"(ptr), [old_val] "r"(old_val), [desired] "r"(desired)
1028 : "memory");
1029 }
1030# elif defined(NEFORCE_ARCH_LOONGARCH)
1031 NEFORCE_IF_CONSTEXPR(sizeof(T) == 4) {
1032 asm volatile("ll.w %[loaded], %[ptr]\n\t"
1033 "bne %[loaded], %[old_val], 1f\n\t"
1034 "sc.w %[desired], %[ptr]\n\t"
1035 "move %[success], %[desired]\n\t"
1036 "1:"
1037 : [loaded] "=&r"(loaded), [success] "=&r"(success_flag)
1038 : [ptr] "m"(*ptr), [old_val] "r"(old_val), [desired] "r"(desired)
1039 : "memory");
1040 }
1041 else NEFORCE_IF_CONSTEXPR(sizeof(T) == 8) {
1042 asm volatile("ll.d %[loaded], %[ptr]\n\t"
1043 "bne %[loaded], %[old_val], 1f\n\t"
1044 "sc.d %[desired], %[ptr]\n\t"
1045 "move %[success], %[desired]\n\t"
1046 "1:"
1047 : [loaded] "=&r"(loaded), [success] "=&r"(success_flag)
1048 : [ptr] "m"(*ptr), [old_val] "r"(old_val), [desired] "r"(desired)
1049 : "memory");
1050 }
1051# endif
1052 if (loaded != old_val) {
1053 *expected = loaded;
1054 return false;
1055 }
1056 return success_flag == 0;
1057# endif
1058#endif
1059}
1060
1072template <typename T>
1073NEFORCE_ALWAYS_INLINE_INLINE bool atomic_cmpexch_strong_any(volatile T* ptr, remove_volatile_t<T>* expected,
1074 remove_volatile_t<T>* desired, const memory_order success,
1075 const memory_order failure) noexcept {
1077#ifdef NEFORCE_COMPILER_GNUC
1078 return __atomic_compare_exchange(ptr, expected, desired, false, static_cast<int32_t>(success),
1079 static_cast<int32_t>(failure));
1080#else
1081# if defined(NEFORCE_ARCH_X86) || defined(NEFORCE_ARCH_AARCH64)
1082 const bool result = inner::interlocked_compare_exchange_impl<sizeof(T)>::call(ptr, expected, *desired);
1083 if (success == memory_order_seq_cst || failure == memory_order_seq_cst) {
1084 ::_ReadWriteBarrier();
1085 }
1086 return result;
1087# else
1088 remove_volatile_t<T> old_val = *expected;
1089 while (true) {
1090 if (_NEFORCE atomic_cmpexch_weak_any(ptr, expected, desired, success, failure)) {
1091 return true;
1092 }
1093 if (_NEFORCE memory_compare<remove_volatile_t<T>>(old_val, *expected) != 0) {
1094 return false;
1095 }
1096 }
1097# endif
1098#endif
1099}
1100
1109template <typename T>
1110NEFORCE_ALWAYS_INLINE_INLINE void atomic_store_any(T* ptr, remove_volatile_t<T> value, const memory_order mo) noexcept {
1111#ifdef NEFORCE_COMPILER_GNUC
1112 __atomic_store(ptr, _NEFORCE addressof(value), static_cast<int32_t>(mo));
1113#else
1114 remove_volatile_t<T> expected = *ptr;
1115 while (!_NEFORCE atomic_cmpexch_weak_any(ptr, &expected, &value, mo, memory_order_relaxed)) {
1116 // Retry
1117 }
1118#endif
1119}
1120
1129template <typename T>
1130NEFORCE_ALWAYS_INLINE_INLINE remove_volatile_t<T> atomic_load_any(const T* ptr, memory_order mo) noexcept {
1131#ifdef NEFORCE_COMPILER_GNUC
1132 alignas(T) byte_t buffer[sizeof(T)];
1133 T* dest = reinterpret_cast<remove_volatile_t<T>*>(buffer);
1134 __atomic_load(ptr, dest, static_cast<int32_t>(mo));
1135 return *dest;
1136#else
1137 remove_volatile_t<T> result;
1138 _NEFORCE memory_copy<remove_volatile_t<T>>(&result, ptr);
1139 // Get a consistency snapshot with CMPXCHG16B self-comparison CAS
1140 inner::atomic_load_verifier<sizeof(T)>::verify(ptr, result);
1141 if (mo == memory_order_seq_cst || mo == memory_order_acquire) {
1142 ::_ReadWriteBarrier();
1143 }
1144 return result;
1145#endif
1146}
1147
1157template <typename T>
1158NEFORCE_ALWAYS_INLINE_INLINE remove_volatile_t<T> atomic_exchange_any(T* ptr, remove_volatile_t<T> desired,
1159 memory_order mo) noexcept {
1160#ifdef NEFORCE_COMPILER_GNUC
1161 alignas(T) byte_t buffer[sizeof(T)];
1162 T* dest = reinterpret_cast<remove_volatile_t<T>*>(buffer);
1163 __atomic_exchange(ptr, _NEFORCE addressof(desired), dest, static_cast<int32_t>(mo));
1164 return *dest;
1165#else
1167 while (!_NEFORCE atomic_cmpexch_weak_any(ptr, &old, &desired, mo, memory_order_relaxed)) {
1168 // Retry
1169 }
1170 return old;
1171#endif
1172}
1173
1182template <typename T>
1185 remove_volatile_t<T> new_value;
1186 do {
1187 new_value = old_value + value;
1188 } while (!_NEFORCE atomic_cmpexch_weak_any(ptr, &old_value, &new_value, mo, memory_order_relaxed));
1189 return old_value;
1190}
1191
1200template <typename T>
1203 remove_volatile_t<T> new_value;
1204 do {
1205 new_value = old_value - value;
1206 } while (!_NEFORCE atomic_cmpexch_weak_any(ptr, &old_value, &new_value, mo, memory_order_relaxed));
1207 return old_value;
1208}
1209
1218template <typename T>
1221 remove_volatile_t<T> new_value;
1222 do {
1223 new_value = old_value + value;
1224 } while (!_NEFORCE atomic_cmpexch_weak_any(ptr, &old_value, &new_value, mo, memory_order_relaxed));
1225 return new_value;
1226}
1227
1236template <typename T>
1239 remove_volatile_t<T> new_value;
1240 do {
1241 new_value = old_value - value;
1242 } while (!_NEFORCE atomic_cmpexch_weak_any(ptr, &old_value, &new_value, mo, memory_order_relaxed));
1243 return new_value;
1244}
1245
1246
1253template <size_t Size, size_t Align>
1254NEFORCE_CONSTEXPR17 bool is_always_lock_free() noexcept {
1255#ifdef NEFORCE_COMPILER_GNUC
1256 return __atomic_is_lock_free(Size, reinterpret_cast<void*>(-Align));
1257#else
1258 return inner::atomic_is_always_lock_free_impl<Size>::value;
1259#endif
1260}
1261
1262
1269struct atomic_flag {
1274#ifdef NEFORCE_COMPILER_MSVC
1275 long;
1276#else
1277 bool;
1278#endif
1279
1280 value_type flag_{static_cast<value_type>(0)};
1281
1282 atomic_flag() noexcept = default;
1283 atomic_flag(const atomic_flag&) = delete;
1284 atomic_flag& operator=(const atomic_flag&) = delete;
1285 atomic_flag& operator=(const atomic_flag&) volatile = delete;
1286 atomic_flag(atomic_flag&&) noexcept = default;
1287 atomic_flag& operator=(atomic_flag&&) noexcept = default;
1288 ~atomic_flag() noexcept = default;
1289
1294 constexpr atomic_flag(const value_type flag) noexcept :
1295 flag_(static_cast<value_type>(static_cast<int>(flag) != 0 ? 1 : 0)) {}
1296
1302 NEFORCE_ALWAYS_INLINE bool test_and_set(const memory_order mo = memory_order_seq_cst) noexcept {
1303#ifdef NEFORCE_COMPILER_GNUC
1304 return __atomic_test_and_set(&flag_, static_cast<int32_t>(mo));
1305#else
1306 const long old_val = ::_InterlockedExchange(&flag_, 1);
1307 if (mo == memory_order_seq_cst) {
1308 ::_ReadWriteBarrier();
1309 }
1310 return old_val != 0;
1311#endif
1312 }
1313
1317 NEFORCE_ALWAYS_INLINE_INLINE bool test_and_set(const memory_order mo = memory_order_seq_cst) volatile noexcept {
1318#ifdef NEFORCE_COMPILER_GNUC
1319 return __atomic_test_and_set(&flag_, static_cast<int32_t>(mo));
1320#else
1321 const long old_val = ::_InterlockedExchange(&flag_, 1);
1322 if (mo == memory_order_seq_cst) {
1323 ::_ReadWriteBarrier();
1324 }
1325 return old_val != 0;
1326#endif
1327 }
1328
1334 NEFORCE_NODISCARD NEFORCE_ALWAYS_INLINE bool test(const memory_order mo = memory_order_seq_cst) const noexcept {
1335#ifdef NEFORCE_COMPILER_GNUC
1336 value_type value = false;
1337 __atomic_load(&flag_, &value, static_cast<int32_t>(mo));
1338 return value != static_cast<value_type>(0);
1339#else
1340 const long as_bytes = flag_;
1341 if (mo != memory_order_relaxed) {
1342 ::_ReadWriteBarrier();
1343 }
1344 return as_bytes != 0;
1345#endif
1346 }
1347
1351 NEFORCE_NODISCARD NEFORCE_ALWAYS_INLINE_INLINE bool test(const memory_order mo = memory_order_seq_cst) const
1352 volatile noexcept {
1353#ifdef NEFORCE_COMPILER_GNUC
1354 value_type value = false;
1355 __atomic_load(&flag_, &value, static_cast<int32_t>(mo));
1356 return value != static_cast<value_type>(0);
1357#else
1358 const long as_bytes = flag_;
1359 if (mo != memory_order_relaxed) {
1360 ::_ReadWriteBarrier();
1361 }
1362 return as_bytes != 0;
1363#endif
1364 }
1365
1371 NEFORCE_ALWAYS_INLINE void wait(const bool old, const memory_order mo = memory_order_seq_cst) const noexcept {
1372 const auto value = static_cast<value_type>(old);
1373 _NEFORCE atomic_wait_address_v(const_cast<const value_type*>(&flag_), value,
1374 [this, mo] { return this->test(mo); });
1375 }
1376
1380 NEFORCE_ALWAYS_INLINE_INLINE void wait(const bool old, const memory_order mo = memory_order_seq_cst) const
1381 volatile noexcept {
1382 const auto value = static_cast<value_type>(old);
1383 _NEFORCE atomic_wait_address_v(const_cast<const value_type*>(&flag_), value,
1384 [this, mo] { return this->test(mo); });
1385 }
1386
1390 NEFORCE_ALWAYS_INLINE void notify_one() noexcept { _NEFORCE atomic_notify_address(&flag_, false); }
1391
1395 NEFORCE_ALWAYS_INLINE void notify_all() noexcept { _NEFORCE atomic_notify_address(&flag_, true); }
1396
1401 NEFORCE_ALWAYS_INLINE void clear(const memory_order mo = memory_order_seq_cst) noexcept {
1402#ifdef NEFORCE_SUPPORT_INTEL_TSX
1407#else
1411#endif
1412
1413#ifdef NEFORCE_COMPILER_GNUC
1414 __atomic_clear(&flag_, static_cast<int32_t>(mo));
1415#else
1416 _NEFORCE atomic_store(&flag_, static_cast<value_type>(0), mo);
1417#endif
1418 }
1419
1423 NEFORCE_ALWAYS_INLINE_INLINE void clear(const memory_order mo = memory_order_seq_cst) volatile noexcept {
1424#ifdef NEFORCE_SUPPORT_INTEL_TSX
1429#else
1433#endif
1434
1435#ifdef NEFORCE_COMPILER_GNUC
1436 __atomic_clear(&flag_, static_cast<int32_t>(mo));
1437#else
1438 _NEFORCE atomic_store(&flag_, static_cast<value_type>(0), mo);
1439#endif
1440 }
1441};
1442
1443
1450template <typename T>
1451struct atomic_base {
1452 using value_type = T;
1454
1455 static_assert(is_integral_like_v<T>, "T must be an integral-like type");
1456
1457private:
1458 static constexpr size_t align_inner = sizeof(T) > alignof(T) ? sizeof(T) : alignof(T);
1459
1460 alignas(align_inner) value_type value_;
1461
1462public:
1463 atomic_base() noexcept = default;
1464 ~atomic_base() noexcept = default;
1465 atomic_base(const atomic_base&) = delete;
1466 atomic_base& operator=(const atomic_base&) = delete;
1467 atomic_base& operator=(const atomic_base&) volatile = delete;
1468 atomic_base(atomic_base&&) noexcept = default;
1469 atomic_base& operator=(atomic_base&&) noexcept = default;
1470
1475 constexpr atomic_base(value_type value) noexcept :
1476 value_(value) {}
1477
1482 operator value_type() const noexcept { return load(); }
1483
1487 operator value_type() const volatile noexcept { return load(); }
1488
1495 atomic_base::store(value);
1496 return value;
1497 }
1498
1502 value_type operator=(value_type value) volatile noexcept {
1503 atomic_base::store(value);
1504 return value;
1505 }
1506
1511 value_type operator++(int) noexcept { return fetch_add(1); }
1512
1516 value_type operator++(int) volatile noexcept { return fetch_add(1); }
1517
1522 value_type operator--(int) noexcept { return fetch_sub(1); }
1523
1527 value_type operator--(int) volatile noexcept { return fetch_sub(1); }
1528
1533 value_type operator++() noexcept { return _NEFORCE atomic_add_fetch(&value_, 1, memory_order_seq_cst); }
1534
1538 value_type operator++() volatile noexcept { return _NEFORCE atomic_add_fetch(&value_, 1, memory_order_seq_cst); }
1539
1544 value_type operator--() noexcept { return _NEFORCE atomic_sub_fetch(&value_, 1, memory_order_seq_cst); }
1545
1549 value_type operator--() volatile noexcept { return _NEFORCE atomic_sub_fetch(&value_, 1, memory_order_seq_cst); }
1550
1557 return _NEFORCE atomic_add_fetch(&value_, value, memory_order_seq_cst);
1558 }
1559
1563 value_type operator+=(value_type value) volatile noexcept {
1564 return _NEFORCE atomic_add_fetch(&value_, value, memory_order_seq_cst);
1565 }
1566
1573 return _NEFORCE atomic_sub_fetch(&value_, value, memory_order_seq_cst);
1574 }
1575
1579 value_type operator-=(value_type value) volatile noexcept {
1580 return _NEFORCE atomic_sub_fetch(&value_, value, memory_order_seq_cst);
1581 }
1582
1589 return _NEFORCE atomic_and_fetch(&value_, value, memory_order_seq_cst);
1590 }
1591
1595 value_type operator&=(value_type value) volatile noexcept {
1596 return _NEFORCE atomic_and_fetch(&value_, value, memory_order_seq_cst);
1597 }
1598
1605 return _NEFORCE atomic_or_fetch(&value_, value, memory_order_seq_cst);
1606 }
1607
1611 value_type operator|=(value_type value) volatile noexcept {
1612 return _NEFORCE atomic_or_fetch(&value_, value, memory_order_seq_cst);
1613 }
1614
1621 return _NEFORCE atomic_xor_fetch(&value_, value, memory_order_seq_cst);
1622 }
1623
1627 value_type operator^=(value_type value) volatile noexcept {
1628 return _NEFORCE atomic_xor_fetch(&value_, value, memory_order_seq_cst);
1629 }
1630
1635 NEFORCE_NODISCARD bool is_lock_free() const noexcept {
1637 }
1638
1642 NEFORCE_NODISCARD bool is_lock_free() const volatile noexcept {
1644 }
1645
1651 NEFORCE_ALWAYS_INLINE void store(value_type value, const memory_order mo = memory_order_seq_cst) noexcept {
1652#ifdef NEFORCE_SUPPORT_INTEL_TSX
1657#else
1661#endif
1662 _NEFORCE atomic_store(&value_, value, mo);
1663 }
1664
1668 NEFORCE_ALWAYS_INLINE void store(value_type value, const memory_order mo = memory_order_seq_cst) volatile noexcept {
1669#ifdef NEFORCE_SUPPORT_INTEL_TSX
1674#else
1678#endif
1679 _NEFORCE atomic_store(&value_, value, mo);
1680 }
1681
1687 NEFORCE_ALWAYS_INLINE value_type load(const memory_order mo = memory_order_seq_cst) const noexcept {
1688#ifdef NEFORCE_SUPPORT_INTEL_TSX
1692#else
1695#endif
1696 return _NEFORCE atomic_load(&value_, mo);
1697 }
1698
1702 NEFORCE_ALWAYS_INLINE value_type load(const memory_order mo = memory_order_seq_cst) const volatile noexcept {
1703#ifdef NEFORCE_SUPPORT_INTEL_TSX
1707#else
1710#endif
1711 return _NEFORCE atomic_load(&value_, mo);
1712 }
1713
1720 NEFORCE_ALWAYS_INLINE value_type exchange(value_type value, const memory_order mo = memory_order_seq_cst) noexcept {
1721 return _NEFORCE atomic_exchange(&value_, value, mo);
1722 }
1723
1727 NEFORCE_ALWAYS_INLINE value_type exchange(value_type value,
1728 const memory_order mo = memory_order_seq_cst) volatile noexcept {
1729 return _NEFORCE atomic_exchange(&value_, value, mo);
1730 }
1731
1740 NEFORCE_ALWAYS_INLINE bool compare_exchange_weak(value_type& expected, value_type desired,
1741 const memory_order success, const memory_order failure) noexcept {
1742 return _NEFORCE atomic_cmpexch_weak_any(&value_, &expected, &desired, success, failure);
1743 }
1744
1748 NEFORCE_ALWAYS_INLINE bool compare_exchange_weak(value_type& expected, value_type desired,
1749 const memory_order success,
1750 const memory_order failure) volatile noexcept {
1751 return _NEFORCE atomic_cmpexch_weak_any(&value_, &expected, &desired, success, failure);
1752 }
1753
1761 NEFORCE_ALWAYS_INLINE bool compare_exchange_weak(value_type& expected, value_type desired,
1762 const memory_order mo = memory_order_seq_cst) noexcept {
1763 return this->compare_exchange_weak(expected, desired, mo, cmpexch_failure_order(mo));
1764 }
1765
1769 NEFORCE_ALWAYS_INLINE bool compare_exchange_weak(value_type& expected, value_type desired,
1770 const memory_order mo = memory_order_seq_cst) volatile noexcept {
1771 return this->compare_exchange_weak(expected, desired, mo, cmpexch_failure_order(mo));
1772 }
1773
1782 NEFORCE_ALWAYS_INLINE bool compare_exchange_strong(value_type& expected, value_type desired,
1783 const memory_order success,
1784 const memory_order failure) noexcept {
1785 return _NEFORCE atomic_cmpexch_strong_any(&value_, &expected, &desired, success, failure);
1786 }
1787
1791 NEFORCE_ALWAYS_INLINE bool compare_exchange_strong(value_type& expected, value_type desired,
1792 const memory_order success,
1793 const memory_order failure) volatile noexcept {
1794 return _NEFORCE atomic_cmpexch_strong_any(&value_, &expected, &desired, success, failure);
1795 }
1796
1804 NEFORCE_ALWAYS_INLINE bool compare_exchange_strong(value_type& expected, value_type desired,
1805 const memory_order mo = memory_order_seq_cst) noexcept {
1806 return this->compare_exchange_strong(expected, desired, mo, cmpexch_failure_order(mo));
1807 }
1808
1812 NEFORCE_ALWAYS_INLINE bool compare_exchange_strong(value_type& expected, value_type desired,
1813 const memory_order mo = memory_order_seq_cst) volatile noexcept {
1814 return this->compare_exchange_strong(expected, desired, mo, cmpexch_failure_order(mo));
1815 }
1816
1822 NEFORCE_ALWAYS_INLINE void wait(value_type old, const memory_order mo = memory_order_seq_cst) const noexcept {
1823 _NEFORCE atomic_wait_address_v(&value_, old, [mo, this] { return this->load(mo); });
1824 }
1825
1829 NEFORCE_ALWAYS_INLINE void notify_one() noexcept { _NEFORCE atomic_notify_address(&value_, false); }
1830
1834 NEFORCE_ALWAYS_INLINE void notify_all() noexcept { _NEFORCE atomic_notify_address(&value_, true); }
1835
1842 NEFORCE_ALWAYS_INLINE value_type fetch_add(value_type value,
1843 const memory_order mo = memory_order_seq_cst) noexcept {
1844 return _NEFORCE atomic_fetch_add(&value_, value, mo);
1845 }
1846
1850 NEFORCE_ALWAYS_INLINE value_type fetch_add(value_type value,
1851 const memory_order mo = memory_order_seq_cst) volatile noexcept {
1852 return _NEFORCE atomic_fetch_add(&value_, value, mo);
1853 }
1854
1861 NEFORCE_ALWAYS_INLINE value_type fetch_sub(value_type value,
1862 const memory_order mo = memory_order_seq_cst) noexcept {
1863 return _NEFORCE atomic_fetch_sub(&value_, value, mo);
1864 }
1865
1869 NEFORCE_ALWAYS_INLINE value_type fetch_sub(value_type value,
1870 const memory_order mo = memory_order_seq_cst) volatile noexcept {
1871 return _NEFORCE atomic_fetch_sub(&value_, value, mo);
1872 }
1873
1880 NEFORCE_ALWAYS_INLINE value_type fetch_and(value_type value,
1881 const memory_order mo = memory_order_seq_cst) noexcept {
1882 return _NEFORCE atomic_fetch_and(&value_, value, mo);
1883 }
1884
1888 NEFORCE_ALWAYS_INLINE value_type fetch_and(value_type value,
1889 const memory_order mo = memory_order_seq_cst) volatile noexcept {
1890 return _NEFORCE atomic_fetch_and(&value_, value, mo);
1891 }
1892
1899 NEFORCE_ALWAYS_INLINE value_type fetch_or(value_type value, const memory_order mo = memory_order_seq_cst) noexcept {
1900 return _NEFORCE atomic_fetch_or(&value_, value, mo);
1901 }
1902
1906 NEFORCE_ALWAYS_INLINE value_type fetch_or(value_type value,
1907 const memory_order mo = memory_order_seq_cst) volatile noexcept {
1908 return _NEFORCE atomic_fetch_or(&value_, value, mo);
1909 }
1910
1917 NEFORCE_ALWAYS_INLINE value_type fetch_xor(value_type value,
1918 const memory_order mo = memory_order_seq_cst) noexcept {
1919 return _NEFORCE atomic_fetch_xor(&value_, value, mo);
1920 }
1921
1925 NEFORCE_ALWAYS_INLINE value_type fetch_xor(value_type value,
1926 const memory_order mo = memory_order_seq_cst) volatile noexcept {
1927 return _NEFORCE atomic_fetch_xor(&value_, value, mo);
1928 }
1929};
1930
1937template <typename T>
1938struct atomic_base<T*> {
1939 using value_type = T*;
1941
1942private:
1943 value_type ptr_ = nullptr;
1944
1945 NEFORCE_ALWAYS_INLINE_INLINE static constexpr difference_type real_type_sizes(const difference_type dest) noexcept {
1946 return dest * sizeof(T);
1947 }
1948
1949public:
1950 atomic_base() noexcept = default;
1951 atomic_base(const atomic_base&) = delete;
1952 atomic_base& operator=(const atomic_base&) = delete;
1953 atomic_base& operator=(const atomic_base&) volatile = delete;
1954 atomic_base(atomic_base&&) noexcept = default;
1955 atomic_base& operator=(atomic_base&&) noexcept = default;
1956 ~atomic_base() noexcept = default;
1957
1962 constexpr atomic_base(const value_type ptr) noexcept :
1963 ptr_(ptr) {}
1964
1969 operator value_type() const noexcept { return load(); }
1970
1974 operator value_type() const volatile noexcept { return load(); }
1975
1981 value_type operator=(const value_type ptr) noexcept {
1982 atomic_base::store(ptr);
1983 return ptr;
1984 }
1985
1989 value_type operator=(const value_type ptr) volatile noexcept {
1990 atomic_base::store(ptr);
1991 return ptr;
1992 }
1993
1998 value_type operator++(int) noexcept { return fetch_add(1); }
1999
2003 value_type operator++(int) volatile noexcept { return fetch_add(1); }
2004
2009 value_type operator--(int) noexcept { return fetch_sub(1); }
2010
2014 value_type operator--(int) volatile noexcept { return fetch_sub(1); }
2015
2020 value_type operator++() noexcept { return fetch_add(1) + 1; }
2021
2025 value_type operator++() volatile noexcept { return fetch_add(1) + 1; }
2026
2031 value_type operator--() noexcept { return fetch_sub(1) - 1; }
2032
2036 value_type operator--() volatile noexcept { return fetch_sub(1) - 1; }
2037
2043 value_type operator+=(const ptrdiff_t dest) noexcept { return fetch_add(dest) + dest; }
2044
2048 value_type operator+=(const ptrdiff_t dest) volatile noexcept { return fetch_add(dest) + dest; }
2049
2055 value_type operator-=(const ptrdiff_t dest) noexcept { return fetch_sub(dest) - dest; }
2056
2060 value_type operator-=(const ptrdiff_t dest) volatile noexcept { return fetch_sub(dest) - dest; }
2061
2066 NEFORCE_NODISCARD bool is_lock_free() const noexcept {
2068 }
2069
2073 NEFORCE_NODISCARD bool is_lock_free() const volatile noexcept {
2075 }
2076
2082 NEFORCE_ALWAYS_INLINE void store(value_type ptr, const memory_order mo = memory_order_seq_cst) noexcept {
2083#ifdef NEFORCE_SUPPORT_INTEL_TSX
2088#else
2092#endif
2093
2094#ifdef NEFORCE_COMPILER_GNUC
2095 __atomic_store_n(&ptr_, ptr, static_cast<int32_t>(mo));
2096#else
2097 ::_InterlockedExchangePointer(reinterpret_cast<void* volatile*>(&ptr_), reinterpret_cast<void*>(ptr));
2098 if (mo == memory_order_seq_cst || mo == memory_order_release) {
2099 ::_ReadWriteBarrier();
2100 }
2101#endif
2102 }
2103
2107 NEFORCE_ALWAYS_INLINE_INLINE void store(const value_type ptr,
2108 const memory_order mo = memory_order_seq_cst) volatile noexcept {
2109#ifdef NEFORCE_SUPPORT_INTEL_TSX
2114#else
2118#endif
2119
2120#ifdef NEFORCE_COMPILER_GNUC
2121 __atomic_store_n(&ptr_, ptr, static_cast<int32_t>(mo));
2122#else
2123 ::_InterlockedExchangePointer(reinterpret_cast<void* volatile*>(&ptr_), ptr);
2124 if (mo == memory_order_seq_cst || mo == memory_order_release) {
2125 ::_ReadWriteBarrier();
2126 }
2127#endif
2128 }
2129
2135 NEFORCE_ALWAYS_INLINE value_type load(const memory_order mo = memory_order_seq_cst) const noexcept {
2136#ifdef NEFORCE_SUPPORT_INTEL_TSX
2140#else
2143#endif
2144
2145#ifdef NEFORCE_COMPILER_GNUC
2146 return __atomic_load_n(&ptr_, static_cast<int32_t>(mo));
2147#else
2148 const value_type result = *reinterpret_cast<value_type const volatile*>(&ptr_);
2149 if (mo == memory_order_seq_cst || mo == memory_order_acquire) {
2150 ::_ReadWriteBarrier();
2151 }
2152 return result;
2153#endif
2154 }
2155
2159 NEFORCE_ALWAYS_INLINE_INLINE value_type load(const memory_order mo = memory_order_seq_cst) const volatile noexcept {
2160#ifdef NEFORCE_SUPPORT_INTEL_TSX
2164#else
2167#endif
2168
2169#ifdef NEFORCE_COMPILER_GNUC
2170 return __atomic_load_n(&ptr_, static_cast<int32_t>(mo));
2171#else
2172 const value_type result = *reinterpret_cast<value_type const volatile*>(&ptr_);
2173 if (mo == memory_order_seq_cst || mo == memory_order_acquire) {
2174 ::_ReadWriteBarrier();
2175 }
2176 return result;
2177#endif
2178 }
2179
2186 NEFORCE_ALWAYS_INLINE value_type exchange(const value_type ptr,
2187 const memory_order mo = memory_order_seq_cst) noexcept {
2188#ifdef NEFORCE_COMPILER_GNUC
2189 return __atomic_exchange_n(&ptr_, ptr, static_cast<int32_t>(mo));
2190#else
2191 const auto old =
2192 static_cast<value_type>(::_InterlockedExchangePointer(reinterpret_cast<void* volatile*>(&ptr_), ptr));
2193 if (mo == memory_order_seq_cst) {
2194 ::_ReadWriteBarrier();
2195 }
2196 return old;
2197#endif
2198 }
2199
2203 NEFORCE_ALWAYS_INLINE_INLINE value_type exchange(const value_type ptr,
2204 const memory_order mo = memory_order_seq_cst) volatile noexcept {
2205#ifdef NEFORCE_COMPILER_GNUC
2206 return __atomic_exchange_n(&ptr_, ptr, static_cast<int32_t>(mo));
2207#else
2208 const auto old =
2209 static_cast<value_type>(::_InterlockedExchangePointer(reinterpret_cast<void* volatile*>(&ptr_), ptr));
2210 if (mo == memory_order_seq_cst) {
2211 ::_ReadWriteBarrier();
2212 }
2213 return old;
2214#endif
2215 }
2216
2225 NEFORCE_ALWAYS_INLINE bool compare_exchange_weak(value_type& expected, value_type desired,
2226 const memory_order success, const memory_order failure) noexcept {
2228 return _NEFORCE atomic_cmpexch_weak_any(_NEFORCE addressof(ptr_), _NEFORCE addressof(expected),
2229 _NEFORCE addressof(desired), success, failure);
2230 }
2231
2235 NEFORCE_ALWAYS_INLINE_INLINE bool compare_exchange_weak(value_type& expected, value_type desired,
2236 const memory_order success,
2237 const memory_order failure) volatile noexcept {
2239 return _NEFORCE atomic_cmpexch_weak_any(_NEFORCE addressof(ptr_), _NEFORCE addressof(expected),
2240 _NEFORCE addressof(desired), success, failure);
2241 }
2242
2250 NEFORCE_ALWAYS_INLINE bool compare_exchange_weak(value_type& expected, value_type desired,
2251 const memory_order mo = memory_order_seq_cst) noexcept {
2252 return atomic_base::compare_exchange_weak(expected, desired, mo, cmpexch_failure_order(mo));
2253 }
2254
2258 NEFORCE_ALWAYS_INLINE bool compare_exchange_weak(value_type& expected, value_type desired,
2259 const memory_order mo = memory_order_seq_cst) volatile noexcept {
2260 return atomic_base::compare_exchange_weak(expected, desired, mo, cmpexch_failure_order(mo));
2261 }
2262
2271 NEFORCE_ALWAYS_INLINE bool compare_exchange_strong(value_type& expected, value_type desired,
2272 const memory_order success,
2273 const memory_order failure) noexcept {
2275 return _NEFORCE atomic_cmpexch_strong_any(_NEFORCE addressof(ptr_), _NEFORCE addressof(expected),
2276 _NEFORCE addressof(desired), success, failure);
2277 }
2278
2282 NEFORCE_ALWAYS_INLINE_INLINE bool compare_exchange_strong(value_type& expected, value_type desired,
2283 const memory_order success,
2284 const memory_order failure) volatile noexcept {
2286 return _NEFORCE atomic_cmpexch_strong_any(_NEFORCE addressof(ptr_), _NEFORCE addressof(expected),
2287 _NEFORCE addressof(desired), success, failure);
2288 }
2289
2297 NEFORCE_ALWAYS_INLINE bool compare_exchange_strong(value_type& expected, value_type desired,
2298 const memory_order mo = memory_order_seq_cst) noexcept {
2299 return atomic_base::compare_exchange_strong(expected, desired, mo, cmpexch_failure_order(mo));
2300 }
2301
2305 NEFORCE_ALWAYS_INLINE bool compare_exchange_strong(value_type& expected, value_type desired,
2306 const memory_order mo = memory_order_seq_cst) volatile noexcept {
2307 return atomic_base::compare_exchange_strong(expected, desired, mo, cmpexch_failure_order(mo));
2308 }
2309
2315 NEFORCE_ALWAYS_INLINE void wait(value_type old, const memory_order mo = memory_order_seq_cst) const noexcept {
2316 _NEFORCE atomic_wait_address_v(&ptr_, old, [mo, this] { return this->load(mo); });
2317 }
2318
2322 NEFORCE_ALWAYS_INLINE void notify_one() noexcept { _NEFORCE atomic_notify_address(&ptr_, false); }
2323
2327 NEFORCE_ALWAYS_INLINE void notify_all() noexcept { _NEFORCE atomic_notify_address(&ptr_, true); }
2328
2335 NEFORCE_ALWAYS_INLINE value_type fetch_add(const ptrdiff_t dest,
2336 const memory_order mo = memory_order_seq_cst) noexcept {
2337 const auto byte_offset = static_cast<uintptr_t>(dest * static_cast<ptrdiff_t>(sizeof(T)));
2338 uintptr_t old_val =
2339 _NEFORCE atomic_fetch_add_any(reinterpret_cast<uintptr_t*>(_NEFORCE addressof(ptr_)), byte_offset, mo);
2340 return reinterpret_cast<value_type>(old_val);
2341 }
2342
2346 NEFORCE_ALWAYS_INLINE_INLINE value_type fetch_add(const ptrdiff_t dest,
2347 const memory_order mo = memory_order_seq_cst) volatile noexcept {
2348 const auto byte_offset = static_cast<uintptr_t>(dest * static_cast<ptrdiff_t>(sizeof(T)));
2349 uintptr_t old_val =
2350 _NEFORCE atomic_fetch_add_any(reinterpret_cast<uintptr_t*>(_NEFORCE addressof(ptr_)), byte_offset, mo);
2351 return reinterpret_cast<value_type>(old_val);
2352 }
2353
2360 NEFORCE_ALWAYS_INLINE value_type fetch_sub(const ptrdiff_t dest,
2361 const memory_order mo = memory_order_seq_cst) noexcept {
2362 const auto byte_offset = static_cast<uintptr_t>(dest * static_cast<ptrdiff_t>(sizeof(T)));
2363 uintptr_t old_val =
2364 _NEFORCE atomic_fetch_sub_any(reinterpret_cast<uintptr_t*>(_NEFORCE addressof(ptr_)), byte_offset, mo);
2365 return reinterpret_cast<value_type>(old_val);
2366 }
2367
2371 NEFORCE_ALWAYS_INLINE_INLINE value_type fetch_sub(const ptrdiff_t dest,
2372 const memory_order mo = memory_order_seq_cst) volatile noexcept {
2373 const auto byte_offset = static_cast<uintptr_t>(dest * static_cast<ptrdiff_t>(sizeof(T)));
2374 uintptr_t old_val =
2375 _NEFORCE atomic_fetch_sub_any(reinterpret_cast<uintptr_t*>(_NEFORCE addressof(ptr_)), byte_offset, mo);
2376 return reinterpret_cast<value_type>(old_val);
2377 }
2378};
2379
2380
2388template <typename Float>
2389struct atomic_float_base {
2390 static_assert(is_floating_point_v<Float>, "atomic_ref_base need floating point T");
2391
2392 using value_type = Float;
2394
2395private:
2396 alignas(alignof(Float)) Float float_ = static_cast<Float>(0);
2397
2398public:
2399 atomic_float_base() = default;
2400 atomic_float_base(const atomic_float_base&) = delete;
2401 atomic_float_base& operator=(const atomic_float_base&) = delete;
2402 atomic_float_base& operator=(const atomic_float_base&) volatile = delete;
2403 atomic_float_base(atomic_float_base&&) noexcept = default;
2404 atomic_float_base& operator=(atomic_float_base&&) noexcept = default;
2405
2410 constexpr atomic_float_base(Float value) noexcept(is_nothrow_copy_constructible_v<Float>) :
2411 float_(value) {}
2412
2416 Float operator=(Float value) noexcept {
2417 this->store(value);
2418 return value;
2419 }
2420
2424 Float operator=(Float value) volatile noexcept {
2425 this->store(value);
2426 return value;
2427 }
2428
2432 NEFORCE_NODISCARD bool is_lock_free() const noexcept {
2434 }
2435
2439 NEFORCE_NODISCARD bool is_lock_free() const volatile noexcept {
2441 }
2442
2446 void store(Float value, const memory_order mo = memory_order_seq_cst) noexcept {
2447 _NEFORCE atomic_store_any(&float_, value, mo);
2448 }
2449
2453 void store(Float value, const memory_order mo = memory_order_seq_cst) volatile noexcept {
2454 _NEFORCE atomic_store_any(&float_, value, mo);
2455 }
2456
2460 Float load(const memory_order mo = memory_order_seq_cst) const noexcept {
2461 return _NEFORCE atomic_load_any(&float_, mo);
2462 }
2463
2467 Float load(const memory_order mo = memory_order_seq_cst) const volatile noexcept {
2468 return _NEFORCE atomic_load_any(&float_, mo);
2469 }
2470
2474 operator Float() const noexcept { return this->load(); }
2475
2479 operator Float() const volatile noexcept { return this->load(); }
2480
2484 Float exchange(Float desire, const memory_order mo = memory_order_seq_cst) noexcept {
2485 return _NEFORCE atomic_exchange_any(&float_, desire, mo);
2486 }
2487
2491 Float exchange(Float desire, const memory_order mo = memory_order_seq_cst) volatile noexcept {
2492 return _NEFORCE atomic_exchange_any(&float_, desire, mo);
2493 }
2494
2498 bool compare_exchange_weak(Float& expected, Float desire, const memory_order success,
2499 const memory_order failure) noexcept {
2500 return _NEFORCE atomic_cmpexch_weak_any(&float_, &expected, &desire, success, failure);
2501 }
2502
2506 bool compare_exchange_weak(Float& expected, Float desire, const memory_order success,
2507 const memory_order failure) volatile noexcept {
2508 return _NEFORCE atomic_cmpexch_weak_any(&float_, &expected, &desire, success, failure);
2509 }
2510
2514 bool compare_exchange_strong(Float& expected, Float desire, const memory_order success,
2515 const memory_order failure) noexcept {
2516 return _NEFORCE atomic_cmpexch_strong_any(&float_, &expected, &desire, success, failure);
2517 }
2518
2522 bool compare_exchange_strong(Float& expected, Float desire, const memory_order success,
2523 const memory_order failure) volatile noexcept {
2524 return _NEFORCE atomic_cmpexch_strong_any(&float_, &expected, &desire, success, failure);
2525 }
2526
2530 bool compare_exchange_weak(Float& expected, Float desire, const memory_order mo = memory_order_seq_cst) noexcept {
2531 return _NEFORCE atomic_cmpexch_weak_any(&float_, &expected, &desire, mo, cmpexch_failure_order(mo));
2532 }
2533
2537 bool compare_exchange_weak(Float& expected, Float desire,
2538 const memory_order mo = memory_order_seq_cst) volatile noexcept {
2539 return _NEFORCE atomic_cmpexch_weak_any(&float_, &expected, &desire, mo, cmpexch_failure_order(mo));
2540 }
2541
2545 bool compare_exchange_strong(Float& expected, Float desire, const memory_order mo = memory_order_seq_cst) noexcept {
2546 return _NEFORCE atomic_cmpexch_strong_any(&float_, &expected, &desire, mo, cmpexch_failure_order(mo));
2547 }
2548
2552 bool compare_exchange_strong(Float& expected, Float desire,
2553 const memory_order mo = memory_order_seq_cst) volatile noexcept {
2554 return _NEFORCE atomic_cmpexch_strong_any(&float_, &expected, &desire, mo, cmpexch_failure_order(mo));
2555 }
2556
2562 NEFORCE_ALWAYS_INLINE void wait(Float old, const memory_order mo = memory_order_seq_cst) const noexcept {
2563 _NEFORCE atomic_wait_address_v(&float_, old, [mo, this] { return this->load(mo); });
2564 }
2565
2569 NEFORCE_ALWAYS_INLINE void notify_one() noexcept { _NEFORCE atomic_notify_address(&float_, false); }
2570
2574 NEFORCE_ALWAYS_INLINE void notify_all() noexcept { _NEFORCE atomic_notify_address(&float_, true); }
2575
2583 return _NEFORCE atomic_fetch_add_any(&float_, value, mo);
2584 }
2585
2589 value_type fetch_add(value_type value, const memory_order mo = memory_order_seq_cst) volatile noexcept {
2590 return _NEFORCE atomic_fetch_add_any(&float_, value, mo);
2591 }
2592
2600 return _NEFORCE atomic_fetch_sub_any(&float_, value, mo);
2601 }
2602
2606 value_type fetch_sub(value_type value, const memory_order mo = memory_order_seq_cst) volatile noexcept {
2607 return _NEFORCE atomic_fetch_sub_any(&float_, value, mo);
2608 }
2609
2616 return _NEFORCE atomic_add_fetch_any(&float_, value, memory_order_seq_cst);
2617 }
2618
2622 value_type operator+=(value_type value) volatile noexcept {
2623 return _NEFORCE atomic_add_fetch_any(&float_, value, memory_order_seq_cst);
2624 }
2625
2632 return _NEFORCE atomic_sub_fetch_any(&float_, value, memory_order_seq_cst);
2633 }
2634
2638 value_type operator-=(value_type value) volatile noexcept {
2639 return _NEFORCE atomic_sub_fetch_any(&float_, value, memory_order_seq_cst);
2640 }
2641};
2642
2643
2653template <typename T, bool IsIntegral = is_integral_v<T>, bool IsFloatingPoint = is_floating_point_v<T>>
2655
2656
2661template <typename T>
2662struct atomic_ref_base<T, false, false> {
2663 static_assert(is_trivially_copyable_v<T>, "atomic_ref_base need trivially copyable T");
2664
2665private:
2666 static constexpr int align_inner = (sizeof(T) & (sizeof(T) - 1)) != 0U || sizeof(T) > 16 ? 0 : sizeof(T);
2667
2668 T* ptr_;
2669
2670public:
2671 using value_type = T;
2672
2674 static constexpr size_t required_alignment = align_inner > alignof(T) ? align_inner : alignof(T);
2675
2680 explicit atomic_ref_base(T& value) :
2681 ptr_(_NEFORCE addressof(value)) {
2682 NEFORCE_CONSTEXPR_ASSERT((static_cast<uintptr_t>(ptr_) % required_alignment) == 0);
2683 }
2684
2685 atomic_ref_base(const atomic_ref_base&) noexcept = default;
2686 atomic_ref_base& operator=(const atomic_ref_base&) = delete;
2687
2693 T operator=(T value) noexcept {
2694 this->store(value);
2695 return value;
2696 }
2697
2702 operator T() const noexcept { return this->load(); }
2703
2708 NEFORCE_NODISCARD bool is_lock_free() const noexcept {
2710 }
2711
2717 void store(T value, const memory_order mo = memory_order_seq_cst) noexcept {
2718 _NEFORCE atomic_store_any(ptr_, value, mo);
2719 }
2720
2726 T load(const memory_order mo = memory_order_seq_cst) const noexcept { return _NEFORCE atomic_load_any(ptr_, mo); }
2727
2734 T exchange(T desire, const memory_order mo = memory_order_seq_cst) noexcept {
2735 return _NEFORCE atomic_exchange_any(ptr_, desire, mo);
2736 }
2737
2746 bool compare_exchange_weak(T& expected, T desire, const memory_order success, const memory_order failure) noexcept {
2747 return _NEFORCE atomic_cmpexch_weak_any(ptr_, expected, desire, success, failure);
2748 }
2749
2758 bool compare_exchange_strong(T& expected, T desire, const memory_order success,
2759 const memory_order failure) noexcept {
2760 return _NEFORCE atomic_cmpexch_strong_any(ptr_, expected, desire, success, failure);
2761 }
2762
2770 bool compare_exchange_weak(T& expected, T desire, const memory_order mo = memory_order_seq_cst) noexcept {
2771 return _NEFORCE atomic_cmpexch_weak_any(ptr_, expected, desire, mo, cmpexch_failure_order(mo));
2772 }
2773
2781 bool compare_exchange_strong(T& expected, T desire, const memory_order mo = memory_order_seq_cst) noexcept {
2782 return _NEFORCE atomic_cmpexch_strong_any(ptr_, expected, desire, mo, cmpexch_failure_order(mo));
2783 }
2784
2790 NEFORCE_ALWAYS_INLINE void wait(T old, const memory_order mo = memory_order_seq_cst) const noexcept {
2791 _NEFORCE atomic_wait_address_v(ptr_, old, [this, mo] { return this->load(mo); });
2792 }
2793
2797 NEFORCE_ALWAYS_INLINE void notify_one() noexcept { _NEFORCE atomic_notify_address(ptr_, false); }
2798
2802 NEFORCE_ALWAYS_INLINE void notify_all() noexcept { _NEFORCE atomic_notify_address(ptr_, true); }
2803};
2804
2809template <typename T>
2810struct atomic_ref_base<T, true, false> {
2811 static_assert(is_integral_like_v<T>, "atomic_ref need integral-like T");
2812
2813private:
2814 T* ptr_;
2815
2816public:
2817 using value_type = T;
2819
2821 static constexpr size_t required_alignment = sizeof(T) > alignof(T) ? sizeof(T) : alignof(T);
2822
2823 atomic_ref_base() = delete;
2824 atomic_ref_base(const atomic_ref_base&) noexcept = default;
2825 atomic_ref_base& operator=(const atomic_ref_base&) = delete;
2826
2831 explicit atomic_ref_base(T& value) :
2832 ptr_(&value) {
2833 NEFORCE_CONSTEXPR_ASSERT((reinterpret_cast<uintptr_t>(ptr_) % required_alignment) == 0);
2834 }
2835
2841 T operator=(T value) noexcept {
2842 this->store(value);
2843 return value;
2844 }
2845
2850 NEFORCE_NODISCARD operator T() const noexcept { return this->load(); }
2851
2856 NEFORCE_NODISCARD bool is_lock_free() const noexcept {
2858 }
2859
2865 void store(T value, const memory_order mo = memory_order_seq_cst) noexcept {
2866 _NEFORCE atomic_store(ptr_, value, mo);
2867 }
2868
2874 T load(const memory_order mo = memory_order_seq_cst) const noexcept { return _NEFORCE atomic_load(ptr_, mo); }
2875
2882 T exchange(T desire, const memory_order mo = memory_order_seq_cst) noexcept {
2883 return _NEFORCE atomic_exchange(ptr_, desire, mo);
2884 }
2885
2894 bool compare_exchange_weak(T& expected, T desire, const memory_order success, const memory_order failure) noexcept {
2895 return _NEFORCE atomic_cmpexch_weak(ptr_, &expected, desire, success, failure);
2896 }
2897
2906 bool compare_exchange_strong(T& expected, T desire, const memory_order success,
2907 const memory_order failure) noexcept {
2908 return _NEFORCE atomic_cmpexch_strong(ptr_, &expected, desire, success, failure);
2909 }
2910
2918 bool compare_exchange_weak(T& expected, T desire, const memory_order mo = memory_order_seq_cst) noexcept {
2919 return _NEFORCE atomic_cmpexch_weak(ptr_, &expected, desire, mo, cmpexch_failure_order(mo));
2920 }
2921
2929 bool compare_exchange_strong(T& expected, T desire, const memory_order mo = memory_order_seq_cst) noexcept {
2930 return _NEFORCE atomic_cmpexch_strong(ptr_, &expected, desire, mo, cmpexch_failure_order(mo));
2931 }
2932
2938 NEFORCE_ALWAYS_INLINE void wait(T old, const memory_order mo = memory_order_seq_cst) const noexcept {
2939 _NEFORCE atomic_wait_address_v(ptr_, old, [this, mo] { return this->load(mo); });
2940 }
2941
2945 NEFORCE_ALWAYS_INLINE void notify_one() noexcept { _NEFORCE atomic_notify_address(ptr_, false); }
2946
2950 NEFORCE_ALWAYS_INLINE void notify_all() noexcept { _NEFORCE atomic_notify_address(ptr_, true); }
2951
2959 return _NEFORCE atomic_fetch_add(ptr_, value, mo);
2960 }
2961
2969 return _NEFORCE atomic_fetch_sub(ptr_, value, mo);
2970 }
2971
2979 return _NEFORCE atomic_fetch_and(ptr_, value, mo);
2980 }
2981
2989 return _NEFORCE atomic_fetch_or(ptr_, value, mo);
2990 }
2991
2999 return _NEFORCE atomic_fetch_xor(ptr_, value, mo);
3000 }
3001
3006 NEFORCE_ALWAYS_INLINE value_type operator++(int) noexcept { return fetch_add(1); }
3007
3012 NEFORCE_ALWAYS_INLINE value_type operator--(int) noexcept { return fetch_sub(1); }
3013
3018 value_type operator++() noexcept { return _NEFORCE atomic_add_fetch(ptr_, value_type(1)); }
3019
3024 value_type operator--() noexcept { return _NEFORCE atomic_sub_fetch(ptr_, value_type(1)); }
3025
3031 value_type operator+=(value_type value) noexcept { return _NEFORCE atomic_add_fetch(ptr_, value); }
3032
3038 value_type operator-=(value_type value) noexcept { return _NEFORCE atomic_sub_fetch(ptr_, value); }
3039
3045 value_type operator&=(value_type value) noexcept { return _NEFORCE atomic_and_fetch(ptr_, value); }
3046
3052 value_type operator|=(value_type value) noexcept { return _NEFORCE atomic_or_fetch(ptr_, value); }
3053
3059 value_type operator^=(value_type value) noexcept { return _NEFORCE atomic_xor_fetch(ptr_, value); }
3060};
3061
3066template <typename Float>
3067struct atomic_ref_base<Float, false, true> {
3068 static_assert(is_floating_point_v<Float>, "atomic_ref_base need floating point T");
3069
3070private:
3071 Float* ptr_;
3072
3073public:
3074 using value_type = Float;
3076
3078 static constexpr size_t required_alignment = alignof(Float);
3079
3080 atomic_ref_base() = delete;
3081 atomic_ref_base(const atomic_ref_base&) noexcept = default;
3082 atomic_ref_base& operator=(const atomic_ref_base&) = delete;
3083
3088 explicit atomic_ref_base(Float& value) :
3089 ptr_(&value) {
3090 NEFORCE_CONSTEXPR_ASSERT((static_cast<uintptr_t>(ptr_) % required_alignment) == 0);
3091 }
3092
3098 Float operator=(Float value) noexcept {
3099 this->store(value);
3100 return value;
3101 }
3102
3107 operator Float() const noexcept { return this->load(); }
3108
3113 NEFORCE_NODISCARD bool is_lock_free() const noexcept {
3115 }
3116
3122 void store(Float value, const memory_order mo = memory_order_seq_cst) noexcept {
3123 _NEFORCE atomic_store_any(ptr_, value, mo);
3124 }
3125
3131 Float load(const memory_order mo = memory_order_seq_cst) const noexcept {
3132 return _NEFORCE atomic_load_any(ptr_, mo);
3133 }
3134
3141 Float exchange(Float desire, const memory_order mo = memory_order_seq_cst) noexcept {
3142 return _NEFORCE atomic_exchange_any(ptr_, desire, mo);
3143 }
3144
3153 bool compare_exchange_weak(Float& expected, Float desire, const memory_order success,
3154 const memory_order failure) noexcept {
3155 return _NEFORCE atomic_cmpexch_weak_any(ptr_, expected, desire, success, failure);
3156 }
3157
3166 bool compare_exchange_strong(Float& expected, Float desire, const memory_order success,
3167 const memory_order failure) noexcept {
3168 return _NEFORCE atomic_cmpexch_strong_any(ptr_, expected, desire, success, failure);
3169 }
3170
3178 bool compare_exchange_weak(Float& expected, Float desire, const memory_order mo = memory_order_seq_cst) noexcept {
3179 return _NEFORCE atomic_cmpexch_weak_any(ptr_, expected, desire, mo, cmpexch_failure_order(mo));
3180 }
3181
3189 bool compare_exchange_strong(Float& expected, Float desire, const memory_order mo = memory_order_seq_cst) noexcept {
3190 return _NEFORCE atomic_cmpexch_strong_any(ptr_, expected, desire, mo, cmpexch_failure_order(mo));
3191 }
3192
3198 NEFORCE_ALWAYS_INLINE void wait(Float old, const memory_order mo = memory_order_seq_cst) const noexcept {
3199 _NEFORCE atomic_wait_address_v(ptr_, old, [this, mo] { return this->load(mo); });
3200 }
3201
3205 NEFORCE_ALWAYS_INLINE void notify_one() noexcept { _NEFORCE atomic_notify_address(ptr_, false); }
3206
3210 NEFORCE_ALWAYS_INLINE void notify_all() noexcept { _NEFORCE atomic_notify_address(ptr_, true); }
3211
3219 return _NEFORCE atomic_fetch_add_any(ptr_, value, mo);
3220 }
3221
3229 return _NEFORCE atomic_fetch_sub_any(ptr_, value, mo);
3230 }
3231
3238 return _NEFORCE atomic_add_fetch_any(ptr_, value, memory_order_seq_cst);
3239 }
3240
3247 return _NEFORCE atomic_sub_fetch_any(ptr_, value, memory_order_seq_cst);
3248 }
3249};
3250
3251
3252#ifdef NEFORCE_COMPILER_CLANG
3253# pragma clang diagnostic push
3254# pragma clang diagnostic ignored "-Watomic-alignment"
3255#endif
3256
3261template <typename T>
3262struct atomic_ref_base<T*, false, false> {
3263public:
3264 using value_type = T*;
3266
3267private:
3268 T** ptr_;
3269
3270 static constexpr difference_type real_type_sizes(const difference_type dest) noexcept {
3271 static_assert(is_object_v<T>, "atomic_ref_base need object T");
3272 return dest * sizeof(T);
3273 }
3274
3275public:
3277 static constexpr size_t required_alignment = sizeof(T*) == 8 ? 8 : alignof(T*);
3278
3279 atomic_ref_base() = delete;
3280 atomic_ref_base(const atomic_ref_base&) noexcept = default;
3281 atomic_ref_base& operator=(const atomic_ref_base&) = delete;
3282
3287 explicit atomic_ref_base(T*& value) :
3288 ptr_(_NEFORCE addressof(value)) {
3289 NEFORCE_CONSTEXPR_ASSERT((static_cast<uintptr_t>(ptr_) % required_alignment) == 0);
3290 }
3291
3297 T* operator=(T* value) noexcept {
3298 this->store(value);
3299 return value;
3300 }
3301
3306 operator T*() const noexcept { return this->load(); }
3307
3312 NEFORCE_NODISCARD bool is_lock_free() const noexcept {
3314 }
3315
3321 void store(T* value, const memory_order mo = memory_order_seq_cst) noexcept {
3322 _NEFORCE atomic_store_any(ptr_, value, mo);
3323 }
3324
3330 T* load(const memory_order mo = memory_order_seq_cst) const noexcept { return _NEFORCE atomic_load_any(ptr_, mo); }
3331
3338 T* exchange(T* desire, const memory_order mo = memory_order_seq_cst) noexcept {
3339 return _NEFORCE atomic_exchange_any(ptr_, desire, mo);
3340 }
3341
3350 bool compare_exchange_weak(T*& expected, T* desire, const memory_order success,
3351 const memory_order failure) noexcept {
3352 return _NEFORCE atomic_cmpexch_weak_any(ptr_, expected, desire, success, failure);
3353 }
3354
3363 bool compare_exchange_strong(T*& expected, T* desire, const memory_order success,
3364 const memory_order failure) noexcept {
3365 return _NEFORCE atomic_cmpexch_strong_any(ptr_, expected, desire, success, failure);
3366 }
3367
3375 bool compare_exchange_weak(T*& expected, T* desire, const memory_order mo = memory_order_seq_cst) noexcept {
3376 return _NEFORCE atomic_cmpexch_weak_any(ptr_, expected, desire, mo, cmpexch_failure_order(mo));
3377 }
3378
3386 bool compare_exchange_strong(T*& expected, T* desire, const memory_order mo = memory_order_seq_cst) noexcept {
3387 return _NEFORCE atomic_cmpexch_strong_any(ptr_, expected, desire, mo, cmpexch_failure_order(mo));
3388 }
3389
3395 NEFORCE_ALWAYS_INLINE void wait(T* old, const memory_order mo = memory_order_seq_cst) const noexcept {
3396 _NEFORCE atomic_wait_address_v(ptr_, old, [this, mo] { return this->load(mo); });
3397 }
3398
3402 NEFORCE_ALWAYS_INLINE void notify_one() noexcept { _NEFORCE atomic_notify_address(ptr_, false); }
3403
3407 NEFORCE_ALWAYS_INLINE void notify_all() noexcept { _NEFORCE atomic_notify_address(ptr_, true); }
3408
3415 NEFORCE_ALWAYS_INLINE value_type fetch_add(const difference_type dest,
3416 const memory_order mo = memory_order_seq_cst) noexcept {
3417 const auto byte_offset = static_cast<uintptr_t>(dest * static_cast<difference_type>(sizeof(T)));
3418 uintptr_t old_val = _NEFORCE atomic_fetch_add_any(reinterpret_cast<uintptr_t*>(ptr_), byte_offset, mo);
3419 return reinterpret_cast<value_type>(old_val);
3420 }
3421
3428 NEFORCE_ALWAYS_INLINE value_type fetch_sub(const difference_type dest,
3429 const memory_order mo = memory_order_seq_cst) noexcept {
3430 const auto byte_offset = static_cast<uintptr_t>(dest * static_cast<difference_type>(sizeof(T)));
3431 uintptr_t old_val = _NEFORCE atomic_fetch_sub_any(reinterpret_cast<uintptr_t*>(ptr_), byte_offset, mo);
3432 return reinterpret_cast<value_type>(old_val);
3433 }
3434
3439 value_type operator++(int) noexcept { return fetch_add(1); }
3440
3445 value_type operator--(int) noexcept { return fetch_sub(1); }
3446
3451 value_type operator++() noexcept { return fetch_add(1) + 1; }
3452
3457 value_type operator--() noexcept { return fetch_sub(1) - 1; }
3458
3464 value_type operator+=(const difference_type dest) noexcept { return fetch_add(dest) + dest; }
3465
3471 value_type operator-=(const difference_type dest) noexcept { return fetch_sub(dest) - dest; }
3472};
3473
3474#ifdef NEFORCE_COMPILER_CLANG
3475# pragma clang diagnostic pop
3476#endif
3477 // AtomicOperations
3479 // AsyncComponents
3481
3482NEFORCE_END_NAMESPACE__
3483#endif // NEFORCE_CORE_ASYNC_ATOMIC_BASE_HPP__
原子等待/通知机制
调试断点和断言工具
constexpr T * addressof(T &x) noexcept
获取对象的地址
remove_volatile_t< T > atomic_or_fetch(volatile T *ptr, remove_volatile_t< T > value, memory_order mo) noexcept
原子或并获取操作
void atomic_signal_fence(const memory_order mo) noexcept
信号内存屏障
void atomic_store(volatile T *ptr, remove_volatile_t< T > value, const memory_order mo) noexcept
原子存储操作
remove_volatile_t< T > atomic_load_any(const T *ptr, memory_order mo) noexcept
通用原子加载操作
bool atomic_cmpexch_strong(volatile T *ptr, remove_volatile_t< T > *expected, remove_volatile_t< T > desired, const memory_order success, const memory_order failure) noexcept
强比较交换操作
remove_volatile_t< T > atomic_fetch_and(volatile T *ptr, remove_volatile_t< T > value, const memory_order mo) noexcept
原子获取并与操作
T atomic_fetch_sub_any(T *ptr, remove_volatile_t< T > value, memory_order mo) noexcept
通用原子获取并减去操作
remove_volatile_t< T > atomic_fetch_xor(volatile T *ptr, remove_volatile_t< T > value, const memory_order mo) noexcept
原子获取并异或操作
remove_volatile_t< T > atomic_and_fetch(volatile T *ptr, remove_volatile_t< T > value, memory_order mo) noexcept
原子与并获取操作
remove_volatile_t< T > atomic_fetch_or(volatile T *ptr, remove_volatile_t< T > value, const memory_order mo) noexcept
原子获取并或操作
conditional_t< is_pointer_v< T >, ptrdiff_t, remove_volatile_t< T > > atomic_diff_t
原子操作的差值类型
remove_volatile_t< T > atomic_fetch_sub(volatile T *ptr, atomic_diff_t< T > value, const memory_order mo) noexcept
原子获取并减去操作
bool atomic_cmpexch_weak(volatile T *ptr, remove_volatile_t< T > *expected, remove_volatile_t< T > desired, const memory_order success, const memory_order failure) noexcept
弱比较交换操作
bool atomic_cmpexch_weak_any(volatile T *ptr, remove_volatile_t< T > *expected, remove_volatile_t< T > *desired, const memory_order success, const memory_order failure) noexcept
通用弱比较交换操作
T atomic_fetch_add_any(T *ptr, remove_volatile_t< T > value, memory_order mo) noexcept
通用原子获取并添加操作
void atomic_wait_address_v(const T *addr, T old, Func f) noexcept
基于值的原子等待
T atomic_sub_fetch_any(T *ptr, remove_volatile_t< T > value, memory_order mo) noexcept
通用原子减去并获取操作
constexpr bool is_always_lock_free() noexcept
检查是否支持无锁操作
bool atomic_cmpexch_strong_any(volatile T *ptr, remove_volatile_t< T > *expected, remove_volatile_t< T > *desired, const memory_order success, const memory_order failure) noexcept
通用强比较交换操作
T atomic_add_fetch_any(T *ptr, remove_volatile_t< T > value, memory_order mo) noexcept
通用原子添加并获取操作
remove_volatile_t< T > atomic_exchange(volatile T *ptr, remove_volatile_t< T > value, const memory_order mo) noexcept
原子交换操作
remove_volatile_t< T > atomic_fetch_add(volatile T *ptr, atomic_diff_t< T > value, const memory_order mo) noexcept
原子获取并添加操作
remove_volatile_t< T > atomic_xor_fetch(volatile T *ptr, remove_volatile_t< T > value, memory_order mo) noexcept
原子异或并获取操作
remove_volatile_t< T > atomic_add_fetch(volatile T *ptr, atomic_diff_t< T > value, memory_order mo) noexcept
原子添加并获取操作
void atomic_store_any(T *ptr, remove_volatile_t< T > value, const memory_order mo) noexcept
通用原子存储操作
remove_volatile_t< T > atomic_exchange_any(T *ptr, remove_volatile_t< T > desired, memory_order mo) noexcept
通用原子交换操作
remove_volatile_t< T > atomic_sub_fetch(volatile T *ptr, atomic_diff_t< T > value, memory_order mo) noexcept
原子减去并获取操作
void atomic_thread_fence(const memory_order mo) noexcept
线程内存屏障
remove_volatile_t< T > atomic_load(const volatile T *ptr, const memory_order mo) noexcept
原子加载操作
void atomic_notify_address(const T *addr, const bool all) noexcept
原子通知
constexpr bool is_floating_point_v
is_floating_point的便捷变量模板
constexpr bool is_integral_v
is_integral的便捷变量模板
constexpr bool is_integral_like_v
is_integral_like的便捷变量模板
constexpr bool is_object_v
is_object的便捷变量模板
unsigned char byte_t
字节类型,定义为无符号字符
unsigned int uint32_t
32位无符号整数类型
unsigned long uint64_t
64位无符号整数类型
int int32_t
32位有符号整数类型
#define NEFORCE_CONSTEXPR_ASSERT(COND)
编译时常量断言
long platform_wait_t
平台等待类型别名
constexpr void * memory_copy(void *__restrict dest, const void *__restrict src, size_t count) noexcept
从源内存复制到目标内存
constexpr int memory_compare(const void *lhs, const void *rhs, size_t count) noexcept
比较两个内存区域的内容
constexpr auto memory_order_release
释放内存顺序常量
constexpr auto memory_order_seq_cst
顺序一致性内存顺序常量
constexpr memory_order cmpexch_failure_order(const memory_order mo) noexcept
获取原子比较交换操作失败时的内存顺序
constexpr auto memory_order_acq_rel
获取-释放内存顺序常量
constexpr auto memory_order_acquire
获取内存顺序常量
memory_order
内存顺序
constexpr auto memory_order_consume
数据依赖内存顺序常量
constexpr bool is_valid_cmpexch_failure_order(const memory_order mo) noexcept
检查比较交换失败内存顺序是否有效
constexpr auto memory_order_relaxed
宽松内存顺序常量
uint64_t uintptr_t
可容纳指针的无符号整数类型
int64_t ptrdiff_t
指针差类型
typename remove_volatile< T >::type remove_volatile_t
remove_volatile的便捷别名
constexpr bool is_trivially_copyable_v
is_trivially_copyable的便捷变量模板
constexpr bool is_nothrow_copy_constructible_v
is_nothrow_copy_constructible的便捷变量模板
typename conditional< Test, T1, T2 >::type conditional_t
conditional的便捷别名
原子内存序定义
bool compare_exchange_strong(value_type &expected, value_type desired, const memory_order mo=memory_order_seq_cst) volatile noexcept
volatile版本的简化版强比较交换指针操作
value_type operator-=(const ptrdiff_t dest) noexcept
指针减法赋值运算符
value_type operator--(int) noexcept
后置递减运算符
value_type fetch_sub(const ptrdiff_t dest, const memory_order mo=memory_order_seq_cst) volatile noexcept
volatile版本的原子获取并减去指针偏移
ptrdiff_t difference_type
差值类型
value_type fetch_add(const ptrdiff_t dest, const memory_order mo=memory_order_seq_cst) noexcept
原子获取并添加指针偏移
value_type operator++(int) volatile noexcept
volatile版本的后置递增运算符
value_type exchange(const value_type ptr, const memory_order mo=memory_order_seq_cst) volatile noexcept
volatile版本的原子交换指针操作
value_type operator++(int) noexcept
后置递增运算符
value_type operator+=(const ptrdiff_t dest) volatile noexcept
volatile版本的指针加法赋值运算符
value_type operator++() volatile noexcept
volatile版本的前置递增运算符
value_type operator+=(const ptrdiff_t dest) noexcept
指针加法赋值运算符
value_type load(const memory_order mo=memory_order_seq_cst) const volatile noexcept
volatile版本的原子加载指针操作
bool is_lock_free() const noexcept
检查是否支持无锁操作
value_type operator=(const value_type ptr) volatile noexcept
volatile版本的赋值运算符
value_type operator--(int) volatile noexcept
volatile版本的后置递减运算符
value_type operator=(const value_type ptr) noexcept
赋值运算符
value_type operator--() noexcept
前置递减运算符
value_type operator--() volatile noexcept
volatile版本的前置递减运算符
void store(const value_type ptr, const memory_order mo=memory_order_seq_cst) volatile noexcept
volatile版本的原子存储指针操作
bool compare_exchange_strong(value_type &expected, value_type desired, const memory_order mo=memory_order_seq_cst) noexcept
简化版强比较交换指针操作
value_type fetch_add(const ptrdiff_t dest, const memory_order mo=memory_order_seq_cst) volatile noexcept
volatile版本的原子获取并添加指针偏移
value_type fetch_sub(const ptrdiff_t dest, const memory_order mo=memory_order_seq_cst) noexcept
原子获取并减去指针偏移
value_type load(const memory_order mo=memory_order_seq_cst) const noexcept
原子加载指针操作
bool compare_exchange_weak(value_type &expected, value_type desired, const memory_order success, const memory_order failure) volatile noexcept
volatile版本的弱比较交换指针操作
value_type exchange(const value_type ptr, const memory_order mo=memory_order_seq_cst) noexcept
原子交换指针操作
value_type operator++() noexcept
前置递增运算符
bool compare_exchange_weak(value_type &expected, value_type desired, const memory_order mo=memory_order_seq_cst) noexcept
简化版弱比较交换指针操作
void store(value_type ptr, const memory_order mo=memory_order_seq_cst) noexcept
原子存储指针操作
bool compare_exchange_strong(value_type &expected, value_type desired, const memory_order success, const memory_order failure) noexcept
强比较交换指针操作
bool is_lock_free() const volatile noexcept
volatile版本的检查是否支持无锁操作
value_type operator-=(const ptrdiff_t dest) volatile noexcept
volatile版本的指针减法赋值运算符
bool compare_exchange_strong(value_type &expected, value_type desired, const memory_order success, const memory_order failure) volatile noexcept
volatile版本的强比较交换指针操作
void notify_all() noexcept
通知所有等待线程
void wait(value_type old, const memory_order mo=memory_order_seq_cst) const noexcept
等待指针改变
bool compare_exchange_weak(value_type &expected, value_type desired, const memory_order mo=memory_order_seq_cst) volatile noexcept
volatile版本的简化版弱比较交换指针操作
void notify_one() noexcept
通知一个等待线程
bool compare_exchange_weak(value_type &expected, value_type desired, const memory_order success, const memory_order failure) noexcept
弱比较交换指针操作
原子类型基础模板类
value_type fetch_xor(value_type value, const memory_order mo=memory_order_seq_cst) noexcept
原子获取并异或操作
bool compare_exchange_strong(value_type &expected, value_type desired, const memory_order success, const memory_order failure) noexcept
强比较交换操作
value_type fetch_sub(value_type value, const memory_order mo=memory_order_seq_cst) volatile noexcept
volatile版本的原子获取并减去操作
value_type operator=(value_type value) volatile noexcept
volatile版本的赋值运算符
value_type operator--(int) volatile noexcept
volatile版本的后置递减运算符
value_type operator&=(value_type value) volatile noexcept
volatile版本的位与赋值运算符
void notify_one() noexcept
通知一个等待线程
value_type operator=(value_type value) noexcept
赋值运算符
value_type operator--() volatile noexcept
volatile版本的前置递减运算符
value_type fetch_or(value_type value, const memory_order mo=memory_order_seq_cst) noexcept
原子获取并或操作
value_type operator-=(value_type value) noexcept
减法赋值运算符
value_type load(const memory_order mo=memory_order_seq_cst) const volatile noexcept
volatile版本的原子加载操作
void notify_all() noexcept
通知所有等待线程
value_type fetch_or(value_type value, const memory_order mo=memory_order_seq_cst) volatile noexcept
volatile版本的原子获取并或操作
value_type load(const memory_order mo=memory_order_seq_cst) const noexcept
value_type fetch_add(value_type value, const memory_order mo=memory_order_seq_cst) volatile noexcept
volatile版本的原子获取并添加操作
value_type operator+=(value_type value) volatile noexcept
volatile版本的加法赋值运算符
void store(value_type value, const memory_order mo=memory_order_seq_cst) volatile noexcept
volatile版本的原子存储操作
bool compare_exchange_strong(value_type &expected, value_type desired, const memory_order success, const memory_order failure) volatile noexcept
volatile版本的强比较交换操作
value_type fetch_and(value_type value, const memory_order mo=memory_order_seq_cst) noexcept
原子获取并与操作
bool compare_exchange_strong(value_type &expected, value_type desired, const memory_order mo=memory_order_seq_cst) noexcept
简化版强比较交换操作
void wait(value_type old, const memory_order mo=memory_order_seq_cst) const noexcept
等待值改变
value_type exchange(value_type value, const memory_order mo=memory_order_seq_cst) volatile noexcept
volatile版本的原子交换操作
value_type fetch_xor(value_type value, const memory_order mo=memory_order_seq_cst) volatile noexcept
volatile版本的原子获取并异或操作
value_type fetch_add(value_type value, const memory_order mo=memory_order_seq_cst) noexcept
bool compare_exchange_strong(value_type &expected, value_type desired, const memory_order mo=memory_order_seq_cst) volatile noexcept
volatile版本的简化版强比较交换操作
value_type operator^=(value_type value) volatile noexcept
volatile版本的位异或赋值运算符
value_type fetch_sub(value_type value, const memory_order mo=memory_order_seq_cst) noexcept
value_type operator&=(value_type value) noexcept
位与赋值运算符
value_type operator--(int) noexcept
后置递减运算符
value_type exchange(value_type value, const memory_order mo=memory_order_seq_cst) noexcept
原子交换操作
bool is_lock_free() const volatile noexcept
volatile版本的检查是否支持无锁操作
value_type operator++() noexcept
前置递增运算符
value_type operator++() volatile noexcept
volatile版本的前置递增运算符
value_type operator|=(value_type value) volatile noexcept
volatile版本的位或赋值运算符
value_type operator-=(value_type value) volatile noexcept
volatile版本的减法赋值运算符
value_type operator+=(value_type value) noexcept
加法赋值运算符
value_type operator--() noexcept
前置递减运算符
void store(value_type value, const memory_order mo=memory_order_seq_cst) noexcept
原子存储操作
value_type operator|=(value_type value) noexcept
位或赋值运算符
value_type operator++(int) noexcept
后置递增运算符
bool compare_exchange_weak(value_type &expected, value_type desired, const memory_order success, const memory_order failure) volatile noexcept
volatile版本的弱比较交换操作
bool compare_exchange_weak(value_type &expected, value_type desired, const memory_order mo=memory_order_seq_cst) volatile noexcept
volatile版本的简化版弱比较交换操作
bool compare_exchange_weak(value_type &expected, value_type desired, const memory_order mo=memory_order_seq_cst) noexcept
简化版弱比较交换操作
value_type fetch_and(value_type value, const memory_order mo=memory_order_seq_cst) volatile noexcept
volatile版本的原子获取并与操作
value_type operator^=(value_type value) noexcept
位异或赋值运算符
value_type operator++(int) volatile noexcept
volatile版本的后置递增运算符
bool compare_exchange_weak(value_type &expected, value_type desired, const memory_order success, const memory_order failure) noexcept
弱比较交换操作
bool is_lock_free() const noexcept
检查是否支持无锁操作
bool test(const memory_order mo=memory_order_seq_cst) const noexcept
测试标志值
void clear(const memory_order mo=memory_order_seq_cst) noexcept
清除标志
value_type flag_
原子标志值
bool test_and_set(const memory_order mo=memory_order_seq_cst) volatile noexcept
volatile版本的测试并设置标志
void wait(const bool old, const memory_order mo=memory_order_seq_cst) const volatile noexcept
volatile版本的等待标志值改变
bool test_and_set(const memory_order mo=memory_order_seq_cst) noexcept
测试并设置标志
bool test(const memory_order mo=memory_order_seq_cst) const volatile noexcept
volatile版本的测试标志值
void clear(const memory_order mo=memory_order_seq_cst) volatile noexcept
volatile版本的清除标志
void notify_all() noexcept
通知所有等待线程
void notify_one() noexcept
通知一个等待线程
void wait(const bool old, const memory_order mo=memory_order_seq_cst) const noexcept
等待标志值改变
long value_type
原子标志类型
void notify_one() noexcept
通知一个等待线程
bool compare_exchange_weak(Float &expected, Float desire, const memory_order mo=memory_order_seq_cst) noexcept
简化版弱比较交换操作
bool compare_exchange_weak(Float &expected, Float desire, const memory_order success, const memory_order failure) volatile noexcept
volatile版本的弱比较交换操作
bool compare_exchange_weak(Float &expected, Float desire, const memory_order success, const memory_order failure) noexcept
弱比较交换操作
Float operator=(Float value) volatile noexcept
volatile版本的赋值运算符
void store(Float value, const memory_order mo=memory_order_seq_cst) noexcept
原子存储操作
Float load(const memory_order mo=memory_order_seq_cst) const noexcept
原子加载操作
value_type operator+=(value_type value) volatile noexcept
volatile版本的加法赋值运算符
bool is_lock_free() const noexcept
检查是否支持无锁操作
value_type operator-=(value_type value) noexcept
减法赋值运算符
Float exchange(Float desire, const memory_order mo=memory_order_seq_cst) noexcept
原子交换操作
value_type operator-=(value_type value) volatile noexcept
volatile版本的减法赋值运算符
value_type difference_type
差值类型
value_type fetch_add(value_type value, const memory_order mo=memory_order_seq_cst) volatile noexcept
volatile版本的原子获取并添加操作
value_type fetch_sub(value_type value, const memory_order mo=memory_order_seq_cst) noexcept
原子获取并减去操作
bool compare_exchange_strong(Float &expected, Float desire, const memory_order mo=memory_order_seq_cst) noexcept
简化版强比较交换操作
value_type fetch_sub(value_type value, const memory_order mo=memory_order_seq_cst) volatile noexcept
volatile版本的原子获取并减去操作
bool is_lock_free() const volatile noexcept
volatile版本的检查是否支持无锁操作
void store(Float value, const memory_order mo=memory_order_seq_cst) volatile noexcept
volatile版本的原子存储操作
void notify_all() noexcept
通知所有等待线程
bool compare_exchange_strong(Float &expected, Float desire, const memory_order success, const memory_order failure) volatile noexcept
volatile版本的强比较交换操作
value_type fetch_add(value_type value, const memory_order mo=memory_order_seq_cst) noexcept
原子获取并添加操作
bool compare_exchange_strong(Float &expected, Float desire, const memory_order mo=memory_order_seq_cst) volatile noexcept
volatile版本的简化版强比较交换操作
value_type operator+=(value_type value) noexcept
加法赋值运算符
Float load(const memory_order mo=memory_order_seq_cst) const volatile noexcept
volatile版本的原子加载操作
bool compare_exchange_weak(Float &expected, Float desire, const memory_order mo=memory_order_seq_cst) volatile noexcept
volatile版本的简化版弱比较交换操作
Float exchange(Float desire, const memory_order mo=memory_order_seq_cst) volatile noexcept
volatile版本的原子交换操作
Float operator=(Float value) noexcept
赋值运算符
bool compare_exchange_strong(Float &expected, Float desire, const memory_order success, const memory_order failure) noexcept
强比较交换操作
void wait(Float old, const memory_order mo=memory_order_seq_cst) const noexcept
等待值改变
void store(Float value, const memory_order mo=memory_order_seq_cst) noexcept
原子存储操作
static constexpr size_t required_alignment
对齐需求
Float exchange(Float desire, const memory_order mo=memory_order_seq_cst) noexcept
原子交换操作
bool compare_exchange_weak(Float &expected, Float desire, const memory_order success, const memory_order failure) noexcept
弱比较交换操作
bool compare_exchange_strong(Float &expected, Float desire, const memory_order mo=memory_order_seq_cst) noexcept
简化版强比较交换操作
Float load(const memory_order mo=memory_order_seq_cst) const noexcept
原子加载操作
bool compare_exchange_strong(Float &expected, Float desire, const memory_order success, const memory_order failure) noexcept
强比较交换操作
value_type fetch_add(value_type value, const memory_order mo=memory_order_seq_cst) noexcept
原子获取并添加操作
bool is_lock_free() const noexcept
检查是否支持无锁操作
bool compare_exchange_weak(Float &expected, Float desire, const memory_order mo=memory_order_seq_cst) noexcept
简化版弱比较交换操作
value_type operator+=(value_type value) noexcept
加法赋值运算符
void wait(Float old, const memory_order mo=memory_order_seq_cst) const noexcept
等待值改变
void notify_one() noexcept
通知一个等待线程
Float operator=(Float value) noexcept
赋值运算符
value_type operator-=(value_type value) noexcept
减法赋值运算符
value_type fetch_sub(value_type value, const memory_order mo=memory_order_seq_cst) noexcept
原子获取并减去操作
void notify_all() noexcept
通知所有等待线程
static constexpr size_t required_alignment
对齐需求
T exchange(T desire, const memory_order mo=memory_order_seq_cst) noexcept
原子交换操作
void notify_one() noexcept
通知一个等待线程
bool compare_exchange_strong(T &expected, T desire, const memory_order success, const memory_order failure) noexcept
强比较交换操作
bool compare_exchange_weak(T &expected, T desire, const memory_order mo=memory_order_seq_cst) noexcept
简化版弱比较交换操作
T load(const memory_order mo=memory_order_seq_cst) const noexcept
原子加载操作
T operator=(T value) noexcept
赋值运算符
void notify_all() noexcept
通知所有等待线程
bool is_lock_free() const noexcept
检查是否支持无锁操作
void wait(T old, const memory_order mo=memory_order_seq_cst) const noexcept
等待值改变
bool compare_exchange_strong(T &expected, T desire, const memory_order mo=memory_order_seq_cst) noexcept
简化版强比较交换操作
void store(T value, const memory_order mo=memory_order_seq_cst) noexcept
原子存储操作
bool compare_exchange_weak(T &expected, T desire, const memory_order success, const memory_order failure) noexcept
弱比较交换操作
bool is_lock_free() const noexcept
检查是否支持无锁操作
bool compare_exchange_strong(T &expected, T desire, const memory_order success, const memory_order failure) noexcept
强比较交换操作
value_type fetch_xor(value_type value, const memory_order mo=memory_order_seq_cst) noexcept
原子获取并异或操作
value_type operator+=(value_type value) noexcept
加法赋值运算符
value_type operator--(int) noexcept
后置递减运算符
value_type operator++(int) noexcept
后置递增运算符
void store(T value, const memory_order mo=memory_order_seq_cst) noexcept
原子存储操作
T exchange(T desire, const memory_order mo=memory_order_seq_cst) noexcept
原子交换操作
value_type fetch_and(value_type value, const memory_order mo=memory_order_seq_cst) noexcept
原子获取并与操作
bool compare_exchange_weak(T &expected, T desire, const memory_order success, const memory_order failure) noexcept
弱比较交换操作
void notify_one() noexcept
通知一个等待线程
static constexpr size_t required_alignment
对齐需求
bool compare_exchange_strong(T &expected, T desire, const memory_order mo=memory_order_seq_cst) noexcept
简化版强比较交换操作
value_type operator|=(value_type value) noexcept
位或赋值运算符
value_type operator&=(value_type value) noexcept
位与赋值运算符
value_type operator++() noexcept
前置递增运算符
value_type fetch_add(value_type value, const memory_order mo=memory_order_seq_cst) noexcept
原子获取并添加操作
T operator=(T value) noexcept
赋值运算符
void wait(T old, const memory_order mo=memory_order_seq_cst) const noexcept
等待值改变
value_type operator-=(value_type value) noexcept
减法赋值运算符
value_type operator^=(value_type value) noexcept
位异或赋值运算符
bool compare_exchange_weak(T &expected, T desire, const memory_order mo=memory_order_seq_cst) noexcept
简化版弱比较交换操作
T load(const memory_order mo=memory_order_seq_cst) const noexcept
原子加载操作
value_type fetch_sub(value_type value, const memory_order mo=memory_order_seq_cst) noexcept
原子获取并减去操作
value_type fetch_or(value_type value, const memory_order mo=memory_order_seq_cst) noexcept
原子获取并或操作
void notify_all() noexcept
通知所有等待线程
value_type operator--() noexcept
前置递减运算符
bool compare_exchange_weak(T *&expected, T *desire, const memory_order mo=memory_order_seq_cst) noexcept
简化版弱比较交换指针操作
value_type operator--(int) noexcept
后置递减运算符
T * operator=(T *value) noexcept
赋值运算符
void wait(T *old, const memory_order mo=memory_order_seq_cst) const noexcept
等待指针改变
bool compare_exchange_strong(T *&expected, T *desire, const memory_order mo=memory_order_seq_cst) noexcept
简化版强比较交换指针操作
value_type operator++() noexcept
前置递增运算符
value_type fetch_add(const difference_type dest, const memory_order mo=memory_order_seq_cst) noexcept
原子获取并添加指针偏移
T * exchange(T *desire, const memory_order mo=memory_order_seq_cst) noexcept
原子交换指针操作
T * load(const memory_order mo=memory_order_seq_cst) const noexcept
原子加载指针操作
bool compare_exchange_strong(T *&expected, T *desire, const memory_order success, const memory_order failure) noexcept
强比较交换指针操作
value_type operator-=(const difference_type dest) noexcept
指针减法赋值运算符
bool is_lock_free() const noexcept
检查是否支持无锁操作
value_type operator--() noexcept
前置递减运算符
value_type operator+=(const difference_type dest) noexcept
指针加法赋值运算符
void notify_all() noexcept
通知所有等待线程
static constexpr size_t required_alignment
对齐需求
value_type fetch_sub(const difference_type dest, const memory_order mo=memory_order_seq_cst) noexcept
原子获取并减去指针偏移
void store(T *value, const memory_order mo=memory_order_seq_cst) noexcept
原子存储指针操作
void notify_one() noexcept
通知一个等待线程
bool compare_exchange_weak(T *&expected, T *desire, const memory_order success, const memory_order failure) noexcept
弱比较交换指针操作
value_type operator++(int) noexcept
后置递增运算符
原子引用基础模板类