NexusForce 1.0.0
A Modern C++ Library with extended functionality, web components, and utility libraries
载入中...
搜索中...
未找到
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
40NEFORCE_ALWAYS_INLINE_INLINE void atomic_thread_fence(const memory_order mo) noexcept {
41#ifdef NEFORCE_COMPILER_MSVC
42 if (mo == memory_order_relaxed) {
43 return;
44 }
45# if defined(NEFORCE_ARCH_X86)
46 ::_ReadWriteBarrier();
47 if (mo == memory_order_seq_cst) {
48 volatile long guard = 0;
49 ::_InterlockedIncrement(&guard);
50 ::_ReadWriteBarrier();
51 }
52# elif defined(NEFORCE_ARCH_ARM)
53 if (mo == memory_order_acquire || mo == memory_order_consume) {
54 ::_Memory_load_acquire_barrier();
55 } else {
56 ::_ReadWriteBarrier();
57 }
58# else
59 ::_ReadWriteBarrier();
60# endif
61#else
62 __atomic_thread_fence(static_cast<int32_t>(mo));
63#endif
64}
65
72NEFORCE_ALWAYS_INLINE_INLINE void atomic_signal_fence(const memory_order mo) noexcept {
73#ifdef NEFORCE_COMPILER_MSVC
74 if (mo != memory_order_relaxed) {
75 ::_ReadWriteBarrier();
76 }
77#else
78 __atomic_signal_fence(static_cast<int32_t>(mo));
79#endif
80}
81
82
84NEFORCE_BEGIN_INNER__
85
86#ifdef NEFORCE_COMPILER_MSVC
87
88template <size_t Size>
89struct interlocked_exchange_impl;
90
91template <>
92struct interlocked_exchange_impl<1> {
93 template <typename T>
94 static T call(volatile T* target, T value) {
95 return static_cast<T>(
96 ::_InterlockedExchange8(reinterpret_cast<volatile char*>(target), static_cast<char>(value)));
97 }
98};
99template <>
100struct interlocked_exchange_impl<2> {
101 template <typename T>
102 static T call(volatile T* target, T value) {
103 return static_cast<T>(
104 ::_InterlockedExchange16(reinterpret_cast<volatile short*>(target), static_cast<short>(value)));
105 }
106};
107template <>
108struct interlocked_exchange_impl<4> {
109 template <typename T>
110 static T call(volatile T* target, T value) {
111 return static_cast<T>(
112 ::_InterlockedExchange(reinterpret_cast<volatile long*>(target), static_cast<long>(value)));
113 }
114};
115template <>
116struct interlocked_exchange_impl<8> {
117 template <typename T>
118 static T call(volatile T* target, T value) {
119# if defined(NEFORCE_ARCH_BITS_64) || defined(NEFORCE_COMPILER_CLANG_CL)
120 return static_cast<T>(
121 ::_InterlockedExchange64(reinterpret_cast<volatile long long*>(target), static_cast<long long>(value)));
122# else
123 return static_cast<T>(
124 ::_interlockedexchange64(reinterpret_cast<volatile long long*>(target), static_cast<long long>(value)));
125# endif
126 }
127};
128
129template <size_t Size>
130struct interlocked_compare_exchange_impl;
131
132template <>
133struct interlocked_compare_exchange_impl<1> {
134 template <typename T>
135 static bool call(volatile T* target, T* expected, T desired) {
136 const char old =
137 ::_InterlockedCompareExchange8(reinterpret_cast<volatile char*>(target),
138 *reinterpret_cast<char*>(&desired), *reinterpret_cast<char*>(expected));
139 if (old == *reinterpret_cast<char*>(expected)) {
140 return true;
141 }
142 *reinterpret_cast<char*>(expected) = old;
143 return false;
144 }
145};
146template <>
147struct interlocked_compare_exchange_impl<2> {
148 template <typename T>
149 static bool call(volatile T* target, T* expected, T desired) {
150 const short old = ::_InterlockedCompareExchange16(reinterpret_cast<volatile short*>(target),
151 *reinterpret_cast<short*>(&desired),
152 *reinterpret_cast<short*>(expected));
153 if (old == *reinterpret_cast<short*>(expected)) {
154 return true;
155 }
156 *reinterpret_cast<short*>(expected) = old;
157 return false;
158 }
159};
160template <>
161struct interlocked_compare_exchange_impl<4> {
162 template <typename T>
163 static bool call(volatile T* target, T* expected, T desired) {
164 const long old =
165 ::_InterlockedCompareExchange(reinterpret_cast<volatile long*>(target),
166 *reinterpret_cast<long*>(&desired), *reinterpret_cast<long*>(expected));
167 if (old == *reinterpret_cast<long*>(expected)) {
168 return true;
169 }
170 *reinterpret_cast<long*>(expected) = old;
171 return false;
172 }
173};
174template <>
175struct interlocked_compare_exchange_impl<8> {
176 template <typename T>
177 static bool call(volatile T* target, T* expected, T desired) {
178 const long long old = ::_InterlockedCompareExchange64(reinterpret_cast<volatile long long*>(target),
179 *reinterpret_cast<long long*>(&desired),
180 *reinterpret_cast<long long*>(expected));
181 if (old == *reinterpret_cast<long long*>(expected)) {
182 return true;
183 }
184 *reinterpret_cast<long long*>(expected) = old;
185 return false;
186 }
187};
188template <>
189struct interlocked_compare_exchange_impl<16> {
190# if !(defined(NEFORCE_ARCH_BITS_64) || defined(NEFORCE_ARCH_AARCH64))
191private:
192 struct futex_lock_128 {
193 alignas(64) volatile platform_wait_t state_ = 0;
194
195 static futex_lock_128& for_addr(const void* addr) noexcept {
196 constexpr uintptr_t pool_size = 64;
197 static futex_lock_128 pool[pool_size];
198 return pool[(reinterpret_cast<uintptr_t>(addr) >> 4) % pool_size];
199 }
200
201 void lock(const void* /*addr*/) noexcept {
202 for (;;) {
203 if (::_InterlockedCompareExchange(&state_, 1, 0) == 0) {
204 return;
205 }
206 _NEFORCE atomic_wait_address_v(const_cast<platform_wait_t*>(&state_), static_cast<platform_wait_t>(1),
207 [this] { return ::_InterlockedExchangeAdd(&state_, 0); });
208 }
209 }
210
211 void unlock(const void* /*addr*/) noexcept {
212 ::_InterlockedExchange(&state_, 0);
213 _NEFORCE atomic_notify_address(const_cast<platform_wait_t*>(&state_), false);
214 }
215 };
216# endif
217
218 template <typename T>
219 static bool call(volatile T* target, T* expected, T desired) {
220 alignas(16) long long exp_arr[2];
221 alignas(16) long long des_arr[2];
222 _NEFORCE memory_copy(exp_arr, expected, 16);
223 _NEFORCE memory_copy(des_arr, &desired, 16);
224 bool result = false;
225
226# if defined(NEFORCE_ARCH_BITS_64) || defined(NEFORCE_ARCH_AARCH64)
227 result = ::_InterlockedCompareExchange128(reinterpret_cast<volatile long long*>(target), des_arr[1], des_arr[0],
228 exp_arr) != 0;
229# else
230 auto& flock = futex_lock_128::for_addr(target);
231 flock.lock(target);
232 if (_NEFORCE memory_compare(const_cast<T*>(target), exp_arr, 16) == 0) {
233 _NEFORCE memory_copy(const_cast<T*>(target), des_arr, 16);
234 flock.unlock(target);
235 result = true;
236 } else {
237 _NEFORCE memory_copy(exp_arr, const_cast<T*>(target), 16);
238 flock.unlock(target);
239 result = false;
240 }
241# endif
242
243 if (!result) {
244 _NEFORCE memory_copy(expected, exp_arr, 16);
245 }
246 return result;
247 }
248};
249
250template <size_t Size>
251struct interlocked_fetch_add_impl;
252
253template <>
254struct interlocked_fetch_add_impl<1> {
255 template <typename T>
256 static T call(volatile T* target, T value) {
257 return static_cast<T>(
258 ::_InterlockedExchangeAdd8(reinterpret_cast<volatile char*>(target), static_cast<char>(value)));
259 }
260};
261template <>
262struct interlocked_fetch_add_impl<2> {
263 template <typename T>
264 static T call(volatile T* target, T value) {
265 return static_cast<T>(
266 ::_InterlockedExchangeAdd16(reinterpret_cast<volatile short*>(target), static_cast<short>(value)));
267 }
268};
269template <>
270struct interlocked_fetch_add_impl<4> {
271 template <typename T>
272 static T call(volatile T* target, T value) {
273 return static_cast<T>(
274 ::_InterlockedExchangeAdd(reinterpret_cast<volatile long*>(target), static_cast<long>(value)));
275 }
276};
277template <>
278struct interlocked_fetch_add_impl<8> {
279 template <typename T>
280 static T call(volatile T* target, T value) {
281# if defined(NEFORCE_ARCH_BITS_64) || defined(NEFORCE_COMPILER_CLANG_CL)
282 return static_cast<T>(::_InterlockedExchangeAdd64(reinterpret_cast<volatile long long*>(target),
283 static_cast<long long>(value)));
284# else
285 return static_cast<T>(::_interlockedexchangeadd64(reinterpret_cast<volatile long long*>(target),
286 static_cast<long long>(value)));
287# endif
288 }
289};
290
291template <size_t Size>
292struct interlocked_fetch_and_impl;
293
294template <>
295struct interlocked_fetch_and_impl<1> {
296 template <typename T>
297 static T call(volatile T* target, T value) {
298 return static_cast<T>(::_InterlockedAnd8(reinterpret_cast<volatile char*>(target), static_cast<char>(value)));
299 }
300};
301template <>
302struct interlocked_fetch_and_impl<2> {
303 template <typename T>
304 static T call(volatile T* target, T value) {
305 return static_cast<T>(
306 ::_InterlockedAnd16(reinterpret_cast<volatile short*>(target), static_cast<short>(value)));
307 }
308};
309template <>
310struct interlocked_fetch_and_impl<4> {
311 template <typename T>
312 static T call(volatile T* target, T value) {
313 return static_cast<T>(::_InterlockedAnd(reinterpret_cast<volatile long*>(target), static_cast<long>(value)));
314 }
315};
316template <>
317struct interlocked_fetch_and_impl<8> {
318 template <typename T>
319 static T call(volatile T* target, T value) {
320# if defined(NEFORCE_ARCH_BITS_64) || defined(NEFORCE_COMPILER_CLANG_CL)
321 return static_cast<T>(
322 ::_InterlockedAnd64(reinterpret_cast<volatile long long*>(target), static_cast<long long>(value)));
323# else
324 return static_cast<T>(
325 ::_interlockedadd64(reinterpret_cast<volatile long long*>(target), static_cast<long long>(value)));
326# endif
327 }
328};
329
330template <size_t Size>
331struct interlocked_fetch_or_impl;
332
333template <>
334struct interlocked_fetch_or_impl<1> {
335 template <typename T>
336 static T call(volatile T* target, T value) {
337 return static_cast<T>(::_InterlockedOr8(reinterpret_cast<volatile char*>(target), static_cast<char>(value)));
338 }
339};
340template <>
341struct interlocked_fetch_or_impl<2> {
342 template <typename T>
343 static T call(volatile T* target, T value) {
344 return static_cast<T>(::_InterlockedOr16(reinterpret_cast<volatile short*>(target), static_cast<short>(value)));
345 }
346};
347template <>
348struct interlocked_fetch_or_impl<4> {
349 template <typename T>
350 static T call(volatile T* target, T value) {
351 return static_cast<T>(::_InterlockedOr(reinterpret_cast<volatile long*>(target), static_cast<long>(value)));
352 }
353};
354template <>
355struct interlocked_fetch_or_impl<8> {
356 template <typename T>
357 static T call(volatile T* target, T value) {
358# if defined(NEFORCE_ARCH_BITS_64) || defined(NEFORCE_COMPILER_CLANG_CL)
359 return static_cast<T>(
360 ::_InterlockedOr64(reinterpret_cast<volatile long long*>(target), static_cast<long long>(value)));
361# else
362 return static_cast<T>(
363 ::_interlockedor64(reinterpret_cast<volatile long long*>(target), static_cast<long long>(value)));
364# endif
365 }
366};
367
368template <size_t Size>
369struct interlocked_fetch_xor_impl;
370
371template <>
372struct interlocked_fetch_xor_impl<1> {
373 template <typename T>
374 static T call(volatile T* target, T value) {
375 return static_cast<T>(::_InterlockedXor8(reinterpret_cast<volatile char*>(target), static_cast<char>(value)));
376 }
377};
378template <>
379struct interlocked_fetch_xor_impl<2> {
380 template <typename T>
381 static T call(volatile T* target, T value) {
382 return static_cast<T>(
383 ::_InterlockedXor16(reinterpret_cast<volatile short*>(target), static_cast<short>(value)));
384 }
385};
386template <>
387struct interlocked_fetch_xor_impl<4> {
388 template <typename T>
389 static T call(volatile T* target, T value) {
390 return static_cast<T>(::_InterlockedXor(reinterpret_cast<volatile long*>(target), static_cast<long>(value)));
391 }
392};
393template <>
394struct interlocked_fetch_xor_impl<8> {
395 template <typename T>
396 static T call(volatile T* target, T value) {
397# if defined(NEFORCE_ARCH_BITS_64) || defined(NEFORCE_COMPILER_CLANG_CL)
398 return static_cast<T>(
399 ::_InterlockedXor64(reinterpret_cast<volatile long long*>(target), static_cast<long long>(value)));
400# else
401 return static_cast<T>(
402 ::_interlockedxor64(reinterpret_cast<volatile long long*>(target), static_cast<long long>(value)));
403# endif
404 }
405};
406
407template <size_t Size>
408struct atomic_is_always_lock_free_impl {
409 static constexpr bool value = false;
410};
411template <>
412struct atomic_is_always_lock_free_impl<1> {
413 static constexpr bool value = true;
414};
415template <>
416struct atomic_is_always_lock_free_impl<2> {
417 static constexpr bool value = true;
418};
419template <>
420struct atomic_is_always_lock_free_impl<4> {
421 static constexpr bool value = true;
422};
423template <>
424struct atomic_is_always_lock_free_impl<8> {
425 static constexpr bool value = true;
426};
427template <>
428struct atomic_is_always_lock_free_impl<16> {
429# if defined(NEFORCE_ARCH_X86_64) || defined(NEFORCE_ARCH_AARCH64)
430 static constexpr bool value = true;
431# else
432 static constexpr bool value = false;
433# endif
434};
435#endif
436
437NEFORCE_END_INNER__
439
440
445template <typename T>
447
448
457template <typename T>
458NEFORCE_ALWAYS_INLINE_INLINE void atomic_store(volatile T* ptr, remove_volatile_t<T> value,
459 const memory_order mo) noexcept {
460 static_assert(is_integral_v<T>, "T must be integral type");
461#ifdef NEFORCE_COMPILER_GNUC
462 __atomic_store_n(ptr, value, static_cast<int32_t>(mo));
463#else
464 inner::interlocked_exchange_impl<sizeof(T)>::call(ptr, value);
465 if (mo == memory_order_seq_cst || mo == memory_order_release) {
466 ::_ReadWriteBarrier();
467 }
468#endif
469}
470
479template <typename T>
480NEFORCE_ALWAYS_INLINE_INLINE remove_volatile_t<T> atomic_load(const volatile T* ptr, const memory_order mo) noexcept {
481 static_assert(is_integral_v<T>, "T must be integral type");
482#ifdef NEFORCE_COMPILER_GNUC
483 return __atomic_load_n(ptr, static_cast<int32_t>(mo));
484#else
485 remove_volatile_t<T> result = *ptr;
486 if (mo == memory_order_seq_cst || mo == memory_order_acquire) {
487 ::_ReadWriteBarrier();
488 }
489 return result;
490#endif
491}
492
502template <typename T>
503NEFORCE_ALWAYS_INLINE_INLINE remove_volatile_t<T> atomic_exchange(volatile T* ptr, remove_volatile_t<T> value,
504 const memory_order mo) noexcept {
505 static_assert(is_integral_v<T>, "T must be integral type");
506#ifdef NEFORCE_COMPILER_GNUC
507 return __atomic_exchange_n(ptr, value, static_cast<int32_t>(mo));
508#else
509 remove_volatile_t<T> old = inner::interlocked_exchange_impl<sizeof(T)>::call(ptr, value);
510 if (mo == memory_order_seq_cst) {
511 ::_ReadWriteBarrier();
512 }
513 return old;
514#endif
515}
516
529template <typename T>
530NEFORCE_ALWAYS_INLINE_INLINE bool atomic_cmpexch_weak(volatile T* ptr, remove_volatile_t<T>* expected,
532 const memory_order failure) noexcept {
533 static_assert(is_integral_v<T>, "T must be integral type");
535#ifdef NEFORCE_COMPILER_GNUC
536 return __atomic_compare_exchange_n(ptr, expected, desired, true, static_cast<int32_t>(success),
537 static_cast<int32_t>(failure));
538#else
539# if defined(NEFORCE_ARCH_X86) || defined(NEFORCE_ARCH_AARCH64)
540 const bool result = inner::interlocked_compare_exchange_impl<sizeof(T)>::call(ptr, expected, desired);
542 ::_ReadWriteBarrier();
543 }
544 return result;
545# else
546 remove_volatile_t<T> old_val = *expected;
548 bool success_flag;
549# if defined(NEFORCE_ARCH_ARM)
550 NEFORCE_IF_CONSTEXPR(sizeof(T) == 1) {
551 asm volatile("ldrexb %[loaded], [%[ptr]]\n\t"
552 "cmp %[loaded], %[old_val]\n\t"
553 "bne 1f\n\t"
554 "strexb %w[success], %w[desired], [%[ptr]]\n\t"
555 "1:"
556 : [loaded] "=&r"(loaded), [success] "=&r"(success_flag)
557 : [ptr] "r"(ptr), [old_val] "r"(old_val), [desired] "r"(desired)
558 : "cc", "memory");
559 }
560 else NEFORCE_IF_CONSTEXPR(sizeof(T) == 2) {
561 asm volatile("ldrexh %[loaded], [%[ptr]]\n\t"
562 "cmp %[loaded], %[old_val]\n\t"
563 "bne 1f\n\t"
564 "strexh %w[success], %w[desired], [%[ptr]]\n\t"
565 "1:"
566 : [loaded] "=&r"(loaded), [success] "=&r"(success_flag)
567 : [ptr] "r"(ptr), [old_val] "r"(old_val), [desired] "r"(desired)
568 : "cc", "memory");
569 }
570 else NEFORCE_IF_CONSTEXPR(sizeof(T) == 4) {
571 asm volatile("ldrex %[loaded], [%[ptr]]\n\t"
572 "cmp %[loaded], %[old_val]\n\t"
573 "bne 1f\n\t"
574 "strex %w[success], %w[desired], [%[ptr]]\n\t"
575 "1:"
576 : [loaded] "=&r"(loaded), [success] "=&r"(success_flag)
577 : [ptr] "r"(ptr), [old_val] "r"(old_val), [desired] "r"(desired)
578 : "cc", "memory");
579 }
580 else NEFORCE_IF_CONSTEXPR(sizeof(T) == 8) {
581 uint32_t loaded_lo, loaded_hi;
582 uint32_t old_lo = static_cast<uint32_t>(old_val);
583 uint32_t old_hi = static_cast<uint32_t>(static_cast<uint64_t>(old_val) >> 32);
584 uint32_t des_lo = static_cast<uint32_t>(static_cast<uint64_t>(desired));
585 uint32_t des_hi = static_cast<uint32_t>(static_cast<uint64_t>(desired) >> 32);
586 uint32_t tmp_success = 0;
587 asm volatile(
588 "ldrexd %[lo], %[hi], [%[ptr]]\n\t"
589 "cmp %[lo], %[old_lo]\n\t"
590 "cmpeq %[hi], %[old_hi]\n\t"
591 "bne 1f\n\t"
592 "strexd %[success], %[des_lo], %[des_hi], [%[ptr]]\n\t"
593 "1:"
594 : [lo] "=&r"(loaded_lo), [hi] "=&r"(loaded_hi), [success] "=&r"(tmp_success)
595 : [ptr] "r"(ptr), [old_lo] "r"(old_lo), [old_hi] "r"(old_hi), [des_lo] "r"(des_lo), [des_hi] "r"(des_hi)
596 : "cc", "memory");
597 loaded = static_cast<T>(static_cast<uint64_t>(loaded_lo) | (static_cast<uint64_t>(loaded_hi) << 32));
598 success_flag = (tmp_success == 0);
599 if (loaded != old_val) {
600 *expected = loaded;
601 return false;
602 }
603 return success_flag;
604 }
605# elif defined(NEFORCE_ARCH_RISCV)
606 NEFORCE_IF_CONSTEXPR(sizeof(T) == 4) {
607 asm volatile("lr.w %[loaded], (%[ptr])\n\t"
608 "bne %[loaded], %[old_val], 1f\n\t"
609 "sc.w %[success], %[desired], (%[ptr])\n\t"
610 "1:"
611 : [loaded] "=&r"(loaded), [success] "=&r"(success_flag)
612 : [ptr] "r"(ptr), [old_val] "r"(old_val), [desired] "r"(desired)
613 : "memory");
614 }
615 else NEFORCE_IF_CONSTEXPR(sizeof(T) == 8) {
616 asm volatile("lr.d %[loaded], (%[ptr])\n\t"
617 "bne %[loaded], %[old_val], 1f\n\t"
618 "sc.d %[success], %[desired], (%[ptr])\n\t"
619 "1:"
620 : [loaded] "=&r"(loaded), [success] "=&r"(success_flag)
621 : [ptr] "r"(ptr), [old_val] "r"(old_val), [desired] "r"(desired)
622 : "memory");
623 }
624# elif defined(NEFORCE_ARCH_LOONGARCH)
625 NEFORCE_IF_CONSTEXPR(sizeof(T) == 4) {
626 uint32_t sc_result;
627 uint32_t des_copy = static_cast<uint32_t>(desired);
628 asm volatile("ll.w %[loaded], %[ptr]\n\t"
629 "bne %[loaded], %[old_val], 1f\n\t"
630 "sc.w %[des_copy], %[ptr]\n\t"
631 "1:\n\t"
632 "move %[success], %[des_copy]\n\t"
633 : [loaded] "=&r"(loaded), [des_copy] "+r"(des_copy), [success] "=r"(sc_result)
634 : [ptr] "m"(*ptr), [old_val] "r"(old_val)
635 : "memory");
636 success_flag = (sc_result == 0);
637 }
638 else NEFORCE_IF_CONSTEXPR(sizeof(T) == 8) {
639 asm volatile("ll.d %[loaded], %[ptr]\n\t"
640 "bne %[loaded], %[old_val], 1f\n\t"
641 "sc.d %[desired], %[ptr]\n\t"
642 "move %[success], %[desired]\n\t"
643 "1:"
644 : [loaded] "=&r"(loaded), [success] "=&r"(success_flag)
645 : [ptr] "m"(*ptr), [old_val] "r"(old_val), [desired] "r"(desired)
646 : "memory");
647 }
648# endif
649 if (loaded != old_val) {
650 *expected = loaded;
651 return false;
652 }
653 return success_flag == 0;
654# endif
655#endif
656}
657
670template <typename T>
671NEFORCE_ALWAYS_INLINE_INLINE bool atomic_cmpexch_strong(volatile T* ptr, remove_volatile_t<T>* expected,
673 const memory_order failure) noexcept {
674 static_assert(is_integral_v<T>, "T must be integral type");
676#ifdef NEFORCE_COMPILER_GNUC
677 return __atomic_compare_exchange_n(ptr, expected, desired, false, static_cast<int32_t>(success),
678 static_cast<int32_t>(failure));
679#else
680# if defined(NEFORCE_ARCH_X86) || defined(NEFORCE_ARCH_AARCH64)
681 return _NEFORCE atomic_cmpexch_weak(ptr, expected, desired, success, failure);
682# else
683 remove_volatile_t<T> old_val = *expected;
684 while (true) {
685 if (_NEFORCE atomic_cmpexch_weak(ptr, expected, desired, success, failure)) {
686 return true;
687 }
688 if (*expected != old_val) {
689 return false;
690 }
691 }
692# endif
693#endif
694}
695
705template <typename T>
706NEFORCE_ALWAYS_INLINE_INLINE remove_volatile_t<T> atomic_fetch_add(volatile T* ptr, atomic_diff_t<T> value,
707 const memory_order mo) noexcept {
708 static_assert(is_integral_v<T>, "T must be integral type");
709#ifdef NEFORCE_COMPILER_GNUC
710 return __atomic_fetch_add(ptr, value, static_cast<int32_t>(mo));
711#else
712 remove_volatile_t<T> old = inner::interlocked_fetch_add_impl<sizeof(T)>::call(ptr, value);
713 if (mo == memory_order_seq_cst) {
714 ::_ReadWriteBarrier();
715 }
716 return old;
717#endif
718}
719
729template <typename T>
730NEFORCE_ALWAYS_INLINE_INLINE remove_volatile_t<T> atomic_fetch_sub(volatile T* ptr, atomic_diff_t<T> value,
731 const memory_order mo) noexcept {
732 static_assert(is_integral_v<T>, "T must be integral type");
733#ifdef NEFORCE_COMPILER_GNUC
734 return __atomic_fetch_sub(ptr, value, static_cast<int32_t>(mo));
735#else
736 return _NEFORCE atomic_fetch_add(ptr, static_cast<atomic_diff_t<T>>(-value), mo);
737#endif
738}
739
749template <typename T>
750NEFORCE_ALWAYS_INLINE_INLINE remove_volatile_t<T> atomic_fetch_and(volatile T* ptr, remove_volatile_t<T> value,
751 const memory_order mo) noexcept {
752 static_assert(is_integral_v<T>, "T must be integral type");
753#ifdef NEFORCE_COMPILER_GNUC
754 return __atomic_fetch_and(ptr, value, static_cast<int32_t>(mo));
755#else
756 remove_volatile_t<T> old = inner::interlocked_fetch_and_impl<sizeof(T)>::call(ptr, value);
757 if (mo == memory_order_seq_cst) {
758 ::_ReadWriteBarrier();
759 }
760 return old;
761#endif
762}
763
773template <typename T>
774NEFORCE_ALWAYS_INLINE_INLINE remove_volatile_t<T> atomic_fetch_or(volatile T* ptr, remove_volatile_t<T> value,
775 const memory_order mo) noexcept {
776 static_assert(is_integral_v<T>, "T must be integral type");
777#ifdef NEFORCE_COMPILER_GNUC
778 return __atomic_fetch_or(ptr, value, static_cast<int32_t>(mo));
779#else
780 remove_volatile_t<T> old = inner::interlocked_fetch_or_impl<sizeof(T)>::call(ptr, value);
781 if (mo == memory_order_seq_cst) {
782 ::_ReadWriteBarrier();
783 }
784 return old;
785#endif
786}
787
797template <typename T>
798NEFORCE_ALWAYS_INLINE_INLINE remove_volatile_t<T> atomic_fetch_xor(volatile T* ptr, remove_volatile_t<T> value,
799 const memory_order mo) noexcept {
800 static_assert(is_integral_v<T>, "T must be integral type");
801#ifdef NEFORCE_COMPILER_GNUC
802 return __atomic_fetch_xor(ptr, value, static_cast<int32_t>(mo));
803#else
804 remove_volatile_t<T> old = inner::interlocked_fetch_xor_impl<sizeof(T)>::call(ptr, value);
805 if (mo == memory_order_seq_cst) {
806 ::_ReadWriteBarrier();
807 }
808 return old;
809#endif
810}
811
821template <typename T>
822NEFORCE_ALWAYS_INLINE_INLINE remove_volatile_t<T> atomic_add_fetch(volatile T* ptr, atomic_diff_t<T> value,
823 memory_order mo) noexcept {
824 static_assert(is_integral_v<T>, "T must be integral type");
825#ifdef NEFORCE_COMPILER_GNUC
826 return __atomic_add_fetch(ptr, value, static_cast<int32_t>(mo));
827#else
828 return _NEFORCE atomic_fetch_add(ptr, value, mo) + value;
829#endif
830}
831
841template <typename T>
842NEFORCE_ALWAYS_INLINE_INLINE remove_volatile_t<T> atomic_sub_fetch(volatile T* ptr, atomic_diff_t<T> value,
843 memory_order mo) noexcept {
844 static_assert(is_integral_v<T>, "T must be integral type");
845#ifdef NEFORCE_COMPILER_GNUC
846 return __atomic_sub_fetch(ptr, value, static_cast<int32_t>(mo));
847#else
848 return _NEFORCE atomic_fetch_sub(ptr, value, mo) - value;
849#endif
850}
851
861template <typename T>
862NEFORCE_ALWAYS_INLINE_INLINE remove_volatile_t<T> atomic_and_fetch(volatile T* ptr, remove_volatile_t<T> value,
863 memory_order mo) noexcept {
864 static_assert(is_integral_v<T>, "T must be integral type");
865#ifdef NEFORCE_COMPILER_GNUC
866 return __atomic_and_fetch(ptr, value, static_cast<int32_t>(mo));
867#else
868 return _NEFORCE atomic_fetch_and(ptr, value, mo) & value;
869#endif
870}
871
881template <typename T>
882NEFORCE_ALWAYS_INLINE_INLINE remove_volatile_t<T> atomic_or_fetch(volatile T* ptr, remove_volatile_t<T> value,
883 memory_order mo) noexcept {
884 static_assert(is_integral_v<T>, "T must be integral type");
885#ifdef NEFORCE_COMPILER_GNUC
886 return __atomic_or_fetch(ptr, value, static_cast<int32_t>(mo));
887#else
888 return _NEFORCE atomic_fetch_or(ptr, value, mo) | value;
889#endif
890}
891
901template <typename T>
902NEFORCE_ALWAYS_INLINE_INLINE remove_volatile_t<T> atomic_xor_fetch(volatile T* ptr, remove_volatile_t<T> value,
903 memory_order mo) noexcept {
904 static_assert(is_integral_v<T>, "T must be integral type");
905#ifdef NEFORCE_COMPILER_GNUC
906 return __atomic_xor_fetch(ptr, value, static_cast<int32_t>(mo));
907#else
908 return _NEFORCE atomic_fetch_xor(ptr, value, mo) ^ value;
909#endif
910}
911
912
924template <typename T>
925NEFORCE_ALWAYS_INLINE_INLINE bool atomic_cmpexch_weak_any(volatile T* ptr, remove_volatile_t<T>* expected,
927 const memory_order failure) noexcept {
929#ifdef NEFORCE_COMPILER_GNUC
930 return __atomic_compare_exchange(ptr, expected, desired, true, static_cast<int32_t>(success),
931 static_cast<int32_t>(failure));
932#else
933# if defined(NEFORCE_ARCH_X86) || defined(NEFORCE_ARCH_AARCH64)
934 const bool result = inner::interlocked_compare_exchange_impl<sizeof(T)>::call(ptr, expected, *desired);
936 ::_ReadWriteBarrier();
937 }
938 return result;
939# else
940 remove_volatile_t<T> old_val = *expected;
942 bool success_flag;
943# if defined(NEFORCE_ARCH_ARM)
944 NEFORCE_IF_CONSTEXPR(sizeof(T) == 1) {
945 asm volatile("ldrexb %[loaded], [%[ptr]]\n\t"
946 "cmp %[loaded], %[old_val]\n\t"
947 "bne 1f\n\t"
948 "strexb %w[success], %w[desired], [%[ptr]]\n\t"
949 "1:"
950 : [loaded] "=&r"(loaded), [success] "=&r"(success_flag)
951 : [ptr] "r"(ptr), [old_val] "r"(old_val), [desired] "r"(desired)
952 : "cc", "memory");
953 }
954 else NEFORCE_IF_CONSTEXPR(sizeof(T) == 2) {
955 asm volatile("ldrexh %[loaded], [%[ptr]]\n\t"
956 "cmp %[loaded], %[old_val]\n\t"
957 "bne 1f\n\t"
958 "strexh %w[success], %w[desired], [%[ptr]]\n\t"
959 "1:"
960 : [loaded] "=&r"(loaded), [success] "=&r"(success_flag)
961 : [ptr] "r"(ptr), [old_val] "r"(old_val), [desired] "r"(desired)
962 : "cc", "memory");
963 }
964 else NEFORCE_IF_CONSTEXPR(sizeof(T) == 4) {
965 asm volatile("ldrex %[loaded], [%[ptr]]\n\t"
966 "cmp %[loaded], %[old_val]\n\t"
967 "bne 1f\n\t"
968 "strex %w[success], %w[desired], [%[ptr]]\n\t"
969 "1:"
970 : [loaded] "=&r"(loaded), [success] "=&r"(success_flag)
971 : [ptr] "r"(ptr), [old_val] "r"(old_val), [desired] "r"(desired)
972 : "cc", "memory");
973 }
974 else NEFORCE_IF_CONSTEXPR(sizeof(T) == 8) {
975 asm volatile("ldrexd %[loaded], [%[ptr]]\n\t"
976 "cmp %[loaded], %[old_val]\n\t"
977 "bne 1f\n\t"
978 "strexd %w[success], %[desired], [%[ptr]]\n\t"
979 "1:"
980 : [loaded] "=&r"(loaded), [success] "=&r"(success_flag)
981 : [ptr] "r"(ptr), [old_val] "r"(old_val), [desired] "r"(desired)
982 : "cc", "memory");
983 }
984# elif defined(NEFORCE_ARCH_RISCV)
985 NEFORCE_IF_CONSTEXPR(sizeof(T) == 4) {
986 asm volatile("lr.w %[loaded], (%[ptr])\n\t"
987 "bne %[loaded], %[old_val], 1f\n\t"
988 "sc.w %[success], %[desired], (%[ptr])\n\t"
989 "1:"
990 : [loaded] "=&r"(loaded), [success] "=&r"(success_flag)
991 : [ptr] "r"(ptr), [old_val] "r"(old_val), [desired] "r"(desired)
992 : "memory");
993 }
994 else NEFORCE_IF_CONSTEXPR(sizeof(T) == 8) {
995 asm volatile("lr.d %[loaded], (%[ptr])\n\t"
996 "bne %[loaded], %[old_val], 1f\n\t"
997 "sc.d %[success], %[desired], (%[ptr])\n\t"
998 "1:"
999 : [loaded] "=&r"(loaded), [success] "=&r"(success_flag)
1000 : [ptr] "r"(ptr), [old_val] "r"(old_val), [desired] "r"(desired)
1001 : "memory");
1002 }
1003# elif defined(NEFORCE_ARCH_LOONGARCH)
1004 NEFORCE_IF_CONSTEXPR(sizeof(T) == 4) {
1005 asm volatile("ll.w %[loaded], %[ptr]\n\t"
1006 "bne %[loaded], %[old_val], 1f\n\t"
1007 "sc.w %[desired], %[ptr]\n\t"
1008 "move %[success], %[desired]\n\t"
1009 "1:"
1010 : [loaded] "=&r"(loaded), [success] "=&r"(success_flag)
1011 : [ptr] "m"(*ptr), [old_val] "r"(old_val), [desired] "r"(desired)
1012 : "memory");
1013 }
1014 else NEFORCE_IF_CONSTEXPR(sizeof(T) == 8) {
1015 asm volatile("ll.d %[loaded], %[ptr]\n\t"
1016 "bne %[loaded], %[old_val], 1f\n\t"
1017 "sc.d %[desired], %[ptr]\n\t"
1018 "move %[success], %[desired]\n\t"
1019 "1:"
1020 : [loaded] "=&r"(loaded), [success] "=&r"(success_flag)
1021 : [ptr] "m"(*ptr), [old_val] "r"(old_val), [desired] "r"(desired)
1022 : "memory");
1023 }
1024# endif
1025 if (loaded != old_val) {
1026 *expected = loaded;
1027 return false;
1028 }
1029 return success_flag == 0;
1030# endif
1031#endif
1032}
1033
1045template <typename T>
1046NEFORCE_ALWAYS_INLINE_INLINE bool atomic_cmpexch_strong_any(volatile T* ptr, remove_volatile_t<T>* expected,
1048 const memory_order failure) noexcept {
1050#ifdef NEFORCE_COMPILER_GNUC
1051 return __atomic_compare_exchange(ptr, expected, desired, false, static_cast<int32_t>(success),
1052 static_cast<int32_t>(failure));
1053#else
1054# if defined(NEFORCE_ARCH_X86) || defined(NEFORCE_ARCH_AARCH64)
1055 const bool result = inner::interlocked_compare_exchange_impl<sizeof(T)>::call(ptr, expected, *desired);
1056 if (success == memory_order_seq_cst || failure == memory_order_seq_cst) {
1057 ::_ReadWriteBarrier();
1058 }
1059 return result;
1060# else
1061 remove_volatile_t<T> old_val = *expected;
1062 while (true) {
1063 if (_NEFORCE atomic_cmpexch_weak_any(ptr, expected, desired, success, failure)) {
1064 return true;
1065 }
1066 if (_NEFORCE memory_compare<remove_volatile_t<T>>(old_val, *expected) != 0) {
1067 return false;
1068 }
1069 }
1070# endif
1071#endif
1072}
1073
1082template <typename T>
1083NEFORCE_ALWAYS_INLINE_INLINE void atomic_store_any(T* ptr, remove_volatile_t<T> value, const memory_order mo) noexcept {
1084#ifdef NEFORCE_COMPILER_GNUC
1085 __atomic_store(ptr, _NEFORCE addressof(value), static_cast<int32_t>(mo));
1086#else
1087 remove_volatile_t<T> expected = *ptr;
1088 while (!_NEFORCE atomic_cmpexch_weak_any(ptr, &expected, &value, mo, memory_order_relaxed)) {
1089 // Retry
1090 }
1091#endif
1092}
1093
1102template <typename T>
1103NEFORCE_ALWAYS_INLINE_INLINE remove_volatile_t<T> atomic_load_any(const T* ptr, memory_order mo) noexcept {
1104#ifdef NEFORCE_COMPILER_GNUC
1105 alignas(T) byte_t buffer[sizeof(T)];
1106 T* dest = reinterpret_cast<remove_volatile_t<T>*>(buffer);
1107 __atomic_load(ptr, dest, static_cast<int32_t>(mo));
1108 return *dest;
1109#else
1110 remove_volatile_t<T> result;
1111 _NEFORCE memory_copy<remove_volatile_t<T>>(&result, ptr);
1112 if (mo == memory_order_seq_cst || mo == memory_order_acquire) {
1113 ::_ReadWriteBarrier();
1114 }
1115 return result;
1116#endif
1117}
1118
1128template <typename T>
1129NEFORCE_ALWAYS_INLINE_INLINE remove_volatile_t<T> atomic_exchange_any(T* ptr, remove_volatile_t<T> desired,
1130 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_exchange(ptr, _NEFORCE addressof(desired), dest, static_cast<int32_t>(mo));
1135 return *dest;
1136#else
1138 while (!_NEFORCE atomic_cmpexch_weak_any(ptr, &old, &desired, mo, memory_order_relaxed)) {
1139 // Retry
1140 }
1141 return old;
1142#endif
1143}
1144
1153template <typename T>
1156 remove_volatile_t<T> new_value;
1157 do {
1158 new_value = old_value + value;
1159 } while (!_NEFORCE atomic_cmpexch_weak_any(ptr, &old_value, &new_value, mo, memory_order_relaxed));
1160 return old_value;
1161}
1162
1171template <typename T>
1174 remove_volatile_t<T> new_value;
1175 do {
1176 new_value = old_value - value;
1177 } while (!_NEFORCE atomic_cmpexch_weak_any(ptr, &old_value, &new_value, mo, memory_order_relaxed));
1178 return old_value;
1179}
1180
1189template <typename T>
1192 remove_volatile_t<T> new_value;
1193 do {
1194 new_value = old_value + value;
1195 } while (!_NEFORCE atomic_cmpexch_weak_any(ptr, &old_value, &new_value, mo, memory_order_relaxed));
1196 return new_value;
1197}
1198
1207template <typename T>
1210 remove_volatile_t<T> new_value;
1211 do {
1212 new_value = old_value - value;
1213 } while (!_NEFORCE atomic_cmpexch_weak_any(ptr, &old_value, &new_value, mo, memory_order_relaxed));
1214 return new_value;
1215}
1216
1217
1224template <size_t Size, size_t Align>
1225NEFORCE_CONSTEXPR17 bool is_always_lock_free() noexcept {
1226#ifdef NEFORCE_COMPILER_GNUC
1227 return __atomic_is_lock_free(Size, reinterpret_cast<void*>(-Align));
1228#else
1229 return inner::atomic_is_always_lock_free_impl<Size>::value;
1230#endif
1231}
1232
1233
1240struct atomic_flag {
1245#ifdef NEFORCE_COMPILER_MSVC
1246 long;
1247#else
1248 bool;
1249#endif
1250
1251 value_type flag_{static_cast<value_type>(0)};
1252
1253 atomic_flag() noexcept = default;
1254 atomic_flag(const atomic_flag&) = delete;
1255 atomic_flag& operator=(const atomic_flag&) = delete;
1256 atomic_flag& operator=(const atomic_flag&) volatile = delete;
1257 atomic_flag(atomic_flag&&) noexcept = default;
1258 atomic_flag& operator=(atomic_flag&&) noexcept = default;
1259 ~atomic_flag() noexcept = default;
1260
1265 constexpr atomic_flag(const value_type flag) noexcept :
1266 flag_(static_cast<value_type>(static_cast<int>(flag) != 0 ? 1 : 0)) {}
1267
1273 NEFORCE_ALWAYS_INLINE bool test_and_set(const memory_order mo = memory_order_seq_cst) noexcept {
1274#ifdef NEFORCE_COMPILER_GNUC
1275 return __atomic_test_and_set(&flag_, static_cast<int32_t>(mo));
1276#else
1277 const long old_val = ::_InterlockedExchange(&flag_, 1);
1278 if (mo == memory_order_seq_cst) {
1279 ::_ReadWriteBarrier();
1280 }
1281 return old_val != 0;
1282#endif
1283 }
1284
1288 NEFORCE_ALWAYS_INLINE_INLINE bool test_and_set(const memory_order mo = memory_order_seq_cst) volatile noexcept {
1289#ifdef NEFORCE_COMPILER_GNUC
1290 return __atomic_test_and_set(&flag_, static_cast<int32_t>(mo));
1291#else
1292 const long old_val = ::_InterlockedExchange(&flag_, 1);
1293 if (mo == memory_order_seq_cst) {
1294 ::_ReadWriteBarrier();
1295 }
1296 return old_val != 0;
1297#endif
1298 }
1299
1305 NEFORCE_NODISCARD NEFORCE_ALWAYS_INLINE bool test(const memory_order mo = memory_order_seq_cst) const noexcept {
1306#ifdef NEFORCE_COMPILER_GNUC
1307 value_type value = false;
1308 __atomic_load(&flag_, &value, static_cast<int32_t>(mo));
1309 return value != static_cast<value_type>(0);
1310#else
1311 const long as_bytes = flag_;
1312 if (mo != memory_order_relaxed) {
1313 ::_ReadWriteBarrier();
1314 }
1315 return as_bytes != 0;
1316#endif
1317 }
1318
1322 NEFORCE_NODISCARD NEFORCE_ALWAYS_INLINE_INLINE bool test(const memory_order mo = memory_order_seq_cst) const
1323 volatile noexcept {
1324#ifdef NEFORCE_COMPILER_GNUC
1325 value_type value = false;
1326 __atomic_load(&flag_, &value, static_cast<int32_t>(mo));
1327 return value != static_cast<value_type>(0);
1328#else
1329 const long as_bytes = flag_;
1330 if (mo != memory_order_relaxed) {
1331 ::_ReadWriteBarrier();
1332 }
1333 return as_bytes != 0;
1334#endif
1335 }
1336
1342 NEFORCE_ALWAYS_INLINE void wait(const bool old, const memory_order mo = memory_order_seq_cst) const noexcept {
1343 const auto value = static_cast<value_type>(old);
1344 _NEFORCE atomic_wait_address_v(const_cast<const value_type*>(&flag_), value,
1345 [this, mo] { return this->test(mo); });
1346 }
1347
1351 NEFORCE_ALWAYS_INLINE_INLINE void wait(const bool old, const memory_order mo = memory_order_seq_cst) const
1352 volatile noexcept {
1353 const auto value = static_cast<value_type>(old);
1354 _NEFORCE atomic_wait_address_v(const_cast<const value_type*>(&flag_), value,
1355 [this, mo] { return this->test(mo); });
1356 }
1357
1361 NEFORCE_ALWAYS_INLINE void notify_one() noexcept { _NEFORCE atomic_notify_address(&flag_, false); }
1362
1366 NEFORCE_ALWAYS_INLINE void notify_all() noexcept { _NEFORCE atomic_notify_address(&flag_, true); }
1367
1372 NEFORCE_ALWAYS_INLINE void clear(const memory_order mo = memory_order_seq_cst) noexcept {
1373#ifdef NEFORCE_SUPPORT_INTEL_TSX
1378#else
1382#endif
1383
1384#ifdef NEFORCE_COMPILER_GNUC
1385 __atomic_clear(&flag_, static_cast<int32_t>(mo));
1386#else
1387 _NEFORCE atomic_store(&flag_, static_cast<value_type>(0), mo);
1388#endif
1389 }
1390
1394 NEFORCE_ALWAYS_INLINE_INLINE void clear(const memory_order mo = memory_order_seq_cst) volatile noexcept {
1395#ifdef NEFORCE_SUPPORT_INTEL_TSX
1400#else
1404#endif
1405
1406#ifdef NEFORCE_COMPILER_GNUC
1407 __atomic_clear(&flag_, static_cast<int32_t>(mo));
1408#else
1409 _NEFORCE atomic_store(&flag_, static_cast<value_type>(0), mo);
1410#endif
1411 }
1412};
1413
1414
1421template <typename T>
1422struct atomic_base {
1423 using value_type = T;
1425
1426 static_assert(is_integral_like_v<T>, "T must be an integral-like type");
1427
1428private:
1429 static constexpr size_t align_inner = sizeof(T) > alignof(T) ? sizeof(T) : alignof(T);
1430
1431 alignas(align_inner) value_type value_;
1432
1433public:
1434 atomic_base() noexcept = default;
1435 ~atomic_base() noexcept = default;
1436 atomic_base(const atomic_base&) = delete;
1437 atomic_base& operator=(const atomic_base&) = delete;
1438 atomic_base& operator=(const atomic_base&) volatile = delete;
1439 atomic_base(atomic_base&&) noexcept = default;
1440 atomic_base& operator=(atomic_base&&) noexcept = default;
1441
1446 constexpr atomic_base(value_type value) noexcept :
1447 value_(value) {}
1448
1453 operator value_type() const noexcept { return load(); }
1454
1458 operator value_type() const volatile noexcept { return load(); }
1459
1466 atomic_base::store(value);
1467 return value;
1468 }
1469
1473 value_type operator=(value_type value) volatile noexcept {
1474 atomic_base::store(value);
1475 return value;
1476 }
1477
1482 value_type operator++(int) noexcept { return fetch_add(1); }
1483
1487 value_type operator++(int) volatile noexcept { return fetch_add(1); }
1488
1493 value_type operator--(int) noexcept { return fetch_sub(1); }
1494
1498 value_type operator--(int) volatile noexcept { return fetch_sub(1); }
1499
1504 value_type operator++() noexcept { return _NEFORCE atomic_add_fetch(&value_, 1, memory_order_seq_cst); }
1505
1509 value_type operator++() volatile noexcept { return _NEFORCE atomic_add_fetch(&value_, 1, memory_order_seq_cst); }
1510
1515 value_type operator--() noexcept { return _NEFORCE atomic_sub_fetch(&value_, 1, memory_order_seq_cst); }
1516
1520 value_type operator--() volatile noexcept { return _NEFORCE atomic_sub_fetch(&value_, 1, memory_order_seq_cst); }
1521
1528 return _NEFORCE atomic_add_fetch(&value_, value, memory_order_seq_cst);
1529 }
1530
1534 value_type operator+=(value_type value) volatile noexcept {
1535 return _NEFORCE atomic_add_fetch(&value_, value, memory_order_seq_cst);
1536 }
1537
1544 return _NEFORCE atomic_sub_fetch(&value_, value, memory_order_seq_cst);
1545 }
1546
1550 value_type operator-=(value_type value) volatile noexcept {
1551 return _NEFORCE atomic_sub_fetch(&value_, value, memory_order_seq_cst);
1552 }
1553
1560 return _NEFORCE atomic_and_fetch(&value_, value, memory_order_seq_cst);
1561 }
1562
1566 value_type operator&=(value_type value) volatile noexcept {
1567 return _NEFORCE atomic_and_fetch(&value_, value, memory_order_seq_cst);
1568 }
1569
1576 return _NEFORCE atomic_or_fetch(&value_, value, memory_order_seq_cst);
1577 }
1578
1582 value_type operator|=(value_type value) volatile noexcept {
1583 return _NEFORCE atomic_or_fetch(&value_, value, memory_order_seq_cst);
1584 }
1585
1592 return _NEFORCE atomic_xor_fetch(&value_, value, memory_order_seq_cst);
1593 }
1594
1598 value_type operator^=(value_type value) volatile noexcept {
1599 return _NEFORCE atomic_xor_fetch(&value_, value, memory_order_seq_cst);
1600 }
1601
1606 NEFORCE_NODISCARD bool is_lock_free() const noexcept {
1608 }
1609
1613 NEFORCE_NODISCARD bool is_lock_free() const volatile noexcept {
1615 }
1616
1622 NEFORCE_ALWAYS_INLINE void store(value_type value, const memory_order mo = memory_order_seq_cst) noexcept {
1623#ifdef NEFORCE_SUPPORT_INTEL_TSX
1628#else
1632#endif
1633 _NEFORCE atomic_store(&value_, value, mo);
1634 }
1635
1639 NEFORCE_ALWAYS_INLINE void store(value_type value, const memory_order mo = memory_order_seq_cst) volatile noexcept {
1640#ifdef NEFORCE_SUPPORT_INTEL_TSX
1645#else
1649#endif
1650 _NEFORCE atomic_store(&value_, value, mo);
1651 }
1652
1658 NEFORCE_ALWAYS_INLINE value_type load(const memory_order mo = memory_order_seq_cst) const noexcept {
1659#ifdef NEFORCE_SUPPORT_INTEL_TSX
1663#else
1666#endif
1667 return _NEFORCE atomic_load(&value_, mo);
1668 }
1669
1673 NEFORCE_ALWAYS_INLINE value_type load(const memory_order mo = memory_order_seq_cst) const volatile noexcept {
1674#ifdef NEFORCE_SUPPORT_INTEL_TSX
1678#else
1681#endif
1682 return _NEFORCE atomic_load(&value_, mo);
1683 }
1684
1691 NEFORCE_ALWAYS_INLINE value_type exchange(value_type value, const memory_order mo = memory_order_seq_cst) noexcept {
1692 return _NEFORCE atomic_exchange(&value_, value, mo);
1693 }
1694
1698 NEFORCE_ALWAYS_INLINE value_type exchange(value_type value,
1699 const memory_order mo = memory_order_seq_cst) volatile noexcept {
1700 return _NEFORCE atomic_exchange(&value_, value, mo);
1701 }
1702
1711 NEFORCE_ALWAYS_INLINE bool compare_exchange_weak(value_type& expected, value_type desired,
1712 const memory_order success, const memory_order failure) noexcept {
1713 return _NEFORCE atomic_cmpexch_weak_any(&value_, &expected, &desired, success, failure);
1714 }
1715
1719 NEFORCE_ALWAYS_INLINE bool compare_exchange_weak(value_type& expected, value_type desired,
1720 const memory_order success,
1721 const memory_order failure) volatile noexcept {
1722 return _NEFORCE atomic_cmpexch_weak_any(&value_, &expected, &desired, success, failure);
1723 }
1724
1732 NEFORCE_ALWAYS_INLINE bool compare_exchange_weak(value_type& expected, value_type desired,
1733 const memory_order mo = memory_order_seq_cst) noexcept {
1734 return this->compare_exchange_weak(expected, desired, mo, cmpexch_failure_order(mo));
1735 }
1736
1740 NEFORCE_ALWAYS_INLINE bool compare_exchange_weak(value_type& expected, value_type desired,
1741 const memory_order mo = memory_order_seq_cst) volatile noexcept {
1742 return this->compare_exchange_weak(expected, desired, mo, cmpexch_failure_order(mo));
1743 }
1744
1753 NEFORCE_ALWAYS_INLINE bool compare_exchange_strong(value_type& expected, value_type desired,
1754 const memory_order success,
1755 const memory_order failure) noexcept {
1756 return _NEFORCE atomic_cmpexch_strong_any(&value_, &expected, &desired, success, failure);
1757 }
1758
1762 NEFORCE_ALWAYS_INLINE bool compare_exchange_strong(value_type& expected, value_type desired,
1763 const memory_order success,
1764 const memory_order failure) volatile noexcept {
1765 return _NEFORCE atomic_cmpexch_strong_any(&value_, &expected, &desired, success, failure);
1766 }
1767
1775 NEFORCE_ALWAYS_INLINE bool compare_exchange_strong(value_type& expected, value_type desired,
1776 const memory_order mo = memory_order_seq_cst) noexcept {
1777 return this->compare_exchange_strong(expected, desired, mo, cmpexch_failure_order(mo));
1778 }
1779
1783 NEFORCE_ALWAYS_INLINE bool compare_exchange_strong(value_type& expected, value_type desired,
1784 const memory_order mo = memory_order_seq_cst) volatile noexcept {
1785 return this->compare_exchange_strong(expected, desired, mo, cmpexch_failure_order(mo));
1786 }
1787
1793 NEFORCE_ALWAYS_INLINE void wait(value_type old, const memory_order mo = memory_order_seq_cst) const noexcept {
1794 _NEFORCE atomic_wait_address_v(&value_, old, [mo, this] { return this->load(mo); });
1795 }
1796
1800 NEFORCE_ALWAYS_INLINE void notify_one() noexcept { _NEFORCE atomic_notify_address(&value_, false); }
1801
1805 NEFORCE_ALWAYS_INLINE void notify_all() noexcept { _NEFORCE atomic_notify_address(&value_, true); }
1806
1813 NEFORCE_ALWAYS_INLINE value_type fetch_add(value_type value,
1814 const memory_order mo = memory_order_seq_cst) noexcept {
1815 return _NEFORCE atomic_fetch_add(&value_, value, mo);
1816 }
1817
1821 NEFORCE_ALWAYS_INLINE value_type fetch_add(value_type value,
1822 const memory_order mo = memory_order_seq_cst) volatile noexcept {
1823 return _NEFORCE atomic_fetch_add(&value_, value, mo);
1824 }
1825
1832 NEFORCE_ALWAYS_INLINE value_type fetch_sub(value_type value,
1833 const memory_order mo = memory_order_seq_cst) noexcept {
1834 return _NEFORCE atomic_fetch_sub(&value_, value, mo);
1835 }
1836
1840 NEFORCE_ALWAYS_INLINE value_type fetch_sub(value_type value,
1841 const memory_order mo = memory_order_seq_cst) volatile noexcept {
1842 return _NEFORCE atomic_fetch_sub(&value_, value, mo);
1843 }
1844
1851 NEFORCE_ALWAYS_INLINE value_type fetch_and(value_type value,
1852 const memory_order mo = memory_order_seq_cst) noexcept {
1853 return _NEFORCE atomic_fetch_and(&value_, value, mo);
1854 }
1855
1859 NEFORCE_ALWAYS_INLINE value_type fetch_and(value_type value,
1860 const memory_order mo = memory_order_seq_cst) volatile noexcept {
1861 return _NEFORCE atomic_fetch_and(&value_, value, mo);
1862 }
1863
1870 NEFORCE_ALWAYS_INLINE value_type fetch_or(value_type value, const memory_order mo = memory_order_seq_cst) noexcept {
1871 return _NEFORCE atomic_fetch_or(&value_, value, mo);
1872 }
1873
1877 NEFORCE_ALWAYS_INLINE value_type fetch_or(value_type value,
1878 const memory_order mo = memory_order_seq_cst) volatile noexcept {
1879 return _NEFORCE atomic_fetch_or(&value_, value, mo);
1880 }
1881
1888 NEFORCE_ALWAYS_INLINE value_type fetch_xor(value_type value,
1889 const memory_order mo = memory_order_seq_cst) noexcept {
1890 return _NEFORCE atomic_fetch_xor(&value_, value, mo);
1891 }
1892
1896 NEFORCE_ALWAYS_INLINE value_type fetch_xor(value_type value,
1897 const memory_order mo = memory_order_seq_cst) volatile noexcept {
1898 return _NEFORCE atomic_fetch_xor(&value_, value, mo);
1899 }
1900};
1901
1908template <typename T>
1909struct atomic_base<T*> {
1910 using value_type = T*;
1912
1913private:
1914 value_type ptr_ = nullptr;
1915
1916 NEFORCE_ALWAYS_INLINE_INLINE static constexpr difference_type real_type_sizes(const difference_type dest) noexcept {
1917 return dest * sizeof(T);
1918 }
1919
1920public:
1921 atomic_base() noexcept = default;
1922 atomic_base(const atomic_base&) = delete;
1923 atomic_base& operator=(const atomic_base&) = delete;
1924 atomic_base& operator=(const atomic_base&) volatile = delete;
1925 atomic_base(atomic_base&&) noexcept = default;
1926 atomic_base& operator=(atomic_base&&) noexcept = default;
1927 ~atomic_base() noexcept = default;
1928
1933 constexpr atomic_base(const value_type ptr) noexcept :
1934 ptr_(ptr) {}
1935
1940 operator value_type() const noexcept { return load(); }
1941
1945 operator value_type() const volatile noexcept { return load(); }
1946
1952 value_type operator=(const value_type ptr) noexcept {
1953 atomic_base::store(ptr);
1954 return ptr;
1955 }
1956
1960 value_type operator=(const value_type ptr) volatile noexcept {
1961 atomic_base::store(ptr);
1962 return ptr;
1963 }
1964
1969 value_type operator++(int) noexcept { return fetch_add(1); }
1970
1974 value_type operator++(int) volatile noexcept { return fetch_add(1); }
1975
1980 value_type operator--(int) noexcept { return fetch_sub(1); }
1981
1985 value_type operator--(int) volatile noexcept { return fetch_sub(1); }
1986
1991 value_type operator++() noexcept { return fetch_add(1) + 1; }
1992
1996 value_type operator++() volatile noexcept { return fetch_add(1) + 1; }
1997
2002 value_type operator--() noexcept { return fetch_sub(1) - 1; }
2003
2007 value_type operator--() volatile noexcept { return fetch_sub(1) - 1; }
2008
2014 value_type operator+=(const ptrdiff_t dest) noexcept { return fetch_add(dest) + dest; }
2015
2019 value_type operator+=(const ptrdiff_t dest) volatile noexcept { return fetch_add(dest) + dest; }
2020
2026 value_type operator-=(const ptrdiff_t dest) noexcept { return fetch_sub(dest) - dest; }
2027
2031 value_type operator-=(const ptrdiff_t dest) volatile noexcept { return fetch_sub(dest) - dest; }
2032
2037 NEFORCE_NODISCARD bool is_lock_free() const noexcept {
2039 }
2040
2044 NEFORCE_NODISCARD bool is_lock_free() const volatile noexcept {
2046 }
2047
2053 NEFORCE_ALWAYS_INLINE void store(value_type ptr, const memory_order mo = memory_order_seq_cst) noexcept {
2054#ifdef NEFORCE_SUPPORT_INTEL_TSX
2059#else
2063#endif
2064
2065#ifdef NEFORCE_COMPILER_GNUC
2066 __atomic_store_n(&ptr_, ptr, static_cast<int32_t>(mo));
2067#else
2068 ::_InterlockedExchangePointer(reinterpret_cast<void* volatile*>(&ptr_), reinterpret_cast<void*>(ptr));
2069 if (mo == memory_order_seq_cst || mo == memory_order_release) {
2070 ::_ReadWriteBarrier();
2071 }
2072#endif
2073 }
2074
2078 NEFORCE_ALWAYS_INLINE_INLINE void store(const value_type ptr,
2079 const memory_order mo = memory_order_seq_cst) volatile noexcept {
2080#ifdef NEFORCE_SUPPORT_INTEL_TSX
2085#else
2089#endif
2090
2091#ifdef NEFORCE_COMPILER_GNUC
2092 __atomic_store_n(&ptr_, ptr, static_cast<int32_t>(mo));
2093#else
2094 ::_InterlockedExchangePointer(reinterpret_cast<void* volatile*>(&ptr_), ptr);
2095 if (mo == memory_order_seq_cst || mo == memory_order_release) {
2096 ::_ReadWriteBarrier();
2097 }
2098#endif
2099 }
2100
2106 NEFORCE_ALWAYS_INLINE value_type load(const memory_order mo = memory_order_seq_cst) const noexcept {
2107#ifdef NEFORCE_SUPPORT_INTEL_TSX
2111#else
2114#endif
2115
2116#ifdef NEFORCE_COMPILER_GNUC
2117 return __atomic_load_n(&ptr_, static_cast<int32_t>(mo));
2118#else
2119 const value_type result = *reinterpret_cast<value_type const volatile*>(&ptr_);
2120 if (mo == memory_order_seq_cst || mo == memory_order_acquire) {
2121 ::_ReadWriteBarrier();
2122 }
2123 return result;
2124#endif
2125 }
2126
2130 NEFORCE_ALWAYS_INLINE_INLINE value_type load(const memory_order mo = memory_order_seq_cst) const volatile noexcept {
2131#ifdef NEFORCE_SUPPORT_INTEL_TSX
2135#else
2138#endif
2139
2140#ifdef NEFORCE_COMPILER_GNUC
2141 return __atomic_load_n(&ptr_, static_cast<int32_t>(mo));
2142#else
2143 const value_type result = *reinterpret_cast<value_type const volatile*>(&ptr_);
2144 if (mo == memory_order_seq_cst || mo == memory_order_acquire) {
2145 ::_ReadWriteBarrier();
2146 }
2147 return result;
2148#endif
2149 }
2150
2157 NEFORCE_ALWAYS_INLINE value_type exchange(const value_type ptr,
2158 const memory_order mo = memory_order_seq_cst) noexcept {
2159#ifdef NEFORCE_COMPILER_GNUC
2160 return __atomic_exchange_n(&ptr_, ptr, static_cast<int32_t>(mo));
2161#else
2162 const auto old =
2163 static_cast<value_type>(::_InterlockedExchangePointer(reinterpret_cast<void* volatile*>(&ptr_), ptr));
2164 if (mo == memory_order_seq_cst) {
2165 ::_ReadWriteBarrier();
2166 }
2167 return old;
2168#endif
2169 }
2170
2174 NEFORCE_ALWAYS_INLINE_INLINE value_type exchange(const value_type ptr,
2175 const memory_order mo = memory_order_seq_cst) volatile noexcept {
2176#ifdef NEFORCE_COMPILER_GNUC
2177 return __atomic_exchange_n(&ptr_, ptr, static_cast<int32_t>(mo));
2178#else
2179 const auto old =
2180 static_cast<value_type>(::_InterlockedExchangePointer(reinterpret_cast<void* volatile*>(&ptr_), ptr));
2181 if (mo == memory_order_seq_cst) {
2182 ::_ReadWriteBarrier();
2183 }
2184 return old;
2185#endif
2186 }
2187
2196 NEFORCE_ALWAYS_INLINE bool compare_exchange_weak(value_type& expected, value_type desired,
2197 const memory_order success, const memory_order failure) noexcept {
2199 return _NEFORCE atomic_cmpexch_weak_any(_NEFORCE addressof(ptr_), _NEFORCE addressof(expected),
2200 _NEFORCE addressof(desired), success, failure);
2201 }
2202
2206 NEFORCE_ALWAYS_INLINE_INLINE bool compare_exchange_weak(value_type& expected, value_type desired,
2207 const memory_order success,
2208 const memory_order failure) volatile noexcept {
2210 return _NEFORCE atomic_cmpexch_weak_any(_NEFORCE addressof(ptr_), _NEFORCE addressof(expected),
2211 _NEFORCE addressof(desired), success, failure);
2212 }
2213
2221 NEFORCE_ALWAYS_INLINE bool compare_exchange_weak(value_type& expected, value_type desired,
2222 const memory_order mo = memory_order_seq_cst) noexcept {
2223 return atomic_base::compare_exchange_weak(expected, desired, mo, cmpexch_failure_order(mo));
2224 }
2225
2229 NEFORCE_ALWAYS_INLINE bool compare_exchange_weak(value_type& expected, value_type desired,
2230 const memory_order mo = memory_order_seq_cst) volatile noexcept {
2231 return atomic_base::compare_exchange_weak(expected, desired, mo, cmpexch_failure_order(mo));
2232 }
2233
2242 NEFORCE_ALWAYS_INLINE bool compare_exchange_strong(value_type& expected, value_type desired,
2243 const memory_order success,
2244 const memory_order failure) noexcept {
2246 return _NEFORCE atomic_cmpexch_strong_any(_NEFORCE addressof(ptr_), _NEFORCE addressof(expected),
2247 _NEFORCE addressof(desired), success, failure);
2248 }
2249
2253 NEFORCE_ALWAYS_INLINE_INLINE bool compare_exchange_strong(value_type& expected, value_type desired,
2254 const memory_order success,
2255 const memory_order failure) volatile noexcept {
2257 return _NEFORCE atomic_cmpexch_strong_any(_NEFORCE addressof(ptr_), _NEFORCE addressof(expected),
2258 _NEFORCE addressof(desired), success, failure);
2259 }
2260
2268 NEFORCE_ALWAYS_INLINE bool compare_exchange_strong(value_type& expected, value_type desired,
2269 const memory_order mo = memory_order_seq_cst) noexcept {
2270 return atomic_base::compare_exchange_strong(expected, desired, mo, cmpexch_failure_order(mo));
2271 }
2272
2276 NEFORCE_ALWAYS_INLINE bool compare_exchange_strong(value_type& expected, value_type desired,
2277 const memory_order mo = memory_order_seq_cst) volatile noexcept {
2278 return atomic_base::compare_exchange_strong(expected, desired, mo, cmpexch_failure_order(mo));
2279 }
2280
2286 NEFORCE_ALWAYS_INLINE void wait(value_type old, const memory_order mo = memory_order_seq_cst) const noexcept {
2287 _NEFORCE atomic_wait_address_v(&ptr_, old, [mo, this] { return this->load(mo); });
2288 }
2289
2293 NEFORCE_ALWAYS_INLINE void notify_one() noexcept { _NEFORCE atomic_notify_address(&ptr_, false); }
2294
2298 NEFORCE_ALWAYS_INLINE void notify_all() noexcept { _NEFORCE atomic_notify_address(&ptr_, true); }
2299
2306 NEFORCE_ALWAYS_INLINE value_type fetch_add(const ptrdiff_t dest,
2307 const memory_order mo = memory_order_seq_cst) noexcept {
2308 const auto byte_offset = static_cast<uintptr_t>(dest * static_cast<ptrdiff_t>(sizeof(T)));
2309 uintptr_t old_val =
2310 _NEFORCE atomic_fetch_add_any(reinterpret_cast<uintptr_t*>(_NEFORCE addressof(ptr_)), byte_offset, mo);
2311 return reinterpret_cast<value_type>(old_val);
2312 }
2313
2317 NEFORCE_ALWAYS_INLINE_INLINE value_type fetch_add(const ptrdiff_t dest,
2318 const memory_order mo = memory_order_seq_cst) volatile noexcept {
2319 const auto byte_offset = static_cast<uintptr_t>(dest * static_cast<ptrdiff_t>(sizeof(T)));
2320 uintptr_t old_val =
2321 _NEFORCE atomic_fetch_add_any(reinterpret_cast<uintptr_t*>(_NEFORCE addressof(ptr_)), byte_offset, mo);
2322 return reinterpret_cast<value_type>(old_val);
2323 }
2324
2331 NEFORCE_ALWAYS_INLINE value_type fetch_sub(const ptrdiff_t dest,
2332 const memory_order mo = memory_order_seq_cst) noexcept {
2333 const auto byte_offset = static_cast<uintptr_t>(dest * static_cast<ptrdiff_t>(sizeof(T)));
2334 uintptr_t old_val =
2335 _NEFORCE atomic_fetch_sub_any(reinterpret_cast<uintptr_t*>(_NEFORCE addressof(ptr_)), byte_offset, mo);
2336 return reinterpret_cast<value_type>(old_val);
2337 }
2338
2342 NEFORCE_ALWAYS_INLINE_INLINE value_type fetch_sub(const ptrdiff_t dest,
2343 const memory_order mo = memory_order_seq_cst) volatile noexcept {
2344 const auto byte_offset = static_cast<uintptr_t>(dest * static_cast<ptrdiff_t>(sizeof(T)));
2345 uintptr_t old_val =
2346 _NEFORCE atomic_fetch_sub_any(reinterpret_cast<uintptr_t*>(_NEFORCE addressof(ptr_)), byte_offset, mo);
2347 return reinterpret_cast<value_type>(old_val);
2348 }
2349};
2350
2351
2359template <typename Float>
2360struct atomic_float_base {
2361 static_assert(is_floating_point_v<Float>, "atomic_ref_base need floating point T");
2362
2363 using value_type = Float;
2365
2366private:
2367 alignas(alignof(Float)) Float float_ = static_cast<Float>(0);
2368
2369public:
2370 atomic_float_base() = default;
2371 atomic_float_base(const atomic_float_base&) = delete;
2372 atomic_float_base& operator=(const atomic_float_base&) = delete;
2373 atomic_float_base& operator=(const atomic_float_base&) volatile = delete;
2374 atomic_float_base(atomic_float_base&&) noexcept = default;
2375 atomic_float_base& operator=(atomic_float_base&&) noexcept = default;
2376
2381 constexpr atomic_float_base(Float value) noexcept(is_nothrow_copy_constructible_v<Float>) :
2382 float_(value) {}
2383
2387 Float operator=(Float value) noexcept {
2388 this->store(value);
2389 return value;
2390 }
2391
2395 Float operator=(Float value) volatile noexcept {
2396 this->store(value);
2397 return value;
2398 }
2399
2403 NEFORCE_NODISCARD bool is_lock_free() const noexcept {
2405 }
2406
2410 NEFORCE_NODISCARD bool is_lock_free() const volatile noexcept {
2412 }
2413
2417 void store(Float value, const memory_order mo = memory_order_seq_cst) noexcept {
2418 _NEFORCE atomic_store_any(&float_, value, mo);
2419 }
2420
2424 void store(Float value, const memory_order mo = memory_order_seq_cst) volatile noexcept {
2425 _NEFORCE atomic_store_any(&float_, value, mo);
2426 }
2427
2431 Float load(const memory_order mo = memory_order_seq_cst) const noexcept {
2432 return _NEFORCE atomic_load_any(&float_, mo);
2433 }
2434
2438 Float load(const memory_order mo = memory_order_seq_cst) const volatile noexcept {
2439 return _NEFORCE atomic_load_any(&float_, mo);
2440 }
2441
2445 operator Float() const noexcept { return this->load(); }
2446
2450 operator Float() const volatile noexcept { return this->load(); }
2451
2455 Float exchange(Float desire, const memory_order mo = memory_order_seq_cst) noexcept {
2456 return _NEFORCE atomic_exchange_any(&float_, desire, mo);
2457 }
2458
2462 Float exchange(Float desire, const memory_order mo = memory_order_seq_cst) volatile noexcept {
2463 return _NEFORCE atomic_exchange_any(&float_, desire, mo);
2464 }
2465
2469 bool compare_exchange_weak(Float& expected, Float desire, const memory_order success,
2470 const memory_order failure) noexcept {
2471 return _NEFORCE atomic_cmpexch_weak_any(&float_, expected, desire, success, failure);
2472 }
2473
2477 bool compare_exchange_weak(Float& expected, Float desire, const memory_order success,
2478 const memory_order failure) volatile noexcept {
2479 return _NEFORCE atomic_cmpexch_weak_any(&float_, expected, desire, success, failure);
2480 }
2481
2485 bool compare_exchange_strong(Float& expected, Float desire, const memory_order success,
2486 const memory_order failure) noexcept {
2487 return _NEFORCE atomic_cmpexch_strong_any(&float_, expected, desire, success, failure);
2488 }
2489
2493 bool compare_exchange_strong(Float& expected, Float desire, const memory_order success,
2494 const memory_order failure) volatile noexcept {
2495 return _NEFORCE atomic_cmpexch_strong_any(&float_, expected, desire, success, failure);
2496 }
2497
2501 bool compare_exchange_weak(Float& expected, Float desire, const memory_order mo = memory_order_seq_cst) noexcept {
2502 return _NEFORCE atomic_cmpexch_weak(&float_, expected, desire, mo, cmpexch_failure_order(mo));
2503 }
2504
2508 bool compare_exchange_weak(Float& expected, Float desire,
2509 const memory_order mo = memory_order_seq_cst) volatile noexcept {
2510 return _NEFORCE atomic_cmpexch_weak(&float_, expected, desire, mo, cmpexch_failure_order(mo));
2511 }
2512
2516 bool compare_exchange_strong(Float& expected, Float desire, const memory_order mo = memory_order_seq_cst) noexcept {
2517 return _NEFORCE atomic_cmpexch_strong(&float_, expected, desire, mo, cmpexch_failure_order(mo));
2518 }
2519
2523 bool compare_exchange_strong(Float& expected, Float desire,
2524 const memory_order mo = memory_order_seq_cst) volatile noexcept {
2525 return _NEFORCE atomic_cmpexch_strong(&float_, expected, desire, mo, cmpexch_failure_order(mo));
2526 }
2527
2533 NEFORCE_ALWAYS_INLINE void wait(Float old, const memory_order mo = memory_order_seq_cst) const noexcept {
2534 _NEFORCE atomic_wait_address_v(&float_, old, [mo, this] { return this->load(mo); });
2535 }
2536
2540 NEFORCE_ALWAYS_INLINE void notify_one() noexcept { _NEFORCE atomic_notify_address(&float_, false); }
2541
2545 NEFORCE_ALWAYS_INLINE void notify_all() noexcept { _NEFORCE atomic_notify_address(&float_, true); }
2546
2554 return _NEFORCE atomic_fetch_add_any(&float_, value, mo);
2555 }
2556
2560 value_type fetch_add(value_type value, const memory_order mo = memory_order_seq_cst) volatile noexcept {
2561 return _NEFORCE atomic_fetch_add_any(&float_, value, mo);
2562 }
2563
2571 return _NEFORCE atomic_fetch_sub_any(&float_, value, mo);
2572 }
2573
2577 value_type fetch_sub(value_type value, const memory_order mo = memory_order_seq_cst) volatile noexcept {
2578 return _NEFORCE atomic_fetch_sub_any(&float_, value, mo);
2579 }
2580
2587 return _NEFORCE atomic_add_fetch_any(&float_, value, memory_order_seq_cst);
2588 }
2589
2593 value_type operator+=(value_type value) volatile noexcept {
2594 return _NEFORCE atomic_add_fetch_any(&float_, value, memory_order_seq_cst);
2595 }
2596
2603 return _NEFORCE atomic_sub_fetch_any(&float_, value, memory_order_seq_cst);
2604 }
2605
2609 value_type operator-=(value_type value) volatile noexcept {
2610 return _NEFORCE atomic_sub_fetch_any(&float_, value, memory_order_seq_cst);
2611 }
2612};
2613
2614
2624template <typename T, bool IsIntegral = is_integral_v<T>, bool IsFloatingPoint = is_floating_point_v<T>>
2626
2627
2632template <typename T>
2633struct atomic_ref_base<T, false, false> {
2634 static_assert(is_trivially_copyable_v<T>, "atomic_ref_base need trivially copyable T");
2635
2636private:
2637 static constexpr int align_inner = (sizeof(T) & (sizeof(T) - 1)) != 0U || sizeof(T) > 16 ? 0 : sizeof(T);
2638
2639 T* ptr_;
2640
2641public:
2642 using value_type = T;
2643
2645 static constexpr size_t required_alignment = align_inner > alignof(T) ? align_inner : alignof(T);
2646
2651 explicit atomic_ref_base(T& value) :
2652 ptr_(_NEFORCE addressof(value)) {
2653 NEFORCE_CONSTEXPR_ASSERT((static_cast<uintptr_t>(ptr_) % required_alignment) == 0);
2654 }
2655
2656 atomic_ref_base(const atomic_ref_base&) noexcept = default;
2657 atomic_ref_base& operator=(const atomic_ref_base&) = delete;
2658
2664 T operator=(T value) noexcept {
2665 this->store(value);
2666 return value;
2667 }
2668
2673 operator T() const noexcept { return this->load(); }
2674
2679 NEFORCE_NODISCARD bool is_lock_free() const noexcept {
2681 }
2682
2688 void store(T value, const memory_order mo = memory_order_seq_cst) noexcept {
2689 _NEFORCE atomic_store_any(ptr_, value, mo);
2690 }
2691
2697 T load(const memory_order mo = memory_order_seq_cst) const noexcept { return _NEFORCE atomic_load_any(ptr_, mo); }
2698
2705 T exchange(T desire, const memory_order mo = memory_order_seq_cst) noexcept {
2706 return _NEFORCE atomic_exchange_any(ptr_, desire, mo);
2707 }
2708
2717 bool compare_exchange_weak(T& expected, T desire, const memory_order success, const memory_order failure) noexcept {
2718 return _NEFORCE atomic_cmpexch_weak_any(ptr_, expected, desire, success, failure);
2719 }
2720
2729 bool compare_exchange_strong(T& expected, T desire, const memory_order success,
2730 const memory_order failure) noexcept {
2731 return _NEFORCE atomic_cmpexch_strong_any(ptr_, expected, desire, success, failure);
2732 }
2733
2741 bool compare_exchange_weak(T& expected, T desire, const memory_order mo = memory_order_seq_cst) noexcept {
2742 return _NEFORCE atomic_cmpexch_weak_any(ptr_, expected, desire, mo, cmpexch_failure_order(mo));
2743 }
2744
2752 bool compare_exchange_strong(T& expected, T desire, const memory_order mo = memory_order_seq_cst) noexcept {
2753 return _NEFORCE atomic_cmpexch_strong_any(ptr_, expected, desire, mo, cmpexch_failure_order(mo));
2754 }
2755
2761 NEFORCE_ALWAYS_INLINE void wait(T old, const memory_order mo = memory_order_seq_cst) const noexcept {
2762 _NEFORCE atomic_wait_address_v(ptr_, old, [this, mo] { return this->load(mo); });
2763 }
2764
2768 NEFORCE_ALWAYS_INLINE void notify_one() noexcept { _NEFORCE atomic_notify_address(ptr_, false); }
2769
2773 NEFORCE_ALWAYS_INLINE void notify_all() noexcept { _NEFORCE atomic_notify_address(ptr_, true); }
2774};
2775
2780template <typename T>
2781struct atomic_ref_base<T, true, false> {
2782 static_assert(is_integral_like_v<T>, "atomic_ref need integral-like T");
2783
2784private:
2785 T* ptr_;
2786
2787public:
2788 using value_type = T;
2790
2792 static constexpr size_t required_alignment = sizeof(T) > alignof(T) ? sizeof(T) : alignof(T);
2793
2794 atomic_ref_base() = delete;
2795 atomic_ref_base(const atomic_ref_base&) noexcept = default;
2796 atomic_ref_base& operator=(const atomic_ref_base&) = delete;
2797
2802 explicit atomic_ref_base(T& value) :
2803 ptr_(&value) {
2804 NEFORCE_CONSTEXPR_ASSERT((reinterpret_cast<uintptr_t>(ptr_) % required_alignment) == 0);
2805 }
2806
2812 T operator=(T value) noexcept {
2813 this->store(value);
2814 return value;
2815 }
2816
2821 NEFORCE_NODISCARD operator T() const noexcept { return this->load(); }
2822
2827 NEFORCE_NODISCARD bool is_lock_free() const noexcept {
2829 }
2830
2836 void store(T value, const memory_order mo = memory_order_seq_cst) noexcept {
2837 _NEFORCE atomic_store(ptr_, value, mo);
2838 }
2839
2845 T load(const memory_order mo = memory_order_seq_cst) const noexcept { return _NEFORCE atomic_load(ptr_, mo); }
2846
2853 T exchange(T desire, const memory_order mo = memory_order_seq_cst) noexcept {
2854 return _NEFORCE atomic_exchange(ptr_, desire, mo);
2855 }
2856
2865 bool compare_exchange_weak(T& expected, T desire, const memory_order success, const memory_order failure) noexcept {
2866 return _NEFORCE atomic_cmpexch_weak(ptr_, &expected, desire, success, failure);
2867 }
2868
2877 bool compare_exchange_strong(T& expected, T desire, const memory_order success,
2878 const memory_order failure) noexcept {
2879 return _NEFORCE atomic_cmpexch_strong(ptr_, &expected, desire, success, failure);
2880 }
2881
2889 bool compare_exchange_weak(T& expected, T desire, const memory_order mo = memory_order_seq_cst) noexcept {
2890 return _NEFORCE atomic_cmpexch_weak(ptr_, &expected, desire, mo, cmpexch_failure_order(mo));
2891 }
2892
2900 bool compare_exchange_strong(T& expected, T desire, const memory_order mo = memory_order_seq_cst) noexcept {
2901 return _NEFORCE atomic_cmpexch_strong(ptr_, &expected, desire, mo, cmpexch_failure_order(mo));
2902 }
2903
2909 NEFORCE_ALWAYS_INLINE void wait(T old, const memory_order mo = memory_order_seq_cst) const noexcept {
2910 _NEFORCE atomic_wait_address_v(ptr_, old, [this, mo] { return this->load(mo); });
2911 }
2912
2916 NEFORCE_ALWAYS_INLINE void notify_one() noexcept { _NEFORCE atomic_notify_address(ptr_, false); }
2917
2921 NEFORCE_ALWAYS_INLINE void notify_all() noexcept { _NEFORCE atomic_notify_address(ptr_, true); }
2922
2930 return _NEFORCE atomic_fetch_add(ptr_, value, mo);
2931 }
2932
2940 return _NEFORCE atomic_fetch_sub(ptr_, value, mo);
2941 }
2942
2950 return _NEFORCE atomic_fetch_and(ptr_, value, mo);
2951 }
2952
2960 return _NEFORCE atomic_fetch_or(ptr_, value, mo);
2961 }
2962
2970 return _NEFORCE atomic_fetch_xor(ptr_, value, mo);
2971 }
2972
2977 NEFORCE_ALWAYS_INLINE value_type operator++(int) noexcept { return fetch_add(1); }
2978
2983 NEFORCE_ALWAYS_INLINE value_type operator--(int) noexcept { return fetch_sub(1); }
2984
2989 value_type operator++() noexcept { return _NEFORCE atomic_add_fetch(ptr_, value_type(1)); }
2990
2995 value_type operator--() noexcept { return _NEFORCE atomic_sub_fetch(ptr_, value_type(1)); }
2996
3002 value_type operator+=(value_type value) noexcept { return _NEFORCE atomic_add_fetch(ptr_, value); }
3003
3009 value_type operator-=(value_type value) noexcept { return _NEFORCE atomic_sub_fetch(ptr_, value); }
3010
3016 value_type operator&=(value_type value) noexcept { return _NEFORCE atomic_and_fetch(ptr_, value); }
3017
3023 value_type operator|=(value_type value) noexcept { return _NEFORCE atomic_or_fetch(ptr_, value); }
3024
3030 value_type operator^=(value_type value) noexcept { return _NEFORCE atomic_xor_fetch(ptr_, value); }
3031};
3032
3037template <typename Float>
3038struct atomic_ref_base<Float, false, true> {
3039 static_assert(is_floating_point_v<Float>, "atomic_ref_base need floating point T");
3040
3041private:
3042 Float* ptr_;
3043
3044public:
3045 using value_type = Float;
3047
3049 static constexpr size_t required_alignment = alignof(Float);
3050
3051 atomic_ref_base() = delete;
3052 atomic_ref_base(const atomic_ref_base&) noexcept = default;
3053 atomic_ref_base& operator=(const atomic_ref_base&) = delete;
3054
3059 explicit atomic_ref_base(Float& value) :
3060 ptr_(&value) {
3061 NEFORCE_CONSTEXPR_ASSERT((static_cast<uintptr_t>(ptr_) % required_alignment) == 0);
3062 }
3063
3069 Float operator=(Float value) noexcept {
3070 this->store(value);
3071 return value;
3072 }
3073
3078 operator Float() const noexcept { return this->load(); }
3079
3084 NEFORCE_NODISCARD bool is_lock_free() const noexcept {
3086 }
3087
3093 void store(Float value, const memory_order mo = memory_order_seq_cst) noexcept {
3094 _NEFORCE atomic_store_any(ptr_, value, mo);
3095 }
3096
3102 Float load(const memory_order mo = memory_order_seq_cst) const noexcept {
3103 return _NEFORCE atomic_load_any(ptr_, mo);
3104 }
3105
3112 Float exchange(Float desire, const memory_order mo = memory_order_seq_cst) noexcept {
3113 return _NEFORCE atomic_exchange_any(ptr_, desire, mo);
3114 }
3115
3124 bool compare_exchange_weak(Float& expected, Float desire, const memory_order success,
3125 const memory_order failure) noexcept {
3126 return _NEFORCE atomic_cmpexch_weak_any(ptr_, expected, desire, success, failure);
3127 }
3128
3137 bool compare_exchange_strong(Float& expected, Float desire, const memory_order success,
3138 const memory_order failure) noexcept {
3139 return _NEFORCE atomic_cmpexch_strong_any(ptr_, expected, desire, success, failure);
3140 }
3141
3149 bool compare_exchange_weak(Float& expected, Float desire, const memory_order mo = memory_order_seq_cst) noexcept {
3150 return _NEFORCE atomic_cmpexch_weak_any(ptr_, expected, desire, mo, cmpexch_failure_order(mo));
3151 }
3152
3160 bool compare_exchange_strong(Float& expected, Float desire, const memory_order mo = memory_order_seq_cst) noexcept {
3161 return _NEFORCE atomic_cmpexch_strong_any(ptr_, expected, desire, mo, cmpexch_failure_order(mo));
3162 }
3163
3169 NEFORCE_ALWAYS_INLINE void wait(Float old, const memory_order mo = memory_order_seq_cst) const noexcept {
3170 _NEFORCE atomic_wait_address_v(ptr_, old, [this, mo] { return this->load(mo); });
3171 }
3172
3176 NEFORCE_ALWAYS_INLINE void notify_one() noexcept { _NEFORCE atomic_notify_address(ptr_, false); }
3177
3181 NEFORCE_ALWAYS_INLINE void notify_all() noexcept { _NEFORCE atomic_notify_address(ptr_, true); }
3182
3190 return _NEFORCE atomic_fetch_add_any(ptr_, value, mo);
3191 }
3192
3200 return _NEFORCE atomic_fetch_sub_any(ptr_, value, mo);
3201 }
3202
3209 return _NEFORCE atomic_add_fetch_any(ptr_, value, memory_order_seq_cst);
3210 }
3211
3218 return _NEFORCE atomic_sub_fetch_any(ptr_, value, memory_order_seq_cst);
3219 }
3220};
3221
3222
3223#ifdef NEFORCE_COMPILER_CLANG
3224# pragma clang diagnostic push
3225# pragma clang diagnostic ignored "-Watomic-alignment"
3226#endif
3227
3228template <typename T>
3229struct atomic_ref_base<T*, false, false> {
3230public:
3231 using value_type = T*;
3232 using difference_type = ptrdiff_t;
3233
3234private:
3235 T** ptr_;
3236
3237 static constexpr difference_type real_type_sizes(const difference_type dest) noexcept {
3238 static_assert(is_object_v<T>, "atomic_ref_base need object T");
3239 return dest * sizeof(T);
3240 }
3241
3242public:
3244 static constexpr size_t required_alignment = sizeof(T*) == 8 ? 8 : alignof(T*);
3245
3246 atomic_ref_base() = delete;
3247 atomic_ref_base(const atomic_ref_base&) noexcept = default;
3248 atomic_ref_base& operator=(const atomic_ref_base&) = delete;
3249
3254 explicit atomic_ref_base(T*& value) :
3255 ptr_(_NEFORCE addressof(value)) {
3256 NEFORCE_CONSTEXPR_ASSERT((static_cast<uintptr_t>(ptr_) % required_alignment) == 0);
3257 }
3258
3264 T* operator=(T* value) noexcept {
3265 this->store(value);
3266 return value;
3267 }
3268
3273 operator T*() const noexcept { return this->load(); }
3274
3279 NEFORCE_NODISCARD bool is_lock_free() const noexcept {
3281 }
3282
3288 void store(T* value, const memory_order mo = memory_order_seq_cst) noexcept {
3289 _NEFORCE atomic_store_any(ptr_, value, mo);
3290 }
3291
3297 T* load(const memory_order mo = memory_order_seq_cst) const noexcept { return _NEFORCE atomic_load_any(ptr_, mo); }
3298
3305 T* exchange(T* desire, const memory_order mo = memory_order_seq_cst) noexcept {
3306 return _NEFORCE atomic_exchange_any(ptr_, desire, mo);
3307 }
3308
3317 bool compare_exchange_weak(T*& expected, T* desire, const memory_order success,
3318 const memory_order failure) noexcept {
3319 return _NEFORCE atomic_cmpexch_weak_any(ptr_, expected, desire, success, failure);
3320 }
3321
3330 bool compare_exchange_strong(T*& expected, T* desire, const memory_order success,
3331 const memory_order failure) noexcept {
3332 return _NEFORCE atomic_cmpexch_strong_any(ptr_, expected, desire, success, failure);
3333 }
3334
3342 bool compare_exchange_weak(T*& expected, T* desire, const memory_order mo = memory_order_seq_cst) noexcept {
3343 return _NEFORCE atomic_cmpexch_weak_any(ptr_, expected, desire, mo, cmpexch_failure_order(mo));
3344 }
3345
3353 bool compare_exchange_strong(T*& expected, T* desire, const memory_order mo = memory_order_seq_cst) noexcept {
3354 return _NEFORCE atomic_cmpexch_strong_any(ptr_, expected, desire, mo, cmpexch_failure_order(mo));
3355 }
3356
3362 NEFORCE_ALWAYS_INLINE void wait(T* old, const memory_order mo = memory_order_seq_cst) const noexcept {
3363 _NEFORCE atomic_wait_address_v(ptr_, old, [this, mo] { return this->load(mo); });
3364 }
3365
3369 NEFORCE_ALWAYS_INLINE void notify_one() noexcept { _NEFORCE atomic_notify_address(ptr_, false); }
3370
3374 NEFORCE_ALWAYS_INLINE void notify_all() noexcept { _NEFORCE atomic_notify_address(ptr_, true); }
3375
3382 NEFORCE_ALWAYS_INLINE value_type fetch_add(const difference_type dest,
3383 const memory_order mo = memory_order_seq_cst) noexcept {
3384 const auto byte_offset = static_cast<uintptr_t>(dest * static_cast<difference_type>(sizeof(T)));
3385 uintptr_t old_val = _NEFORCE atomic_fetch_add_any(reinterpret_cast<uintptr_t*>(ptr_), byte_offset, mo);
3386 return reinterpret_cast<value_type>(old_val);
3387 }
3388
3395 NEFORCE_ALWAYS_INLINE value_type fetch_sub(const difference_type dest,
3396 const memory_order mo = memory_order_seq_cst) noexcept {
3397 const auto byte_offset = static_cast<uintptr_t>(dest * static_cast<difference_type>(sizeof(T)));
3398 uintptr_t old_val = _NEFORCE atomic_fetch_sub_any(reinterpret_cast<uintptr_t*>(ptr_), byte_offset, mo);
3399 return reinterpret_cast<value_type>(old_val);
3400 }
3401
3406 value_type operator++(int) noexcept { return fetch_add(1); }
3407
3412 value_type operator--(int) noexcept { return fetch_sub(1); }
3413
3418 value_type operator++() noexcept { return fetch_add(1) + 1; }
3419
3424 value_type operator--() noexcept { return fetch_sub(1) - 1; }
3425
3431 value_type operator+=(const difference_type dest) noexcept { return fetch_add(dest) + dest; }
3432
3438 value_type operator-=(const difference_type dest) noexcept { return fetch_sub(dest) - dest; }
3439};
3440
3441#ifdef NEFORCE_COMPILER_CLANG
3442# pragma clang diagnostic pop
3443#endif
3444 // AtomicOperations
3446 // AsyncComponents
3448
3449NEFORCE_END_NAMESPACE__
3450#endif // NEFORCE_CORE_ASYNC_ATOMIC_BASE_HPP__
原子等待/通知机制
调试断点和断言工具
constexpr T * addressof(T &x) 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_fetch_add_any(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
原子获取并或操作
remove_volatile_t< T > atomic_sub_fetch(volatile T *ptr, atomic_diff_t< T > value, 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
强比较交换操作
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_sub_any(T *ptr, remove_volatile_t< T > value, memory_order mo) noexcept
通用原子获取并减去操作
T atomic_add_fetch_any(T *ptr, remove_volatile_t< T > value, memory_order mo) noexcept
通用原子添加并获取操作
constexpr bool is_always_lock_free() noexcept
检查是否支持无锁操作
void atomic_wait_address_v(const T *addr, T old, Func f) noexcept
基于值的原子等待
void atomic_notify_address(const T *addr, const bool all) noexcept
原子通知
T atomic_sub_fetch_any(T *ptr, remove_volatile_t< T > value, 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_load_any(const T *ptr, memory_order mo) noexcept
通用原子加载操作
void atomic_thread_fence(const 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_signal_fence(const 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
原子与并获取操作
void atomic_store_any(T *ptr, remove_volatile_t< T > value, const 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_sub(volatile T *ptr, atomic_diff_t< T > value, const memory_order mo) noexcept
原子获取并减去操作
remove_volatile_t< T > atomic_or_fetch(volatile T *ptr, remove_volatile_t< T > value, memory_order mo) noexcept
原子或并获取操作
remove_volatile_t< T > atomic_load(const volatile T *ptr, const memory_order mo) noexcept
原子加载操作
conditional_t< is_pointer_v< T >, ptrdiff_t, remove_volatile_t< T > > atomic_diff_t
原子操作的差值类型
void atomic_store(volatile T *ptr, remove_volatile_t< T > value, const memory_order mo) noexcept
原子存储操作
remove_volatile_t< T > atomic_fetch_and(volatile 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
通用原子交换操作
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
弱比较交换操作
remove_volatile_t< T > atomic_fetch_add(volatile T *ptr, atomic_diff_t< T > value, const memory_order mo) noexcept
原子获取并添加操作
constexpr bool is_integral_v
is_integral的便捷变量模板
constexpr bool is_floating_point_v
is_floating_point的便捷变量模板
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 long uint64_t
64位无符号整数类型
int int32_t
32位有符号整数类型
#define NEFORCE_CONSTEXPR_ASSERT(COND)
编译时常量断言
long platform_wait_t
平台等待类型别名
@ wait
等待操作
constexpr int memory_compare(const void *lhs, const void *rhs, size_t count) noexcept
比较两个内存区域的内容
constexpr void * memory_copy(void *NEFORCE_RESTRICT dest, const void *NEFORCE_RESTRICT src, size_t count) noexcept
从源内存复制到目标内存
constexpr bool is_valid_cmpexch_failure_order(const memory_order mo) noexcept
检查比较交换失败内存顺序是否有效
constexpr auto memory_order_release
释放内存顺序常量
constexpr auto memory_order_seq_cst
顺序一致性内存顺序常量
constexpr auto memory_order_relaxed
宽松内存顺序常量
constexpr auto memory_order_acquire
获取内存顺序常量
constexpr auto memory_order_consume
数据依赖内存顺序常量
constexpr auto memory_order_acq_rel
获取-释放内存顺序常量
memory_order
内存顺序
constexpr memory_order cmpexch_failure_order(const memory_order mo) noexcept
获取原子比较交换操作失败时的内存顺序
@ memory_order_mask
内存顺序掩码
uint64_t uintptr_t
可容纳指针的无符号整数类型
int64_t ptrdiff_t
指针差类型
typename remove_volatile< T >::type remove_volatile_t
remove_volatile的便捷别名
constexpr T exchange(T &val, U &&new_val) noexcept(is_nothrow_move_constructible_v< T > &&is_nothrow_assignable_v< T &, U >)
将新值赋给对象并返回旧值
constexpr bool is_nothrow_copy_constructible_v
is_nothrow_copy_constructible的便捷变量模板
constexpr bool is_trivially_copyable_v
is_trivially_copyable的便捷变量模板
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--(int) noexcept
后置递减运算符
value_type operator++(int) volatile noexcept
volatile版本的后置递增运算符
void store(value_type ptr, const memory_order mo=memory_order_seq_cst) noexcept
原子存储指针操作
value_type load(const memory_order mo=memory_order_seq_cst) const noexcept
原子加载指针操作
value_type load(const memory_order mo=memory_order_seq_cst) const volatile noexcept
volatile版本的原子加载指针操作
bool compare_exchange_weak(value_type &expected, value_type desired, const memory_order success, const memory_order failure) volatile noexcept
volatile版本的弱比较交换指针操作
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) noexcept
简化版弱比较交换指针操作
value_type operator--(int) 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 exchange(const value_type ptr, const memory_order mo=memory_order_seq_cst) noexcept
原子交换指针操作
value_type fetch_sub(const ptrdiff_t dest, const memory_order mo=memory_order_seq_cst) volatile noexcept
volatile版本的原子获取并减去指针偏移
value_type fetch_add(const ptrdiff_t dest, 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 operator+=(const ptrdiff_t dest) noexcept
指针加法赋值运算符
value_type fetch_sub(const ptrdiff_t dest, const memory_order mo=memory_order_seq_cst) noexcept
原子获取并减去指针偏移
value_type exchange(const value_type ptr, const memory_order mo=memory_order_seq_cst) volatile noexcept
volatile版本的原子交换指针操作
value_type operator--() noexcept
前置递减运算符
bool is_lock_free() const volatile noexcept
volatile版本的检查是否支持无锁操作
void notify_one() noexcept
通知一个等待线程
value_type operator=(const value_type ptr) noexcept
赋值运算符
value_type operator++() volatile noexcept
volatile版本的前置递增运算符
value_type operator-=(const ptrdiff_t dest) volatile noexcept
volatile版本的指针减法赋值运算符
bool is_lock_free() const noexcept
检查是否支持无锁操作
void store(const value_type ptr, const memory_order mo=memory_order_seq_cst) volatile noexcept
volatile版本的原子存储指针操作
value_type operator--() volatile noexcept
volatile版本的前置递减运算符
bool compare_exchange_strong(value_type &expected, value_type desired, const memory_order success, const memory_order failure) noexcept
强比较交换指针操作
bool compare_exchange_weak(value_type &expected, value_type desired, const memory_order success, const memory_order failure) noexcept
弱比较交换指针操作
bool compare_exchange_weak(value_type &expected, value_type desired, const memory_order mo=memory_order_seq_cst) volatile noexcept
volatile版本的简化版弱比较交换指针操作
value_type operator++() noexcept
前置递增运算符
value_type operator=(const value_type ptr) 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 mo=memory_order_seq_cst) noexcept
简化版强比较交换指针操作
ptrdiff_t difference_type
差值类型
value_type operator-=(const ptrdiff_t dest) noexcept
指针减法赋值运算符
value_type operator++(int) noexcept
后置递增运算符
void notify_all() noexcept
通知所有等待线程
原子类型基础模板类
value_type operator--(int) noexcept
后置递减运算符
value_type load(const memory_order mo=memory_order_seq_cst) const volatile noexcept
volatile版本的原子加载操作
bool compare_exchange_weak(value_type &expected, value_type desired, const memory_order mo=memory_order_seq_cst) volatile noexcept
volatile版本的简化版弱比较交换操作
value_type load(const memory_order mo=memory_order_seq_cst) const 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) noexcept
原子交换操作
void notify_one() noexcept
通知一个等待线程
value_type operator|=(value_type value) volatile noexcept
volatile版本的位或赋值运算符
bool is_lock_free() const noexcept
检查是否支持无锁操作
bool compare_exchange_weak(value_type &expected, value_type desired, const memory_order mo=memory_order_seq_cst) noexcept
简化版弱比较交换操作
value_type operator--() noexcept
前置递减运算符
value_type fetch_and(value_type value, const memory_order mo=memory_order_seq_cst) noexcept
原子获取并与操作
value_type fetch_xor(value_type value, const memory_order mo=memory_order_seq_cst) volatile noexcept
volatile版本的原子获取并异或操作
void notify_all() noexcept
通知所有等待线程
value_type fetch_add(value_type value, const memory_order mo=memory_order_seq_cst) noexcept
原子获取并添加操作
bool is_lock_free() const volatile noexcept
volatile版本的检查是否支持无锁操作
value_type operator--() volatile noexcept
volatile版本的前置递减运算符
value_type operator-=(value_type value) volatile noexcept
volatile版本的减法赋值运算符
value_type operator-=(value_type value) noexcept
减法赋值运算符
value_type operator=(value_type value) volatile noexcept
volatile版本的赋值运算符
bool compare_exchange_strong(value_type &expected, value_type desired, const memory_order success, const memory_order failure) noexcept
强比较交换操作
value_type operator^=(value_type value) noexcept
位异或赋值运算符
value_type fetch_sub(value_type value, const memory_order mo=memory_order_seq_cst) volatile noexcept
volatile版本的原子获取并减去操作
value_type operator++(int) volatile noexcept
volatile版本的后置递增运算符
value_type operator++(int) noexcept
后置递增运算符
value_type operator+=(value_type value) noexcept
加法赋值运算符
value_type fetch_and(value_type value, const memory_order mo=memory_order_seq_cst) volatile noexcept
volatile版本的原子获取并与操作
value_type exchange(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 mo=memory_order_seq_cst) noexcept
简化版强比较交换操作
value_type operator--(int) 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
赋值运算符
void store(value_type value, const memory_order mo=memory_order_seq_cst) noexcept
原子存储操作
value_type operator++() noexcept
前置递增运算符
value_type fetch_sub(value_type value, const memory_order mo=memory_order_seq_cst) noexcept
原子获取并减去操作
value_type operator+=(value_type value) volatile noexcept
volatile版本的加法赋值运算符
bool compare_exchange_weak(value_type &expected, value_type desired, const memory_order success, const memory_order failure) 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版本的位异或赋值运算符
void store(value_type value, const memory_order mo=memory_order_seq_cst) volatile noexcept
volatile版本的原子存储操作
value_type operator|=(value_type value) noexcept
位或赋值运算符
bool compare_exchange_strong(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 success, const memory_order failure) volatile noexcept
volatile版本的弱比较交换操作
value_type operator++() volatile noexcept
volatile版本的前置递增运算符
value_type fetch_add(value_type value, const memory_order mo=memory_order_seq_cst) volatile noexcept
volatile版本的原子获取并添加操作
value_type operator&=(value_type value) noexcept
位与赋值运算符
value_type fetch_or(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 fetch_xor(value_type value, const memory_order mo=memory_order_seq_cst) noexcept
原子获取并异或操作
void notify_one() noexcept
通知一个等待线程
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
测试并设置标志
value_type flag_
原子标志值
bool test(const memory_order mo=memory_order_seq_cst) const noexcept
测试标志值
void wait(const bool old, const memory_order mo=memory_order_seq_cst) const noexcept
等待标志值改变
long value_type
原子标志类型
void clear(const memory_order mo=memory_order_seq_cst) volatile noexcept
volatile版本的清除标志
void clear(const memory_order mo=memory_order_seq_cst) noexcept
清除标志
bool test(const memory_order mo=memory_order_seq_cst) const volatile noexcept
volatile版本的测试标志值
void notify_all() noexcept
通知所有等待线程
value_type fetch_add(value_type value, const memory_order mo=memory_order_seq_cst) noexcept
原子获取并添加操作
value_type fetch_sub(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 success, const memory_order failure) volatile noexcept
volatile版本的弱比较交换操作
bool compare_exchange_strong(Float &expected, Float desire, const memory_order mo=memory_order_seq_cst) noexcept
简化版强比较交换操作
value_type operator-=(value_type value) volatile noexcept
volatile版本的减法赋值运算符
Float load(const memory_order mo=memory_order_seq_cst) const noexcept
原子加载操作
void wait(Float old, const memory_order mo=memory_order_seq_cst) const noexcept
等待值改变
Float operator=(Float value) noexcept
赋值运算符
value_type difference_type
差值类型
value_type operator+=(value_type value) volatile noexcept
volatile版本的加法赋值运算符
void store(Float value, const memory_order mo=memory_order_seq_cst) volatile noexcept
volatile版本的原子存储操作
bool is_lock_free() const volatile noexcept
volatile版本的检查是否支持无锁操作
value_type fetch_sub(value_type value, const memory_order mo=memory_order_seq_cst) volatile noexcept
volatile版本的原子获取并减去操作
Float operator=(Float value) 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) volatile noexcept
volatile版本的原子获取并添加操作
Float exchange(Float desire, const memory_order mo=memory_order_seq_cst) noexcept
原子交换操作
value_type operator-=(value_type value) noexcept
减法赋值运算符
bool compare_exchange_strong(Float &expected, Float desire, const memory_order mo=memory_order_seq_cst) volatile noexcept
volatile版本的简化版强比较交换操作
void store(Float value, const memory_order mo=memory_order_seq_cst) noexcept
原子存储操作
bool compare_exchange_weak(Float &expected, Float desire, const memory_order mo=memory_order_seq_cst) volatile noexcept
volatile版本的简化版弱比较交换操作
value_type operator+=(value_type value) noexcept
加法赋值运算符
Float exchange(Float desire, const memory_order mo=memory_order_seq_cst) volatile noexcept
volatile版本的原子交换操作
bool compare_exchange_weak(Float &expected, Float desire, const memory_order success, const memory_order failure) noexcept
弱比较交换操作
void notify_one() noexcept
通知一个等待线程
bool compare_exchange_strong(Float &expected, Float desire, const memory_order success, const memory_order failure) 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) noexcept
简化版弱比较交换操作
Float exchange(Float desire, const memory_order mo=memory_order_seq_cst) noexcept
原子交换操作
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
原子加载操作
void wait(Float old, 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
强比较交换操作
void notify_all() noexcept
通知所有等待线程
value_type operator+=(value_type value) noexcept
加法赋值运算符
bool is_lock_free() const noexcept
检查是否支持无锁操作
value_type operator-=(value_type value) noexcept
减法赋值运算符
value_type fetch_add(value_type value, const memory_order mo=memory_order_seq_cst) noexcept
原子获取并添加操作
static constexpr size_t required_alignment
对齐需求
bool compare_exchange_strong(Float &expected, Float desire, const memory_order mo=memory_order_seq_cst) noexcept
简化版强比较交换操作
bool compare_exchange_weak(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) noexcept
原子获取并减去操作
Float operator=(Float value) noexcept
赋值运算符
bool compare_exchange_weak(Float &expected, Float desire, const memory_order success, const memory_order failure) noexcept
弱比较交换操作
void notify_one() noexcept
通知一个等待线程
bool compare_exchange_weak(T &expected, T desire, const memory_order success, const memory_order failure) noexcept
弱比较交换操作
bool compare_exchange_strong(T &expected, T desire, const memory_order mo=memory_order_seq_cst) noexcept
简化版强比较交换操作
bool compare_exchange_strong(T &expected, T desire, const memory_order success, const memory_order failure) noexcept
强比较交换操作
T load(const memory_order mo=memory_order_seq_cst) const noexcept
原子加载操作
void notify_all() noexcept
通知所有等待线程
bool is_lock_free() const noexcept
检查是否支持无锁操作
bool compare_exchange_weak(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
原子存储操作
T operator=(T value) noexcept
赋值运算符
void wait(T old, const memory_order mo=memory_order_seq_cst) const noexcept
等待值改变
void notify_one() noexcept
通知一个等待线程
static constexpr size_t required_alignment
对齐需求
T exchange(T desire, const memory_order mo=memory_order_seq_cst) noexcept
原子交换操作
value_type operator--(int) noexcept
后置递减运算符
bool compare_exchange_weak(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
原子获取并异或操作
bool is_lock_free() const noexcept
检查是否支持无锁操作
void notify_one() noexcept
通知一个等待线程
static constexpr size_t required_alignment
对齐需求
bool compare_exchange_weak(T &expected, T desire, const memory_order mo=memory_order_seq_cst) noexcept
简化版弱比较交换操作
value_type operator++() noexcept
前置递增运算符
value_type fetch_and(value_type value, const memory_order mo=memory_order_seq_cst) noexcept
原子获取并与操作
T operator=(T value) noexcept
赋值运算符
T exchange(T desire, const memory_order mo=memory_order_seq_cst) noexcept
原子交换操作
value_type operator^=(value_type value) noexcept
位异或赋值运算符
value_type fetch_add(value_type value, const memory_order mo=memory_order_seq_cst) noexcept
原子获取并添加操作
void wait(T old, const memory_order mo=memory_order_seq_cst) const noexcept
等待值改变
void store(T value, const memory_order mo=memory_order_seq_cst) noexcept
原子存储操作
bool compare_exchange_strong(T &expected, T desire, const memory_order success, const memory_order failure) noexcept
强比较交换操作
value_type fetch_sub(value_type value, const memory_order mo=memory_order_seq_cst) noexcept
原子获取并减去操作
value_type operator&=(value_type value) noexcept
位与赋值运算符
T load(const memory_order mo=memory_order_seq_cst) const noexcept
原子加载操作
value_type operator-=(value_type value) noexcept
减法赋值运算符
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 operator|=(value_type value) noexcept
位或赋值运算符
void notify_all() noexcept
通知所有等待线程
value_type operator--() noexcept
前置递减运算符
value_type operator++(int) noexcept
后置递增运算符
bool compare_exchange_strong(T &expected, T desire, const memory_order mo=memory_order_seq_cst) noexcept
简化版强比较交换操作
原子引用基础模板类