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