1e78f53d1SNikolas Klauser //===----------------------------------------------------------------------===// 2e78f53d1SNikolas Klauser // 3e78f53d1SNikolas Klauser // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4e78f53d1SNikolas Klauser // See https://llvm.org/LICENSE.txt for license information. 5e78f53d1SNikolas Klauser // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6e78f53d1SNikolas Klauser // 7e78f53d1SNikolas Klauser //===----------------------------------------------------------------------===// 8e78f53d1SNikolas Klauser 9*ce777190SNikolas Klauser #ifndef _LIBCPP___CXX03___ATOMIC_CXX_ATOMIC_IMPL_H 10*ce777190SNikolas Klauser #define _LIBCPP___CXX03___ATOMIC_CXX_ATOMIC_IMPL_H 11e78f53d1SNikolas Klauser 1273fbae83SNikolas Klauser #include <__cxx03/__atomic/memory_order.h> 1373fbae83SNikolas Klauser #include <__cxx03/__atomic/to_gcc_order.h> 1473fbae83SNikolas Klauser #include <__cxx03/__config> 1573fbae83SNikolas Klauser #include <__cxx03/__memory/addressof.h> 1673fbae83SNikolas Klauser #include <__cxx03/__type_traits/is_assignable.h> 1773fbae83SNikolas Klauser #include <__cxx03/__type_traits/is_trivially_copyable.h> 1873fbae83SNikolas Klauser #include <__cxx03/__type_traits/remove_const.h> 1973fbae83SNikolas Klauser #include <__cxx03/cstddef> 20e78f53d1SNikolas Klauser 21e78f53d1SNikolas Klauser #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 22e78f53d1SNikolas Klauser # pragma GCC system_header 23e78f53d1SNikolas Klauser #endif 24e78f53d1SNikolas Klauser 25e78f53d1SNikolas Klauser _LIBCPP_BEGIN_NAMESPACE_STD 26e78f53d1SNikolas Klauser 27e78f53d1SNikolas Klauser #if defined(_LIBCPP_HAS_GCC_ATOMIC_IMP) 28e78f53d1SNikolas Klauser 29e78f53d1SNikolas Klauser // [atomics.types.generic]p1 guarantees _Tp is trivially copyable. Because 30e78f53d1SNikolas Klauser // the default operator= in an object is not volatile, a byte-by-byte copy 31e78f53d1SNikolas Klauser // is required. 32e78f53d1SNikolas Klauser template <typename _Tp, typename _Tv, __enable_if_t<is_assignable<_Tp&, _Tv>::value, int> = 0> 33e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI void __cxx_atomic_assign_volatile(_Tp& __a_value, _Tv const& __val) { 34e78f53d1SNikolas Klauser __a_value = __val; 35e78f53d1SNikolas Klauser } 36e78f53d1SNikolas Klauser template <typename _Tp, typename _Tv, __enable_if_t<is_assignable<_Tp&, _Tv>::value, int> = 0> 37e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI void __cxx_atomic_assign_volatile(_Tp volatile& __a_value, _Tv volatile const& __val) { 38e78f53d1SNikolas Klauser volatile char* __to = reinterpret_cast<volatile char*>(std::addressof(__a_value)); 39e78f53d1SNikolas Klauser volatile char* __end = __to + sizeof(_Tp); 40e78f53d1SNikolas Klauser volatile const char* __from = reinterpret_cast<volatile const char*>(std::addressof(__val)); 41e78f53d1SNikolas Klauser while (__to != __end) 42e78f53d1SNikolas Klauser *__to++ = *__from++; 43e78f53d1SNikolas Klauser } 44e78f53d1SNikolas Klauser 45e78f53d1SNikolas Klauser template <typename _Tp> 46e78f53d1SNikolas Klauser struct __cxx_atomic_base_impl { 47e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI 48e78f53d1SNikolas Klauser # ifndef _LIBCPP_CXX03_LANG 49e78f53d1SNikolas Klauser __cxx_atomic_base_impl() _NOEXCEPT = default; 50e78f53d1SNikolas Klauser # else 51e78f53d1SNikolas Klauser __cxx_atomic_base_impl() _NOEXCEPT : __a_value() { 52e78f53d1SNikolas Klauser } 53e78f53d1SNikolas Klauser # endif // _LIBCPP_CXX03_LANG 54e78f53d1SNikolas Klauser _LIBCPP_CONSTEXPR explicit __cxx_atomic_base_impl(_Tp value) _NOEXCEPT : __a_value(value) {} 55e78f53d1SNikolas Klauser _Tp __a_value; 56e78f53d1SNikolas Klauser }; 57e78f53d1SNikolas Klauser 58e78f53d1SNikolas Klauser template <typename _Tp> 59e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI void __cxx_atomic_init(volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp __val) { 60e78f53d1SNikolas Klauser __cxx_atomic_assign_volatile(__a->__a_value, __val); 61e78f53d1SNikolas Klauser } 62e78f53d1SNikolas Klauser 63e78f53d1SNikolas Klauser template <typename _Tp> 64e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI void __cxx_atomic_init(__cxx_atomic_base_impl<_Tp>* __a, _Tp __val) { 65e78f53d1SNikolas Klauser __a->__a_value = __val; 66e78f53d1SNikolas Klauser } 67e78f53d1SNikolas Klauser 68e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI inline void __cxx_atomic_thread_fence(memory_order __order) { 69e78f53d1SNikolas Klauser __atomic_thread_fence(__to_gcc_order(__order)); 70e78f53d1SNikolas Klauser } 71e78f53d1SNikolas Klauser 72e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI inline void __cxx_atomic_signal_fence(memory_order __order) { 73e78f53d1SNikolas Klauser __atomic_signal_fence(__to_gcc_order(__order)); 74e78f53d1SNikolas Klauser } 75e78f53d1SNikolas Klauser 76e78f53d1SNikolas Klauser template <typename _Tp> 77e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI void 78e78f53d1SNikolas Klauser __cxx_atomic_store(volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp __val, memory_order __order) { 79e78f53d1SNikolas Klauser __atomic_store(std::addressof(__a->__a_value), std::addressof(__val), __to_gcc_order(__order)); 80e78f53d1SNikolas Klauser } 81e78f53d1SNikolas Klauser 82e78f53d1SNikolas Klauser template <typename _Tp> 83e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI void __cxx_atomic_store(__cxx_atomic_base_impl<_Tp>* __a, _Tp __val, memory_order __order) { 84e78f53d1SNikolas Klauser __atomic_store(std::addressof(__a->__a_value), std::addressof(__val), __to_gcc_order(__order)); 85e78f53d1SNikolas Klauser } 86e78f53d1SNikolas Klauser 87e78f53d1SNikolas Klauser template <typename _Tp> 88e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI _Tp __cxx_atomic_load(const volatile __cxx_atomic_base_impl<_Tp>* __a, memory_order __order) { 89e78f53d1SNikolas Klauser _Tp __ret; 90e78f53d1SNikolas Klauser __atomic_load(std::addressof(__a->__a_value), std::addressof(__ret), __to_gcc_order(__order)); 91e78f53d1SNikolas Klauser return __ret; 92e78f53d1SNikolas Klauser } 93e78f53d1SNikolas Klauser 94e78f53d1SNikolas Klauser template <typename _Tp> 95e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI void 96e78f53d1SNikolas Klauser __cxx_atomic_load_inplace(const volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp* __dst, memory_order __order) { 97e78f53d1SNikolas Klauser __atomic_load(std::addressof(__a->__a_value), __dst, __to_gcc_order(__order)); 98e78f53d1SNikolas Klauser } 99e78f53d1SNikolas Klauser 100e78f53d1SNikolas Klauser template <typename _Tp> 101e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI void 102e78f53d1SNikolas Klauser __cxx_atomic_load_inplace(const __cxx_atomic_base_impl<_Tp>* __a, _Tp* __dst, memory_order __order) { 103e78f53d1SNikolas Klauser __atomic_load(std::addressof(__a->__a_value), __dst, __to_gcc_order(__order)); 104e78f53d1SNikolas Klauser } 105e78f53d1SNikolas Klauser 106e78f53d1SNikolas Klauser template <typename _Tp> 107e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI _Tp __cxx_atomic_load(const __cxx_atomic_base_impl<_Tp>* __a, memory_order __order) { 108e78f53d1SNikolas Klauser _Tp __ret; 109e78f53d1SNikolas Klauser __atomic_load(std::addressof(__a->__a_value), std::addressof(__ret), __to_gcc_order(__order)); 110e78f53d1SNikolas Klauser return __ret; 111e78f53d1SNikolas Klauser } 112e78f53d1SNikolas Klauser 113e78f53d1SNikolas Klauser template <typename _Tp> 114e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI _Tp 115e78f53d1SNikolas Klauser __cxx_atomic_exchange(volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp __value, memory_order __order) { 116e78f53d1SNikolas Klauser _Tp __ret; 117e78f53d1SNikolas Klauser __atomic_exchange( 118e78f53d1SNikolas Klauser std::addressof(__a->__a_value), std::addressof(__value), std::addressof(__ret), __to_gcc_order(__order)); 119e78f53d1SNikolas Klauser return __ret; 120e78f53d1SNikolas Klauser } 121e78f53d1SNikolas Klauser 122e78f53d1SNikolas Klauser template <typename _Tp> 123e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI _Tp __cxx_atomic_exchange(__cxx_atomic_base_impl<_Tp>* __a, _Tp __value, memory_order __order) { 124e78f53d1SNikolas Klauser _Tp __ret; 125e78f53d1SNikolas Klauser __atomic_exchange( 126e78f53d1SNikolas Klauser std::addressof(__a->__a_value), std::addressof(__value), std::addressof(__ret), __to_gcc_order(__order)); 127e78f53d1SNikolas Klauser return __ret; 128e78f53d1SNikolas Klauser } 129e78f53d1SNikolas Klauser 130e78f53d1SNikolas Klauser template <typename _Tp> 131e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI bool __cxx_atomic_compare_exchange_strong( 132e78f53d1SNikolas Klauser volatile __cxx_atomic_base_impl<_Tp>* __a, 133e78f53d1SNikolas Klauser _Tp* __expected, 134e78f53d1SNikolas Klauser _Tp __value, 135e78f53d1SNikolas Klauser memory_order __success, 136e78f53d1SNikolas Klauser memory_order __failure) { 137e78f53d1SNikolas Klauser return __atomic_compare_exchange( 138e78f53d1SNikolas Klauser std::addressof(__a->__a_value), 139e78f53d1SNikolas Klauser __expected, 140e78f53d1SNikolas Klauser std::addressof(__value), 141e78f53d1SNikolas Klauser false, 142e78f53d1SNikolas Klauser __to_gcc_order(__success), 143e78f53d1SNikolas Klauser __to_gcc_failure_order(__failure)); 144e78f53d1SNikolas Klauser } 145e78f53d1SNikolas Klauser 146e78f53d1SNikolas Klauser template <typename _Tp> 147e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI bool __cxx_atomic_compare_exchange_strong( 148e78f53d1SNikolas Klauser __cxx_atomic_base_impl<_Tp>* __a, _Tp* __expected, _Tp __value, memory_order __success, memory_order __failure) { 149e78f53d1SNikolas Klauser return __atomic_compare_exchange( 150e78f53d1SNikolas Klauser std::addressof(__a->__a_value), 151e78f53d1SNikolas Klauser __expected, 152e78f53d1SNikolas Klauser std::addressof(__value), 153e78f53d1SNikolas Klauser false, 154e78f53d1SNikolas Klauser __to_gcc_order(__success), 155e78f53d1SNikolas Klauser __to_gcc_failure_order(__failure)); 156e78f53d1SNikolas Klauser } 157e78f53d1SNikolas Klauser 158e78f53d1SNikolas Klauser template <typename _Tp> 159e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI bool __cxx_atomic_compare_exchange_weak( 160e78f53d1SNikolas Klauser volatile __cxx_atomic_base_impl<_Tp>* __a, 161e78f53d1SNikolas Klauser _Tp* __expected, 162e78f53d1SNikolas Klauser _Tp __value, 163e78f53d1SNikolas Klauser memory_order __success, 164e78f53d1SNikolas Klauser memory_order __failure) { 165e78f53d1SNikolas Klauser return __atomic_compare_exchange( 166e78f53d1SNikolas Klauser std::addressof(__a->__a_value), 167e78f53d1SNikolas Klauser __expected, 168e78f53d1SNikolas Klauser std::addressof(__value), 169e78f53d1SNikolas Klauser true, 170e78f53d1SNikolas Klauser __to_gcc_order(__success), 171e78f53d1SNikolas Klauser __to_gcc_failure_order(__failure)); 172e78f53d1SNikolas Klauser } 173e78f53d1SNikolas Klauser 174e78f53d1SNikolas Klauser template <typename _Tp> 175e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI bool __cxx_atomic_compare_exchange_weak( 176e78f53d1SNikolas Klauser __cxx_atomic_base_impl<_Tp>* __a, _Tp* __expected, _Tp __value, memory_order __success, memory_order __failure) { 177e78f53d1SNikolas Klauser return __atomic_compare_exchange( 178e78f53d1SNikolas Klauser std::addressof(__a->__a_value), 179e78f53d1SNikolas Klauser __expected, 180e78f53d1SNikolas Klauser std::addressof(__value), 181e78f53d1SNikolas Klauser true, 182e78f53d1SNikolas Klauser __to_gcc_order(__success), 183e78f53d1SNikolas Klauser __to_gcc_failure_order(__failure)); 184e78f53d1SNikolas Klauser } 185e78f53d1SNikolas Klauser 186e78f53d1SNikolas Klauser template <typename _Tp> 187e78f53d1SNikolas Klauser struct __skip_amt { 188e78f53d1SNikolas Klauser enum { value = 1 }; 189e78f53d1SNikolas Klauser }; 190e78f53d1SNikolas Klauser 191e78f53d1SNikolas Klauser template <typename _Tp> 192e78f53d1SNikolas Klauser struct __skip_amt<_Tp*> { 193e78f53d1SNikolas Klauser enum { value = sizeof(_Tp) }; 194e78f53d1SNikolas Klauser }; 195e78f53d1SNikolas Klauser 196e78f53d1SNikolas Klauser // FIXME: Haven't figured out what the spec says about using arrays with 197e78f53d1SNikolas Klauser // atomic_fetch_add. Force a failure rather than creating bad behavior. 198e78f53d1SNikolas Klauser template <typename _Tp> 199e78f53d1SNikolas Klauser struct __skip_amt<_Tp[]> {}; 200e78f53d1SNikolas Klauser template <typename _Tp, int n> 201e78f53d1SNikolas Klauser struct __skip_amt<_Tp[n]> {}; 202e78f53d1SNikolas Klauser 203e78f53d1SNikolas Klauser template <typename _Tp, typename _Td> 204e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI _Tp 205e78f53d1SNikolas Klauser __cxx_atomic_fetch_add(volatile __cxx_atomic_base_impl<_Tp>* __a, _Td __delta, memory_order __order) { 206e78f53d1SNikolas Klauser return __atomic_fetch_add(std::addressof(__a->__a_value), __delta * __skip_amt<_Tp>::value, __to_gcc_order(__order)); 207e78f53d1SNikolas Klauser } 208e78f53d1SNikolas Klauser 209e78f53d1SNikolas Klauser template <typename _Tp, typename _Td> 210e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI _Tp __cxx_atomic_fetch_add(__cxx_atomic_base_impl<_Tp>* __a, _Td __delta, memory_order __order) { 211e78f53d1SNikolas Klauser return __atomic_fetch_add(std::addressof(__a->__a_value), __delta * __skip_amt<_Tp>::value, __to_gcc_order(__order)); 212e78f53d1SNikolas Klauser } 213e78f53d1SNikolas Klauser 214e78f53d1SNikolas Klauser template <typename _Tp, typename _Td> 215e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI _Tp 216e78f53d1SNikolas Klauser __cxx_atomic_fetch_sub(volatile __cxx_atomic_base_impl<_Tp>* __a, _Td __delta, memory_order __order) { 217e78f53d1SNikolas Klauser return __atomic_fetch_sub(std::addressof(__a->__a_value), __delta * __skip_amt<_Tp>::value, __to_gcc_order(__order)); 218e78f53d1SNikolas Klauser } 219e78f53d1SNikolas Klauser 220e78f53d1SNikolas Klauser template <typename _Tp, typename _Td> 221e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI _Tp __cxx_atomic_fetch_sub(__cxx_atomic_base_impl<_Tp>* __a, _Td __delta, memory_order __order) { 222e78f53d1SNikolas Klauser return __atomic_fetch_sub(std::addressof(__a->__a_value), __delta * __skip_amt<_Tp>::value, __to_gcc_order(__order)); 223e78f53d1SNikolas Klauser } 224e78f53d1SNikolas Klauser 225e78f53d1SNikolas Klauser template <typename _Tp> 226e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI _Tp 227e78f53d1SNikolas Klauser __cxx_atomic_fetch_and(volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, memory_order __order) { 228e78f53d1SNikolas Klauser return __atomic_fetch_and(std::addressof(__a->__a_value), __pattern, __to_gcc_order(__order)); 229e78f53d1SNikolas Klauser } 230e78f53d1SNikolas Klauser 231e78f53d1SNikolas Klauser template <typename _Tp> 232e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI _Tp 233e78f53d1SNikolas Klauser __cxx_atomic_fetch_and(__cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, memory_order __order) { 234e78f53d1SNikolas Klauser return __atomic_fetch_and(std::addressof(__a->__a_value), __pattern, __to_gcc_order(__order)); 235e78f53d1SNikolas Klauser } 236e78f53d1SNikolas Klauser 237e78f53d1SNikolas Klauser template <typename _Tp> 238e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI _Tp 239e78f53d1SNikolas Klauser __cxx_atomic_fetch_or(volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, memory_order __order) { 240e78f53d1SNikolas Klauser return __atomic_fetch_or(std::addressof(__a->__a_value), __pattern, __to_gcc_order(__order)); 241e78f53d1SNikolas Klauser } 242e78f53d1SNikolas Klauser 243e78f53d1SNikolas Klauser template <typename _Tp> 244e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI _Tp __cxx_atomic_fetch_or(__cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, memory_order __order) { 245e78f53d1SNikolas Klauser return __atomic_fetch_or(std::addressof(__a->__a_value), __pattern, __to_gcc_order(__order)); 246e78f53d1SNikolas Klauser } 247e78f53d1SNikolas Klauser 248e78f53d1SNikolas Klauser template <typename _Tp> 249e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI _Tp 250e78f53d1SNikolas Klauser __cxx_atomic_fetch_xor(volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, memory_order __order) { 251e78f53d1SNikolas Klauser return __atomic_fetch_xor(std::addressof(__a->__a_value), __pattern, __to_gcc_order(__order)); 252e78f53d1SNikolas Klauser } 253e78f53d1SNikolas Klauser 254e78f53d1SNikolas Klauser template <typename _Tp> 255e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI _Tp 256e78f53d1SNikolas Klauser __cxx_atomic_fetch_xor(__cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, memory_order __order) { 257e78f53d1SNikolas Klauser return __atomic_fetch_xor(std::addressof(__a->__a_value), __pattern, __to_gcc_order(__order)); 258e78f53d1SNikolas Klauser } 259e78f53d1SNikolas Klauser 260e78f53d1SNikolas Klauser # define __cxx_atomic_is_lock_free(__s) __atomic_is_lock_free(__s, 0) 261e78f53d1SNikolas Klauser 262e78f53d1SNikolas Klauser #elif defined(_LIBCPP_HAS_C_ATOMIC_IMP) 263e78f53d1SNikolas Klauser 264e78f53d1SNikolas Klauser template <typename _Tp> 265e78f53d1SNikolas Klauser struct __cxx_atomic_base_impl { 266e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI 267e78f53d1SNikolas Klauser # ifndef _LIBCPP_CXX03_LANG 268e78f53d1SNikolas Klauser __cxx_atomic_base_impl() _NOEXCEPT = default; 269e78f53d1SNikolas Klauser # else 270e78f53d1SNikolas Klauser __cxx_atomic_base_impl() _NOEXCEPT : __a_value() { 271e78f53d1SNikolas Klauser } 272e78f53d1SNikolas Klauser # endif // _LIBCPP_CXX03_LANG 273e78f53d1SNikolas Klauser _LIBCPP_CONSTEXPR explicit __cxx_atomic_base_impl(_Tp __value) _NOEXCEPT : __a_value(__value) {} 274e78f53d1SNikolas Klauser _LIBCPP_DISABLE_EXTENSION_WARNING _Atomic(_Tp) __a_value; 275e78f53d1SNikolas Klauser }; 276e78f53d1SNikolas Klauser 277e78f53d1SNikolas Klauser # define __cxx_atomic_is_lock_free(__s) __c11_atomic_is_lock_free(__s) 278e78f53d1SNikolas Klauser 279e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI inline void __cxx_atomic_thread_fence(memory_order __order) _NOEXCEPT { 280e78f53d1SNikolas Klauser __c11_atomic_thread_fence(static_cast<__memory_order_underlying_t>(__order)); 281e78f53d1SNikolas Klauser } 282e78f53d1SNikolas Klauser 283e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI inline void __cxx_atomic_signal_fence(memory_order __order) _NOEXCEPT { 284e78f53d1SNikolas Klauser __c11_atomic_signal_fence(static_cast<__memory_order_underlying_t>(__order)); 285e78f53d1SNikolas Klauser } 286e78f53d1SNikolas Klauser 287e78f53d1SNikolas Klauser template <class _Tp> 288e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI void __cxx_atomic_init(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __val) _NOEXCEPT { 289e78f53d1SNikolas Klauser __c11_atomic_init(std::addressof(__a->__a_value), __val); 290e78f53d1SNikolas Klauser } 291e78f53d1SNikolas Klauser template <class _Tp> 292e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI void __cxx_atomic_init(__cxx_atomic_base_impl<_Tp>* __a, _Tp __val) _NOEXCEPT { 293e78f53d1SNikolas Klauser __c11_atomic_init(std::addressof(__a->__a_value), __val); 294e78f53d1SNikolas Klauser } 295e78f53d1SNikolas Klauser 296e78f53d1SNikolas Klauser template <class _Tp> 297e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI void 298e78f53d1SNikolas Klauser __cxx_atomic_store(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __val, memory_order __order) _NOEXCEPT { 299e78f53d1SNikolas Klauser __c11_atomic_store(std::addressof(__a->__a_value), __val, static_cast<__memory_order_underlying_t>(__order)); 300e78f53d1SNikolas Klauser } 301e78f53d1SNikolas Klauser template <class _Tp> 302e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI void 303e78f53d1SNikolas Klauser __cxx_atomic_store(__cxx_atomic_base_impl<_Tp>* __a, _Tp __val, memory_order __order) _NOEXCEPT { 304e78f53d1SNikolas Klauser __c11_atomic_store(std::addressof(__a->__a_value), __val, static_cast<__memory_order_underlying_t>(__order)); 305e78f53d1SNikolas Klauser } 306e78f53d1SNikolas Klauser 307e78f53d1SNikolas Klauser template <class _Tp> 308e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI _Tp 309e78f53d1SNikolas Klauser __cxx_atomic_load(__cxx_atomic_base_impl<_Tp> const volatile* __a, memory_order __order) _NOEXCEPT { 310e78f53d1SNikolas Klauser using __ptr_type = __remove_const_t<decltype(__a->__a_value)>*; 311e78f53d1SNikolas Klauser return __c11_atomic_load( 312e78f53d1SNikolas Klauser const_cast<__ptr_type>(std::addressof(__a->__a_value)), static_cast<__memory_order_underlying_t>(__order)); 313e78f53d1SNikolas Klauser } 314e78f53d1SNikolas Klauser template <class _Tp> 315e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI _Tp __cxx_atomic_load(__cxx_atomic_base_impl<_Tp> const* __a, memory_order __order) _NOEXCEPT { 316e78f53d1SNikolas Klauser using __ptr_type = __remove_const_t<decltype(__a->__a_value)>*; 317e78f53d1SNikolas Klauser return __c11_atomic_load( 318e78f53d1SNikolas Klauser const_cast<__ptr_type>(std::addressof(__a->__a_value)), static_cast<__memory_order_underlying_t>(__order)); 319e78f53d1SNikolas Klauser } 320e78f53d1SNikolas Klauser 321e78f53d1SNikolas Klauser template <class _Tp> 322e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI void 323e78f53d1SNikolas Klauser __cxx_atomic_load_inplace(__cxx_atomic_base_impl<_Tp> const volatile* __a, _Tp* __dst, memory_order __order) _NOEXCEPT { 324e78f53d1SNikolas Klauser using __ptr_type = __remove_const_t<decltype(__a->__a_value)>*; 325e78f53d1SNikolas Klauser *__dst = __c11_atomic_load( 326e78f53d1SNikolas Klauser const_cast<__ptr_type>(std::addressof(__a->__a_value)), static_cast<__memory_order_underlying_t>(__order)); 327e78f53d1SNikolas Klauser } 328e78f53d1SNikolas Klauser template <class _Tp> 329e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI void 330e78f53d1SNikolas Klauser __cxx_atomic_load_inplace(__cxx_atomic_base_impl<_Tp> const* __a, _Tp* __dst, memory_order __order) _NOEXCEPT { 331e78f53d1SNikolas Klauser using __ptr_type = __remove_const_t<decltype(__a->__a_value)>*; 332e78f53d1SNikolas Klauser *__dst = __c11_atomic_load( 333e78f53d1SNikolas Klauser const_cast<__ptr_type>(std::addressof(__a->__a_value)), static_cast<__memory_order_underlying_t>(__order)); 334e78f53d1SNikolas Klauser } 335e78f53d1SNikolas Klauser 336e78f53d1SNikolas Klauser template <class _Tp> 337e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI _Tp 338e78f53d1SNikolas Klauser __cxx_atomic_exchange(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __value, memory_order __order) _NOEXCEPT { 339e78f53d1SNikolas Klauser return __c11_atomic_exchange( 340e78f53d1SNikolas Klauser std::addressof(__a->__a_value), __value, static_cast<__memory_order_underlying_t>(__order)); 341e78f53d1SNikolas Klauser } 342e78f53d1SNikolas Klauser template <class _Tp> 343e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI _Tp 344e78f53d1SNikolas Klauser __cxx_atomic_exchange(__cxx_atomic_base_impl<_Tp>* __a, _Tp __value, memory_order __order) _NOEXCEPT { 345e78f53d1SNikolas Klauser return __c11_atomic_exchange( 346e78f53d1SNikolas Klauser std::addressof(__a->__a_value), __value, static_cast<__memory_order_underlying_t>(__order)); 347e78f53d1SNikolas Klauser } 348e78f53d1SNikolas Klauser 349e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI inline _LIBCPP_CONSTEXPR memory_order __to_failure_order(memory_order __order) { 350e78f53d1SNikolas Klauser // Avoid switch statement to make this a constexpr. 351e78f53d1SNikolas Klauser return __order == memory_order_release 352e78f53d1SNikolas Klauser ? memory_order_relaxed 353e78f53d1SNikolas Klauser : (__order == memory_order_acq_rel ? memory_order_acquire : __order); 354e78f53d1SNikolas Klauser } 355e78f53d1SNikolas Klauser 356e78f53d1SNikolas Klauser template <class _Tp> 357e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI bool __cxx_atomic_compare_exchange_strong( 358e78f53d1SNikolas Klauser __cxx_atomic_base_impl<_Tp> volatile* __a, 359e78f53d1SNikolas Klauser _Tp* __expected, 360e78f53d1SNikolas Klauser _Tp __value, 361e78f53d1SNikolas Klauser memory_order __success, 362e78f53d1SNikolas Klauser memory_order __failure) _NOEXCEPT { 363e78f53d1SNikolas Klauser return __c11_atomic_compare_exchange_strong( 364e78f53d1SNikolas Klauser std::addressof(__a->__a_value), 365e78f53d1SNikolas Klauser __expected, 366e78f53d1SNikolas Klauser __value, 367e78f53d1SNikolas Klauser static_cast<__memory_order_underlying_t>(__success), 368e78f53d1SNikolas Klauser static_cast<__memory_order_underlying_t>(__to_failure_order(__failure))); 369e78f53d1SNikolas Klauser } 370e78f53d1SNikolas Klauser template <class _Tp> 371e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI bool __cxx_atomic_compare_exchange_strong( 372e78f53d1SNikolas Klauser __cxx_atomic_base_impl<_Tp>* __a, _Tp* __expected, _Tp __value, memory_order __success, memory_order __failure) 373e78f53d1SNikolas Klauser _NOEXCEPT { 374e78f53d1SNikolas Klauser return __c11_atomic_compare_exchange_strong( 375e78f53d1SNikolas Klauser std::addressof(__a->__a_value), 376e78f53d1SNikolas Klauser __expected, 377e78f53d1SNikolas Klauser __value, 378e78f53d1SNikolas Klauser static_cast<__memory_order_underlying_t>(__success), 379e78f53d1SNikolas Klauser static_cast<__memory_order_underlying_t>(__to_failure_order(__failure))); 380e78f53d1SNikolas Klauser } 381e78f53d1SNikolas Klauser 382e78f53d1SNikolas Klauser template <class _Tp> 383e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI bool __cxx_atomic_compare_exchange_weak( 384e78f53d1SNikolas Klauser __cxx_atomic_base_impl<_Tp> volatile* __a, 385e78f53d1SNikolas Klauser _Tp* __expected, 386e78f53d1SNikolas Klauser _Tp __value, 387e78f53d1SNikolas Klauser memory_order __success, 388e78f53d1SNikolas Klauser memory_order __failure) _NOEXCEPT { 389e78f53d1SNikolas Klauser return __c11_atomic_compare_exchange_weak( 390e78f53d1SNikolas Klauser std::addressof(__a->__a_value), 391e78f53d1SNikolas Klauser __expected, 392e78f53d1SNikolas Klauser __value, 393e78f53d1SNikolas Klauser static_cast<__memory_order_underlying_t>(__success), 394e78f53d1SNikolas Klauser static_cast<__memory_order_underlying_t>(__to_failure_order(__failure))); 395e78f53d1SNikolas Klauser } 396e78f53d1SNikolas Klauser template <class _Tp> 397e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI bool __cxx_atomic_compare_exchange_weak( 398e78f53d1SNikolas Klauser __cxx_atomic_base_impl<_Tp>* __a, _Tp* __expected, _Tp __value, memory_order __success, memory_order __failure) 399e78f53d1SNikolas Klauser _NOEXCEPT { 400e78f53d1SNikolas Klauser return __c11_atomic_compare_exchange_weak( 401e78f53d1SNikolas Klauser std::addressof(__a->__a_value), 402e78f53d1SNikolas Klauser __expected, 403e78f53d1SNikolas Klauser __value, 404e78f53d1SNikolas Klauser static_cast<__memory_order_underlying_t>(__success), 405e78f53d1SNikolas Klauser static_cast<__memory_order_underlying_t>(__to_failure_order(__failure))); 406e78f53d1SNikolas Klauser } 407e78f53d1SNikolas Klauser 408e78f53d1SNikolas Klauser template <class _Tp> 409e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI _Tp 410e78f53d1SNikolas Klauser __cxx_atomic_fetch_add(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __delta, memory_order __order) _NOEXCEPT { 411e78f53d1SNikolas Klauser return __c11_atomic_fetch_add( 412e78f53d1SNikolas Klauser std::addressof(__a->__a_value), __delta, static_cast<__memory_order_underlying_t>(__order)); 413e78f53d1SNikolas Klauser } 414e78f53d1SNikolas Klauser template <class _Tp> 415e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI _Tp 416e78f53d1SNikolas Klauser __cxx_atomic_fetch_add(__cxx_atomic_base_impl<_Tp>* __a, _Tp __delta, memory_order __order) _NOEXCEPT { 417e78f53d1SNikolas Klauser return __c11_atomic_fetch_add( 418e78f53d1SNikolas Klauser std::addressof(__a->__a_value), __delta, static_cast<__memory_order_underlying_t>(__order)); 419e78f53d1SNikolas Klauser } 420e78f53d1SNikolas Klauser 421e78f53d1SNikolas Klauser template <class _Tp> 422e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI _Tp* 423e78f53d1SNikolas Klauser __cxx_atomic_fetch_add(__cxx_atomic_base_impl<_Tp*> volatile* __a, ptrdiff_t __delta, memory_order __order) _NOEXCEPT { 424e78f53d1SNikolas Klauser return __c11_atomic_fetch_add( 425e78f53d1SNikolas Klauser std::addressof(__a->__a_value), __delta, static_cast<__memory_order_underlying_t>(__order)); 426e78f53d1SNikolas Klauser } 427e78f53d1SNikolas Klauser template <class _Tp> 428e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI _Tp* 429e78f53d1SNikolas Klauser __cxx_atomic_fetch_add(__cxx_atomic_base_impl<_Tp*>* __a, ptrdiff_t __delta, memory_order __order) _NOEXCEPT { 430e78f53d1SNikolas Klauser return __c11_atomic_fetch_add( 431e78f53d1SNikolas Klauser std::addressof(__a->__a_value), __delta, static_cast<__memory_order_underlying_t>(__order)); 432e78f53d1SNikolas Klauser } 433e78f53d1SNikolas Klauser 434e78f53d1SNikolas Klauser template <class _Tp> 435e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI _Tp 436e78f53d1SNikolas Klauser __cxx_atomic_fetch_sub(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __delta, memory_order __order) _NOEXCEPT { 437e78f53d1SNikolas Klauser return __c11_atomic_fetch_sub( 438e78f53d1SNikolas Klauser std::addressof(__a->__a_value), __delta, static_cast<__memory_order_underlying_t>(__order)); 439e78f53d1SNikolas Klauser } 440e78f53d1SNikolas Klauser template <class _Tp> 441e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI _Tp 442e78f53d1SNikolas Klauser __cxx_atomic_fetch_sub(__cxx_atomic_base_impl<_Tp>* __a, _Tp __delta, memory_order __order) _NOEXCEPT { 443e78f53d1SNikolas Klauser return __c11_atomic_fetch_sub( 444e78f53d1SNikolas Klauser std::addressof(__a->__a_value), __delta, static_cast<__memory_order_underlying_t>(__order)); 445e78f53d1SNikolas Klauser } 446e78f53d1SNikolas Klauser template <class _Tp> 447e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI _Tp* 448e78f53d1SNikolas Klauser __cxx_atomic_fetch_sub(__cxx_atomic_base_impl<_Tp*> volatile* __a, ptrdiff_t __delta, memory_order __order) _NOEXCEPT { 449e78f53d1SNikolas Klauser return __c11_atomic_fetch_sub( 450e78f53d1SNikolas Klauser std::addressof(__a->__a_value), __delta, static_cast<__memory_order_underlying_t>(__order)); 451e78f53d1SNikolas Klauser } 452e78f53d1SNikolas Klauser template <class _Tp> 453e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI _Tp* 454e78f53d1SNikolas Klauser __cxx_atomic_fetch_sub(__cxx_atomic_base_impl<_Tp*>* __a, ptrdiff_t __delta, memory_order __order) _NOEXCEPT { 455e78f53d1SNikolas Klauser return __c11_atomic_fetch_sub( 456e78f53d1SNikolas Klauser std::addressof(__a->__a_value), __delta, static_cast<__memory_order_underlying_t>(__order)); 457e78f53d1SNikolas Klauser } 458e78f53d1SNikolas Klauser 459e78f53d1SNikolas Klauser template <class _Tp> 460e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI _Tp 461e78f53d1SNikolas Klauser __cxx_atomic_fetch_and(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __pattern, memory_order __order) _NOEXCEPT { 462e78f53d1SNikolas Klauser return __c11_atomic_fetch_and( 463e78f53d1SNikolas Klauser std::addressof(__a->__a_value), __pattern, static_cast<__memory_order_underlying_t>(__order)); 464e78f53d1SNikolas Klauser } 465e78f53d1SNikolas Klauser template <class _Tp> 466e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI _Tp 467e78f53d1SNikolas Klauser __cxx_atomic_fetch_and(__cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, memory_order __order) _NOEXCEPT { 468e78f53d1SNikolas Klauser return __c11_atomic_fetch_and( 469e78f53d1SNikolas Klauser std::addressof(__a->__a_value), __pattern, static_cast<__memory_order_underlying_t>(__order)); 470e78f53d1SNikolas Klauser } 471e78f53d1SNikolas Klauser 472e78f53d1SNikolas Klauser template <class _Tp> 473e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI _Tp 474e78f53d1SNikolas Klauser __cxx_atomic_fetch_or(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __pattern, memory_order __order) _NOEXCEPT { 475e78f53d1SNikolas Klauser return __c11_atomic_fetch_or( 476e78f53d1SNikolas Klauser std::addressof(__a->__a_value), __pattern, static_cast<__memory_order_underlying_t>(__order)); 477e78f53d1SNikolas Klauser } 478e78f53d1SNikolas Klauser template <class _Tp> 479e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI _Tp 480e78f53d1SNikolas Klauser __cxx_atomic_fetch_or(__cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, memory_order __order) _NOEXCEPT { 481e78f53d1SNikolas Klauser return __c11_atomic_fetch_or( 482e78f53d1SNikolas Klauser std::addressof(__a->__a_value), __pattern, static_cast<__memory_order_underlying_t>(__order)); 483e78f53d1SNikolas Klauser } 484e78f53d1SNikolas Klauser 485e78f53d1SNikolas Klauser template <class _Tp> 486e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI _Tp 487e78f53d1SNikolas Klauser __cxx_atomic_fetch_xor(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __pattern, memory_order __order) _NOEXCEPT { 488e78f53d1SNikolas Klauser return __c11_atomic_fetch_xor( 489e78f53d1SNikolas Klauser std::addressof(__a->__a_value), __pattern, static_cast<__memory_order_underlying_t>(__order)); 490e78f53d1SNikolas Klauser } 491e78f53d1SNikolas Klauser template <class _Tp> 492e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI _Tp 493e78f53d1SNikolas Klauser __cxx_atomic_fetch_xor(__cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, memory_order __order) _NOEXCEPT { 494e78f53d1SNikolas Klauser return __c11_atomic_fetch_xor( 495e78f53d1SNikolas Klauser std::addressof(__a->__a_value), __pattern, static_cast<__memory_order_underlying_t>(__order)); 496e78f53d1SNikolas Klauser } 497e78f53d1SNikolas Klauser 498e78f53d1SNikolas Klauser #endif // _LIBCPP_HAS_GCC_ATOMIC_IMP, _LIBCPP_HAS_C_ATOMIC_IMP 499e78f53d1SNikolas Klauser 500e78f53d1SNikolas Klauser template <typename _Tp, typename _Base = __cxx_atomic_base_impl<_Tp> > 501e78f53d1SNikolas Klauser struct __cxx_atomic_impl : public _Base { 502e78f53d1SNikolas Klauser static_assert(is_trivially_copyable<_Tp>::value, "std::atomic<T> requires that 'T' be a trivially copyable type"); 503e78f53d1SNikolas Klauser 504e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI __cxx_atomic_impl() _NOEXCEPT = default; 505e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR explicit __cxx_atomic_impl(_Tp __value) _NOEXCEPT : _Base(__value) {} 506e78f53d1SNikolas Klauser }; 507e78f53d1SNikolas Klauser 508e78f53d1SNikolas Klauser _LIBCPP_END_NAMESPACE_STD 509e78f53d1SNikolas Klauser 510*ce777190SNikolas Klauser #endif // _LIBCPP___CXX03___ATOMIC_CXX_ATOMIC_IMPL_H 511