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