106c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 206c3fb27SDimitry Andric // 306c3fb27SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 406c3fb27SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 506c3fb27SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 606c3fb27SDimitry Andric // 706c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 806c3fb27SDimitry Andric 906c3fb27SDimitry Andric #ifndef _LIBCPP___ATOMIC_CXX_ATOMIC_IMPL_H 1006c3fb27SDimitry Andric #define _LIBCPP___ATOMIC_CXX_ATOMIC_IMPL_H 1106c3fb27SDimitry Andric 1206c3fb27SDimitry Andric #include <__atomic/memory_order.h> 13*0fca6ea1SDimitry Andric #include <__atomic/to_gcc_order.h> 1406c3fb27SDimitry Andric #include <__config> 1506c3fb27SDimitry Andric #include <__memory/addressof.h> 1606c3fb27SDimitry Andric #include <__type_traits/is_assignable.h> 1706c3fb27SDimitry Andric #include <__type_traits/is_trivially_copyable.h> 1806c3fb27SDimitry Andric #include <__type_traits/remove_const.h> 1906c3fb27SDimitry Andric #include <cstddef> 2006c3fb27SDimitry Andric 2106c3fb27SDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 2206c3fb27SDimitry Andric # pragma GCC system_header 2306c3fb27SDimitry Andric #endif 2406c3fb27SDimitry Andric 2506c3fb27SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD 2606c3fb27SDimitry Andric 27*0fca6ea1SDimitry Andric #if defined(_LIBCPP_HAS_GCC_ATOMIC_IMP) 2806c3fb27SDimitry Andric 2906c3fb27SDimitry Andric // [atomics.types.generic]p1 guarantees _Tp is trivially copyable. Because 3006c3fb27SDimitry Andric // the default operator= in an object is not volatile, a byte-by-byte copy 3106c3fb27SDimitry Andric // is required. 32cb14a3feSDimitry Andric template <typename _Tp, typename _Tv, __enable_if_t<is_assignable<_Tp&, _Tv>::value, int> = 0> 33cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI void __cxx_atomic_assign_volatile(_Tp& __a_value, _Tv const& __val) { 3406c3fb27SDimitry Andric __a_value = __val; 3506c3fb27SDimitry Andric } 36cb14a3feSDimitry Andric template <typename _Tp, typename _Tv, __enable_if_t<is_assignable<_Tp&, _Tv>::value, int> = 0> 37cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI void __cxx_atomic_assign_volatile(_Tp volatile& __a_value, _Tv volatile const& __val) { 3806c3fb27SDimitry Andric volatile char* __to = reinterpret_cast<volatile char*>(std::addressof(__a_value)); 3906c3fb27SDimitry Andric volatile char* __end = __to + sizeof(_Tp); 4006c3fb27SDimitry Andric volatile const char* __from = reinterpret_cast<volatile const char*>(std::addressof(__val)); 4106c3fb27SDimitry Andric while (__to != __end) 4206c3fb27SDimitry Andric *__to++ = *__from++; 4306c3fb27SDimitry Andric } 4406c3fb27SDimitry Andric 4506c3fb27SDimitry Andric template <typename _Tp> 4606c3fb27SDimitry Andric struct __cxx_atomic_base_impl { 4706c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI 4806c3fb27SDimitry Andric # ifndef _LIBCPP_CXX03_LANG 4906c3fb27SDimitry Andric __cxx_atomic_base_impl() _NOEXCEPT = default; 5006c3fb27SDimitry Andric # else 51cb14a3feSDimitry Andric __cxx_atomic_base_impl() _NOEXCEPT : __a_value() { 52cb14a3feSDimitry Andric } 5306c3fb27SDimitry Andric # endif // _LIBCPP_CXX03_LANG 54cb14a3feSDimitry Andric _LIBCPP_CONSTEXPR explicit __cxx_atomic_base_impl(_Tp value) _NOEXCEPT : __a_value(value) {} 5506c3fb27SDimitry Andric _Tp __a_value; 5606c3fb27SDimitry Andric }; 5706c3fb27SDimitry Andric 5806c3fb27SDimitry Andric template <typename _Tp> 59cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI void __cxx_atomic_init(volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp __val) { 6006c3fb27SDimitry Andric __cxx_atomic_assign_volatile(__a->__a_value, __val); 6106c3fb27SDimitry Andric } 6206c3fb27SDimitry Andric 6306c3fb27SDimitry Andric template <typename _Tp> 64cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI void __cxx_atomic_init(__cxx_atomic_base_impl<_Tp>* __a, _Tp __val) { 6506c3fb27SDimitry Andric __a->__a_value = __val; 6606c3fb27SDimitry Andric } 6706c3fb27SDimitry Andric 68cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI inline void __cxx_atomic_thread_fence(memory_order __order) { 6906c3fb27SDimitry Andric __atomic_thread_fence(__to_gcc_order(__order)); 7006c3fb27SDimitry Andric } 7106c3fb27SDimitry Andric 72cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI inline void __cxx_atomic_signal_fence(memory_order __order) { 7306c3fb27SDimitry Andric __atomic_signal_fence(__to_gcc_order(__order)); 7406c3fb27SDimitry Andric } 7506c3fb27SDimitry Andric 7606c3fb27SDimitry Andric template <typename _Tp> 77cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI void 78cb14a3feSDimitry Andric __cxx_atomic_store(volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp __val, memory_order __order) { 7906c3fb27SDimitry Andric __atomic_store(std::addressof(__a->__a_value), std::addressof(__val), __to_gcc_order(__order)); 8006c3fb27SDimitry Andric } 8106c3fb27SDimitry Andric 8206c3fb27SDimitry Andric template <typename _Tp> 83cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI void __cxx_atomic_store(__cxx_atomic_base_impl<_Tp>* __a, _Tp __val, memory_order __order) { 8406c3fb27SDimitry Andric __atomic_store(std::addressof(__a->__a_value), std::addressof(__val), __to_gcc_order(__order)); 8506c3fb27SDimitry Andric } 8606c3fb27SDimitry Andric 8706c3fb27SDimitry Andric template <typename _Tp> 88cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _Tp __cxx_atomic_load(const volatile __cxx_atomic_base_impl<_Tp>* __a, memory_order __order) { 8906c3fb27SDimitry Andric _Tp __ret; 9006c3fb27SDimitry Andric __atomic_load(std::addressof(__a->__a_value), std::addressof(__ret), __to_gcc_order(__order)); 9106c3fb27SDimitry Andric return __ret; 9206c3fb27SDimitry Andric } 9306c3fb27SDimitry Andric 9406c3fb27SDimitry Andric template <typename _Tp> 955f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI void 965f757f3fSDimitry Andric __cxx_atomic_load_inplace(const volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp* __dst, memory_order __order) { 975f757f3fSDimitry Andric __atomic_load(std::addressof(__a->__a_value), __dst, __to_gcc_order(__order)); 985f757f3fSDimitry Andric } 995f757f3fSDimitry Andric 1005f757f3fSDimitry Andric template <typename _Tp> 1015f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI void 1025f757f3fSDimitry Andric __cxx_atomic_load_inplace(const __cxx_atomic_base_impl<_Tp>* __a, _Tp* __dst, memory_order __order) { 1035f757f3fSDimitry Andric __atomic_load(std::addressof(__a->__a_value), __dst, __to_gcc_order(__order)); 1045f757f3fSDimitry Andric } 1055f757f3fSDimitry Andric 1065f757f3fSDimitry Andric template <typename _Tp> 107cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _Tp __cxx_atomic_load(const __cxx_atomic_base_impl<_Tp>* __a, memory_order __order) { 10806c3fb27SDimitry Andric _Tp __ret; 10906c3fb27SDimitry Andric __atomic_load(std::addressof(__a->__a_value), std::addressof(__ret), __to_gcc_order(__order)); 11006c3fb27SDimitry Andric return __ret; 11106c3fb27SDimitry Andric } 11206c3fb27SDimitry Andric 11306c3fb27SDimitry Andric template <typename _Tp> 114cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _Tp 115cb14a3feSDimitry Andric __cxx_atomic_exchange(volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp __value, memory_order __order) { 11606c3fb27SDimitry Andric _Tp __ret; 11706c3fb27SDimitry Andric __atomic_exchange( 11806c3fb27SDimitry Andric std::addressof(__a->__a_value), std::addressof(__value), std::addressof(__ret), __to_gcc_order(__order)); 11906c3fb27SDimitry Andric return __ret; 12006c3fb27SDimitry Andric } 12106c3fb27SDimitry Andric 12206c3fb27SDimitry Andric template <typename _Tp> 123cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _Tp __cxx_atomic_exchange(__cxx_atomic_base_impl<_Tp>* __a, _Tp __value, memory_order __order) { 12406c3fb27SDimitry Andric _Tp __ret; 12506c3fb27SDimitry Andric __atomic_exchange( 12606c3fb27SDimitry Andric std::addressof(__a->__a_value), std::addressof(__value), std::addressof(__ret), __to_gcc_order(__order)); 12706c3fb27SDimitry Andric return __ret; 12806c3fb27SDimitry Andric } 12906c3fb27SDimitry Andric 13006c3fb27SDimitry Andric template <typename _Tp> 131cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI bool __cxx_atomic_compare_exchange_strong( 132cb14a3feSDimitry Andric volatile __cxx_atomic_base_impl<_Tp>* __a, 133cb14a3feSDimitry Andric _Tp* __expected, 134cb14a3feSDimitry Andric _Tp __value, 135cb14a3feSDimitry Andric memory_order __success, 13606c3fb27SDimitry Andric memory_order __failure) { 13706c3fb27SDimitry Andric return __atomic_compare_exchange( 13806c3fb27SDimitry Andric std::addressof(__a->__a_value), 13906c3fb27SDimitry Andric __expected, 14006c3fb27SDimitry Andric std::addressof(__value), 14106c3fb27SDimitry Andric false, 14206c3fb27SDimitry Andric __to_gcc_order(__success), 14306c3fb27SDimitry Andric __to_gcc_failure_order(__failure)); 14406c3fb27SDimitry Andric } 14506c3fb27SDimitry Andric 14606c3fb27SDimitry Andric template <typename _Tp> 147cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI bool __cxx_atomic_compare_exchange_strong( 148cb14a3feSDimitry Andric __cxx_atomic_base_impl<_Tp>* __a, _Tp* __expected, _Tp __value, memory_order __success, memory_order __failure) { 14906c3fb27SDimitry Andric return __atomic_compare_exchange( 15006c3fb27SDimitry Andric std::addressof(__a->__a_value), 15106c3fb27SDimitry Andric __expected, 15206c3fb27SDimitry Andric std::addressof(__value), 153cb14a3feSDimitry Andric false, 15406c3fb27SDimitry Andric __to_gcc_order(__success), 15506c3fb27SDimitry Andric __to_gcc_failure_order(__failure)); 15606c3fb27SDimitry Andric } 15706c3fb27SDimitry Andric 15806c3fb27SDimitry Andric template <typename _Tp> 159cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI bool __cxx_atomic_compare_exchange_weak( 160cb14a3feSDimitry Andric volatile __cxx_atomic_base_impl<_Tp>* __a, 161cb14a3feSDimitry Andric _Tp* __expected, 162cb14a3feSDimitry Andric _Tp __value, 163cb14a3feSDimitry Andric memory_order __success, 16406c3fb27SDimitry Andric memory_order __failure) { 16506c3fb27SDimitry Andric return __atomic_compare_exchange( 16606c3fb27SDimitry Andric std::addressof(__a->__a_value), 16706c3fb27SDimitry Andric __expected, 16806c3fb27SDimitry Andric std::addressof(__value), 16906c3fb27SDimitry Andric true, 17006c3fb27SDimitry Andric __to_gcc_order(__success), 17106c3fb27SDimitry Andric __to_gcc_failure_order(__failure)); 17206c3fb27SDimitry Andric } 17306c3fb27SDimitry Andric 17406c3fb27SDimitry Andric template <typename _Tp> 175cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI bool __cxx_atomic_compare_exchange_weak( 176cb14a3feSDimitry Andric __cxx_atomic_base_impl<_Tp>* __a, _Tp* __expected, _Tp __value, memory_order __success, memory_order __failure) { 177cb14a3feSDimitry Andric return __atomic_compare_exchange( 178cb14a3feSDimitry Andric std::addressof(__a->__a_value), 179cb14a3feSDimitry Andric __expected, 180cb14a3feSDimitry Andric std::addressof(__value), 181cb14a3feSDimitry Andric true, 182cb14a3feSDimitry Andric __to_gcc_order(__success), 183cb14a3feSDimitry Andric __to_gcc_failure_order(__failure)); 184cb14a3feSDimitry Andric } 18506c3fb27SDimitry Andric 18606c3fb27SDimitry Andric template <typename _Tp> 187cb14a3feSDimitry Andric struct __skip_amt { 188cb14a3feSDimitry Andric enum { value = 1 }; 189cb14a3feSDimitry Andric }; 190cb14a3feSDimitry Andric 191cb14a3feSDimitry Andric template <typename _Tp> 192cb14a3feSDimitry Andric struct __skip_amt<_Tp*> { 193cb14a3feSDimitry Andric enum { value = sizeof(_Tp) }; 194cb14a3feSDimitry Andric }; 19506c3fb27SDimitry Andric 19606c3fb27SDimitry Andric // FIXME: Haven't figured out what the spec says about using arrays with 19706c3fb27SDimitry Andric // atomic_fetch_add. Force a failure rather than creating bad behavior. 19806c3fb27SDimitry Andric template <typename _Tp> 19906c3fb27SDimitry Andric struct __skip_amt<_Tp[]> {}; 20006c3fb27SDimitry Andric template <typename _Tp, int n> 20106c3fb27SDimitry Andric struct __skip_amt<_Tp[n]> {}; 20206c3fb27SDimitry Andric 20306c3fb27SDimitry Andric template <typename _Tp, typename _Td> 204cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _Tp 205cb14a3feSDimitry Andric __cxx_atomic_fetch_add(volatile __cxx_atomic_base_impl<_Tp>* __a, _Td __delta, memory_order __order) { 20606c3fb27SDimitry Andric return __atomic_fetch_add(std::addressof(__a->__a_value), __delta * __skip_amt<_Tp>::value, __to_gcc_order(__order)); 20706c3fb27SDimitry Andric } 20806c3fb27SDimitry Andric 20906c3fb27SDimitry Andric template <typename _Tp, typename _Td> 210cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _Tp __cxx_atomic_fetch_add(__cxx_atomic_base_impl<_Tp>* __a, _Td __delta, memory_order __order) { 21106c3fb27SDimitry Andric return __atomic_fetch_add(std::addressof(__a->__a_value), __delta * __skip_amt<_Tp>::value, __to_gcc_order(__order)); 21206c3fb27SDimitry Andric } 21306c3fb27SDimitry Andric 21406c3fb27SDimitry Andric template <typename _Tp, typename _Td> 215cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _Tp 216cb14a3feSDimitry Andric __cxx_atomic_fetch_sub(volatile __cxx_atomic_base_impl<_Tp>* __a, _Td __delta, memory_order __order) { 21706c3fb27SDimitry Andric return __atomic_fetch_sub(std::addressof(__a->__a_value), __delta * __skip_amt<_Tp>::value, __to_gcc_order(__order)); 21806c3fb27SDimitry Andric } 21906c3fb27SDimitry Andric 22006c3fb27SDimitry Andric template <typename _Tp, typename _Td> 221cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _Tp __cxx_atomic_fetch_sub(__cxx_atomic_base_impl<_Tp>* __a, _Td __delta, memory_order __order) { 22206c3fb27SDimitry Andric return __atomic_fetch_sub(std::addressof(__a->__a_value), __delta * __skip_amt<_Tp>::value, __to_gcc_order(__order)); 22306c3fb27SDimitry Andric } 22406c3fb27SDimitry Andric 22506c3fb27SDimitry Andric template <typename _Tp> 226cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _Tp 227cb14a3feSDimitry Andric __cxx_atomic_fetch_and(volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, memory_order __order) { 22806c3fb27SDimitry Andric return __atomic_fetch_and(std::addressof(__a->__a_value), __pattern, __to_gcc_order(__order)); 22906c3fb27SDimitry Andric } 23006c3fb27SDimitry Andric 23106c3fb27SDimitry Andric template <typename _Tp> 232cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _Tp 233cb14a3feSDimitry Andric __cxx_atomic_fetch_and(__cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, memory_order __order) { 23406c3fb27SDimitry Andric return __atomic_fetch_and(std::addressof(__a->__a_value), __pattern, __to_gcc_order(__order)); 23506c3fb27SDimitry Andric } 23606c3fb27SDimitry Andric 23706c3fb27SDimitry Andric template <typename _Tp> 238cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _Tp 239cb14a3feSDimitry Andric __cxx_atomic_fetch_or(volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, memory_order __order) { 24006c3fb27SDimitry Andric return __atomic_fetch_or(std::addressof(__a->__a_value), __pattern, __to_gcc_order(__order)); 24106c3fb27SDimitry Andric } 24206c3fb27SDimitry Andric 24306c3fb27SDimitry Andric template <typename _Tp> 244cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _Tp __cxx_atomic_fetch_or(__cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, memory_order __order) { 24506c3fb27SDimitry Andric return __atomic_fetch_or(std::addressof(__a->__a_value), __pattern, __to_gcc_order(__order)); 24606c3fb27SDimitry Andric } 24706c3fb27SDimitry Andric 24806c3fb27SDimitry Andric template <typename _Tp> 249cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _Tp 250cb14a3feSDimitry Andric __cxx_atomic_fetch_xor(volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, memory_order __order) { 25106c3fb27SDimitry Andric return __atomic_fetch_xor(std::addressof(__a->__a_value), __pattern, __to_gcc_order(__order)); 25206c3fb27SDimitry Andric } 25306c3fb27SDimitry Andric 25406c3fb27SDimitry Andric template <typename _Tp> 255cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _Tp 256cb14a3feSDimitry Andric __cxx_atomic_fetch_xor(__cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, memory_order __order) { 25706c3fb27SDimitry Andric return __atomic_fetch_xor(std::addressof(__a->__a_value), __pattern, __to_gcc_order(__order)); 25806c3fb27SDimitry Andric } 25906c3fb27SDimitry Andric 26006c3fb27SDimitry Andric # define __cxx_atomic_is_lock_free(__s) __atomic_is_lock_free(__s, 0) 26106c3fb27SDimitry Andric 26206c3fb27SDimitry Andric #elif defined(_LIBCPP_HAS_C_ATOMIC_IMP) 26306c3fb27SDimitry Andric 26406c3fb27SDimitry Andric template <typename _Tp> 26506c3fb27SDimitry Andric struct __cxx_atomic_base_impl { 26606c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI 26706c3fb27SDimitry Andric # ifndef _LIBCPP_CXX03_LANG 26806c3fb27SDimitry Andric __cxx_atomic_base_impl() _NOEXCEPT = default; 26906c3fb27SDimitry Andric # else 270cb14a3feSDimitry Andric __cxx_atomic_base_impl() _NOEXCEPT : __a_value() { 271cb14a3feSDimitry Andric } 27206c3fb27SDimitry Andric # endif // _LIBCPP_CXX03_LANG 273cb14a3feSDimitry Andric _LIBCPP_CONSTEXPR explicit __cxx_atomic_base_impl(_Tp __value) _NOEXCEPT : __a_value(__value) {} 27406c3fb27SDimitry Andric _LIBCPP_DISABLE_EXTENSION_WARNING _Atomic(_Tp) __a_value; 27506c3fb27SDimitry Andric }; 27606c3fb27SDimitry Andric 27706c3fb27SDimitry Andric # define __cxx_atomic_is_lock_free(__s) __c11_atomic_is_lock_free(__s) 27806c3fb27SDimitry Andric 279cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI inline void __cxx_atomic_thread_fence(memory_order __order) _NOEXCEPT { 28006c3fb27SDimitry Andric __c11_atomic_thread_fence(static_cast<__memory_order_underlying_t>(__order)); 28106c3fb27SDimitry Andric } 28206c3fb27SDimitry Andric 283cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI inline void __cxx_atomic_signal_fence(memory_order __order) _NOEXCEPT { 28406c3fb27SDimitry Andric __c11_atomic_signal_fence(static_cast<__memory_order_underlying_t>(__order)); 28506c3fb27SDimitry Andric } 28606c3fb27SDimitry Andric 28706c3fb27SDimitry Andric template <class _Tp> 288cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI void __cxx_atomic_init(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __val) _NOEXCEPT { 28906c3fb27SDimitry Andric __c11_atomic_init(std::addressof(__a->__a_value), __val); 29006c3fb27SDimitry Andric } 29106c3fb27SDimitry Andric template <class _Tp> 292cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI void __cxx_atomic_init(__cxx_atomic_base_impl<_Tp>* __a, _Tp __val) _NOEXCEPT { 29306c3fb27SDimitry Andric __c11_atomic_init(std::addressof(__a->__a_value), __val); 29406c3fb27SDimitry Andric } 29506c3fb27SDimitry Andric 29606c3fb27SDimitry Andric template <class _Tp> 297cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI void 298cb14a3feSDimitry Andric __cxx_atomic_store(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __val, memory_order __order) _NOEXCEPT { 29906c3fb27SDimitry Andric __c11_atomic_store(std::addressof(__a->__a_value), __val, static_cast<__memory_order_underlying_t>(__order)); 30006c3fb27SDimitry Andric } 30106c3fb27SDimitry Andric template <class _Tp> 302cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI void 303cb14a3feSDimitry Andric __cxx_atomic_store(__cxx_atomic_base_impl<_Tp>* __a, _Tp __val, memory_order __order) _NOEXCEPT { 30406c3fb27SDimitry Andric __c11_atomic_store(std::addressof(__a->__a_value), __val, static_cast<__memory_order_underlying_t>(__order)); 30506c3fb27SDimitry Andric } 30606c3fb27SDimitry Andric 30706c3fb27SDimitry Andric template <class _Tp> 308cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _Tp 309cb14a3feSDimitry Andric __cxx_atomic_load(__cxx_atomic_base_impl<_Tp> const volatile* __a, memory_order __order) _NOEXCEPT { 31006c3fb27SDimitry Andric using __ptr_type = __remove_const_t<decltype(__a->__a_value)>*; 31106c3fb27SDimitry Andric return __c11_atomic_load( 31206c3fb27SDimitry Andric const_cast<__ptr_type>(std::addressof(__a->__a_value)), static_cast<__memory_order_underlying_t>(__order)); 31306c3fb27SDimitry Andric } 31406c3fb27SDimitry Andric template <class _Tp> 315cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _Tp __cxx_atomic_load(__cxx_atomic_base_impl<_Tp> const* __a, memory_order __order) _NOEXCEPT { 31606c3fb27SDimitry Andric using __ptr_type = __remove_const_t<decltype(__a->__a_value)>*; 31706c3fb27SDimitry Andric return __c11_atomic_load( 31806c3fb27SDimitry Andric const_cast<__ptr_type>(std::addressof(__a->__a_value)), static_cast<__memory_order_underlying_t>(__order)); 31906c3fb27SDimitry Andric } 32006c3fb27SDimitry Andric 32106c3fb27SDimitry Andric template <class _Tp> 3225f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI void 3235f757f3fSDimitry Andric __cxx_atomic_load_inplace(__cxx_atomic_base_impl<_Tp> const volatile* __a, _Tp* __dst, memory_order __order) _NOEXCEPT { 3245f757f3fSDimitry Andric using __ptr_type = __remove_const_t<decltype(__a->__a_value)>*; 3255f757f3fSDimitry Andric *__dst = __c11_atomic_load( 3265f757f3fSDimitry Andric const_cast<__ptr_type>(std::addressof(__a->__a_value)), static_cast<__memory_order_underlying_t>(__order)); 3275f757f3fSDimitry Andric } 3285f757f3fSDimitry Andric template <class _Tp> 3295f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI void 3305f757f3fSDimitry Andric __cxx_atomic_load_inplace(__cxx_atomic_base_impl<_Tp> const* __a, _Tp* __dst, memory_order __order) _NOEXCEPT { 3315f757f3fSDimitry Andric using __ptr_type = __remove_const_t<decltype(__a->__a_value)>*; 3325f757f3fSDimitry Andric *__dst = __c11_atomic_load( 3335f757f3fSDimitry Andric const_cast<__ptr_type>(std::addressof(__a->__a_value)), static_cast<__memory_order_underlying_t>(__order)); 3345f757f3fSDimitry Andric } 3355f757f3fSDimitry Andric 3365f757f3fSDimitry Andric template <class _Tp> 337cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _Tp 338cb14a3feSDimitry Andric __cxx_atomic_exchange(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __value, memory_order __order) _NOEXCEPT { 33906c3fb27SDimitry Andric return __c11_atomic_exchange( 34006c3fb27SDimitry Andric std::addressof(__a->__a_value), __value, static_cast<__memory_order_underlying_t>(__order)); 34106c3fb27SDimitry Andric } 34206c3fb27SDimitry Andric template <class _Tp> 343cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _Tp 344cb14a3feSDimitry Andric __cxx_atomic_exchange(__cxx_atomic_base_impl<_Tp>* __a, _Tp __value, memory_order __order) _NOEXCEPT { 34506c3fb27SDimitry Andric return __c11_atomic_exchange( 34606c3fb27SDimitry Andric std::addressof(__a->__a_value), __value, static_cast<__memory_order_underlying_t>(__order)); 34706c3fb27SDimitry Andric } 34806c3fb27SDimitry Andric 34906c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI inline _LIBCPP_CONSTEXPR memory_order __to_failure_order(memory_order __order) { 35006c3fb27SDimitry Andric // Avoid switch statement to make this a constexpr. 351cb14a3feSDimitry Andric return __order == memory_order_release 352cb14a3feSDimitry Andric ? memory_order_relaxed 353cb14a3feSDimitry Andric : (__order == memory_order_acq_rel ? memory_order_acquire : __order); 35406c3fb27SDimitry Andric } 35506c3fb27SDimitry Andric 35606c3fb27SDimitry Andric template <class _Tp> 357cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI bool __cxx_atomic_compare_exchange_strong( 358cb14a3feSDimitry Andric __cxx_atomic_base_impl<_Tp> volatile* __a, 359cb14a3feSDimitry Andric _Tp* __expected, 360cb14a3feSDimitry Andric _Tp __value, 361cb14a3feSDimitry Andric memory_order __success, 362cb14a3feSDimitry Andric memory_order __failure) _NOEXCEPT { 36306c3fb27SDimitry Andric return __c11_atomic_compare_exchange_strong( 36406c3fb27SDimitry Andric std::addressof(__a->__a_value), 36506c3fb27SDimitry Andric __expected, 36606c3fb27SDimitry Andric __value, 36706c3fb27SDimitry Andric static_cast<__memory_order_underlying_t>(__success), 36806c3fb27SDimitry Andric static_cast<__memory_order_underlying_t>(__to_failure_order(__failure))); 36906c3fb27SDimitry Andric } 37006c3fb27SDimitry Andric template <class _Tp> 371cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI bool __cxx_atomic_compare_exchange_strong( 372cb14a3feSDimitry Andric __cxx_atomic_base_impl<_Tp>* __a, _Tp* __expected, _Tp __value, memory_order __success, memory_order __failure) 373cb14a3feSDimitry Andric _NOEXCEPT { 37406c3fb27SDimitry Andric return __c11_atomic_compare_exchange_strong( 37506c3fb27SDimitry Andric std::addressof(__a->__a_value), 37606c3fb27SDimitry Andric __expected, 37706c3fb27SDimitry Andric __value, 37806c3fb27SDimitry Andric static_cast<__memory_order_underlying_t>(__success), 37906c3fb27SDimitry Andric static_cast<__memory_order_underlying_t>(__to_failure_order(__failure))); 38006c3fb27SDimitry Andric } 38106c3fb27SDimitry Andric 38206c3fb27SDimitry Andric template <class _Tp> 383cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI bool __cxx_atomic_compare_exchange_weak( 384cb14a3feSDimitry Andric __cxx_atomic_base_impl<_Tp> volatile* __a, 385cb14a3feSDimitry Andric _Tp* __expected, 386cb14a3feSDimitry Andric _Tp __value, 387cb14a3feSDimitry Andric memory_order __success, 388cb14a3feSDimitry Andric memory_order __failure) _NOEXCEPT { 38906c3fb27SDimitry Andric return __c11_atomic_compare_exchange_weak( 39006c3fb27SDimitry Andric std::addressof(__a->__a_value), 39106c3fb27SDimitry Andric __expected, 39206c3fb27SDimitry Andric __value, 39306c3fb27SDimitry Andric static_cast<__memory_order_underlying_t>(__success), 39406c3fb27SDimitry Andric static_cast<__memory_order_underlying_t>(__to_failure_order(__failure))); 39506c3fb27SDimitry Andric } 39606c3fb27SDimitry Andric template <class _Tp> 397cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI bool __cxx_atomic_compare_exchange_weak( 398cb14a3feSDimitry Andric __cxx_atomic_base_impl<_Tp>* __a, _Tp* __expected, _Tp __value, memory_order __success, memory_order __failure) 399cb14a3feSDimitry Andric _NOEXCEPT { 40006c3fb27SDimitry Andric return __c11_atomic_compare_exchange_weak( 40106c3fb27SDimitry Andric std::addressof(__a->__a_value), 40206c3fb27SDimitry Andric __expected, 40306c3fb27SDimitry Andric __value, 40406c3fb27SDimitry Andric static_cast<__memory_order_underlying_t>(__success), 40506c3fb27SDimitry Andric static_cast<__memory_order_underlying_t>(__to_failure_order(__failure))); 40606c3fb27SDimitry Andric } 40706c3fb27SDimitry Andric 40806c3fb27SDimitry Andric template <class _Tp> 409cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _Tp 410cb14a3feSDimitry Andric __cxx_atomic_fetch_add(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __delta, memory_order __order) _NOEXCEPT { 41106c3fb27SDimitry Andric return __c11_atomic_fetch_add( 41206c3fb27SDimitry Andric std::addressof(__a->__a_value), __delta, static_cast<__memory_order_underlying_t>(__order)); 41306c3fb27SDimitry Andric } 41406c3fb27SDimitry Andric template <class _Tp> 415cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _Tp 416cb14a3feSDimitry Andric __cxx_atomic_fetch_add(__cxx_atomic_base_impl<_Tp>* __a, _Tp __delta, memory_order __order) _NOEXCEPT { 41706c3fb27SDimitry Andric return __c11_atomic_fetch_add( 41806c3fb27SDimitry Andric std::addressof(__a->__a_value), __delta, static_cast<__memory_order_underlying_t>(__order)); 41906c3fb27SDimitry Andric } 42006c3fb27SDimitry Andric 42106c3fb27SDimitry Andric template <class _Tp> 422cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _Tp* 423cb14a3feSDimitry Andric __cxx_atomic_fetch_add(__cxx_atomic_base_impl<_Tp*> volatile* __a, ptrdiff_t __delta, memory_order __order) _NOEXCEPT { 42406c3fb27SDimitry Andric return __c11_atomic_fetch_add( 42506c3fb27SDimitry Andric std::addressof(__a->__a_value), __delta, static_cast<__memory_order_underlying_t>(__order)); 42606c3fb27SDimitry Andric } 42706c3fb27SDimitry Andric template <class _Tp> 428cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _Tp* 429cb14a3feSDimitry Andric __cxx_atomic_fetch_add(__cxx_atomic_base_impl<_Tp*>* __a, ptrdiff_t __delta, memory_order __order) _NOEXCEPT { 43006c3fb27SDimitry Andric return __c11_atomic_fetch_add( 43106c3fb27SDimitry Andric std::addressof(__a->__a_value), __delta, static_cast<__memory_order_underlying_t>(__order)); 43206c3fb27SDimitry Andric } 43306c3fb27SDimitry Andric 43406c3fb27SDimitry Andric template <class _Tp> 435cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _Tp 436cb14a3feSDimitry Andric __cxx_atomic_fetch_sub(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __delta, memory_order __order) _NOEXCEPT { 43706c3fb27SDimitry Andric return __c11_atomic_fetch_sub( 43806c3fb27SDimitry Andric std::addressof(__a->__a_value), __delta, static_cast<__memory_order_underlying_t>(__order)); 43906c3fb27SDimitry Andric } 44006c3fb27SDimitry Andric template <class _Tp> 441cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _Tp 442cb14a3feSDimitry Andric __cxx_atomic_fetch_sub(__cxx_atomic_base_impl<_Tp>* __a, _Tp __delta, memory_order __order) _NOEXCEPT { 44306c3fb27SDimitry Andric return __c11_atomic_fetch_sub( 44406c3fb27SDimitry Andric std::addressof(__a->__a_value), __delta, static_cast<__memory_order_underlying_t>(__order)); 44506c3fb27SDimitry Andric } 44606c3fb27SDimitry Andric template <class _Tp> 447cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _Tp* 448cb14a3feSDimitry Andric __cxx_atomic_fetch_sub(__cxx_atomic_base_impl<_Tp*> volatile* __a, ptrdiff_t __delta, memory_order __order) _NOEXCEPT { 44906c3fb27SDimitry Andric return __c11_atomic_fetch_sub( 45006c3fb27SDimitry Andric std::addressof(__a->__a_value), __delta, static_cast<__memory_order_underlying_t>(__order)); 45106c3fb27SDimitry Andric } 45206c3fb27SDimitry Andric template <class _Tp> 453cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _Tp* 454cb14a3feSDimitry Andric __cxx_atomic_fetch_sub(__cxx_atomic_base_impl<_Tp*>* __a, ptrdiff_t __delta, memory_order __order) _NOEXCEPT { 45506c3fb27SDimitry Andric return __c11_atomic_fetch_sub( 45606c3fb27SDimitry Andric std::addressof(__a->__a_value), __delta, static_cast<__memory_order_underlying_t>(__order)); 45706c3fb27SDimitry Andric } 45806c3fb27SDimitry Andric 45906c3fb27SDimitry Andric template <class _Tp> 460cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _Tp 461cb14a3feSDimitry Andric __cxx_atomic_fetch_and(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __pattern, memory_order __order) _NOEXCEPT { 46206c3fb27SDimitry Andric return __c11_atomic_fetch_and( 46306c3fb27SDimitry Andric std::addressof(__a->__a_value), __pattern, static_cast<__memory_order_underlying_t>(__order)); 46406c3fb27SDimitry Andric } 46506c3fb27SDimitry Andric template <class _Tp> 466cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _Tp 467cb14a3feSDimitry Andric __cxx_atomic_fetch_and(__cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, memory_order __order) _NOEXCEPT { 46806c3fb27SDimitry Andric return __c11_atomic_fetch_and( 46906c3fb27SDimitry Andric std::addressof(__a->__a_value), __pattern, static_cast<__memory_order_underlying_t>(__order)); 47006c3fb27SDimitry Andric } 47106c3fb27SDimitry Andric 47206c3fb27SDimitry Andric template <class _Tp> 473cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _Tp 474cb14a3feSDimitry Andric __cxx_atomic_fetch_or(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __pattern, memory_order __order) _NOEXCEPT { 47506c3fb27SDimitry Andric return __c11_atomic_fetch_or( 47606c3fb27SDimitry Andric std::addressof(__a->__a_value), __pattern, static_cast<__memory_order_underlying_t>(__order)); 47706c3fb27SDimitry Andric } 47806c3fb27SDimitry Andric template <class _Tp> 479cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _Tp 480cb14a3feSDimitry Andric __cxx_atomic_fetch_or(__cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, memory_order __order) _NOEXCEPT { 48106c3fb27SDimitry Andric return __c11_atomic_fetch_or( 48206c3fb27SDimitry Andric std::addressof(__a->__a_value), __pattern, static_cast<__memory_order_underlying_t>(__order)); 48306c3fb27SDimitry Andric } 48406c3fb27SDimitry Andric 48506c3fb27SDimitry Andric template <class _Tp> 486cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _Tp 487cb14a3feSDimitry Andric __cxx_atomic_fetch_xor(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __pattern, memory_order __order) _NOEXCEPT { 48806c3fb27SDimitry Andric return __c11_atomic_fetch_xor( 48906c3fb27SDimitry Andric std::addressof(__a->__a_value), __pattern, static_cast<__memory_order_underlying_t>(__order)); 49006c3fb27SDimitry Andric } 49106c3fb27SDimitry Andric template <class _Tp> 492cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _Tp 493cb14a3feSDimitry Andric __cxx_atomic_fetch_xor(__cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, memory_order __order) _NOEXCEPT { 49406c3fb27SDimitry Andric return __c11_atomic_fetch_xor( 49506c3fb27SDimitry Andric std::addressof(__a->__a_value), __pattern, static_cast<__memory_order_underlying_t>(__order)); 49606c3fb27SDimitry Andric } 49706c3fb27SDimitry Andric 49806c3fb27SDimitry Andric #endif // _LIBCPP_HAS_GCC_ATOMIC_IMP, _LIBCPP_HAS_C_ATOMIC_IMP 49906c3fb27SDimitry Andric 500cb14a3feSDimitry Andric template <typename _Tp, typename _Base = __cxx_atomic_base_impl<_Tp> > 50106c3fb27SDimitry Andric struct __cxx_atomic_impl : public _Base { 502cb14a3feSDimitry Andric static_assert(is_trivially_copyable<_Tp>::value, "std::atomic<T> requires that 'T' be a trivially copyable type"); 50306c3fb27SDimitry Andric 50406c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI __cxx_atomic_impl() _NOEXCEPT = default; 505cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR explicit __cxx_atomic_impl(_Tp __value) _NOEXCEPT : _Base(__value) {} 50606c3fb27SDimitry Andric }; 50706c3fb27SDimitry Andric 50806c3fb27SDimitry Andric _LIBCPP_END_NAMESPACE_STD 50906c3fb27SDimitry Andric 51006c3fb27SDimitry Andric #endif // _LIBCPP___ATOMIC_CXX_ATOMIC_IMPL_H 511