/* * Copyright (c) 2017 - present Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. */ #pragma once #include #include #include #include #include INFER_NAMESPACE_STD_BEGIN typedef enum memory_order { memory_order_relaxed, memory_order_consume, memory_order_acquire, memory_order_release, memory_order_acq_rel, memory_order_seq_cst } memory_order; template T kill_dependency(T y) noexcept { return y; } // lock-free property #define ATOMIC_BOOL_LOCK_FREE 2 #define ATOMIC_CHAR_LOCK_FREE 2 #define ATOMIC_CHAR16_T_LOCK_FREE 2 #define ATOMIC_CHAR32_T_LOCK_FREE 2 #define ATOMIC_WCHAR_T_LOCK_FREE 2 #define ATOMIC_SHORT_LOCK_FREE 2 #define ATOMIC_INT_LOCK_FREE 2 #define ATOMIC_LONG_LOCK_FREE 2 #define ATOMIC_LLONG_LOCK_FREE 2 #define ATOMIC_POINTER_LOCK_FREE 2 // NOTE1: We are missing the atomic specialization here. Will need to add // it when necessary // NOTE2: In reality, most of the atomic operations, including load, store, // exchange, etc. are implemented with compiler intrinsics. Some of them are // really hard to emulate with a source-level model due to various constraints // in the source language. We try our best here to violate as few constraints as // possible, but if it turns out to be a problem in practice, we may need to // consider moving some of the model implementation to BuiltinDefn. template struct __infer_atomic_base { bool is_lock_free() const volatile noexcept { return false; } bool is_lock_free() const noexcept { return false; } // Note that the biabduction analysis has a hard time understanding memcpy // with non-array args. If this function turns out to be a blocker for the // backend, consider moving it to BuiltinDefn. void store(T t, memory_order mo = memory_order_seq_cst) volatile noexcept { memcpy(&_wrapped_value, &t, sizeof(T)); } void store(T t, memory_order mo = memory_order_seq_cst) noexcept { memcpy(&_wrapped_value, &t, sizeof(T)); } T load(memory_order mo = memory_order_seq_cst) const volatile noexcept { return _wrapped_value; } T load(memory_order mo = memory_order_seq_cst) const noexcept { return _wrapped_value; } operator T() const volatile noexcept { return _wrapped_value; } operator T() const noexcept { return _wrapped_value; } // Note that these two functions are not standard-compliant: if T is not // copy-constructible, then we are going to get a compilation failure. // The body of this function could be a candidate for BuiltinDefn, if // necessary. T exchange(T t, memory_order mo = memory_order_seq_cst) volatile noexcept { T tmp = _wrapped_value; _wrapped_value = t; return tmp; } T exchange(T t, memory_order mo = memory_order_seq_cst) noexcept { T tmp = _wrapped_value; _wrapped_value = t; return tmp; } // For arbitrary type T, we have to rely on memcmp/memcpy instead of // operator==/operator= for comparison/assignment // Note that the biabduction analysis has a hard time understanding memcpy // with non-array args. If this function turns out to be a blocker for the // backend, consider moving it to BuiltinDefn. bool __infer_compare_exchange_impl(T* expected, T* desired) volatile noexcept { if (memcmp(&_wrapped_value, expected, sizeof(T))) { memcpy(&_wrapped_value, desired, sizeof(T)); return true; } else { memcpy(expected, &_wrapped_value, sizeof(T)); return false; } } bool __infer_compare_exchange_impl(T* expected, T* desired) noexcept { if (memcmp(&_wrapped_value, expected, sizeof(T))) { memcpy(&_wrapped_value, desired, sizeof(T)); return true; } else { memcpy(expected, &_wrapped_value, sizeof(T)); return false; } } bool compare_exchange_weak( T& expected, T desired, memory_order mo = memory_order_seq_cst) volatile noexcept { return __infer_compare_exchange_impl(&expected, &desired); } bool compare_exchange_weak(T& expected, T desired, memory_order mo = memory_order_seq_cst) noexcept { return __infer_compare_exchange_impl(&expected, &desired); } bool compare_exchange_weak(T& expected, T desired, memory_order succ, memory_order fail) volatile noexcept { return __infer_compare_exchange_impl(&expected, &desired); } bool compare_exchange_weak(T& expected, T desired, memory_order succ, memory_order fail) noexcept { return __infer_compare_exchange_impl(&expected, &desired); } bool compare_exchange_strong( T& expected, T desired, memory_order mo = memory_order_seq_cst) volatile noexcept { return __infer_compare_exchange_impl(&expected, &desired); } bool compare_exchange_strong( T& expected, T desired, memory_order mo = memory_order_seq_cst) noexcept { return __infer_compare_exchange_impl(&expected, &desired); } bool compare_exchange_strong(T& expected, T desired, memory_order succ, memory_order fail) volatile noexcept { return __infer_compare_exchange_impl(&expected, &desired); } bool compare_exchange_strong(T& expected, T desired, memory_order succ, memory_order fail) noexcept { return __infer_compare_exchange_impl(&expected, &desired); } __infer_atomic_base() noexcept = default; constexpr __infer_atomic_base(T desired) : _wrapped_value(desired) {} __infer_atomic_base(const __infer_atomic_base&) = delete; __infer_atomic_base& operator=(const __infer_atomic_base&) = delete; __infer_atomic_base& operator=(const __infer_atomic_base&) volatile = delete; T operator=(T other) volatile noexcept { store(other); return other; } T operator=(T other) noexcept { store(other); return other; } T _wrapped_value; }; template struct __infer_atomic_integral : public __infer_atomic_base { typedef __infer_atomic_base __base; __infer_atomic_integral() noexcept = default; constexpr __infer_atomic_integral(T d) noexcept : __base(d) {} bool is_lock_free() const volatile noexcept { return true; } bool is_lock_free() const noexcept { return true; } void store(T t, memory_order mo = memory_order_seq_cst) volatile noexcept { this->_wrapped_value = t; } void store(T t, memory_order mo = memory_order_seq_cst) noexcept { this->_wrapped_value = t; } T load(memory_order mo = memory_order_seq_cst) const volatile noexcept { return this->_wrapped_value; } T load(memory_order mo = memory_order_seq_cst) const noexcept { return this->_wrapped_value; } operator T() const volatile noexcept { return this->_wrapped_value; } operator T() const noexcept { return this->_wrapped_value; } bool __infer_compare_exchange_impl(T& expected, T desired) volatile noexcept { if (this->_wrapped_value == expected) { this->_wrapped_value = desired; return true; } else { expected = this->_wrapped_value; return false; } } bool __infer_compare_exchange_impl(T& expected, T desired) noexcept { if (this->_wrapped_value == expected) { this->_wrapped_value = desired; return true; } else { expected = this->_wrapped_value; return false; } } bool compare_exchange_weak( T& expected, T desired, memory_order mo = memory_order_seq_cst) volatile noexcept { return __infer_compare_exchange_impl(expected, desired); } bool compare_exchange_weak(T& expected, T desired, memory_order mo = memory_order_seq_cst) noexcept { return __infer_compare_exchange_impl(expected, desired); } bool compare_exchange_weak(T& expected, T desired, memory_order succ, memory_order fail) volatile noexcept { return __infer_compare_exchange_impl(expected, desired); } bool compare_exchange_weak(T& expected, T desired, memory_order succ, memory_order fail) noexcept { return __infer_compare_exchange_impl(expected, desired); } bool compare_exchange_strong( T& expected, T desired, memory_order mo = memory_order_seq_cst) volatile noexcept { return __infer_compare_exchange_impl(expected, desired); } bool compare_exchange_strong( T& expected, T desired, memory_order mo = memory_order_seq_cst) noexcept { return __infer_compare_exchange_impl(expected, desired); } bool compare_exchange_strong(T& expected, T desired, memory_order succ, memory_order fail) volatile noexcept { return __infer_compare_exchange_impl(expected, desired); } bool compare_exchange_strong(T& expected, T desired, memory_order succ, memory_order fail) noexcept { return __infer_compare_exchange_impl(expected, desired); } T operator=(T other) volatile noexcept { this->_wrapped_value = other; return other; } T operator=(T other) noexcept { this->_wrapped_value = other; return other; } T fetch_add(T op, memory_order mo = memory_order_seq_cst) volatile noexcept { T ret = this->_wrapped_value; this->_wrapped_value += op; return ret; } T fetch_add(T op, memory_order mo = memory_order_seq_cst) noexcept { T ret = this->_wrapped_value; this->_wrapped_value += op; return ret; } T fetch_sub(T op, memory_order mo = memory_order_seq_cst) volatile noexcept { T ret = this->_wrapped_value; this->_wrapped_value -= op; return ret; } T fetch_sub(T op, memory_order mo = memory_order_seq_cst) noexcept { T ret = this->_wrapped_value; this->_wrapped_value -= op; return ret; } T fetch_and(T op, memory_order mo = memory_order_seq_cst) volatile noexcept { T ret = this->_wrapped_value; this->_wrapped_value &= op; return ret; } T fetch_and(T op, memory_order mo = memory_order_seq_cst) noexcept { T ret = this->_wrapped_value; this->_wrapped_value &= op; return ret; } T fetch_or(T op, memory_order mo = memory_order_seq_cst) volatile noexcept { T ret = this->_wrapped_value; this->_wrapped_value |= op; return ret; } T fetch_or(T op, memory_order mo = memory_order_seq_cst) noexcept { T ret = this->_wrapped_value; this->_wrapped_value |= op; return ret; } T fetch_xor(T op, memory_order mo = memory_order_seq_cst) volatile noexcept { T ret = this->_wrapped_value; this->_wrapped_value ^= op; return ret; } T fetch_xor(T op, memory_order mo = memory_order_seq_cst) noexcept { T ret = this->_wrapped_value; this->_wrapped_value ^= op; return ret; } T operator++(int)volatile noexcept { return fetch_add(T(1)); } T operator++(int)noexcept { return fetch_add(T(1)); } T operator--(int)volatile noexcept { return fetch_sub(T(1)); } T operator--(int)noexcept { return fetch_sub(T(1)); } T operator++() volatile noexcept { return fetch_add(T(1)) + T(1); } T operator++() noexcept { return fetch_add(T(1)) + T(1); } T operator--() volatile noexcept { return fetch_sub(T(1)) - T(1); } T operator--() noexcept { return fetch_sub(T(1)) - T(1); } T operator+=(T op) volatile noexcept { return fetch_add(op) + op; } T operator+=(T op) noexcept { return fetch_add(op) + op; } T operator-=(T op) volatile noexcept { return fetch_sub(op) - op; } T operator-=(T op) noexcept { return fetch_sub(op) - op; } T operator&=(T op) volatile noexcept { return fetch_and(op) & op; } T operator&=(T op) noexcept { return fetch_and(op) & op; } T operator|=(T op) volatile noexcept { return fetch_or(op) | op; } T operator|=(T op) noexcept { return fetch_or(op) | op; } T operator^=(T op) volatile noexcept { return fetch_xor(op) ^ op; } T operator^=(T op) noexcept { return fetch_xor(op) ^ op; } }; template struct atomic : public __infer_atomic_base { typedef __infer_atomic_base __base; atomic() noexcept = default; constexpr atomic(T d) noexcept : __base(d) {} T operator=(T d) volatile noexcept { __base::store(d); return d; } T operator=(T d) noexcept { __base::store(d); return d; } }; template <> struct atomic : public __infer_atomic_integral { typedef __infer_atomic_integral __base; typedef char __integral_type; atomic() noexcept = default; constexpr atomic(__integral_type d) noexcept : __base(d) {} using __base::operator=; }; template <> struct atomic : public __infer_atomic_integral { typedef __infer_atomic_integral __base; typedef signed char __integral_type; atomic() noexcept = default; constexpr atomic(__integral_type d) noexcept : __base(d) {} using __base::operator=; }; template <> struct atomic : public __infer_atomic_integral { typedef __infer_atomic_integral __base; typedef unsigned char __integral_type; atomic() noexcept = default; constexpr atomic(__integral_type d) noexcept : __base(d) {} using __base::operator=; }; template <> struct atomic : public __infer_atomic_integral { typedef __infer_atomic_integral __base; typedef short __integral_type; atomic() noexcept = default; constexpr atomic(__integral_type d) noexcept : __base(d) {} using __base::operator=; }; template <> struct atomic : public __infer_atomic_integral { typedef __infer_atomic_integral __base; typedef unsigned short __integral_type; atomic() noexcept = default; constexpr atomic(__integral_type d) noexcept : __base(d) {} using __base::operator=; }; template <> struct atomic : public __infer_atomic_integral { typedef __infer_atomic_integral __base; typedef int __integral_type; atomic() noexcept = default; constexpr atomic(__integral_type d) noexcept : __base(d) {} using __base::operator=; }; template <> struct atomic : public __infer_atomic_integral { typedef __infer_atomic_integral __base; typedef unsigned int __integral_type; atomic() noexcept = default; constexpr atomic(__integral_type d) noexcept : __base(d) {} using __base::operator=; }; template <> struct atomic : public __infer_atomic_integral { typedef __infer_atomic_integral __base; typedef long __integral_type; atomic() noexcept = default; constexpr atomic(__integral_type d) noexcept : __base(d) {} using __base::operator=; }; template <> struct atomic : public __infer_atomic_integral { typedef __infer_atomic_integral __base; typedef unsigned long __integral_type; atomic() noexcept = default; constexpr atomic(__integral_type d) noexcept : __base(d) {} using __base::operator=; }; template <> struct atomic : public __infer_atomic_integral { typedef __infer_atomic_integral __base; typedef long long __integral_type; atomic() noexcept = default; constexpr atomic(__integral_type d) noexcept : __base(d) {} using __base::operator=; }; template <> struct atomic : public __infer_atomic_integral { typedef __infer_atomic_integral __base; typedef unsigned long long __integral_type; atomic() noexcept = default; constexpr atomic(__integral_type d) noexcept : __base(d) {} using __base::operator=; }; template <> struct atomic : public __infer_atomic_integral { typedef __infer_atomic_integral __base; typedef wchar_t __integral_type; atomic() noexcept = default; constexpr atomic(__integral_type d) noexcept : __base(d) {} using __base::operator=; }; template <> struct atomic : public __infer_atomic_integral { typedef __infer_atomic_integral __base; typedef char16_t __integral_type; atomic() noexcept = default; constexpr atomic(__integral_type d) noexcept : __base(d) {} using __base::operator=; }; template <> struct atomic : public __infer_atomic_integral { typedef __infer_atomic_integral __base; typedef char32_t __integral_type; atomic() noexcept = default; constexpr atomic(__integral_type d) noexcept : __base(d) {} using __base::operator=; }; template struct atomic : public __infer_atomic_base { typedef __infer_atomic_base __base; atomic() noexcept = default; constexpr atomic(T* d) noexcept : __base(d) {} bool is_lock_free() const volatile noexcept { return true; } bool is_lock_free() const noexcept { return true; } void store(T* t, memory_order mo = memory_order_seq_cst) volatile noexcept { this->_wrapped_value = t; } void store(T* t, memory_order mo = memory_order_seq_cst) noexcept { this->_wrapped_value = t; } T* load(memory_order mo = memory_order_seq_cst) const volatile noexcept { return this->_wrapped_value; } T* load(memory_order mo = memory_order_seq_cst) const noexcept { return this->_wrapped_value; } operator T*() const volatile noexcept { return this->_wrapped_value; } operator T*() const noexcept { return this->_wrapped_value; } bool __infer_compare_exchange_impl(T*& expected, T* desired) volatile noexcept { if (this->_wrapped_value == expected) { this->_wrapped_value = desired; return true; } else { expected = this->_wrapped_value; return false; } } bool __infer_compare_exchange_impl(T*& expected, T* desired) noexcept { if (this->_wrapped_value == expected) { this->_wrapped_value = desired; return true; } else { expected = this->_wrapped_value; return false; } } bool compare_exchange_weak( T*& expected, T* desired, memory_order mo = memory_order_seq_cst) volatile noexcept { return __infer_compare_exchange_impl(expected, desired); } bool compare_exchange_weak(T*& expected, T* desired, memory_order mo = memory_order_seq_cst) noexcept { return __infer_compare_exchange_impl(expected, desired); } bool compare_exchange_weak(T*& expected, T* desired, memory_order succ, memory_order fail) volatile noexcept { return __infer_compare_exchange_impl(expected, desired); } bool compare_exchange_weak(T*& expected, T* desired, memory_order succ, memory_order fail) noexcept { return __infer_compare_exchange_impl(expected, desired); } bool compare_exchange_strong( T*& expected, T* desired, memory_order mo = memory_order_seq_cst) volatile noexcept { return __infer_compare_exchange_impl(expected, desired); } bool compare_exchange_strong( T*& expected, T* desired, memory_order mo = memory_order_seq_cst) noexcept { return __infer_compare_exchange_impl(expected, desired); } bool compare_exchange_strong(T*& expected, T* desired, memory_order succ, memory_order fail) volatile noexcept { return __infer_compare_exchange_impl(expected, desired); } bool compare_exchange_strong(T*& expected, T* desired, memory_order succ, memory_order fail) noexcept { return __infer_compare_exchange_impl(expected, desired); } T* operator=(T* d) volatile noexcept { this->_wrapped_value = d; return d; } T* operator=(T* d) noexcept { this->_wrapped_value = d; return d; } T* fetch_add(ptrdiff_t op, memory_order mo = memory_order_seq_cst) volatile noexcept { T* ret = this->_wrapped_value; this->_wrapped_value += op; return ret; } T* fetch_add(ptrdiff_t op, memory_order mo = memory_order_seq_cst) noexcept { T* ret = this->_wrapped_value; this->_wrapped_value += op; return ret; } T* fetch_sub(ptrdiff_t op, memory_order mo = memory_order_seq_cst) volatile noexcept { T* ret = this->_wrapped_value; this->_wrapped_value -= op; return ret; } T* fetch_sub(ptrdiff_t op, memory_order mo = memory_order_seq_cst) noexcept { T* ret = this->_wrapped_value; this->_wrapped_value -= op; return ret; } T* operator++(int)volatile noexcept { return fetch_add(1); } T* operator++(int)noexcept { return fetch_add(1); } T* operator--(int)volatile noexcept { return fetch_sub(1); } T* operator--(int)noexcept { return fetch_sub(1); } T* operator++() volatile noexcept { return fetch_add(1) + 1; } T* operator++() noexcept { return fetch_add(1) + T(1); } T* operator--() volatile noexcept { return fetch_sub(1) - 1; } T* operator--() noexcept { return fetch_sub(1) - 1; } T* operator+=(ptrdiff_t op) volatile noexcept { return fetch_add(op) + op; } T* operator+=(ptrdiff_t op) noexcept { return fetch_add(op) + op; } T* operator-=(ptrdiff_t op) volatile noexcept { return fetch_sub(op) - op; } T* operator-=(ptrdiff_t op) noexcept { return fetch_sub(op) - op; } }; // named typedefs typedef atomic atomic_bool; typedef atomic atomic_char; typedef atomic atomic_schar; typedef atomic atomic_uchar; typedef atomic atomic_short; typedef atomic atomic_ushort; typedef atomic atomic_int; typedef atomic atomic_uint; typedef atomic atomic_long; typedef atomic atomic_ulong; typedef atomic atomic_llong; typedef atomic atomic_ullong; typedef atomic atomic_char16_t; typedef atomic atomic_char32_t; typedef atomic atomic_wchar_t; typedef atomic atomic_int_least8_t; typedef atomic atomic_uint_least8_t; typedef atomic atomic_int_least16_t; typedef atomic atomic_uint_least16_t; typedef atomic atomic_int_least32_t; typedef atomic atomic_uint_least32_t; typedef atomic atomic_int_least64_t; typedef atomic atomic_uint_least64_t; typedef atomic atomic_int_fast8_t; typedef atomic atomic_uint_fast8_t; typedef atomic atomic_int_fast16_t; typedef atomic atomic_uint_fast16_t; typedef atomic atomic_int_fast32_t; typedef atomic atomic_uint_fast32_t; typedef atomic atomic_int_fast64_t; typedef atomic atomic_uint_fast64_t; typedef atomic atomic_intptr_t; typedef atomic atomic_uintptr_t; typedef atomic atomic_size_t; typedef atomic atomic_ptrdiff_t; typedef atomic atomic_intmax_t; typedef atomic atomic_uintmax_t; // general operations on atomic types template bool atomic_is_lock_free(const volatile atomic* a) noexcept { return a->is_lock_free(); } template void atomic_is_lock_free(const atomic* a) noexcept { return a->is_lock_free(); } template void atomic_init(volatile atomic* a, T d) noexcept { a->store(d); } template bool atomic_init(atomic* a, T d) noexcept { a->store(d); } template void atomic_store(volatile atomic* a, T d) noexcept { a->store(d); } template void atomic_store(atomic* a, T d) noexcept { a->store(d); } template void atomic_store_explicit(volatile atomic* a, T d, memory_order mo) noexcept { a->store(d, mo); } template void atomic_store_explicit(atomic* a, T d, memory_order mo) noexcept { a->store(d, mo); } template T atomic_load(const volatile atomic* a) noexcept { return a->load(); } template T atomic_load(const atomic* a) noexcept { return a->load(); } template T atomic_load_explicit(const volatile atomic* a, memory_order mo) noexcept { return a->load(mo); } template T atomic_load_explicit(const atomic* a, memory_order mo) noexcept { return a->load(mo); } template T atomic_exchange(volatile atomic* a, T d) noexcept { return a->exchange(d); } template T atomic_exchange(atomic* a, T d) noexcept { return a->exchange(d); } template T atomic_echange_explicit(volatile atomic* a, T d, memory_order mo) noexcept { return a->exchange(d, mo); } template T atomic_exchange_explicit(atomic* a, T d, memory_order mo) noexcept { return a->exchange(d, mo); } template bool atomic_compare_exchange_weak(volatile atomic* a, T* d, T e) noexcept { return a->compare_exchange_weak(*d, e); } template bool atomic_compare_exchange_weak(atomic* a, T* d, T e) noexcept { return a->compare_exchange_weak(*d, e); } template bool atomic_compare_exchange_strong(volatile atomic* a, T* d, T e) noexcept { return a->compare_exchange_strong(*d, e); } template bool atomic_compare_exchange_strong(atomic* a, T* d, T e) noexcept { return a->compare_exchange_strong(*d, e); } template bool atomic_compare_exchange_weak_explicit(volatile atomic* a, T* d, T e, memory_order so, memory_order fo) noexcept { return a->compare_exchange_weak(*d, e, so, fo); } template bool atomic_compare_exchange_weak_explicit( atomic* a, T* d, T e, memory_order so, memory_order fo) noexcept { return a->compare_exchange_weak(*d, e, so, fo); } template bool atomic_compare_exchange_strong_explicit(volatile atomic* a, T* d, T e, memory_order so, memory_order fo) noexcept { return a->compare_exchange_strong(*d, e, so, fo); } template bool atomic_compare_exchange_strong_explicit( atomic* a, T* d, T e, memory_order so, memory_order fo) noexcept { return a->compare_exchange_strong(*d, e, so, fo); } template T atomic_fetch_add(volatile __infer_atomic_integral* a, T i) noexcept { return a->fetch_add(i); } template T atomic_fetch_add(__infer_atomic_integral* a, T i) noexcept { return a->fetch_add(i); } template T atomic_fetch_add_explicit(volatile __infer_atomic_integral* a, T i, memory_order mo) noexcept { return a->fetch_add(i, mo); } template T atomic_fetch_add_explicit(__infer_atomic_integral* a, T i, memory_order mo) noexcept { return a->fetch_add(i, mo); } template T atomic_fetch_sub(volatile __infer_atomic_integral* a, T i) noexcept { return a->fetch_sub(i); } template T atomic_fetch_sub(__infer_atomic_integral* a, T i) noexcept { return a->fetch_sub(i); } template T atomic_fetch_sub_explicit(volatile __infer_atomic_integral* a, T i, memory_order mo) noexcept { return a->fetch_sub(i, mo); } template T atomic_fetch_sub_explicit(__infer_atomic_integral* a, T i, memory_order mo) noexcept { return a->fetch_sub(i, mo); } template T atomic_fetch_and(volatile __infer_atomic_integral* a, T i) noexcept { return a->fetch_and(i); } template T atomic_fetch_and(__infer_atomic_integral* a, T i) noexcept { return a->fetch_and(i); } template T atomic_fetch_and_explicit(volatile __infer_atomic_integral* a, T i, memory_order mo) noexcept { return a->fetch_and(i, mo); } template T atomic_fetch_and_explicit(__infer_atomic_integral* a, T i, memory_order mo) noexcept { return a->fetch_and(i, mo); } template T atomic_fetch_or(volatile __infer_atomic_integral* a, T i) noexcept { return a->fetch_or(i); } template T atomic_fetch_or(__infer_atomic_integral* a, T i) noexcept { return a->fetch_or(i); } template T atomic_fetch_or_explicit(volatile __infer_atomic_integral* a, T i, memory_order mo) noexcept { return a->fetch_or(i, mo); } template T atomic_fetch_or_explicit(__infer_atomic_integral* a, T i, memory_order mo) noexcept { return a->fetch_or(i, mo); } template T atomic_fetch_xor(volatile __infer_atomic_integral* a, T i) noexcept { return a->fetch_xor(i); } template T atomic_fetch_xor(__infer_atomic_integral* a, T i) noexcept { return a->fetch_xor(i); } template T atomic_fetch_xor_explicit(volatile __infer_atomic_integral* a, T i, memory_order mo) noexcept { return a->fetch_xor(i, mo); } template T atomic_fetch_xor_explicit(__infer_atomic_integral* a, T i, memory_order mo) noexcept { return a->fetch_xor(i, mo); } // partial specialization for pointers template T* atomic_fetch_add(volatile atomic* a, ptrdiff_t i) noexcept { return a->fetch_add(i); } template T* atomic_fetch_add(atomic* a, ptrdiff_t i) noexcept { return a->fetch_add(i); } template T* atomic_fetch_add_explicit(volatile atomic* a, ptrdiff_t i, memory_order mo) noexcept { return a->fetch_add(i, mo); } template T* atomic_fetch_add_explicit(atomic* a, ptrdiff_t i, memory_order mo) noexcept { return a->fetch_add(i, mo); } template T* atomic_fetch_sub(volatile atomic* a, ptrdiff_t i) noexcept { return a->fetch_sub(i); } template T* atomic_fetch_sub(atomic* a, ptrdiff_t i) noexcept { return a->fetch_sub(i); } template T* atomic_fetch_sub_explicit(volatile atomic* a, ptrdiff_t i, memory_order mo) noexcept { return a->fetch_sub(i, mo); } template T* atomic_fetch_sub_explicit(atomic* a, ptrdiff_t i, memory_order mo) noexcept { return a->fetch_sub(i, mo); } typedef struct atomic_flag { bool a; atomic_flag() noexcept = default; constexpr atomic_flag(bool i) noexcept : a(i) {} atomic_flag(const atomic_flag&) = delete; atomic_flag& operator=(const atomic_flag&) = delete; atomic_flag& operator=(const atomic_flag&) volatile = delete; bool test_and_set(memory_order mo = memory_order_seq_cst) volatile noexcept { bool ret = a; a = true; return ret; } bool test_and_set(memory_order mo = memory_order_seq_cst) noexcept { bool ret = a; a = true; return ret; } void clear(memory_order mo = memory_order_seq_cst) volatile noexcept { a = false; } void clear(memory_order mo = memory_order_seq_cst) noexcept { a = false; } } atomic_flag; bool atomic_flag_test_and_set(volatile atomic_flag* f) noexcept { return f->test_and_set(); } bool atomic_flag_test_and_set(atomic_flag* f) noexcept { return f->test_and_set(); } bool atomic_flag_test_and_set_explicit(volatile atomic_flag* f, memory_order m) noexcept { return f->test_and_set(m); } bool atomic_flag_test_and_set_explicit(atomic_flag* f, memory_order m) noexcept { return f->test_and_set(m); } void atomic_flag_clear(volatile atomic_flag* f) noexcept { f->clear(); } void atomic_flag_clear(atomic_flag* f) noexcept { f->clear(); } void atomic_flag_clear_explicit(volatile atomic_flag* f, memory_order mo) noexcept { f->clear(mo); } void atomic_flag_clear_explicit(atomic_flag* f, memory_order mo) noexcept { f->clear(mo); } void atomic_thread_fence(memory_order mo) noexcept {} void atomic_signal_fence(memory_order mo) noexcept {} #define ATOMIC_FLAG_INIT \ { false } #define ATOMIC_VAR_INIT(__v) \ { __v } INFER_NAMESPACE_STD_END