xref: /llvm-project/libcxx/include/__cxx03/__atomic/cxx_atomic_impl.h (revision ce7771902dc50d900de639d499a60486b83f70e0)
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