/* Atomics for OctaSTD. Supports GCC/Clang and possibly MSVC. * * This file is part of OctaSTD. See COPYING.md for futher information. */ #ifndef OSTD_ATOMIC_HH #define OSTD_ATOMIC_HH #include #include #include "ostd/types.hh" #include "ostd/type_traits.hh" namespace ostd { enum class MemoryOrder { relaxed = 0, consume, acquire, release, acq_rel, seq_cst }; namespace detail { template struct AtomicBase { AtomicBase() {} explicit AtomicBase(T v): p_value(v) {} T p_value; }; template T atomic_create(); template EnableIfvalue = atomic_create()), char> test_atomic_assignable(int); template int test_atomic_assignable(...); template struct CanAtomicAssign { static constexpr bool value = (sizeof(test_atomic_assignable(1)) == sizeof(char)); }; template static inline EnableIf< CanAtomicAssign *, T>::value > atomic_init(volatile AtomicBase *a, T v) { a->p_value = v; } template static inline EnableIf< !CanAtomicAssign *, T>::value && CanAtomicAssign< AtomicBase *, T>::value > atomic_init(volatile AtomicBase *a, T v) { volatile char *to = (volatile char *)(&a->p_value); volatile char *end = to + sizeof(T); char *from = (char *)(&v); while (to != end) *to++ =*from++; } template static inline void atomic_init(AtomicBase *a, T v) { a->p_value = v; } } /* GCC, Clang support * * libc++ used for reference */ #ifdef __GNUC__ static constexpr Size AtomicBoolLockFree = __GCC_ATOMIC_BOOL_LOCK_FREE; static constexpr Size AtomicCharLockFree = __GCC_ATOMIC_CHAR_LOCK_FREE; static constexpr Size AtomicChar16LockFree = __GCC_ATOMIC_CHAR16_T_LOCK_FREE; static constexpr Size AtomicChar32LockFree = __GCC_ATOMIC_CHAR32_T_LOCK_FREE; static constexpr Size AtomicWcharLockFree = __GCC_ATOMIC_WCHAR_T_LOCK_FREE; static constexpr Size AtomicShortLockFree = __GCC_ATOMIC_SHORT_LOCK_FREE; static constexpr Size AtomicIntLockFree = __GCC_ATOMIC_INT_LOCK_FREE; static constexpr Size AtomicLongLockFree = __GCC_ATOMIC_LONG_LOCK_FREE; static constexpr Size AtomicLlongLockFree = __GCC_ATOMIC_LLONG_LOCK_FREE; static constexpr Size AtomicPointerLockFree = __GCC_ATOMIC_POINTER_LOCK_FREE; namespace detail { static inline constexpr int to_gcc_order(MemoryOrder ord) { return ((ord == MemoryOrder::relaxed) ? __ATOMIC_RELAXED : ((ord == MemoryOrder::acquire) ? __ATOMIC_ACQUIRE : ((ord == MemoryOrder::release) ? __ATOMIC_RELEASE : ((ord == MemoryOrder::seq_cst) ? __ATOMIC_SEQ_CST : ((ord == MemoryOrder::acq_rel) ? __ATOMIC_ACQ_REL : __ATOMIC_CONSUME))))); } static inline constexpr int to_gcc_failure_order(MemoryOrder ord) { return ((ord == MemoryOrder::relaxed) ? __ATOMIC_RELAXED : ((ord == MemoryOrder::acquire) ? __ATOMIC_ACQUIRE : ((ord == MemoryOrder::release) ? __ATOMIC_RELAXED : ((ord == MemoryOrder::seq_cst) ? __ATOMIC_SEQ_CST : ((ord == MemoryOrder::acq_rel) ? __ATOMIC_ACQUIRE : __ATOMIC_CONSUME))))); } static inline void atomic_thread_fence(MemoryOrder ord) { __atomic_thread_fence(to_gcc_order(ord)); } static inline void atomic_signal_fence(MemoryOrder ord) { __atomic_signal_fence(to_gcc_order(ord)); } static inline bool atomic_is_lock_free(Size size) { /* return __atomic_is_lock_free(size, 0); cannot be used on some platforms */ return size <= sizeof(void *); } template static inline void atomic_store(volatile AtomicBase *a, T v, MemoryOrder ord) { __atomic_store(&a->p_value, &v, to_gcc_order(ord)); } template static inline void atomic_store(AtomicBase *a, T v, MemoryOrder ord) { __atomic_store(&a->p_value, &v, to_gcc_order(ord)); } template static inline T atomic_load(volatile AtomicBase *a, MemoryOrder ord) { T r; __atomic_load(&a->p_value, &r, to_gcc_order(ord)); return r; } template static inline T atomic_load(AtomicBase *a, MemoryOrder ord) { T r; __atomic_load(&a->p_value, &r, to_gcc_order(ord)); return r; } template static inline T atomic_exchange(volatile AtomicBase *a, T v, MemoryOrder ord) { T r; __atomic_exchange(&a->p_value, &v, &r, to_gcc_order(ord)); return r; } template static inline T atomic_exchange(AtomicBase *a, T v, MemoryOrder ord) { T r; __atomic_exchange(&a->p_value, &v, &r, to_gcc_order(ord)); return r; } template static inline bool atomic_compare_exchange_strong( volatile AtomicBase *a, T *expected, T v, MemoryOrder success, MemoryOrder failure ) { return __atomic_compare_exchange(&a->p_value, expected, &v, false, to_gcc_order(success), to_gcc_failure_order(failure)); } template static inline bool atomic_compare_exchange_strong( AtomicBase *a, T *expected, T v, MemoryOrder success, MemoryOrder failure ) { return __atomic_compare_exchange(&a->p_value, expected, &v, false, to_gcc_order(success), to_gcc_failure_order(failure)); } template static inline bool atomic_compare_exchange_weak( volatile AtomicBase *a, T *expected, T v, MemoryOrder success, MemoryOrder failure ) { return __atomic_compare_exchange(&a->p_value, expected, &v, true, to_gcc_order(success), to_gcc_failure_order(failure)); } template static inline bool atomic_compare_exchange_weak( AtomicBase *a, T *expected, T v, MemoryOrder success, MemoryOrder failure ) { return __atomic_compare_exchange(&a->p_value, expected, &v, true, to_gcc_order(success), to_gcc_failure_order(failure)); } template struct SkipAmt { static constexpr Size value = 1; }; template struct SkipAmt { static constexpr Size value = sizeof(T); }; template struct SkipAmt {}; template struct SkipAmt {}; template static inline T atomic_fetch_add(volatile AtomicBase *a, U d, MemoryOrder ord) { return __atomic_fetch_add(&a->p_value, d * SkipAmt::value, to_gcc_order(ord)); } template static inline T atomic_fetch_add(AtomicBase *a, U d, MemoryOrder ord) { return __atomic_fetch_add(&a->p_value, d * SkipAmt::value, to_gcc_order(ord)); } template static inline T atomic_fetch_sub(volatile AtomicBase *a, U d, MemoryOrder ord) { return __atomic_fetch_sub(&a->p_value, d * SkipAmt::value, to_gcc_order(ord)); } template static inline T atomic_fetch_sub(AtomicBase *a, U d, MemoryOrder ord) { return __atomic_fetch_sub(&a->p_value, d * SkipAmt::value, to_gcc_order(ord)); } template static inline T atomic_fetch_and(volatile AtomicBase *a, T pattern, MemoryOrder ord) { return __atomic_fetch_and(&a->p_value, pattern, to_gcc_order(ord)); } template static inline T atomic_fetch_and(AtomicBase *a, T pattern, MemoryOrder ord) { return __atomic_fetch_and(&a->p_value, pattern, to_gcc_order(ord)); } template static inline T atomic_fetch_or(volatile AtomicBase *a, T pattern, MemoryOrder ord) { return __atomic_fetch_or(&a->p_value, pattern, to_gcc_order(ord)); } template static inline T atomic_fetch_or(AtomicBase *a, T pattern, MemoryOrder ord) { return __atomic_fetch_or(&a->p_value, pattern, to_gcc_order(ord)); } template static inline T atomic_fetch_xor(volatile AtomicBase *a, T pattern, MemoryOrder ord) { return __atomic_fetch_xor(&a->p_value, pattern, to_gcc_order(ord)); } template static inline T atomic_fetch_xor(AtomicBase *a, T pattern, MemoryOrder ord) { return __atomic_fetch_xor(&a->p_value, pattern, to_gcc_order(ord)); } } /* namespace detail */ #else # error Unsupported compiler #endif template inline T kill_dependency(T v) { return v; } namespace detail { template && !IsSame> struct Atomic { mutable AtomicBase p_a; Atomic() = default; constexpr Atomic(T v): p_a(v) {} Atomic(const Atomic &) = delete; Atomic &operator=(const Atomic &) = delete; Atomic &operator=(const Atomic &) volatile = delete; bool is_lock_free() const volatile { return atomic_is_lock_free(sizeof(T)); } bool is_lock_free() const { return atomic_is_lock_free(sizeof(T)); } void store(T v, MemoryOrder ord = MemoryOrder::seq_cst) volatile { atomic_store(&p_a, v, ord); } void store(T v, MemoryOrder ord = MemoryOrder::seq_cst) { atomic_store(&p_a, v, ord); } T load(MemoryOrder ord = MemoryOrder::seq_cst) const volatile { return atomic_load(&p_a, ord); } T load(MemoryOrder ord = MemoryOrder::seq_cst) const { return atomic_load(&p_a, ord); } operator T() const volatile { return load(); } operator T() const { return load(); } T exchange(T v, MemoryOrder ord = MemoryOrder::seq_cst) volatile { return atomic_exchange(&p_a, v, ord); } T exchange(T v, MemoryOrder ord = MemoryOrder::seq_cst) { return atomic_exchange(&p_a, v, ord); } bool compare_exchange_weak(T &e, T v, MemoryOrder s, MemoryOrder f) volatile { return atomic_compare_exchange_weak(&p_a, &e, v, s, f); } bool compare_exchange_weak(T &e, T v, MemoryOrder s, MemoryOrder f) { return atomic_compare_exchange_weak(&p_a, &e, v, s, f); } bool compare_exchange_strong(T &e, T v, MemoryOrder s, MemoryOrder f) volatile { return atomic_compare_exchange_strong(&p_a, &e, v, s, f); } bool compare_exchange_strong(T &e, T v, MemoryOrder s, MemoryOrder f) { return atomic_compare_exchange_strong(&p_a, &e, v, s, f); } bool compare_exchange_weak(T &e, T v, MemoryOrder ord = MemoryOrder::seq_cst) volatile { return atomic_compare_exchange_weak(&p_a, &e, v, ord, ord); } bool compare_exchange_weak(T &e, T v, MemoryOrder ord = MemoryOrder::seq_cst) { return atomic_compare_exchange_weak(&p_a, &e, v, ord, ord); } bool compare_exchange_strong(T &e, T v, MemoryOrder ord = MemoryOrder::seq_cst) volatile { return atomic_compare_exchange_strong(&p_a, &e, v, ord, ord); } bool compare_exchange_strong(T &e, T v, MemoryOrder ord = MemoryOrder::seq_cst) { return atomic_compare_exchange_strong(&p_a, &e, v, ord, ord); } }; template struct Atomic: Atomic { using Base = Atomic; Atomic() = default; constexpr Atomic(T v): Base(v) {} T fetch_add(T op, MemoryOrder ord = MemoryOrder::seq_cst) volatile { return atomic_fetch_add(&this->p_a, op, ord); } T fetch_add(T op, MemoryOrder ord = MemoryOrder::seq_cst) { return atomic_fetch_add(&this->p_a, op, ord); } T fetch_sub(T op, MemoryOrder ord = MemoryOrder::seq_cst) volatile { return atomic_fetch_sub(&this->p_a, op, ord); } T fetch_sub(T op, MemoryOrder ord = MemoryOrder::seq_cst) { return atomic_fetch_sub(&this->p_a, op, ord); } T fetch_and(T op, MemoryOrder ord = MemoryOrder::seq_cst) volatile { return atomic_fetch_and(&this->p_a, op, ord); } T fetch_and(T op, MemoryOrder ord = MemoryOrder::seq_cst) { return atomic_fetch_and(&this->p_a, op, ord); } T fetch_or(T op, MemoryOrder ord = MemoryOrder::seq_cst) volatile { return atomic_fetch_or(&this->p_a, op, ord); } T fetch_or(T op, MemoryOrder ord = MemoryOrder::seq_cst) { return atomic_fetch_or(&this->p_a, op, ord); } T fetch_xor(T op, MemoryOrder ord = MemoryOrder::seq_cst) volatile { return atomic_fetch_xor(&this->p_a, op, ord); } T fetch_xor(T op, MemoryOrder ord = MemoryOrder::seq_cst) { return atomic_fetch_xor(&this->p_a, op, ord); } T operator++(int) volatile { return fetch_add(T(1)); } T operator++(int) { return fetch_add(T(1)); } T operator--(int) volatile { return fetch_sub(T(1)); } T operator--(int) { return fetch_sub(T(1)); } T operator++( ) volatile { return fetch_add(T(1)) + T(1); } T operator++( ) { return fetch_add(T(1)) + T(1); } T operator--( ) volatile { return fetch_sub(T(1)) - T(1); } T operator--( ) { return fetch_sub(T(1)) - T(1); } T operator+=(T op) volatile { return fetch_add(op) + op; } T operator+=(T op) { return fetch_add(op) + op; } T operator-=(T op) volatile { return fetch_sub(op) - op; } T operator-=(T op) { return fetch_sub(op) - op; } T operator&=(T op) volatile { return fetch_and(op) & op; } T operator&=(T op) { return fetch_and(op) & op; } T operator|=(T op) volatile { return fetch_or (op) | op; } T operator|=(T op) { return fetch_or (op) | op; } T operator^=(T op) volatile { return fetch_xor(op) ^ op; } T operator^=(T op) { return fetch_xor(op) ^ op; } }; } template struct Atomic: detail::Atomic { using Base = detail::Atomic; Atomic() = default; constexpr Atomic(T v): Base(v) {} T operator=(T v) volatile { Base::store(v); return v; } T operator=(T v) { Base::store(v); return v; } }; template struct Atomic: detail::Atomic { using Base = detail::Atomic; Atomic() = default; constexpr Atomic(T *v): Base(v) {} T *operator=(T *v) volatile { Base::store(v); return v; } T *operator=(T *v) { Base::store(v); return v; } T *fetch_add(Ptrdiff op, MemoryOrder ord = MemoryOrder::seq_cst) volatile { return detail::atomic_fetch_add(&this->p_a, op, ord); } T *fetch_add(Ptrdiff op, MemoryOrder ord = MemoryOrder::seq_cst) { return detail::atomic_fetch_add(&this->p_a, op, ord); } T *fetch_sub(Ptrdiff op, MemoryOrder ord = MemoryOrder::seq_cst) volatile { return detail::atomic_fetch_sub(&this->p_a, op, ord); } T *fetch_sub(Ptrdiff op, MemoryOrder ord = MemoryOrder::seq_cst) { return detail::atomic_fetch_sub(&this->p_a, op, ord); } T *operator++(int) volatile { return fetch_add(1); } T *operator++(int) { return fetch_add(1); } T *operator--(int) volatile { return fetch_sub(1); } T *operator--(int) { return fetch_sub(1); } T *operator++( ) volatile { return fetch_add(1) + 1; } T *operator++( ) { return fetch_add(1) + 1; } T *operator--( ) volatile { return fetch_sub(1) - 1; } T *operator--( ) { return fetch_sub(1) - 1; } T *operator+=(Ptrdiff op) volatile { return fetch_add(op) + op; } T *operator+=(Ptrdiff op) { return fetch_add(op) + op; } T *operator-=(Ptrdiff op) volatile { return fetch_sub(op) - op; } T *operator-=(Ptrdiff op) { return fetch_sub(op) - op; } }; template inline bool atomic_is_lock_free(const volatile Atomic *a) { return a->is_lock_free(); } template inline bool atomic_is_lock_free(const Atomic *a) { return a->is_lock_free(); } template inline void atomic_init(volatile Atomic *a, T v) { detail::atomic_init(&a->p_a, v); } template inline void atomic_init(Atomic *a, T v) { detail::atomic_init(&a->p_a, v); } template inline void atomic_store(volatile Atomic *a, T v) { a->store(v); } template inline void atomic_store(Atomic *a, T v) { a->store(v); } template inline void atomic_store_explicit(volatile Atomic *a, T v, MemoryOrder ord) { a->store(v, ord); } template inline void atomic_store_explicit(Atomic *a, T v, MemoryOrder ord) { a->store(v, ord); } template inline T atomic_load(const volatile Atomic *a) { return a->load(); } template inline T atomic_load(const Atomic *a) { return a->load(); } template inline T atomic_load_explicit(const volatile Atomic *a, MemoryOrder ord) { return a->load(ord); } template inline T atomic_load_explicit(const Atomic *a, MemoryOrder ord) { return a->load(ord); } template inline T atomic_exchange(volatile Atomic *a, T v) { return a->exchange(v); } template inline T atomic_exchange(Atomic *a, T v) { return a->exchange(v); } template inline T atomic_exchange_explicit(volatile Atomic *a, T v, MemoryOrder ord) { return a->exchange(v, ord); } template inline T atomic_exchange_explicit(Atomic *a, T v, MemoryOrder ord) { return a->exchange(v, ord); } template inline bool atomic_compare_exchange_weak(volatile Atomic *a, T *e, T v) { return a->compare_exchange_weak(*e, v); } template inline bool atomic_compare_exchange_weak(Atomic *a, T *e, T v) { return a->compare_exchange_weak(*e, v); } template inline bool atomic_compare_exchange_strong(volatile Atomic *a, T *e, T v) { return a->compare_exchange_strong(*e, v); } template inline bool atomic_compare_exchange_strong(Atomic *a, T *e, T v) { return a->compare_exchange_strong(*e, v); } template inline bool atomic_compare_exchange_weak_explicit(volatile Atomic *a, T *e, T v, MemoryOrder s, MemoryOrder f) { return a->compare_exchange_weak(*e, v, s, f); } template inline bool atomic_compare_exchange_weak_explicit(Atomic *a, T *e, T v, MemoryOrder s, MemoryOrder f) { return a->compare_exchange_weak(*e, v, s, f); } template inline bool atomic_compare_exchange_strong_explicit(volatile Atomic *a, T *e, T v, MemoryOrder s, MemoryOrder f) { return a->compare_exchange_strong(*e, v, s, f); } template inline bool atomic_compare_exchange_strong_explicit(Atomic *a, T *e, T v, MemoryOrder s, MemoryOrder f) { return a->compare_exchange_strong(*e, v, s, f); } template inline EnableIf && !IsSame, T> atomic_fetch_add(volatile Atomic *a, T op) { return a->fetch_add(op); } template inline EnableIf && !IsSame, T> atomic_fetch_add(Atomic *a, T op) { return a->fetch_add(op); } template inline T *atomic_fetch_add(volatile Atomic *a, Ptrdiff op) { return a->fetch_add(op); } template inline T *atomic_fetch_add(Atomic *a, Ptrdiff op) { return a->fetch_add(op); } template inline EnableIf && !IsSame, T> atomic_fetch_add_explicit(volatile Atomic *a, T op, MemoryOrder ord) { return a->fetch_add(op, ord); } template inline EnableIf && !IsSame, T> atomic_fetch_add_explicit(Atomic *a, T op, MemoryOrder ord) { return a->fetch_add(op, ord); } template inline T *atomic_fetch_add_explicit(volatile Atomic *a, Ptrdiff op, MemoryOrder ord) { return a->fetch_add(op, ord); } template inline T *atomic_fetch_add_explicit(Atomic *a, Ptrdiff op, MemoryOrder ord) { return a->fetch_add(op, ord); } template inline EnableIf && !IsSame, T> atomic_fetch_sub(volatile Atomic *a, T op) { return a->fetch_sub(op); } template inline EnableIf && !IsSame, T> atomic_fetch_sub(Atomic *a, T op) { return a->fetch_sub(op); } template inline T *atomic_fetch_sub(volatile Atomic *a, Ptrdiff op) { return a->fetch_sub(op); } template inline T *atomic_fetch_sub(Atomic *a, Ptrdiff op) { return a->fetch_sub(op); } template inline EnableIf && !IsSame, T> atomic_fetch_sub_explicit(volatile Atomic *a, T op, MemoryOrder ord) { return a->fetch_sub(op, ord); } template inline EnableIf && !IsSame, T> atomic_fetch_sub_explicit(Atomic *a, T op, MemoryOrder ord) { return a->fetch_sub(op, ord); } template inline T *atomic_fetch_sub_explicit(volatile Atomic *a, Ptrdiff op, MemoryOrder ord) { return a->fetch_sub(op, ord); } template inline T *atomic_fetch_sub_explicit(Atomic *a, Ptrdiff op, MemoryOrder ord) { return a->fetch_sub(op, ord); } template inline EnableIf && !IsSame, T> atomic_fetch_and(volatile Atomic *a, T op) { return a->fetch_and(op); } template inline EnableIf && !IsSame, T> atomic_fetch_and(Atomic *a, T op) { return a->fetch_and(op); } template inline EnableIf && !IsSame, T> atomic_fetch_and_explicit(volatile Atomic *a, T op, MemoryOrder ord) { return a->fetch_and(op, ord); } template inline EnableIf && !IsSame, T> atomic_fetch_and_explicit(Atomic *a, T op, MemoryOrder ord) { return a->fetch_and(op, ord); } template inline EnableIf && !IsSame, T> atomic_fetch_or(volatile Atomic *a, T op) { return a->fetch_or(op); } template inline EnableIf && !IsSame, T> atomic_fetch_or(Atomic *a, T op) { return a->fetch_or(op); } template inline EnableIf && !IsSame, T> atomic_fetch_or_explicit(volatile Atomic *a, T op, MemoryOrder ord) { return a->fetch_or(op, ord); } template inline EnableIf && !IsSame, T> atomic_fetch_or_explicit(Atomic *a, T op, MemoryOrder ord) { return a->fetch_or(op, ord); } template inline EnableIf && !IsSame, T> atomic_fetch_xor(volatile Atomic *a, T op) { return a->fetch_xor(op); } template inline EnableIf && !IsSame, T> atomic_fetch_xor(Atomic *a, T op) { return a->fetch_xor(op); } template inline EnableIf && !IsSame, T> atomic_fetch_xor_explicit(volatile Atomic *a, T op, MemoryOrder ord) { return a->fetch_xor(op, ord); } template inline EnableIf && !IsSame, T> atomic_fetch_xor_explicit(Atomic *a, T op, MemoryOrder ord) { return a->fetch_xor(op, ord); } struct AtomicFlag { detail::AtomicBase p_a; AtomicFlag() = default; AtomicFlag(bool b): p_a(b) {} AtomicFlag(const AtomicFlag &) = delete; AtomicFlag &operator=(const AtomicFlag &) = delete; AtomicFlag &operator=(const AtomicFlag &) volatile = delete; bool test_and_set(MemoryOrder ord = MemoryOrder::seq_cst) volatile { return detail::atomic_exchange(&p_a, true, ord); } bool test_and_set(MemoryOrder ord = MemoryOrder::seq_cst) { return detail::atomic_exchange(&p_a, true, ord); } void clear(MemoryOrder ord = MemoryOrder::seq_cst) volatile { detail::atomic_store(&p_a, false, ord); } void clear(MemoryOrder ord = MemoryOrder::seq_cst) { detail::atomic_store(&p_a, false, ord); } }; inline bool atomic_flag_test_and_set(volatile AtomicFlag *a) { return a->test_and_set(); } inline bool atomic_flag_test_and_set(AtomicFlag *a) { return a->test_and_set(); } inline bool atomic_flag_test_and_set_explicit(volatile AtomicFlag *a, MemoryOrder ord) { return a->test_and_set(ord); } inline bool atomic_flag_test_and_set_explicit(AtomicFlag *a, MemoryOrder ord) { return a->test_and_set(ord); } inline void atomic_flag_clear(volatile AtomicFlag *a) { a->clear(); } inline void atomic_flag_clear(AtomicFlag *a) { a->clear(); } inline void atomic_flag_clear_explicit(volatile AtomicFlag *a, MemoryOrder ord) { a->clear(ord); } inline void atomic_flag_clear_explicit(AtomicFlag *a, MemoryOrder ord) { a->clear(ord); } inline void atomic_thread_fence(MemoryOrder ord) { detail::atomic_thread_fence(ord); } inline void atomic_signal_fence(MemoryOrder ord) { detail::atomic_signal_fence(ord); } using AtomicBool = Atomic; using AtomicChar = Atomic; using AtomicShort = Atomic; using AtomicInt = Atomic; using AtomicLong = Atomic; using AtomicSbyte = Atomic; using AtomicByte = Atomic; using AtomicUshort = Atomic; using AtomicUint = Atomic; using AtomicUlong = Atomic; using AtomicLlong = Atomic; using AtomicUllong = Atomic; using AtomicChar16 = Atomic; using AtomicChar32 = Atomic; using AtomicWchar = Atomic; using AtomicPtrdiff = Atomic; using AtomicSize = Atomic; using AtomicIntmax = Atomic; using AtomicUintmax = Atomic; using AtomicIntptr = Atomic; using AtomicUintptr = Atomic; using AtomicInt8 = Atomic; using AtomicInt16 = Atomic; using AtomicInt32 = Atomic; using AtomicInt64 = Atomic; using AtomicUint8 = Atomic; using AtomicUint16 = Atomic; using AtomicUint32 = Atomic; using AtomicUint64 = Atomic; using AtomicIntLeast8 = Atomic; using AtomicIntLeast16 = Atomic; using AtomicIntLeast32 = Atomic; using AtomicIntLeast64 = Atomic; using AtomicUintLeast8 = Atomic; using AtomicUintLeast16 = Atomic; using AtomicUintLeast32 = Atomic; using AtomicUintLeast64 = Atomic; using AtomicIntFast8 = Atomic; using AtomicIntFast16 = Atomic; using AtomicIntFast32 = Atomic; using AtomicIntFast64 = Atomic; using AtomicUintFast8 = Atomic; using AtomicUintFast16 = Atomic; using AtomicUintFast32 = Atomic; using AtomicUintFast64 = Atomic; #define ATOMIC_FLAG_INIT {false} #define ATOMIC_VAR_INIT(v) {v} } #endif