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_ATOMIC_H 10 #define _LIBCPP___ATOMIC_ATOMIC_H 11 12 #include <__atomic/atomic_base.h> 13 #include <__atomic/check_memory_order.h> 14 #include <__atomic/cxx_atomic_impl.h> 15 #include <__atomic/memory_order.h> 16 #include <__config> 17 #include <__functional/operations.h> 18 #include <__memory/addressof.h> 19 #include <__type_traits/is_floating_point.h> 20 #include <__type_traits/is_function.h> 21 #include <__type_traits/is_same.h> 22 #include <__type_traits/remove_const.h> 23 #include <__type_traits/remove_pointer.h> 24 #include <__type_traits/remove_volatile.h> 25 #include <__utility/forward.h> 26 #include <cstddef> 27 #include <cstring> 28 29 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 30 # pragma GCC system_header 31 #endif 32 33 _LIBCPP_BEGIN_NAMESPACE_STD 34 35 template <class _Tp> 36 struct atomic 37 : public __atomic_base<_Tp> 38 { 39 using __base = __atomic_base<_Tp>; 40 using value_type = _Tp; 41 using difference_type = value_type; 42 43 #if _LIBCPP_STD_VER >= 20 44 _LIBCPP_HIDE_FROM_ABI 45 atomic() = default; 46 #else 47 _LIBCPP_HIDE_FROM_ABI 48 atomic() _NOEXCEPT = default; 49 #endif 50 51 _LIBCPP_HIDE_FROM_ABI atomicatomic52 _LIBCPP_CONSTEXPR atomic(_Tp __d) _NOEXCEPT : __base(__d) {} 53 54 _LIBCPP_HIDE_FROM_ABI 55 _Tp operator=(_Tp __d) volatile _NOEXCEPT 56 {__base::store(__d); return __d;} 57 _LIBCPP_HIDE_FROM_ABI 58 _Tp operator=(_Tp __d) _NOEXCEPT 59 {__base::store(__d); return __d;} 60 61 atomic& operator=(const atomic&) = delete; 62 atomic& operator=(const atomic&) volatile = delete; 63 }; 64 65 // atomic<T*> 66 67 template <class _Tp> 68 struct atomic<_Tp*> 69 : public __atomic_base<_Tp*> 70 { 71 using __base = __atomic_base<_Tp*>; 72 using value_type = _Tp*; 73 using difference_type = ptrdiff_t; 74 75 _LIBCPP_HIDE_FROM_ABI 76 atomic() _NOEXCEPT = default; 77 78 _LIBCPP_HIDE_FROM_ABI 79 _LIBCPP_CONSTEXPR atomic(_Tp* __d) _NOEXCEPT : __base(__d) {} 80 81 _LIBCPP_HIDE_FROM_ABI 82 _Tp* operator=(_Tp* __d) volatile _NOEXCEPT 83 {__base::store(__d); return __d;} 84 _LIBCPP_HIDE_FROM_ABI 85 _Tp* operator=(_Tp* __d) _NOEXCEPT 86 {__base::store(__d); return __d;} 87 88 _LIBCPP_HIDE_FROM_ABI 89 _Tp* fetch_add(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT { 90 // __atomic_fetch_add accepts function pointers, guard against them. 91 static_assert(!is_function<__remove_pointer_t<_Tp> >::value, "Pointer to function isn't allowed"); 92 return std::__cxx_atomic_fetch_add(std::addressof(this->__a_), __op, __m); 93 } 94 95 _LIBCPP_HIDE_FROM_ABI 96 _Tp* fetch_add(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT { 97 // __atomic_fetch_add accepts function pointers, guard against them. 98 static_assert(!is_function<__remove_pointer_t<_Tp> >::value, "Pointer to function isn't allowed"); 99 return std::__cxx_atomic_fetch_add(std::addressof(this->__a_), __op, __m); 100 } 101 102 _LIBCPP_HIDE_FROM_ABI 103 _Tp* fetch_sub(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT { 104 // __atomic_fetch_add accepts function pointers, guard against them. 105 static_assert(!is_function<__remove_pointer_t<_Tp> >::value, "Pointer to function isn't allowed"); 106 return std::__cxx_atomic_fetch_sub(std::addressof(this->__a_), __op, __m); 107 } 108 109 _LIBCPP_HIDE_FROM_ABI 110 _Tp* fetch_sub(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT { 111 // __atomic_fetch_add accepts function pointers, guard against them. 112 static_assert(!is_function<__remove_pointer_t<_Tp> >::value, "Pointer to function isn't allowed"); 113 return std::__cxx_atomic_fetch_sub(std::addressof(this->__a_), __op, __m); 114 } 115 116 _LIBCPP_HIDE_FROM_ABI 117 _Tp* operator++(int) volatile _NOEXCEPT {return fetch_add(1);} 118 _LIBCPP_HIDE_FROM_ABI 119 _Tp* operator++(int) _NOEXCEPT {return fetch_add(1);} 120 _LIBCPP_HIDE_FROM_ABI 121 _Tp* operator--(int) volatile _NOEXCEPT {return fetch_sub(1);} 122 _LIBCPP_HIDE_FROM_ABI 123 _Tp* operator--(int) _NOEXCEPT {return fetch_sub(1);} 124 _LIBCPP_HIDE_FROM_ABI 125 _Tp* operator++() volatile _NOEXCEPT {return fetch_add(1) + 1;} 126 _LIBCPP_HIDE_FROM_ABI 127 _Tp* operator++() _NOEXCEPT {return fetch_add(1) + 1;} 128 _LIBCPP_HIDE_FROM_ABI 129 _Tp* operator--() volatile _NOEXCEPT {return fetch_sub(1) - 1;} 130 _LIBCPP_HIDE_FROM_ABI 131 _Tp* operator--() _NOEXCEPT {return fetch_sub(1) - 1;} 132 _LIBCPP_HIDE_FROM_ABI 133 _Tp* operator+=(ptrdiff_t __op) volatile _NOEXCEPT {return fetch_add(__op) + __op;} 134 _LIBCPP_HIDE_FROM_ABI 135 _Tp* operator+=(ptrdiff_t __op) _NOEXCEPT {return fetch_add(__op) + __op;} 136 _LIBCPP_HIDE_FROM_ABI 137 _Tp* operator-=(ptrdiff_t __op) volatile _NOEXCEPT {return fetch_sub(__op) - __op;} 138 _LIBCPP_HIDE_FROM_ABI 139 _Tp* operator-=(ptrdiff_t __op) _NOEXCEPT {return fetch_sub(__op) - __op;} 140 141 atomic& operator=(const atomic&) = delete; 142 atomic& operator=(const atomic&) volatile = delete; 143 }; 144 145 #if _LIBCPP_STD_VER >= 20 146 template <class _Tp> 147 requires is_floating_point_v<_Tp> 148 struct atomic<_Tp> : __atomic_base<_Tp> { 149 private: 150 _LIBCPP_HIDE_FROM_ABI static constexpr bool __is_fp80_long_double() { 151 // Only x87-fp80 long double has 64-bit mantissa 152 return __LDBL_MANT_DIG__ == 64 && std::is_same_v<_Tp, long double>; 153 } 154 155 _LIBCPP_HIDE_FROM_ABI static constexpr bool __has_rmw_builtin() { 156 # ifndef _LIBCPP_COMPILER_CLANG_BASED 157 return false; 158 # else 159 // The builtin __cxx_atomic_fetch_add errors during compilation for 160 // long double on platforms with fp80 format. 161 // For more details, see 162 // lib/Sema/SemaChecking.cpp function IsAllowedValueType 163 // LLVM Parser does not allow atomicrmw with x86_fp80 type. 164 // if (ValType->isSpecificBuiltinType(BuiltinType::LongDouble) && 165 // &Context.getTargetInfo().getLongDoubleFormat() == 166 // &llvm::APFloat::x87DoubleExtended()) 167 // For more info 168 // https://github.com/llvm/llvm-project/issues/68602 169 // https://reviews.llvm.org/D53965 170 return !__is_fp80_long_double(); 171 # endif 172 } 173 174 template <class _This, class _Operation, class _BuiltinOp> 175 _LIBCPP_HIDE_FROM_ABI static _Tp 176 __rmw_op(_This&& __self, _Tp __operand, memory_order __m, _Operation __operation, _BuiltinOp __builtin_op) { 177 if constexpr (__has_rmw_builtin()) { 178 return __builtin_op(std::addressof(std::forward<_This>(__self).__a_), __operand, __m); 179 } else { 180 _Tp __old = __self.load(memory_order_relaxed); 181 _Tp __new = __operation(__old, __operand); 182 while (!__self.compare_exchange_weak(__old, __new, __m, memory_order_relaxed)) { 183 # ifdef _LIBCPP_COMPILER_CLANG_BASED 184 if constexpr (__is_fp80_long_double()) { 185 // https://github.com/llvm/llvm-project/issues/47978 186 // clang bug: __old is not updated on failure for atomic<long double>::compare_exchange_weak 187 // Note __old = __self.load(memory_order_relaxed) will not work 188 std::__cxx_atomic_load_inplace(std::addressof(__self.__a_), &__old, memory_order_relaxed); 189 } 190 # endif 191 __new = __operation(__old, __operand); 192 } 193 return __old; 194 } 195 } 196 197 template <class _This> 198 _LIBCPP_HIDE_FROM_ABI static _Tp __fetch_add(_This&& __self, _Tp __operand, memory_order __m) { 199 auto __builtin_op = [](auto __a, auto __builtin_operand, auto __order) { 200 return std::__cxx_atomic_fetch_add(__a, __builtin_operand, __order); 201 }; 202 return __rmw_op(std::forward<_This>(__self), __operand, __m, std::plus<>{}, __builtin_op); 203 } 204 205 template <class _This> 206 _LIBCPP_HIDE_FROM_ABI static _Tp __fetch_sub(_This&& __self, _Tp __operand, memory_order __m) { 207 auto __builtin_op = [](auto __a, auto __builtin_operand, auto __order) { 208 return std::__cxx_atomic_fetch_sub(__a, __builtin_operand, __order); 209 }; 210 return __rmw_op(std::forward<_This>(__self), __operand, __m, std::minus<>{}, __builtin_op); 211 } 212 213 public: 214 using __base = __atomic_base<_Tp>; 215 using value_type = _Tp; 216 using difference_type = value_type; 217 218 _LIBCPP_HIDE_FROM_ABI constexpr atomic() noexcept = default; 219 _LIBCPP_HIDE_FROM_ABI constexpr atomic(_Tp __d) noexcept : __base(__d) {} 220 221 atomic(const atomic&) = delete; 222 atomic& operator=(const atomic&) = delete; 223 atomic& operator=(const atomic&) volatile = delete; 224 225 _LIBCPP_HIDE_FROM_ABI _Tp operator=(_Tp __d) volatile noexcept 226 requires __base::is_always_lock_free 227 { 228 __base::store(__d); 229 return __d; 230 } 231 _LIBCPP_HIDE_FROM_ABI _Tp operator=(_Tp __d) noexcept { 232 __base::store(__d); 233 return __d; 234 } 235 236 _LIBCPP_HIDE_FROM_ABI _Tp fetch_add(_Tp __op, memory_order __m = memory_order_seq_cst) volatile noexcept 237 requires __base::is_always_lock_free 238 { 239 return __fetch_add(*this, __op, __m); 240 } 241 242 _LIBCPP_HIDE_FROM_ABI _Tp fetch_add(_Tp __op, memory_order __m = memory_order_seq_cst) noexcept { 243 return __fetch_add(*this, __op, __m); 244 } 245 246 _LIBCPP_HIDE_FROM_ABI _Tp fetch_sub(_Tp __op, memory_order __m = memory_order_seq_cst) volatile noexcept 247 requires __base::is_always_lock_free 248 { 249 return __fetch_sub(*this, __op, __m); 250 } 251 252 _LIBCPP_HIDE_FROM_ABI _Tp fetch_sub(_Tp __op, memory_order __m = memory_order_seq_cst) noexcept { 253 return __fetch_sub(*this, __op, __m); 254 } 255 256 _LIBCPP_HIDE_FROM_ABI _Tp operator+=(_Tp __op) volatile noexcept 257 requires __base::is_always_lock_free 258 { 259 return fetch_add(__op) + __op; 260 } 261 262 _LIBCPP_HIDE_FROM_ABI _Tp operator+=(_Tp __op) noexcept { return fetch_add(__op) + __op; } 263 264 _LIBCPP_HIDE_FROM_ABI _Tp operator-=(_Tp __op) volatile noexcept 265 requires __base::is_always_lock_free 266 { 267 return fetch_sub(__op) - __op; 268 } 269 270 _LIBCPP_HIDE_FROM_ABI _Tp operator-=(_Tp __op) noexcept { return fetch_sub(__op) - __op; } 271 }; 272 273 #endif // _LIBCPP_STD_VER >= 20 274 275 // atomic_is_lock_free 276 277 template <class _Tp> 278 _LIBCPP_HIDE_FROM_ABI 279 bool 280 atomic_is_lock_free(const volatile atomic<_Tp>* __o) _NOEXCEPT 281 { 282 return __o->is_lock_free(); 283 } 284 285 template <class _Tp> 286 _LIBCPP_HIDE_FROM_ABI 287 bool 288 atomic_is_lock_free(const atomic<_Tp>* __o) _NOEXCEPT 289 { 290 return __o->is_lock_free(); 291 } 292 293 // atomic_init 294 295 template <class _Tp> 296 _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_HIDE_FROM_ABI 297 void 298 atomic_init(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT 299 { 300 std::__cxx_atomic_init(std::addressof(__o->__a_), __d); 301 } 302 303 template <class _Tp> 304 _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_HIDE_FROM_ABI 305 void 306 atomic_init(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT 307 { 308 std::__cxx_atomic_init(std::addressof(__o->__a_), __d); 309 } 310 311 // atomic_store 312 313 template <class _Tp> 314 _LIBCPP_HIDE_FROM_ABI 315 void 316 atomic_store(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT 317 { 318 __o->store(__d); 319 } 320 321 template <class _Tp> 322 _LIBCPP_HIDE_FROM_ABI 323 void 324 atomic_store(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT 325 { 326 __o->store(__d); 327 } 328 329 // atomic_store_explicit 330 331 template <class _Tp> 332 _LIBCPP_HIDE_FROM_ABI 333 void 334 atomic_store_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d, memory_order __m) _NOEXCEPT 335 _LIBCPP_CHECK_STORE_MEMORY_ORDER(__m) 336 { 337 __o->store(__d, __m); 338 } 339 340 template <class _Tp> 341 _LIBCPP_HIDE_FROM_ABI 342 void 343 atomic_store_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d, memory_order __m) _NOEXCEPT 344 _LIBCPP_CHECK_STORE_MEMORY_ORDER(__m) 345 { 346 __o->store(__d, __m); 347 } 348 349 // atomic_load 350 351 template <class _Tp> 352 _LIBCPP_HIDE_FROM_ABI 353 _Tp 354 atomic_load(const volatile atomic<_Tp>* __o) _NOEXCEPT 355 { 356 return __o->load(); 357 } 358 359 template <class _Tp> 360 _LIBCPP_HIDE_FROM_ABI 361 _Tp 362 atomic_load(const atomic<_Tp>* __o) _NOEXCEPT 363 { 364 return __o->load(); 365 } 366 367 // atomic_load_explicit 368 369 template <class _Tp> 370 _LIBCPP_HIDE_FROM_ABI 371 _Tp 372 atomic_load_explicit(const volatile atomic<_Tp>* __o, memory_order __m) _NOEXCEPT 373 _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) 374 { 375 return __o->load(__m); 376 } 377 378 template <class _Tp> 379 _LIBCPP_HIDE_FROM_ABI 380 _Tp 381 atomic_load_explicit(const atomic<_Tp>* __o, memory_order __m) _NOEXCEPT 382 _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) 383 { 384 return __o->load(__m); 385 } 386 387 // atomic_exchange 388 389 template <class _Tp> 390 _LIBCPP_HIDE_FROM_ABI 391 _Tp 392 atomic_exchange(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT 393 { 394 return __o->exchange(__d); 395 } 396 397 template <class _Tp> 398 _LIBCPP_HIDE_FROM_ABI 399 _Tp 400 atomic_exchange(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT 401 { 402 return __o->exchange(__d); 403 } 404 405 // atomic_exchange_explicit 406 407 template <class _Tp> 408 _LIBCPP_HIDE_FROM_ABI 409 _Tp 410 atomic_exchange_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d, memory_order __m) _NOEXCEPT 411 { 412 return __o->exchange(__d, __m); 413 } 414 415 template <class _Tp> 416 _LIBCPP_HIDE_FROM_ABI 417 _Tp 418 atomic_exchange_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d, memory_order __m) _NOEXCEPT 419 { 420 return __o->exchange(__d, __m); 421 } 422 423 // atomic_compare_exchange_weak 424 425 template <class _Tp> 426 _LIBCPP_HIDE_FROM_ABI 427 bool 428 atomic_compare_exchange_weak(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d) _NOEXCEPT 429 { 430 return __o->compare_exchange_weak(*__e, __d); 431 } 432 433 template <class _Tp> 434 _LIBCPP_HIDE_FROM_ABI 435 bool 436 atomic_compare_exchange_weak(atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d) _NOEXCEPT 437 { 438 return __o->compare_exchange_weak(*__e, __d); 439 } 440 441 // atomic_compare_exchange_strong 442 443 template <class _Tp> 444 _LIBCPP_HIDE_FROM_ABI 445 bool 446 atomic_compare_exchange_strong(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d) _NOEXCEPT 447 { 448 return __o->compare_exchange_strong(*__e, __d); 449 } 450 451 template <class _Tp> 452 _LIBCPP_HIDE_FROM_ABI 453 bool 454 atomic_compare_exchange_strong(atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d) _NOEXCEPT 455 { 456 return __o->compare_exchange_strong(*__e, __d); 457 } 458 459 // atomic_compare_exchange_weak_explicit 460 461 template <class _Tp> 462 _LIBCPP_HIDE_FROM_ABI 463 bool 464 atomic_compare_exchange_weak_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, 465 typename atomic<_Tp>::value_type __d, 466 memory_order __s, memory_order __f) _NOEXCEPT 467 _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) 468 { 469 return __o->compare_exchange_weak(*__e, __d, __s, __f); 470 } 471 472 template <class _Tp> 473 _LIBCPP_HIDE_FROM_ABI 474 bool 475 atomic_compare_exchange_weak_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d, 476 memory_order __s, memory_order __f) _NOEXCEPT 477 _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) 478 { 479 return __o->compare_exchange_weak(*__e, __d, __s, __f); 480 } 481 482 // atomic_compare_exchange_strong_explicit 483 484 template <class _Tp> 485 _LIBCPP_HIDE_FROM_ABI 486 bool 487 atomic_compare_exchange_strong_explicit(volatile atomic<_Tp>* __o, 488 typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d, 489 memory_order __s, memory_order __f) _NOEXCEPT 490 _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) 491 { 492 return __o->compare_exchange_strong(*__e, __d, __s, __f); 493 } 494 495 template <class _Tp> 496 _LIBCPP_HIDE_FROM_ABI 497 bool 498 atomic_compare_exchange_strong_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, 499 typename atomic<_Tp>::value_type __d, 500 memory_order __s, memory_order __f) _NOEXCEPT 501 _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) 502 { 503 return __o->compare_exchange_strong(*__e, __d, __s, __f); 504 } 505 506 // atomic_wait 507 508 template <class _Tp> 509 _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI 510 void atomic_wait(const volatile atomic<_Tp>* __o, 511 typename atomic<_Tp>::value_type __v) _NOEXCEPT 512 { 513 return __o->wait(__v); 514 } 515 516 template <class _Tp> 517 _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI 518 void atomic_wait(const atomic<_Tp>* __o, 519 typename atomic<_Tp>::value_type __v) _NOEXCEPT 520 { 521 return __o->wait(__v); 522 } 523 524 // atomic_wait_explicit 525 526 template <class _Tp> 527 _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI 528 void atomic_wait_explicit(const volatile atomic<_Tp>* __o, 529 typename atomic<_Tp>::value_type __v, 530 memory_order __m) _NOEXCEPT 531 _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) 532 { 533 return __o->wait(__v, __m); 534 } 535 536 template <class _Tp> 537 _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI 538 void atomic_wait_explicit(const atomic<_Tp>* __o, 539 typename atomic<_Tp>::value_type __v, 540 memory_order __m) _NOEXCEPT 541 _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) 542 { 543 return __o->wait(__v, __m); 544 } 545 546 // atomic_notify_one 547 548 template <class _Tp> 549 _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI 550 void atomic_notify_one(volatile atomic<_Tp>* __o) _NOEXCEPT 551 { 552 __o->notify_one(); 553 } 554 template <class _Tp> 555 _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI 556 void atomic_notify_one(atomic<_Tp>* __o) _NOEXCEPT 557 { 558 __o->notify_one(); 559 } 560 561 // atomic_notify_all 562 563 template <class _Tp> 564 _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI 565 void atomic_notify_all(volatile atomic<_Tp>* __o) _NOEXCEPT 566 { 567 __o->notify_all(); 568 } 569 template <class _Tp> 570 _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI 571 void atomic_notify_all(atomic<_Tp>* __o) _NOEXCEPT 572 { 573 __o->notify_all(); 574 } 575 576 // atomic_fetch_add 577 578 template <class _Tp> 579 _LIBCPP_HIDE_FROM_ABI 580 _Tp 581 atomic_fetch_add(volatile atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op) _NOEXCEPT 582 { 583 return __o->fetch_add(__op); 584 } 585 586 template <class _Tp> 587 _LIBCPP_HIDE_FROM_ABI 588 _Tp 589 atomic_fetch_add(atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op) _NOEXCEPT 590 { 591 return __o->fetch_add(__op); 592 } 593 594 // atomic_fetch_add_explicit 595 596 template <class _Tp> 597 _LIBCPP_HIDE_FROM_ABI 598 _Tp atomic_fetch_add_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op, memory_order __m) _NOEXCEPT 599 { 600 return __o->fetch_add(__op, __m); 601 } 602 603 template <class _Tp> 604 _LIBCPP_HIDE_FROM_ABI 605 _Tp atomic_fetch_add_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op, memory_order __m) _NOEXCEPT 606 { 607 return __o->fetch_add(__op, __m); 608 } 609 610 // atomic_fetch_sub 611 612 template <class _Tp> 613 _LIBCPP_HIDE_FROM_ABI 614 _Tp atomic_fetch_sub(volatile atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op) _NOEXCEPT 615 { 616 return __o->fetch_sub(__op); 617 } 618 619 template <class _Tp> 620 _LIBCPP_HIDE_FROM_ABI 621 _Tp atomic_fetch_sub(atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op) _NOEXCEPT 622 { 623 return __o->fetch_sub(__op); 624 } 625 626 // atomic_fetch_sub_explicit 627 628 template <class _Tp> 629 _LIBCPP_HIDE_FROM_ABI 630 _Tp atomic_fetch_sub_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op, memory_order __m) _NOEXCEPT 631 { 632 return __o->fetch_sub(__op, __m); 633 } 634 635 template <class _Tp> 636 _LIBCPP_HIDE_FROM_ABI 637 _Tp atomic_fetch_sub_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op, memory_order __m) _NOEXCEPT 638 { 639 return __o->fetch_sub(__op, __m); 640 } 641 642 // atomic_fetch_and 643 644 template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0> 645 _LIBCPP_HIDE_FROM_ABI 646 _Tp 647 atomic_fetch_and(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT 648 { 649 return __o->fetch_and(__op); 650 } 651 652 template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0> 653 _LIBCPP_HIDE_FROM_ABI 654 _Tp 655 atomic_fetch_and(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT 656 { 657 return __o->fetch_and(__op); 658 } 659 660 // atomic_fetch_and_explicit 661 662 template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0> 663 _LIBCPP_HIDE_FROM_ABI 664 _Tp 665 atomic_fetch_and_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT 666 { 667 return __o->fetch_and(__op, __m); 668 } 669 670 template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0> 671 _LIBCPP_HIDE_FROM_ABI 672 _Tp 673 atomic_fetch_and_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT 674 { 675 return __o->fetch_and(__op, __m); 676 } 677 678 // atomic_fetch_or 679 680 template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0> 681 _LIBCPP_HIDE_FROM_ABI 682 _Tp 683 atomic_fetch_or(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT 684 { 685 return __o->fetch_or(__op); 686 } 687 688 template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0> 689 _LIBCPP_HIDE_FROM_ABI 690 _Tp 691 atomic_fetch_or(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT 692 { 693 return __o->fetch_or(__op); 694 } 695 696 // atomic_fetch_or_explicit 697 698 template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0> 699 _LIBCPP_HIDE_FROM_ABI 700 _Tp 701 atomic_fetch_or_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT 702 { 703 return __o->fetch_or(__op, __m); 704 } 705 706 template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0> 707 _LIBCPP_HIDE_FROM_ABI 708 _Tp 709 atomic_fetch_or_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT 710 { 711 return __o->fetch_or(__op, __m); 712 } 713 714 // atomic_fetch_xor 715 716 template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0> 717 _LIBCPP_HIDE_FROM_ABI 718 _Tp 719 atomic_fetch_xor(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT 720 { 721 return __o->fetch_xor(__op); 722 } 723 724 template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0> 725 _LIBCPP_HIDE_FROM_ABI 726 _Tp 727 atomic_fetch_xor(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT 728 { 729 return __o->fetch_xor(__op); 730 } 731 732 // atomic_fetch_xor_explicit 733 734 template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0> 735 _LIBCPP_HIDE_FROM_ABI 736 _Tp 737 atomic_fetch_xor_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT 738 { 739 return __o->fetch_xor(__op, __m); 740 } 741 742 template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0> 743 _LIBCPP_HIDE_FROM_ABI 744 _Tp 745 atomic_fetch_xor_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT 746 { 747 return __o->fetch_xor(__op, __m); 748 } 749 750 _LIBCPP_END_NAMESPACE_STD 751 752 #endif // _LIBCPP___ATOMIC_ATOMIC_H 753