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