1 // -*- C++ -*- header. 2 3 // Copyright (C) 2008-2024 Free Software Foundation, Inc. 4 // 5 // This file is part of the GNU ISO C++ Library. This library is free 6 // software; you can redistribute it and/or modify it under the 7 // terms of the GNU General Public License as published by the 8 // Free Software Foundation; either version 3, or (at your option) 9 // any later version. 10 11 // This library is distributed in the hope that it will be useful, 12 // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 // GNU General Public License for more details. 15 16 // Under Section 7 of GPL version 3, you are granted additional 17 // permissions described in the GCC Runtime Library Exception, version 18 // 3.1, as published by the Free Software Foundation. 19 20 // You should have received a copy of the GNU General Public License and 21 // a copy of the GCC Runtime Library Exception along with this program; 22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23 // <http://www.gnu.org/licenses/>. 24 25 /** @file include/atomic 26 * This is a Standard C++ Library header. 27 */ 28 29 // Based on "C++ Atomic Types and Operations" by Hans Boehm and Lawrence Crowl. 30 // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2427.html 31 32 #ifndef _GLIBCXX_ATOMIC 33 #define _GLIBCXX_ATOMIC 1 34 35 #pragma GCC system_header 36 37 #if __cplusplus < 201103L 38 # include <bits/c++0x_warning.h> 39 #else 40 41 #define __glibcxx_want_atomic_is_always_lock_free 42 #define __glibcxx_want_atomic_flag_test 43 #define __glibcxx_want_atomic_float 44 #define __glibcxx_want_atomic_ref 45 #define __glibcxx_want_atomic_lock_free_type_aliases 46 #define __glibcxx_want_atomic_value_initialization 47 #define __glibcxx_want_atomic_wait 48 #include <bits/version.h> 49 50 #include <bits/atomic_base.h> 51 52 namespace std _GLIBCXX_VISIBILITY(default) 53 { 54 _GLIBCXX_BEGIN_NAMESPACE_VERSION 55 56 /** 57 * @addtogroup atomics 58 * @{ 59 */ 60 61 template<typename _Tp> 62 struct atomic; 63 64 /// atomic<bool> 65 // NB: No operators or fetch-operations for this type. 66 template<> 67 struct atomic<bool> 68 { 69 using value_type = bool; 70 71 private: 72 __atomic_base<bool> _M_base; 73 74 public: 75 atomic() noexcept = default; 76 ~atomic() noexcept = default; 77 atomic(const atomic&) = delete; 78 atomic& operator=(const atomic&) = delete; 79 atomic& operator=(const atomic&) volatile = delete; 80 81 constexpr atomic(bool __i) noexcept : _M_base(__i) { } 82 83 bool 84 operator=(bool __i) noexcept 85 { return _M_base.operator=(__i); } 86 87 bool 88 operator=(bool __i) volatile noexcept 89 { return _M_base.operator=(__i); } 90 91 operator bool() const noexcept 92 { return _M_base.load(); } 93 94 operator bool() const volatile noexcept 95 { return _M_base.load(); } 96 97 bool 98 is_lock_free() const noexcept { return _M_base.is_lock_free(); } 99 100 bool 101 is_lock_free() const volatile noexcept { return _M_base.is_lock_free(); } 102 103 #ifdef __cpp_lib_atomic_is_always_lock_free // C++ >= 17 104 static constexpr bool is_always_lock_free = ATOMIC_BOOL_LOCK_FREE == 2; 105 #endif 106 107 void 108 store(bool __i, memory_order __m = memory_order_seq_cst) noexcept 109 { _M_base.store(__i, __m); } 110 111 void 112 store(bool __i, memory_order __m = memory_order_seq_cst) volatile noexcept 113 { _M_base.store(__i, __m); } 114 115 bool 116 load(memory_order __m = memory_order_seq_cst) const noexcept 117 { return _M_base.load(__m); } 118 119 bool 120 load(memory_order __m = memory_order_seq_cst) const volatile noexcept 121 { return _M_base.load(__m); } 122 123 bool 124 exchange(bool __i, memory_order __m = memory_order_seq_cst) noexcept 125 { return _M_base.exchange(__i, __m); } 126 127 bool 128 exchange(bool __i, 129 memory_order __m = memory_order_seq_cst) volatile noexcept 130 { return _M_base.exchange(__i, __m); } 131 132 bool 133 compare_exchange_weak(bool& __i1, bool __i2, memory_order __m1, 134 memory_order __m2) noexcept 135 { return _M_base.compare_exchange_weak(__i1, __i2, __m1, __m2); } 136 137 bool 138 compare_exchange_weak(bool& __i1, bool __i2, memory_order __m1, 139 memory_order __m2) volatile noexcept 140 { return _M_base.compare_exchange_weak(__i1, __i2, __m1, __m2); } 141 142 bool 143 compare_exchange_weak(bool& __i1, bool __i2, 144 memory_order __m = memory_order_seq_cst) noexcept 145 { return _M_base.compare_exchange_weak(__i1, __i2, __m); } 146 147 bool 148 compare_exchange_weak(bool& __i1, bool __i2, 149 memory_order __m = memory_order_seq_cst) volatile noexcept 150 { return _M_base.compare_exchange_weak(__i1, __i2, __m); } 151 152 bool 153 compare_exchange_strong(bool& __i1, bool __i2, memory_order __m1, 154 memory_order __m2) noexcept 155 { return _M_base.compare_exchange_strong(__i1, __i2, __m1, __m2); } 156 157 bool 158 compare_exchange_strong(bool& __i1, bool __i2, memory_order __m1, 159 memory_order __m2) volatile noexcept 160 { return _M_base.compare_exchange_strong(__i1, __i2, __m1, __m2); } 161 162 bool 163 compare_exchange_strong(bool& __i1, bool __i2, 164 memory_order __m = memory_order_seq_cst) noexcept 165 { return _M_base.compare_exchange_strong(__i1, __i2, __m); } 166 167 bool 168 compare_exchange_strong(bool& __i1, bool __i2, 169 memory_order __m = memory_order_seq_cst) volatile noexcept 170 { return _M_base.compare_exchange_strong(__i1, __i2, __m); } 171 172 #if __cpp_lib_atomic_wait 173 void 174 wait(bool __old, memory_order __m = memory_order_seq_cst) const noexcept 175 { _M_base.wait(__old, __m); } 176 177 // TODO add const volatile overload 178 179 void 180 notify_one() noexcept 181 { _M_base.notify_one(); } 182 183 void 184 notify_all() noexcept 185 { _M_base.notify_all(); } 186 #endif // __cpp_lib_atomic_wait 187 }; 188 189 /// @cond undocumented 190 #if __cpp_lib_atomic_value_initialization 191 # define _GLIBCXX20_INIT(I) = I 192 #else 193 # define _GLIBCXX20_INIT(I) 194 #endif 195 /// @endcond 196 197 /** 198 * @brief Generic atomic type, primary class template. 199 * 200 * @tparam _Tp Type to be made atomic, must be trivially copyable. 201 */ 202 template<typename _Tp> 203 struct atomic 204 { 205 using value_type = _Tp; 206 207 private: 208 // Align 1/2/4/8/16-byte types to at least their size. 209 static constexpr int _S_min_alignment 210 = (sizeof(_Tp) & (sizeof(_Tp) - 1)) || sizeof(_Tp) > 16 211 ? 0 : sizeof(_Tp); 212 213 static constexpr int _S_alignment 214 = _S_min_alignment > alignof(_Tp) ? _S_min_alignment : alignof(_Tp); 215 216 alignas(_S_alignment) _Tp _M_i _GLIBCXX20_INIT(_Tp()); 217 218 static_assert(__is_trivially_copyable(_Tp), 219 "std::atomic requires a trivially copyable type"); 220 221 static_assert(sizeof(_Tp) > 0, 222 "Incomplete or zero-sized types are not supported"); 223 224 #if __cplusplus > 201703L 225 static_assert(is_copy_constructible_v<_Tp>); 226 static_assert(is_move_constructible_v<_Tp>); 227 static_assert(is_copy_assignable_v<_Tp>); 228 static_assert(is_move_assignable_v<_Tp>); 229 #endif 230 231 public: 232 atomic() = default; 233 ~atomic() noexcept = default; 234 atomic(const atomic&) = delete; 235 atomic& operator=(const atomic&) = delete; 236 atomic& operator=(const atomic&) volatile = delete; 237 238 constexpr atomic(_Tp __i) noexcept : _M_i(__i) 239 { 240 #if __cplusplus >= 201402L && __has_builtin(__builtin_clear_padding) 241 if _GLIBCXX17_CONSTEXPR (__atomic_impl::__maybe_has_padding<_Tp>()) 242 __builtin_clear_padding(std::__addressof(_M_i)); 243 #endif 244 } 245 246 operator _Tp() const noexcept 247 { return load(); } 248 249 operator _Tp() const volatile noexcept 250 { return load(); } 251 252 _Tp 253 operator=(_Tp __i) noexcept 254 { store(__i); return __i; } 255 256 _Tp 257 operator=(_Tp __i) volatile noexcept 258 { store(__i); return __i; } 259 260 bool 261 is_lock_free() const noexcept 262 { 263 // Produce a fake, minimally aligned pointer. 264 return __atomic_is_lock_free(sizeof(_M_i), 265 reinterpret_cast<void *>(-_S_alignment)); 266 } 267 268 bool 269 is_lock_free() const volatile noexcept 270 { 271 // Produce a fake, minimally aligned pointer. 272 return __atomic_is_lock_free(sizeof(_M_i), 273 reinterpret_cast<void *>(-_S_alignment)); 274 } 275 276 #ifdef __cpp_lib_atomic_is_always_lock_free // C++ >= 17 277 static constexpr bool is_always_lock_free 278 = __atomic_always_lock_free(sizeof(_M_i), 0); 279 #endif 280 281 void 282 store(_Tp __i, memory_order __m = memory_order_seq_cst) noexcept 283 { 284 __atomic_store(std::__addressof(_M_i), 285 __atomic_impl::__clear_padding(__i), 286 int(__m)); 287 } 288 289 void 290 store(_Tp __i, memory_order __m = memory_order_seq_cst) volatile noexcept 291 { 292 __atomic_store(std::__addressof(_M_i), 293 __atomic_impl::__clear_padding(__i), 294 int(__m)); 295 } 296 297 _Tp 298 load(memory_order __m = memory_order_seq_cst) const noexcept 299 { 300 alignas(_Tp) unsigned char __buf[sizeof(_Tp)]; 301 _Tp* __ptr = reinterpret_cast<_Tp*>(__buf); 302 __atomic_load(std::__addressof(_M_i), __ptr, int(__m)); 303 return *__ptr; 304 } 305 306 _Tp 307 load(memory_order __m = memory_order_seq_cst) const volatile noexcept 308 { 309 alignas(_Tp) unsigned char __buf[sizeof(_Tp)]; 310 _Tp* __ptr = reinterpret_cast<_Tp*>(__buf); 311 __atomic_load(std::__addressof(_M_i), __ptr, int(__m)); 312 return *__ptr; 313 } 314 315 _Tp 316 exchange(_Tp __i, memory_order __m = memory_order_seq_cst) noexcept 317 { 318 alignas(_Tp) unsigned char __buf[sizeof(_Tp)]; 319 _Tp* __ptr = reinterpret_cast<_Tp*>(__buf); 320 __atomic_exchange(std::__addressof(_M_i), 321 __atomic_impl::__clear_padding(__i), 322 __ptr, int(__m)); 323 return *__ptr; 324 } 325 326 _Tp 327 exchange(_Tp __i, 328 memory_order __m = memory_order_seq_cst) volatile noexcept 329 { 330 alignas(_Tp) unsigned char __buf[sizeof(_Tp)]; 331 _Tp* __ptr = reinterpret_cast<_Tp*>(__buf); 332 __atomic_exchange(std::__addressof(_M_i), 333 __atomic_impl::__clear_padding(__i), 334 __ptr, int(__m)); 335 return *__ptr; 336 } 337 338 bool 339 compare_exchange_weak(_Tp& __e, _Tp __i, memory_order __s, 340 memory_order __f) noexcept 341 { 342 return __atomic_impl::__compare_exchange(_M_i, __e, __i, true, 343 __s, __f); 344 } 345 346 bool 347 compare_exchange_weak(_Tp& __e, _Tp __i, memory_order __s, 348 memory_order __f) volatile noexcept 349 { 350 return __atomic_impl::__compare_exchange(_M_i, __e, __i, true, 351 __s, __f); 352 } 353 354 bool 355 compare_exchange_weak(_Tp& __e, _Tp __i, 356 memory_order __m = memory_order_seq_cst) noexcept 357 { return compare_exchange_weak(__e, __i, __m, 358 __cmpexch_failure_order(__m)); } 359 360 bool 361 compare_exchange_weak(_Tp& __e, _Tp __i, 362 memory_order __m = memory_order_seq_cst) volatile noexcept 363 { return compare_exchange_weak(__e, __i, __m, 364 __cmpexch_failure_order(__m)); } 365 366 bool 367 compare_exchange_strong(_Tp& __e, _Tp __i, memory_order __s, 368 memory_order __f) noexcept 369 { 370 return __atomic_impl::__compare_exchange(_M_i, __e, __i, false, 371 __s, __f); 372 } 373 374 bool 375 compare_exchange_strong(_Tp& __e, _Tp __i, memory_order __s, 376 memory_order __f) volatile noexcept 377 { 378 return __atomic_impl::__compare_exchange(_M_i, __e, __i, false, 379 __s, __f); 380 } 381 382 bool 383 compare_exchange_strong(_Tp& __e, _Tp __i, 384 memory_order __m = memory_order_seq_cst) noexcept 385 { return compare_exchange_strong(__e, __i, __m, 386 __cmpexch_failure_order(__m)); } 387 388 bool 389 compare_exchange_strong(_Tp& __e, _Tp __i, 390 memory_order __m = memory_order_seq_cst) volatile noexcept 391 { return compare_exchange_strong(__e, __i, __m, 392 __cmpexch_failure_order(__m)); } 393 394 #if __cpp_lib_atomic_wait // C++ >= 20 395 void 396 wait(_Tp __old, memory_order __m = memory_order_seq_cst) const noexcept 397 { 398 std::__atomic_wait_address_v(&_M_i, __old, 399 [__m, this] { return this->load(__m); }); 400 } 401 402 // TODO add const volatile overload 403 404 void 405 notify_one() noexcept 406 { std::__atomic_notify_address(&_M_i, false); } 407 408 void 409 notify_all() noexcept 410 { std::__atomic_notify_address(&_M_i, true); } 411 #endif // __cpp_lib_atomic_wait 412 413 }; 414 #undef _GLIBCXX20_INIT 415 416 /// Partial specialization for pointer types. 417 template<typename _Tp> 418 struct atomic<_Tp*> 419 { 420 using value_type = _Tp*; 421 using difference_type = ptrdiff_t; 422 423 typedef _Tp* __pointer_type; 424 typedef __atomic_base<_Tp*> __base_type; 425 __base_type _M_b; 426 427 atomic() noexcept = default; 428 ~atomic() noexcept = default; 429 atomic(const atomic&) = delete; 430 atomic& operator=(const atomic&) = delete; 431 atomic& operator=(const atomic&) volatile = delete; 432 433 constexpr atomic(__pointer_type __p) noexcept : _M_b(__p) { } 434 435 operator __pointer_type() const noexcept 436 { return __pointer_type(_M_b); } 437 438 operator __pointer_type() const volatile noexcept 439 { return __pointer_type(_M_b); } 440 441 __pointer_type 442 operator=(__pointer_type __p) noexcept 443 { return _M_b.operator=(__p); } 444 445 __pointer_type 446 operator=(__pointer_type __p) volatile noexcept 447 { return _M_b.operator=(__p); } 448 449 __pointer_type 450 operator++(int) noexcept 451 { 452 #if __cplusplus >= 201703L 453 static_assert( is_object<_Tp>::value, "pointer to object type" ); 454 #endif 455 return _M_b++; 456 } 457 458 __pointer_type 459 operator++(int) volatile noexcept 460 { 461 #if __cplusplus >= 201703L 462 static_assert( is_object<_Tp>::value, "pointer to object type" ); 463 #endif 464 return _M_b++; 465 } 466 467 __pointer_type 468 operator--(int) noexcept 469 { 470 #if __cplusplus >= 201703L 471 static_assert( is_object<_Tp>::value, "pointer to object type" ); 472 #endif 473 return _M_b--; 474 } 475 476 __pointer_type 477 operator--(int) volatile noexcept 478 { 479 #if __cplusplus >= 201703L 480 static_assert( is_object<_Tp>::value, "pointer to object type" ); 481 #endif 482 return _M_b--; 483 } 484 485 __pointer_type 486 operator++() noexcept 487 { 488 #if __cplusplus >= 201703L 489 static_assert( is_object<_Tp>::value, "pointer to object type" ); 490 #endif 491 return ++_M_b; 492 } 493 494 __pointer_type 495 operator++() volatile noexcept 496 { 497 #if __cplusplus >= 201703L 498 static_assert( is_object<_Tp>::value, "pointer to object type" ); 499 #endif 500 return ++_M_b; 501 } 502 503 __pointer_type 504 operator--() noexcept 505 { 506 #if __cplusplus >= 201703L 507 static_assert( is_object<_Tp>::value, "pointer to object type" ); 508 #endif 509 return --_M_b; 510 } 511 512 __pointer_type 513 operator--() volatile noexcept 514 { 515 #if __cplusplus >= 201703L 516 static_assert( is_object<_Tp>::value, "pointer to object type" ); 517 #endif 518 return --_M_b; 519 } 520 521 __pointer_type 522 operator+=(ptrdiff_t __d) noexcept 523 { 524 #if __cplusplus >= 201703L 525 static_assert( is_object<_Tp>::value, "pointer to object type" ); 526 #endif 527 return _M_b.operator+=(__d); 528 } 529 530 __pointer_type 531 operator+=(ptrdiff_t __d) volatile noexcept 532 { 533 #if __cplusplus >= 201703L 534 static_assert( is_object<_Tp>::value, "pointer to object type" ); 535 #endif 536 return _M_b.operator+=(__d); 537 } 538 539 __pointer_type 540 operator-=(ptrdiff_t __d) noexcept 541 { 542 #if __cplusplus >= 201703L 543 static_assert( is_object<_Tp>::value, "pointer to object type" ); 544 #endif 545 return _M_b.operator-=(__d); 546 } 547 548 __pointer_type 549 operator-=(ptrdiff_t __d) volatile noexcept 550 { 551 #if __cplusplus >= 201703L 552 static_assert( is_object<_Tp>::value, "pointer to object type" ); 553 #endif 554 return _M_b.operator-=(__d); 555 } 556 557 bool 558 is_lock_free() const noexcept 559 { return _M_b.is_lock_free(); } 560 561 bool 562 is_lock_free() const volatile noexcept 563 { return _M_b.is_lock_free(); } 564 565 #ifdef __cpp_lib_atomic_is_always_lock_free // C++ >= 17 566 static constexpr bool is_always_lock_free 567 = ATOMIC_POINTER_LOCK_FREE == 2; 568 #endif 569 570 void 571 store(__pointer_type __p, 572 memory_order __m = memory_order_seq_cst) noexcept 573 { return _M_b.store(__p, __m); } 574 575 void 576 store(__pointer_type __p, 577 memory_order __m = memory_order_seq_cst) volatile noexcept 578 { return _M_b.store(__p, __m); } 579 580 __pointer_type 581 load(memory_order __m = memory_order_seq_cst) const noexcept 582 { return _M_b.load(__m); } 583 584 __pointer_type 585 load(memory_order __m = memory_order_seq_cst) const volatile noexcept 586 { return _M_b.load(__m); } 587 588 __pointer_type 589 exchange(__pointer_type __p, 590 memory_order __m = memory_order_seq_cst) noexcept 591 { return _M_b.exchange(__p, __m); } 592 593 __pointer_type 594 exchange(__pointer_type __p, 595 memory_order __m = memory_order_seq_cst) volatile noexcept 596 { return _M_b.exchange(__p, __m); } 597 598 bool 599 compare_exchange_weak(__pointer_type& __p1, __pointer_type __p2, 600 memory_order __m1, memory_order __m2) noexcept 601 { return _M_b.compare_exchange_weak(__p1, __p2, __m1, __m2); } 602 603 bool 604 compare_exchange_weak(__pointer_type& __p1, __pointer_type __p2, 605 memory_order __m1, 606 memory_order __m2) volatile noexcept 607 { return _M_b.compare_exchange_weak(__p1, __p2, __m1, __m2); } 608 609 bool 610 compare_exchange_weak(__pointer_type& __p1, __pointer_type __p2, 611 memory_order __m = memory_order_seq_cst) noexcept 612 { 613 return compare_exchange_weak(__p1, __p2, __m, 614 __cmpexch_failure_order(__m)); 615 } 616 617 bool 618 compare_exchange_weak(__pointer_type& __p1, __pointer_type __p2, 619 memory_order __m = memory_order_seq_cst) volatile noexcept 620 { 621 return compare_exchange_weak(__p1, __p2, __m, 622 __cmpexch_failure_order(__m)); 623 } 624 625 bool 626 compare_exchange_strong(__pointer_type& __p1, __pointer_type __p2, 627 memory_order __m1, memory_order __m2) noexcept 628 { return _M_b.compare_exchange_strong(__p1, __p2, __m1, __m2); } 629 630 bool 631 compare_exchange_strong(__pointer_type& __p1, __pointer_type __p2, 632 memory_order __m1, 633 memory_order __m2) volatile noexcept 634 { return _M_b.compare_exchange_strong(__p1, __p2, __m1, __m2); } 635 636 bool 637 compare_exchange_strong(__pointer_type& __p1, __pointer_type __p2, 638 memory_order __m = memory_order_seq_cst) noexcept 639 { 640 return _M_b.compare_exchange_strong(__p1, __p2, __m, 641 __cmpexch_failure_order(__m)); 642 } 643 644 bool 645 compare_exchange_strong(__pointer_type& __p1, __pointer_type __p2, 646 memory_order __m = memory_order_seq_cst) volatile noexcept 647 { 648 return _M_b.compare_exchange_strong(__p1, __p2, __m, 649 __cmpexch_failure_order(__m)); 650 } 651 652 #if __cpp_lib_atomic_wait 653 void 654 wait(__pointer_type __old, memory_order __m = memory_order_seq_cst) const noexcept 655 { _M_b.wait(__old, __m); } 656 657 // TODO add const volatile overload 658 659 void 660 notify_one() noexcept 661 { _M_b.notify_one(); } 662 663 void 664 notify_all() noexcept 665 { _M_b.notify_all(); } 666 #endif // __cpp_lib_atomic_wait 667 668 __pointer_type 669 fetch_add(ptrdiff_t __d, 670 memory_order __m = memory_order_seq_cst) noexcept 671 { 672 #if __cplusplus >= 201703L 673 static_assert( is_object<_Tp>::value, "pointer to object type" ); 674 #endif 675 return _M_b.fetch_add(__d, __m); 676 } 677 678 __pointer_type 679 fetch_add(ptrdiff_t __d, 680 memory_order __m = memory_order_seq_cst) volatile noexcept 681 { 682 #if __cplusplus >= 201703L 683 static_assert( is_object<_Tp>::value, "pointer to object type" ); 684 #endif 685 return _M_b.fetch_add(__d, __m); 686 } 687 688 __pointer_type 689 fetch_sub(ptrdiff_t __d, 690 memory_order __m = memory_order_seq_cst) noexcept 691 { 692 #if __cplusplus >= 201703L 693 static_assert( is_object<_Tp>::value, "pointer to object type" ); 694 #endif 695 return _M_b.fetch_sub(__d, __m); 696 } 697 698 __pointer_type 699 fetch_sub(ptrdiff_t __d, 700 memory_order __m = memory_order_seq_cst) volatile noexcept 701 { 702 #if __cplusplus >= 201703L 703 static_assert( is_object<_Tp>::value, "pointer to object type" ); 704 #endif 705 return _M_b.fetch_sub(__d, __m); 706 } 707 }; 708 709 710 /// Explicit specialization for char. 711 template<> 712 struct atomic<char> : __atomic_base<char> 713 { 714 typedef char __integral_type; 715 typedef __atomic_base<char> __base_type; 716 717 atomic() noexcept = default; 718 ~atomic() noexcept = default; 719 atomic(const atomic&) = delete; 720 atomic& operator=(const atomic&) = delete; 721 atomic& operator=(const atomic&) volatile = delete; 722 723 constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } 724 725 using __base_type::operator __integral_type; 726 using __base_type::operator=; 727 728 #ifdef __cpp_lib_atomic_is_always_lock_free // C++ >= 17 729 static constexpr bool is_always_lock_free = ATOMIC_CHAR_LOCK_FREE == 2; 730 #endif 731 }; 732 733 /// Explicit specialization for signed char. 734 template<> 735 struct atomic<signed char> : __atomic_base<signed char> 736 { 737 typedef signed char __integral_type; 738 typedef __atomic_base<signed char> __base_type; 739 740 atomic() noexcept= default; 741 ~atomic() noexcept = default; 742 atomic(const atomic&) = delete; 743 atomic& operator=(const atomic&) = delete; 744 atomic& operator=(const atomic&) volatile = delete; 745 746 constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } 747 748 using __base_type::operator __integral_type; 749 using __base_type::operator=; 750 751 #ifdef __cpp_lib_atomic_is_always_lock_free // C++ >= 17 752 static constexpr bool is_always_lock_free = ATOMIC_CHAR_LOCK_FREE == 2; 753 #endif 754 }; 755 756 /// Explicit specialization for unsigned char. 757 template<> 758 struct atomic<unsigned char> : __atomic_base<unsigned char> 759 { 760 typedef unsigned char __integral_type; 761 typedef __atomic_base<unsigned char> __base_type; 762 763 atomic() noexcept= default; 764 ~atomic() noexcept = default; 765 atomic(const atomic&) = delete; 766 atomic& operator=(const atomic&) = delete; 767 atomic& operator=(const atomic&) volatile = delete; 768 769 constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } 770 771 using __base_type::operator __integral_type; 772 using __base_type::operator=; 773 774 #ifdef __cpp_lib_atomic_is_always_lock_free // C++ >= 17 775 static constexpr bool is_always_lock_free = ATOMIC_CHAR_LOCK_FREE == 2; 776 #endif 777 }; 778 779 /// Explicit specialization for short. 780 template<> 781 struct atomic<short> : __atomic_base<short> 782 { 783 typedef short __integral_type; 784 typedef __atomic_base<short> __base_type; 785 786 atomic() noexcept = default; 787 ~atomic() noexcept = default; 788 atomic(const atomic&) = delete; 789 atomic& operator=(const atomic&) = delete; 790 atomic& operator=(const atomic&) volatile = delete; 791 792 constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } 793 794 using __base_type::operator __integral_type; 795 using __base_type::operator=; 796 797 #ifdef __cpp_lib_atomic_is_always_lock_free // C++ >= 17 798 static constexpr bool is_always_lock_free = ATOMIC_SHORT_LOCK_FREE == 2; 799 #endif 800 }; 801 802 /// Explicit specialization for unsigned short. 803 template<> 804 struct atomic<unsigned short> : __atomic_base<unsigned short> 805 { 806 typedef unsigned short __integral_type; 807 typedef __atomic_base<unsigned short> __base_type; 808 809 atomic() noexcept = default; 810 ~atomic() noexcept = default; 811 atomic(const atomic&) = delete; 812 atomic& operator=(const atomic&) = delete; 813 atomic& operator=(const atomic&) volatile = delete; 814 815 constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } 816 817 using __base_type::operator __integral_type; 818 using __base_type::operator=; 819 820 #ifdef __cpp_lib_atomic_is_always_lock_free // C++ >= 17 821 static constexpr bool is_always_lock_free = ATOMIC_SHORT_LOCK_FREE == 2; 822 #endif 823 }; 824 825 /// Explicit specialization for int. 826 template<> 827 struct atomic<int> : __atomic_base<int> 828 { 829 typedef int __integral_type; 830 typedef __atomic_base<int> __base_type; 831 832 atomic() noexcept = default; 833 ~atomic() noexcept = default; 834 atomic(const atomic&) = delete; 835 atomic& operator=(const atomic&) = delete; 836 atomic& operator=(const atomic&) volatile = delete; 837 838 constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } 839 840 using __base_type::operator __integral_type; 841 using __base_type::operator=; 842 843 #ifdef __cpp_lib_atomic_is_always_lock_free // C++ >= 17 844 static constexpr bool is_always_lock_free = ATOMIC_INT_LOCK_FREE == 2; 845 #endif 846 }; 847 848 /// Explicit specialization for unsigned int. 849 template<> 850 struct atomic<unsigned int> : __atomic_base<unsigned int> 851 { 852 typedef unsigned int __integral_type; 853 typedef __atomic_base<unsigned int> __base_type; 854 855 atomic() noexcept = default; 856 ~atomic() noexcept = default; 857 atomic(const atomic&) = delete; 858 atomic& operator=(const atomic&) = delete; 859 atomic& operator=(const atomic&) volatile = delete; 860 861 constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } 862 863 using __base_type::operator __integral_type; 864 using __base_type::operator=; 865 866 #ifdef __cpp_lib_atomic_is_always_lock_free // C++ >= 17 867 static constexpr bool is_always_lock_free = ATOMIC_INT_LOCK_FREE == 2; 868 #endif 869 }; 870 871 /// Explicit specialization for long. 872 template<> 873 struct atomic<long> : __atomic_base<long> 874 { 875 typedef long __integral_type; 876 typedef __atomic_base<long> __base_type; 877 878 atomic() noexcept = default; 879 ~atomic() noexcept = default; 880 atomic(const atomic&) = delete; 881 atomic& operator=(const atomic&) = delete; 882 atomic& operator=(const atomic&) volatile = delete; 883 884 constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } 885 886 using __base_type::operator __integral_type; 887 using __base_type::operator=; 888 889 #ifdef __cpp_lib_atomic_is_always_lock_free // C++ >= 17 890 static constexpr bool is_always_lock_free = ATOMIC_LONG_LOCK_FREE == 2; 891 #endif 892 }; 893 894 /// Explicit specialization for unsigned long. 895 template<> 896 struct atomic<unsigned long> : __atomic_base<unsigned long> 897 { 898 typedef unsigned long __integral_type; 899 typedef __atomic_base<unsigned long> __base_type; 900 901 atomic() noexcept = default; 902 ~atomic() noexcept = default; 903 atomic(const atomic&) = delete; 904 atomic& operator=(const atomic&) = delete; 905 atomic& operator=(const atomic&) volatile = delete; 906 907 constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } 908 909 using __base_type::operator __integral_type; 910 using __base_type::operator=; 911 912 #ifdef __cpp_lib_atomic_is_always_lock_free // C++ >= 17 913 static constexpr bool is_always_lock_free = ATOMIC_LONG_LOCK_FREE == 2; 914 #endif 915 }; 916 917 /// Explicit specialization for long long. 918 template<> 919 struct atomic<long long> : __atomic_base<long long> 920 { 921 typedef long long __integral_type; 922 typedef __atomic_base<long long> __base_type; 923 924 atomic() noexcept = default; 925 ~atomic() noexcept = default; 926 atomic(const atomic&) = delete; 927 atomic& operator=(const atomic&) = delete; 928 atomic& operator=(const atomic&) volatile = delete; 929 930 constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } 931 932 using __base_type::operator __integral_type; 933 using __base_type::operator=; 934 935 #ifdef __cpp_lib_atomic_is_always_lock_free // C++ >= 17 936 static constexpr bool is_always_lock_free = ATOMIC_LLONG_LOCK_FREE == 2; 937 #endif 938 }; 939 940 /// Explicit specialization for unsigned long long. 941 template<> 942 struct atomic<unsigned long long> : __atomic_base<unsigned long long> 943 { 944 typedef unsigned long long __integral_type; 945 typedef __atomic_base<unsigned long long> __base_type; 946 947 atomic() noexcept = default; 948 ~atomic() noexcept = default; 949 atomic(const atomic&) = delete; 950 atomic& operator=(const atomic&) = delete; 951 atomic& operator=(const atomic&) volatile = delete; 952 953 constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } 954 955 using __base_type::operator __integral_type; 956 using __base_type::operator=; 957 958 #ifdef __cpp_lib_atomic_is_always_lock_free // C++ >= 17 959 static constexpr bool is_always_lock_free = ATOMIC_LLONG_LOCK_FREE == 2; 960 #endif 961 }; 962 963 /// Explicit specialization for wchar_t. 964 template<> 965 struct atomic<wchar_t> : __atomic_base<wchar_t> 966 { 967 typedef wchar_t __integral_type; 968 typedef __atomic_base<wchar_t> __base_type; 969 970 atomic() noexcept = default; 971 ~atomic() noexcept = default; 972 atomic(const atomic&) = delete; 973 atomic& operator=(const atomic&) = delete; 974 atomic& operator=(const atomic&) volatile = delete; 975 976 constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } 977 978 using __base_type::operator __integral_type; 979 using __base_type::operator=; 980 981 #ifdef __cpp_lib_atomic_is_always_lock_free // C++ >= 17 982 static constexpr bool is_always_lock_free = ATOMIC_WCHAR_T_LOCK_FREE == 2; 983 #endif 984 }; 985 986 #ifdef _GLIBCXX_USE_CHAR8_T 987 /// Explicit specialization for char8_t. 988 template<> 989 struct atomic<char8_t> : __atomic_base<char8_t> 990 { 991 typedef char8_t __integral_type; 992 typedef __atomic_base<char8_t> __base_type; 993 994 atomic() noexcept = default; 995 ~atomic() noexcept = default; 996 atomic(const atomic&) = delete; 997 atomic& operator=(const atomic&) = delete; 998 atomic& operator=(const atomic&) volatile = delete; 999 1000 constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } 1001 1002 using __base_type::operator __integral_type; 1003 using __base_type::operator=; 1004 1005 #ifdef __cpp_lib_atomic_is_always_lock_free // C++ >= 17 1006 static constexpr bool is_always_lock_free 1007 = ATOMIC_CHAR8_T_LOCK_FREE == 2; 1008 #endif 1009 }; 1010 #endif 1011 1012 /// Explicit specialization for char16_t. 1013 template<> 1014 struct atomic<char16_t> : __atomic_base<char16_t> 1015 { 1016 typedef char16_t __integral_type; 1017 typedef __atomic_base<char16_t> __base_type; 1018 1019 atomic() noexcept = default; 1020 ~atomic() noexcept = default; 1021 atomic(const atomic&) = delete; 1022 atomic& operator=(const atomic&) = delete; 1023 atomic& operator=(const atomic&) volatile = delete; 1024 1025 constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } 1026 1027 using __base_type::operator __integral_type; 1028 using __base_type::operator=; 1029 1030 #ifdef __cpp_lib_atomic_is_always_lock_free // C++ >= 17 1031 static constexpr bool is_always_lock_free 1032 = ATOMIC_CHAR16_T_LOCK_FREE == 2; 1033 #endif 1034 }; 1035 1036 /// Explicit specialization for char32_t. 1037 template<> 1038 struct atomic<char32_t> : __atomic_base<char32_t> 1039 { 1040 typedef char32_t __integral_type; 1041 typedef __atomic_base<char32_t> __base_type; 1042 1043 atomic() noexcept = default; 1044 ~atomic() noexcept = default; 1045 atomic(const atomic&) = delete; 1046 atomic& operator=(const atomic&) = delete; 1047 atomic& operator=(const atomic&) volatile = delete; 1048 1049 constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } 1050 1051 using __base_type::operator __integral_type; 1052 using __base_type::operator=; 1053 1054 #ifdef __cpp_lib_atomic_is_always_lock_free // C++ >= 17 1055 static constexpr bool is_always_lock_free 1056 = ATOMIC_CHAR32_T_LOCK_FREE == 2; 1057 #endif 1058 }; 1059 1060 1061 /// atomic_bool 1062 typedef atomic<bool> atomic_bool; 1063 1064 /// atomic_char 1065 typedef atomic<char> atomic_char; 1066 1067 /// atomic_schar 1068 typedef atomic<signed char> atomic_schar; 1069 1070 /// atomic_uchar 1071 typedef atomic<unsigned char> atomic_uchar; 1072 1073 /// atomic_short 1074 typedef atomic<short> atomic_short; 1075 1076 /// atomic_ushort 1077 typedef atomic<unsigned short> atomic_ushort; 1078 1079 /// atomic_int 1080 typedef atomic<int> atomic_int; 1081 1082 /// atomic_uint 1083 typedef atomic<unsigned int> atomic_uint; 1084 1085 /// atomic_long 1086 typedef atomic<long> atomic_long; 1087 1088 /// atomic_ulong 1089 typedef atomic<unsigned long> atomic_ulong; 1090 1091 /// atomic_llong 1092 typedef atomic<long long> atomic_llong; 1093 1094 /// atomic_ullong 1095 typedef atomic<unsigned long long> atomic_ullong; 1096 1097 /// atomic_wchar_t 1098 typedef atomic<wchar_t> atomic_wchar_t; 1099 1100 #ifdef _GLIBCXX_USE_CHAR8_T 1101 /// atomic_char8_t 1102 typedef atomic<char8_t> atomic_char8_t; 1103 #endif 1104 1105 /// atomic_char16_t 1106 typedef atomic<char16_t> atomic_char16_t; 1107 1108 /// atomic_char32_t 1109 typedef atomic<char32_t> atomic_char32_t; 1110 1111 #ifdef _GLIBCXX_USE_C99_STDINT 1112 // _GLIBCXX_RESOLVE_LIB_DEFECTS 1113 // 2441. Exact-width atomic typedefs should be provided 1114 1115 /// atomic_int8_t 1116 typedef atomic<int8_t> atomic_int8_t; 1117 1118 /// atomic_uint8_t 1119 typedef atomic<uint8_t> atomic_uint8_t; 1120 1121 /// atomic_int16_t 1122 typedef atomic<int16_t> atomic_int16_t; 1123 1124 /// atomic_uint16_t 1125 typedef atomic<uint16_t> atomic_uint16_t; 1126 1127 /// atomic_int32_t 1128 typedef atomic<int32_t> atomic_int32_t; 1129 1130 /// atomic_uint32_t 1131 typedef atomic<uint32_t> atomic_uint32_t; 1132 1133 /// atomic_int64_t 1134 typedef atomic<int64_t> atomic_int64_t; 1135 1136 /// atomic_uint64_t 1137 typedef atomic<uint64_t> atomic_uint64_t; 1138 #endif 1139 1140 /// atomic_int_least8_t 1141 typedef atomic<int_least8_t> atomic_int_least8_t; 1142 1143 /// atomic_uint_least8_t 1144 typedef atomic<uint_least8_t> atomic_uint_least8_t; 1145 1146 /// atomic_int_least16_t 1147 typedef atomic<int_least16_t> atomic_int_least16_t; 1148 1149 /// atomic_uint_least16_t 1150 typedef atomic<uint_least16_t> atomic_uint_least16_t; 1151 1152 /// atomic_int_least32_t 1153 typedef atomic<int_least32_t> atomic_int_least32_t; 1154 1155 /// atomic_uint_least32_t 1156 typedef atomic<uint_least32_t> atomic_uint_least32_t; 1157 1158 /// atomic_int_least64_t 1159 typedef atomic<int_least64_t> atomic_int_least64_t; 1160 1161 /// atomic_uint_least64_t 1162 typedef atomic<uint_least64_t> atomic_uint_least64_t; 1163 1164 1165 /// atomic_int_fast8_t 1166 typedef atomic<int_fast8_t> atomic_int_fast8_t; 1167 1168 /// atomic_uint_fast8_t 1169 typedef atomic<uint_fast8_t> atomic_uint_fast8_t; 1170 1171 /// atomic_int_fast16_t 1172 typedef atomic<int_fast16_t> atomic_int_fast16_t; 1173 1174 /// atomic_uint_fast16_t 1175 typedef atomic<uint_fast16_t> atomic_uint_fast16_t; 1176 1177 /// atomic_int_fast32_t 1178 typedef atomic<int_fast32_t> atomic_int_fast32_t; 1179 1180 /// atomic_uint_fast32_t 1181 typedef atomic<uint_fast32_t> atomic_uint_fast32_t; 1182 1183 /// atomic_int_fast64_t 1184 typedef atomic<int_fast64_t> atomic_int_fast64_t; 1185 1186 /// atomic_uint_fast64_t 1187 typedef atomic<uint_fast64_t> atomic_uint_fast64_t; 1188 1189 1190 /// atomic_intptr_t 1191 typedef atomic<intptr_t> atomic_intptr_t; 1192 1193 /// atomic_uintptr_t 1194 typedef atomic<uintptr_t> atomic_uintptr_t; 1195 1196 /// atomic_size_t 1197 typedef atomic<size_t> atomic_size_t; 1198 1199 /// atomic_ptrdiff_t 1200 typedef atomic<ptrdiff_t> atomic_ptrdiff_t; 1201 1202 /// atomic_intmax_t 1203 typedef atomic<intmax_t> atomic_intmax_t; 1204 1205 /// atomic_uintmax_t 1206 typedef atomic<uintmax_t> atomic_uintmax_t; 1207 1208 // Function definitions, atomic_flag operations. 1209 inline bool 1210 atomic_flag_test_and_set_explicit(atomic_flag* __a, 1211 memory_order __m) noexcept 1212 { return __a->test_and_set(__m); } 1213 1214 inline bool 1215 atomic_flag_test_and_set_explicit(volatile atomic_flag* __a, 1216 memory_order __m) noexcept 1217 { return __a->test_and_set(__m); } 1218 1219 #if __cpp_lib_atomic_flag_test 1220 inline bool 1221 atomic_flag_test(const atomic_flag* __a) noexcept 1222 { return __a->test(); } 1223 1224 inline bool 1225 atomic_flag_test(const volatile atomic_flag* __a) noexcept 1226 { return __a->test(); } 1227 1228 inline bool 1229 atomic_flag_test_explicit(const atomic_flag* __a, 1230 memory_order __m) noexcept 1231 { return __a->test(__m); } 1232 1233 inline bool 1234 atomic_flag_test_explicit(const volatile atomic_flag* __a, 1235 memory_order __m) noexcept 1236 { return __a->test(__m); } 1237 #endif 1238 1239 inline void 1240 atomic_flag_clear_explicit(atomic_flag* __a, memory_order __m) noexcept 1241 { __a->clear(__m); } 1242 1243 inline void 1244 atomic_flag_clear_explicit(volatile atomic_flag* __a, 1245 memory_order __m) noexcept 1246 { __a->clear(__m); } 1247 1248 inline bool 1249 atomic_flag_test_and_set(atomic_flag* __a) noexcept 1250 { return atomic_flag_test_and_set_explicit(__a, memory_order_seq_cst); } 1251 1252 inline bool 1253 atomic_flag_test_and_set(volatile atomic_flag* __a) noexcept 1254 { return atomic_flag_test_and_set_explicit(__a, memory_order_seq_cst); } 1255 1256 inline void 1257 atomic_flag_clear(atomic_flag* __a) noexcept 1258 { atomic_flag_clear_explicit(__a, memory_order_seq_cst); } 1259 1260 inline void 1261 atomic_flag_clear(volatile atomic_flag* __a) noexcept 1262 { atomic_flag_clear_explicit(__a, memory_order_seq_cst); } 1263 1264 #if __cpp_lib_atomic_wait 1265 inline void 1266 atomic_flag_wait(atomic_flag* __a, bool __old) noexcept 1267 { __a->wait(__old); } 1268 1269 inline void 1270 atomic_flag_wait_explicit(atomic_flag* __a, bool __old, 1271 memory_order __m) noexcept 1272 { __a->wait(__old, __m); } 1273 1274 inline void 1275 atomic_flag_notify_one(atomic_flag* __a) noexcept 1276 { __a->notify_one(); } 1277 1278 inline void 1279 atomic_flag_notify_all(atomic_flag* __a) noexcept 1280 { __a->notify_all(); } 1281 #endif // __cpp_lib_atomic_wait 1282 1283 /// @cond undocumented 1284 // _GLIBCXX_RESOLVE_LIB_DEFECTS 1285 // 3220. P0558 broke conforming C++14 uses of atomic shared_ptr 1286 template<typename _Tp> 1287 using __atomic_val_t = __type_identity_t<_Tp>; 1288 template<typename _Tp> 1289 using __atomic_diff_t = typename atomic<_Tp>::difference_type; 1290 /// @endcond 1291 1292 // [atomics.nonmembers] Non-member functions. 1293 // Function templates generally applicable to atomic types. 1294 template<typename _ITp> 1295 inline bool 1296 atomic_is_lock_free(const atomic<_ITp>* __a) noexcept 1297 { return __a->is_lock_free(); } 1298 1299 template<typename _ITp> 1300 inline bool 1301 atomic_is_lock_free(const volatile atomic<_ITp>* __a) noexcept 1302 { return __a->is_lock_free(); } 1303 1304 template<typename _ITp> 1305 inline void 1306 atomic_init(atomic<_ITp>* __a, __atomic_val_t<_ITp> __i) noexcept 1307 { __a->store(__i, memory_order_relaxed); } 1308 1309 template<typename _ITp> 1310 inline void 1311 atomic_init(volatile atomic<_ITp>* __a, __atomic_val_t<_ITp> __i) noexcept 1312 { __a->store(__i, memory_order_relaxed); } 1313 1314 template<typename _ITp> 1315 inline void 1316 atomic_store_explicit(atomic<_ITp>* __a, __atomic_val_t<_ITp> __i, 1317 memory_order __m) noexcept 1318 { __a->store(__i, __m); } 1319 1320 template<typename _ITp> 1321 inline void 1322 atomic_store_explicit(volatile atomic<_ITp>* __a, __atomic_val_t<_ITp> __i, 1323 memory_order __m) noexcept 1324 { __a->store(__i, __m); } 1325 1326 template<typename _ITp> 1327 inline _ITp 1328 atomic_load_explicit(const atomic<_ITp>* __a, memory_order __m) noexcept 1329 { return __a->load(__m); } 1330 1331 template<typename _ITp> 1332 inline _ITp 1333 atomic_load_explicit(const volatile atomic<_ITp>* __a, 1334 memory_order __m) noexcept 1335 { return __a->load(__m); } 1336 1337 template<typename _ITp> 1338 inline _ITp 1339 atomic_exchange_explicit(atomic<_ITp>* __a, __atomic_val_t<_ITp> __i, 1340 memory_order __m) noexcept 1341 { return __a->exchange(__i, __m); } 1342 1343 template<typename _ITp> 1344 inline _ITp 1345 atomic_exchange_explicit(volatile atomic<_ITp>* __a, 1346 __atomic_val_t<_ITp> __i, 1347 memory_order __m) noexcept 1348 { return __a->exchange(__i, __m); } 1349 1350 template<typename _ITp> 1351 inline bool 1352 atomic_compare_exchange_weak_explicit(atomic<_ITp>* __a, 1353 __atomic_val_t<_ITp>* __i1, 1354 __atomic_val_t<_ITp> __i2, 1355 memory_order __m1, 1356 memory_order __m2) noexcept 1357 { return __a->compare_exchange_weak(*__i1, __i2, __m1, __m2); } 1358 1359 template<typename _ITp> 1360 inline bool 1361 atomic_compare_exchange_weak_explicit(volatile atomic<_ITp>* __a, 1362 __atomic_val_t<_ITp>* __i1, 1363 __atomic_val_t<_ITp> __i2, 1364 memory_order __m1, 1365 memory_order __m2) noexcept 1366 { return __a->compare_exchange_weak(*__i1, __i2, __m1, __m2); } 1367 1368 template<typename _ITp> 1369 inline bool 1370 atomic_compare_exchange_strong_explicit(atomic<_ITp>* __a, 1371 __atomic_val_t<_ITp>* __i1, 1372 __atomic_val_t<_ITp> __i2, 1373 memory_order __m1, 1374 memory_order __m2) noexcept 1375 { return __a->compare_exchange_strong(*__i1, __i2, __m1, __m2); } 1376 1377 template<typename _ITp> 1378 inline bool 1379 atomic_compare_exchange_strong_explicit(volatile atomic<_ITp>* __a, 1380 __atomic_val_t<_ITp>* __i1, 1381 __atomic_val_t<_ITp> __i2, 1382 memory_order __m1, 1383 memory_order __m2) noexcept 1384 { return __a->compare_exchange_strong(*__i1, __i2, __m1, __m2); } 1385 1386 1387 template<typename _ITp> 1388 inline void 1389 atomic_store(atomic<_ITp>* __a, __atomic_val_t<_ITp> __i) noexcept 1390 { atomic_store_explicit(__a, __i, memory_order_seq_cst); } 1391 1392 template<typename _ITp> 1393 inline void 1394 atomic_store(volatile atomic<_ITp>* __a, __atomic_val_t<_ITp> __i) noexcept 1395 { atomic_store_explicit(__a, __i, memory_order_seq_cst); } 1396 1397 template<typename _ITp> 1398 inline _ITp 1399 atomic_load(const atomic<_ITp>* __a) noexcept 1400 { return atomic_load_explicit(__a, memory_order_seq_cst); } 1401 1402 template<typename _ITp> 1403 inline _ITp 1404 atomic_load(const volatile atomic<_ITp>* __a) noexcept 1405 { return atomic_load_explicit(__a, memory_order_seq_cst); } 1406 1407 template<typename _ITp> 1408 inline _ITp 1409 atomic_exchange(atomic<_ITp>* __a, __atomic_val_t<_ITp> __i) noexcept 1410 { return atomic_exchange_explicit(__a, __i, memory_order_seq_cst); } 1411 1412 template<typename _ITp> 1413 inline _ITp 1414 atomic_exchange(volatile atomic<_ITp>* __a, 1415 __atomic_val_t<_ITp> __i) noexcept 1416 { return atomic_exchange_explicit(__a, __i, memory_order_seq_cst); } 1417 1418 template<typename _ITp> 1419 inline bool 1420 atomic_compare_exchange_weak(atomic<_ITp>* __a, 1421 __atomic_val_t<_ITp>* __i1, 1422 __atomic_val_t<_ITp> __i2) noexcept 1423 { 1424 return atomic_compare_exchange_weak_explicit(__a, __i1, __i2, 1425 memory_order_seq_cst, 1426 memory_order_seq_cst); 1427 } 1428 1429 template<typename _ITp> 1430 inline bool 1431 atomic_compare_exchange_weak(volatile atomic<_ITp>* __a, 1432 __atomic_val_t<_ITp>* __i1, 1433 __atomic_val_t<_ITp> __i2) noexcept 1434 { 1435 return atomic_compare_exchange_weak_explicit(__a, __i1, __i2, 1436 memory_order_seq_cst, 1437 memory_order_seq_cst); 1438 } 1439 1440 template<typename _ITp> 1441 inline bool 1442 atomic_compare_exchange_strong(atomic<_ITp>* __a, 1443 __atomic_val_t<_ITp>* __i1, 1444 __atomic_val_t<_ITp> __i2) noexcept 1445 { 1446 return atomic_compare_exchange_strong_explicit(__a, __i1, __i2, 1447 memory_order_seq_cst, 1448 memory_order_seq_cst); 1449 } 1450 1451 template<typename _ITp> 1452 inline bool 1453 atomic_compare_exchange_strong(volatile atomic<_ITp>* __a, 1454 __atomic_val_t<_ITp>* __i1, 1455 __atomic_val_t<_ITp> __i2) noexcept 1456 { 1457 return atomic_compare_exchange_strong_explicit(__a, __i1, __i2, 1458 memory_order_seq_cst, 1459 memory_order_seq_cst); 1460 } 1461 1462 1463 #if __cpp_lib_atomic_wait 1464 template<typename _Tp> 1465 inline void 1466 atomic_wait(const atomic<_Tp>* __a, 1467 typename std::atomic<_Tp>::value_type __old) noexcept 1468 { __a->wait(__old); } 1469 1470 template<typename _Tp> 1471 inline void 1472 atomic_wait_explicit(const atomic<_Tp>* __a, 1473 typename std::atomic<_Tp>::value_type __old, 1474 std::memory_order __m) noexcept 1475 { __a->wait(__old, __m); } 1476 1477 template<typename _Tp> 1478 inline void 1479 atomic_notify_one(atomic<_Tp>* __a) noexcept 1480 { __a->notify_one(); } 1481 1482 template<typename _Tp> 1483 inline void 1484 atomic_notify_all(atomic<_Tp>* __a) noexcept 1485 { __a->notify_all(); } 1486 #endif // __cpp_lib_atomic_wait 1487 1488 // Function templates for atomic_integral and atomic_pointer operations only. 1489 // Some operations (and, or, xor) are only available for atomic integrals, 1490 // which is implemented by taking a parameter of type __atomic_base<_ITp>*. 1491 1492 template<typename _ITp> 1493 inline _ITp 1494 atomic_fetch_add_explicit(atomic<_ITp>* __a, 1495 __atomic_diff_t<_ITp> __i, 1496 memory_order __m) noexcept 1497 { return __a->fetch_add(__i, __m); } 1498 1499 template<typename _ITp> 1500 inline _ITp 1501 atomic_fetch_add_explicit(volatile atomic<_ITp>* __a, 1502 __atomic_diff_t<_ITp> __i, 1503 memory_order __m) noexcept 1504 { return __a->fetch_add(__i, __m); } 1505 1506 template<typename _ITp> 1507 inline _ITp 1508 atomic_fetch_sub_explicit(atomic<_ITp>* __a, 1509 __atomic_diff_t<_ITp> __i, 1510 memory_order __m) noexcept 1511 { return __a->fetch_sub(__i, __m); } 1512 1513 template<typename _ITp> 1514 inline _ITp 1515 atomic_fetch_sub_explicit(volatile atomic<_ITp>* __a, 1516 __atomic_diff_t<_ITp> __i, 1517 memory_order __m) noexcept 1518 { return __a->fetch_sub(__i, __m); } 1519 1520 template<typename _ITp> 1521 inline _ITp 1522 atomic_fetch_and_explicit(__atomic_base<_ITp>* __a, 1523 __atomic_val_t<_ITp> __i, 1524 memory_order __m) noexcept 1525 { return __a->fetch_and(__i, __m); } 1526 1527 template<typename _ITp> 1528 inline _ITp 1529 atomic_fetch_and_explicit(volatile __atomic_base<_ITp>* __a, 1530 __atomic_val_t<_ITp> __i, 1531 memory_order __m) noexcept 1532 { return __a->fetch_and(__i, __m); } 1533 1534 template<typename _ITp> 1535 inline _ITp 1536 atomic_fetch_or_explicit(__atomic_base<_ITp>* __a, 1537 __atomic_val_t<_ITp> __i, 1538 memory_order __m) noexcept 1539 { return __a->fetch_or(__i, __m); } 1540 1541 template<typename _ITp> 1542 inline _ITp 1543 atomic_fetch_or_explicit(volatile __atomic_base<_ITp>* __a, 1544 __atomic_val_t<_ITp> __i, 1545 memory_order __m) noexcept 1546 { return __a->fetch_or(__i, __m); } 1547 1548 template<typename _ITp> 1549 inline _ITp 1550 atomic_fetch_xor_explicit(__atomic_base<_ITp>* __a, 1551 __atomic_val_t<_ITp> __i, 1552 memory_order __m) noexcept 1553 { return __a->fetch_xor(__i, __m); } 1554 1555 template<typename _ITp> 1556 inline _ITp 1557 atomic_fetch_xor_explicit(volatile __atomic_base<_ITp>* __a, 1558 __atomic_val_t<_ITp> __i, 1559 memory_order __m) noexcept 1560 { return __a->fetch_xor(__i, __m); } 1561 1562 template<typename _ITp> 1563 inline _ITp 1564 atomic_fetch_add(atomic<_ITp>* __a, 1565 __atomic_diff_t<_ITp> __i) noexcept 1566 { return atomic_fetch_add_explicit(__a, __i, memory_order_seq_cst); } 1567 1568 template<typename _ITp> 1569 inline _ITp 1570 atomic_fetch_add(volatile atomic<_ITp>* __a, 1571 __atomic_diff_t<_ITp> __i) noexcept 1572 { return atomic_fetch_add_explicit(__a, __i, memory_order_seq_cst); } 1573 1574 template<typename _ITp> 1575 inline _ITp 1576 atomic_fetch_sub(atomic<_ITp>* __a, 1577 __atomic_diff_t<_ITp> __i) noexcept 1578 { return atomic_fetch_sub_explicit(__a, __i, memory_order_seq_cst); } 1579 1580 template<typename _ITp> 1581 inline _ITp 1582 atomic_fetch_sub(volatile atomic<_ITp>* __a, 1583 __atomic_diff_t<_ITp> __i) noexcept 1584 { return atomic_fetch_sub_explicit(__a, __i, memory_order_seq_cst); } 1585 1586 template<typename _ITp> 1587 inline _ITp 1588 atomic_fetch_and(__atomic_base<_ITp>* __a, 1589 __atomic_val_t<_ITp> __i) noexcept 1590 { return atomic_fetch_and_explicit(__a, __i, memory_order_seq_cst); } 1591 1592 template<typename _ITp> 1593 inline _ITp 1594 atomic_fetch_and(volatile __atomic_base<_ITp>* __a, 1595 __atomic_val_t<_ITp> __i) noexcept 1596 { return atomic_fetch_and_explicit(__a, __i, memory_order_seq_cst); } 1597 1598 template<typename _ITp> 1599 inline _ITp 1600 atomic_fetch_or(__atomic_base<_ITp>* __a, 1601 __atomic_val_t<_ITp> __i) noexcept 1602 { return atomic_fetch_or_explicit(__a, __i, memory_order_seq_cst); } 1603 1604 template<typename _ITp> 1605 inline _ITp 1606 atomic_fetch_or(volatile __atomic_base<_ITp>* __a, 1607 __atomic_val_t<_ITp> __i) noexcept 1608 { return atomic_fetch_or_explicit(__a, __i, memory_order_seq_cst); } 1609 1610 template<typename _ITp> 1611 inline _ITp 1612 atomic_fetch_xor(__atomic_base<_ITp>* __a, 1613 __atomic_val_t<_ITp> __i) noexcept 1614 { return atomic_fetch_xor_explicit(__a, __i, memory_order_seq_cst); } 1615 1616 template<typename _ITp> 1617 inline _ITp 1618 atomic_fetch_xor(volatile __atomic_base<_ITp>* __a, 1619 __atomic_val_t<_ITp> __i) noexcept 1620 { return atomic_fetch_xor_explicit(__a, __i, memory_order_seq_cst); } 1621 1622 #ifdef __cpp_lib_atomic_float 1623 template<> 1624 struct atomic<float> : __atomic_float<float> 1625 { 1626 atomic() noexcept = default; 1627 1628 constexpr 1629 atomic(float __fp) noexcept : __atomic_float<float>(__fp) 1630 { } 1631 1632 atomic& operator=(const atomic&) volatile = delete; 1633 atomic& operator=(const atomic&) = delete; 1634 1635 using __atomic_float<float>::operator=; 1636 }; 1637 1638 template<> 1639 struct atomic<double> : __atomic_float<double> 1640 { 1641 atomic() noexcept = default; 1642 1643 constexpr 1644 atomic(double __fp) noexcept : __atomic_float<double>(__fp) 1645 { } 1646 1647 atomic& operator=(const atomic&) volatile = delete; 1648 atomic& operator=(const atomic&) = delete; 1649 1650 using __atomic_float<double>::operator=; 1651 }; 1652 1653 template<> 1654 struct atomic<long double> : __atomic_float<long double> 1655 { 1656 atomic() noexcept = default; 1657 1658 constexpr 1659 atomic(long double __fp) noexcept : __atomic_float<long double>(__fp) 1660 { } 1661 1662 atomic& operator=(const atomic&) volatile = delete; 1663 atomic& operator=(const atomic&) = delete; 1664 1665 using __atomic_float<long double>::operator=; 1666 }; 1667 1668 #ifdef __STDCPP_FLOAT16_T__ 1669 template<> 1670 struct atomic<_Float16> : __atomic_float<_Float16> 1671 { 1672 atomic() noexcept = default; 1673 1674 constexpr 1675 atomic(_Float16 __fp) noexcept : __atomic_float<_Float16>(__fp) 1676 { } 1677 1678 atomic& operator=(const atomic&) volatile = delete; 1679 atomic& operator=(const atomic&) = delete; 1680 1681 using __atomic_float<_Float16>::operator=; 1682 }; 1683 #endif 1684 1685 #ifdef __STDCPP_FLOAT32_T__ 1686 template<> 1687 struct atomic<_Float32> : __atomic_float<_Float32> 1688 { 1689 atomic() noexcept = default; 1690 1691 constexpr 1692 atomic(_Float32 __fp) noexcept : __atomic_float<_Float32>(__fp) 1693 { } 1694 1695 atomic& operator=(const atomic&) volatile = delete; 1696 atomic& operator=(const atomic&) = delete; 1697 1698 using __atomic_float<_Float32>::operator=; 1699 }; 1700 #endif 1701 1702 #ifdef __STDCPP_FLOAT64_T__ 1703 template<> 1704 struct atomic<_Float64> : __atomic_float<_Float64> 1705 { 1706 atomic() noexcept = default; 1707 1708 constexpr 1709 atomic(_Float64 __fp) noexcept : __atomic_float<_Float64>(__fp) 1710 { } 1711 1712 atomic& operator=(const atomic&) volatile = delete; 1713 atomic& operator=(const atomic&) = delete; 1714 1715 using __atomic_float<_Float64>::operator=; 1716 }; 1717 #endif 1718 1719 #ifdef __STDCPP_FLOAT128_T__ 1720 template<> 1721 struct atomic<_Float128> : __atomic_float<_Float128> 1722 { 1723 atomic() noexcept = default; 1724 1725 constexpr 1726 atomic(_Float128 __fp) noexcept : __atomic_float<_Float128>(__fp) 1727 { } 1728 1729 atomic& operator=(const atomic&) volatile = delete; 1730 atomic& operator=(const atomic&) = delete; 1731 1732 using __atomic_float<_Float128>::operator=; 1733 }; 1734 #endif 1735 1736 #ifdef __STDCPP_BFLOAT16_T__ 1737 template<> 1738 struct atomic<__gnu_cxx::__bfloat16_t> : __atomic_float<__gnu_cxx::__bfloat16_t> 1739 { 1740 atomic() noexcept = default; 1741 1742 constexpr 1743 atomic(__gnu_cxx::__bfloat16_t __fp) noexcept : __atomic_float<__gnu_cxx::__bfloat16_t>(__fp) 1744 { } 1745 1746 atomic& operator=(const atomic&) volatile = delete; 1747 atomic& operator=(const atomic&) = delete; 1748 1749 using __atomic_float<__gnu_cxx::__bfloat16_t>::operator=; 1750 }; 1751 #endif 1752 #endif // __cpp_lib_atomic_float 1753 1754 #ifdef __cpp_lib_atomic_ref 1755 /// Class template to provide atomic operations on a non-atomic variable. 1756 template<typename _Tp> 1757 struct atomic_ref : __atomic_ref<_Tp> 1758 { 1759 explicit 1760 atomic_ref(_Tp& __t) noexcept : __atomic_ref<_Tp>(__t) 1761 { } 1762 1763 atomic_ref& operator=(const atomic_ref&) = delete; 1764 1765 atomic_ref(const atomic_ref&) = default; 1766 1767 using __atomic_ref<_Tp>::operator=; 1768 }; 1769 #endif // __cpp_lib_atomic_ref 1770 1771 #ifdef __cpp_lib_atomic_lock_free_type_aliases 1772 # ifdef _GLIBCXX_HAVE_PLATFORM_WAIT 1773 using atomic_signed_lock_free 1774 = atomic<make_signed_t<__detail::__platform_wait_t>>; 1775 using atomic_unsigned_lock_free 1776 = atomic<make_unsigned_t<__detail::__platform_wait_t>>; 1777 # elif ATOMIC_INT_LOCK_FREE == 2 1778 using atomic_signed_lock_free = atomic<signed int>; 1779 using atomic_unsigned_lock_free = atomic<unsigned int>; 1780 # elif ATOMIC_LONG_LOCK_FREE == 2 1781 using atomic_signed_lock_free = atomic<signed long>; 1782 using atomic_unsigned_lock_free = atomic<unsigned long>; 1783 # elif ATOMIC_CHAR_LOCK_FREE == 2 1784 using atomic_signed_lock_free = atomic<signed char>; 1785 using atomic_unsigned_lock_free = atomic<unsigned char>; 1786 # else 1787 # error "libstdc++ bug: no lock-free atomics but they were emitted in <version>" 1788 # endif 1789 #endif 1790 1791 /// @} group atomics 1792 1793 _GLIBCXX_END_NAMESPACE_VERSION 1794 } // namespace 1795 1796 #endif // C++11 1797 1798 #endif // _GLIBCXX_ATOMIC 1799