Where Online Learning is simpler!
The C and C++ Include Header Files
/usr/include/c++/13/bits/atomic_base.h
$ cat -n /usr/include/c++/13/bits/atomic_base.h 1 // -*- C++ -*- header. 2 3 // Copyright (C) 2008-2023 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 //
. 24 25 /** @file bits/atomic_base.h 26 * This is an internal header file, included by other library headers. 27 * Do not attempt to use it directly. @headername{atomic} 28 */ 29 30 #ifndef _GLIBCXX_ATOMIC_BASE_H 31 #define _GLIBCXX_ATOMIC_BASE_H 1 32 33 #pragma GCC system_header 34 35 #include
36 #include
// For placement new 37 #include
38 #include
39 #include
40 41 #if __cplusplus > 201703L && _GLIBCXX_HOSTED 42 #include
43 #endif 44 45 #ifndef _GLIBCXX_ALWAYS_INLINE 46 #define _GLIBCXX_ALWAYS_INLINE inline __attribute__((__always_inline__)) 47 #endif 48 49 namespace std _GLIBCXX_VISIBILITY(default) 50 { 51 _GLIBCXX_BEGIN_NAMESPACE_VERSION 52 53 /** 54 * @defgroup atomics Atomics 55 * 56 * Components for performing atomic operations. 57 * @{ 58 */ 59 60 /// Enumeration for memory_order 61 #if __cplusplus > 201703L 62 enum class memory_order : int 63 { 64 relaxed, 65 consume, 66 acquire, 67 release, 68 acq_rel, 69 seq_cst 70 }; 71 72 inline constexpr memory_order memory_order_relaxed = memory_order::relaxed; 73 inline constexpr memory_order memory_order_consume = memory_order::consume; 74 inline constexpr memory_order memory_order_acquire = memory_order::acquire; 75 inline constexpr memory_order memory_order_release = memory_order::release; 76 inline constexpr memory_order memory_order_acq_rel = memory_order::acq_rel; 77 inline constexpr memory_order memory_order_seq_cst = memory_order::seq_cst; 78 #else 79 typedef enum memory_order 80 { 81 memory_order_relaxed, 82 memory_order_consume, 83 memory_order_acquire, 84 memory_order_release, 85 memory_order_acq_rel, 86 memory_order_seq_cst 87 } memory_order; 88 #endif 89 90 /// @cond undocumented 91 enum __memory_order_modifier 92 { 93 __memory_order_mask = 0x0ffff, 94 __memory_order_modifier_mask = 0xffff0000, 95 __memory_order_hle_acquire = 0x10000, 96 __memory_order_hle_release = 0x20000 97 }; 98 /// @endcond 99 100 constexpr memory_order 101 operator|(memory_order __m, __memory_order_modifier __mod) 102 { 103 return memory_order(int(__m) | int(__mod)); 104 } 105 106 constexpr memory_order 107 operator&(memory_order __m, __memory_order_modifier __mod) 108 { 109 return memory_order(int(__m) & int(__mod)); 110 } 111 112 /// @cond undocumented 113 114 // Drop release ordering as per [atomics.types.operations.req]/21 115 constexpr memory_order 116 __cmpexch_failure_order2(memory_order __m) noexcept 117 { 118 return __m == memory_order_acq_rel ? memory_order_acquire 119 : __m == memory_order_release ? memory_order_relaxed : __m; 120 } 121 122 constexpr memory_order 123 __cmpexch_failure_order(memory_order __m) noexcept 124 { 125 return memory_order(__cmpexch_failure_order2(__m & __memory_order_mask) 126 | __memory_order_modifier(__m & __memory_order_modifier_mask)); 127 } 128 129 constexpr bool 130 __is_valid_cmpexch_failure_order(memory_order __m) noexcept 131 { 132 return (__m & __memory_order_mask) != memory_order_release 133 && (__m & __memory_order_mask) != memory_order_acq_rel; 134 } 135 136 // Base types for atomics. 137 template
138 struct __atomic_base; 139 140 /// @endcond 141 142 _GLIBCXX_ALWAYS_INLINE void 143 atomic_thread_fence(memory_order __m) noexcept 144 { __atomic_thread_fence(int(__m)); } 145 146 _GLIBCXX_ALWAYS_INLINE void 147 atomic_signal_fence(memory_order __m) noexcept 148 { __atomic_signal_fence(int(__m)); } 149 150 /// kill_dependency 151 template
152 inline _Tp 153 kill_dependency(_Tp __y) noexcept 154 { 155 _Tp __ret(__y); 156 return __ret; 157 } 158 159 #if __cplusplus >= 202002L 160 # define __cpp_lib_atomic_value_initialization 201911L 161 #endif 162 163 /// @cond undocumented 164 #if __cpp_lib_atomic_value_initialization 165 # define _GLIBCXX20_INIT(I) = I 166 #else 167 # define _GLIBCXX20_INIT(I) 168 #endif 169 /// @endcond 170 171 #define ATOMIC_VAR_INIT(_VI) { _VI } 172 173 template
174 struct atomic; 175 176 template
177 struct atomic<_Tp*>; 178 179 /* The target's "set" value for test-and-set may not be exactly 1. */ 180 #if __GCC_ATOMIC_TEST_AND_SET_TRUEVAL == 1 181 typedef bool __atomic_flag_data_type; 182 #else 183 typedef unsigned char __atomic_flag_data_type; 184 #endif 185 186 /// @cond undocumented 187 188 /* 189 * Base type for atomic_flag. 190 * 191 * Base type is POD with data, allowing atomic_flag to derive from 192 * it and meet the standard layout type requirement. In addition to 193 * compatibility with a C interface, this allows different 194 * implementations of atomic_flag to use the same atomic operation 195 * functions, via a standard conversion to the __atomic_flag_base 196 * argument. 197 */ 198 _GLIBCXX_BEGIN_EXTERN_C 199 200 struct __atomic_flag_base 201 { 202 __atomic_flag_data_type _M_i _GLIBCXX20_INIT({}); 203 }; 204 205 _GLIBCXX_END_EXTERN_C 206 207 /// @endcond 208 209 #define ATOMIC_FLAG_INIT { 0 } 210 211 /// atomic_flag 212 struct atomic_flag : public __atomic_flag_base 213 { 214 atomic_flag() noexcept = default; 215 ~atomic_flag() noexcept = default; 216 atomic_flag(const atomic_flag&) = delete; 217 atomic_flag& operator=(const atomic_flag&) = delete; 218 atomic_flag& operator=(const atomic_flag&) volatile = delete; 219 220 // Conversion to ATOMIC_FLAG_INIT. 221 constexpr atomic_flag(bool __i) noexcept 222 : __atomic_flag_base{ _S_init(__i) } 223 { } 224 225 _GLIBCXX_ALWAYS_INLINE bool 226 test_and_set(memory_order __m = memory_order_seq_cst) noexcept 227 { 228 return __atomic_test_and_set (&_M_i, int(__m)); 229 } 230 231 _GLIBCXX_ALWAYS_INLINE bool 232 test_and_set(memory_order __m = memory_order_seq_cst) volatile noexcept 233 { 234 return __atomic_test_and_set (&_M_i, int(__m)); 235 } 236 237 #if __cplusplus > 201703L 238 #define __cpp_lib_atomic_flag_test 201907L 239 240 _GLIBCXX_ALWAYS_INLINE bool 241 test(memory_order __m = memory_order_seq_cst) const noexcept 242 { 243 __atomic_flag_data_type __v; 244 __atomic_load(&_M_i, &__v, int(__m)); 245 return __v == __GCC_ATOMIC_TEST_AND_SET_TRUEVAL; 246 } 247 248 _GLIBCXX_ALWAYS_INLINE bool 249 test(memory_order __m = memory_order_seq_cst) const volatile noexcept 250 { 251 __atomic_flag_data_type __v; 252 __atomic_load(&_M_i, &__v, int(__m)); 253 return __v == __GCC_ATOMIC_TEST_AND_SET_TRUEVAL; 254 } 255 256 #if __cpp_lib_atomic_wait 257 _GLIBCXX_ALWAYS_INLINE void 258 wait(bool __old, 259 memory_order __m = memory_order_seq_cst) const noexcept 260 { 261 const __atomic_flag_data_type __v 262 = __old ? __GCC_ATOMIC_TEST_AND_SET_TRUEVAL : 0; 263 264 std::__atomic_wait_address_v(&_M_i, __v, 265 [__m, this] { return __atomic_load_n(&_M_i, int(__m)); }); 266 } 267 268 // TODO add const volatile overload 269 270 _GLIBCXX_ALWAYS_INLINE void 271 notify_one() noexcept 272 { std::__atomic_notify_address(&_M_i, false); } 273 274 // TODO add const volatile overload 275 276 _GLIBCXX_ALWAYS_INLINE void 277 notify_all() noexcept 278 { std::__atomic_notify_address(&_M_i, true); } 279 280 // TODO add const volatile overload 281 #endif // __cpp_lib_atomic_wait 282 #endif // C++20 283 284 _GLIBCXX_ALWAYS_INLINE void 285 clear(memory_order __m = memory_order_seq_cst) noexcept 286 { 287 memory_order __b __attribute__ ((__unused__)) 288 = __m & __memory_order_mask; 289 __glibcxx_assert(__b != memory_order_consume); 290 __glibcxx_assert(__b != memory_order_acquire); 291 __glibcxx_assert(__b != memory_order_acq_rel); 292 293 __atomic_clear (&_M_i, int(__m)); 294 } 295 296 _GLIBCXX_ALWAYS_INLINE void 297 clear(memory_order __m = memory_order_seq_cst) volatile noexcept 298 { 299 memory_order __b __attribute__ ((__unused__)) 300 = __m & __memory_order_mask; 301 __glibcxx_assert(__b != memory_order_consume); 302 __glibcxx_assert(__b != memory_order_acquire); 303 __glibcxx_assert(__b != memory_order_acq_rel); 304 305 __atomic_clear (&_M_i, int(__m)); 306 } 307 308 private: 309 static constexpr __atomic_flag_data_type 310 _S_init(bool __i) 311 { return __i ? __GCC_ATOMIC_TEST_AND_SET_TRUEVAL : 0; } 312 }; 313 314 /// @cond undocumented 315 316 /// Base class for atomic integrals. 317 // 318 // For each of the integral types, define atomic_[integral type] struct 319 // 320 // atomic_bool bool 321 // atomic_char char 322 // atomic_schar signed char 323 // atomic_uchar unsigned char 324 // atomic_short short 325 // atomic_ushort unsigned short 326 // atomic_int int 327 // atomic_uint unsigned int 328 // atomic_long long 329 // atomic_ulong unsigned long 330 // atomic_llong long long 331 // atomic_ullong unsigned long long 332 // atomic_char8_t char8_t 333 // atomic_char16_t char16_t 334 // atomic_char32_t char32_t 335 // atomic_wchar_t wchar_t 336 // 337 // NB: Assuming _ITp is an integral scalar type that is 1, 2, 4, or 338 // 8 bytes, since that is what GCC built-in functions for atomic 339 // memory access expect. 340 template
341 struct __atomic_base 342 { 343 using value_type = _ITp; 344 using difference_type = value_type; 345 346 private: 347 typedef _ITp __int_type; 348 349 static constexpr int _S_alignment = 350 sizeof(_ITp) > alignof(_ITp) ? sizeof(_ITp) : alignof(_ITp); 351 352 alignas(_S_alignment) __int_type _M_i _GLIBCXX20_INIT(0); 353 354 public: 355 __atomic_base() noexcept = default; 356 ~__atomic_base() noexcept = default; 357 __atomic_base(const __atomic_base&) = delete; 358 __atomic_base& operator=(const __atomic_base&) = delete; 359 __atomic_base& operator=(const __atomic_base&) volatile = delete; 360 361 // Requires __int_type convertible to _M_i. 362 constexpr __atomic_base(__int_type __i) noexcept : _M_i (__i) { } 363 364 operator __int_type() const noexcept 365 { return load(); } 366 367 operator __int_type() const volatile noexcept 368 { return load(); } 369 370 __int_type 371 operator=(__int_type __i) noexcept 372 { 373 store(__i); 374 return __i; 375 } 376 377 __int_type 378 operator=(__int_type __i) volatile noexcept 379 { 380 store(__i); 381 return __i; 382 } 383 384 __int_type 385 operator++(int) noexcept 386 { return fetch_add(1); } 387 388 __int_type 389 operator++(int) volatile noexcept 390 { return fetch_add(1); } 391 392 __int_type 393 operator--(int) noexcept 394 { return fetch_sub(1); } 395 396 __int_type 397 operator--(int) volatile noexcept 398 { return fetch_sub(1); } 399 400 __int_type 401 operator++() noexcept 402 { return __atomic_add_fetch(&_M_i, 1, int(memory_order_seq_cst)); } 403 404 __int_type 405 operator++() volatile noexcept 406 { return __atomic_add_fetch(&_M_i, 1, int(memory_order_seq_cst)); } 407 408 __int_type 409 operator--() noexcept 410 { return __atomic_sub_fetch(&_M_i, 1, int(memory_order_seq_cst)); } 411 412 __int_type 413 operator--() volatile noexcept 414 { return __atomic_sub_fetch(&_M_i, 1, int(memory_order_seq_cst)); } 415 416 __int_type 417 operator+=(__int_type __i) noexcept 418 { return __atomic_add_fetch(&_M_i, __i, int(memory_order_seq_cst)); } 419 420 __int_type 421 operator+=(__int_type __i) volatile noexcept 422 { return __atomic_add_fetch(&_M_i, __i, int(memory_order_seq_cst)); } 423 424 __int_type 425 operator-=(__int_type __i) noexcept 426 { return __atomic_sub_fetch(&_M_i, __i, int(memory_order_seq_cst)); } 427 428 __int_type 429 operator-=(__int_type __i) volatile noexcept 430 { return __atomic_sub_fetch(&_M_i, __i, int(memory_order_seq_cst)); } 431 432 __int_type 433 operator&=(__int_type __i) noexcept 434 { return __atomic_and_fetch(&_M_i, __i, int(memory_order_seq_cst)); } 435 436 __int_type 437 operator&=(__int_type __i) volatile noexcept 438 { return __atomic_and_fetch(&_M_i, __i, int(memory_order_seq_cst)); } 439 440 __int_type 441 operator|=(__int_type __i) noexcept 442 { return __atomic_or_fetch(&_M_i, __i, int(memory_order_seq_cst)); } 443 444 __int_type 445 operator|=(__int_type __i) volatile noexcept 446 { return __atomic_or_fetch(&_M_i, __i, int(memory_order_seq_cst)); } 447 448 __int_type 449 operator^=(__int_type __i) noexcept 450 { return __atomic_xor_fetch(&_M_i, __i, int(memory_order_seq_cst)); } 451 452 __int_type 453 operator^=(__int_type __i) volatile noexcept 454 { return __atomic_xor_fetch(&_M_i, __i, int(memory_order_seq_cst)); } 455 456 bool 457 is_lock_free() const noexcept 458 { 459 // Use a fake, minimally aligned pointer. 460 return __atomic_is_lock_free(sizeof(_M_i), 461 reinterpret_cast
(-_S_alignment)); 462 } 463 464 bool 465 is_lock_free() const volatile noexcept 466 { 467 // Use a fake, minimally aligned pointer. 468 return __atomic_is_lock_free(sizeof(_M_i), 469 reinterpret_cast
(-_S_alignment)); 470 } 471 472 _GLIBCXX_ALWAYS_INLINE void 473 store(__int_type __i, memory_order __m = memory_order_seq_cst) noexcept 474 { 475 memory_order __b __attribute__ ((__unused__)) 476 = __m & __memory_order_mask; 477 __glibcxx_assert(__b != memory_order_acquire); 478 __glibcxx_assert(__b != memory_order_acq_rel); 479 __glibcxx_assert(__b != memory_order_consume); 480 481 __atomic_store_n(&_M_i, __i, int(__m)); 482 } 483 484 _GLIBCXX_ALWAYS_INLINE void 485 store(__int_type __i, 486 memory_order __m = memory_order_seq_cst) volatile noexcept 487 { 488 memory_order __b __attribute__ ((__unused__)) 489 = __m & __memory_order_mask; 490 __glibcxx_assert(__b != memory_order_acquire); 491 __glibcxx_assert(__b != memory_order_acq_rel); 492 __glibcxx_assert(__b != memory_order_consume); 493 494 __atomic_store_n(&_M_i, __i, int(__m)); 495 } 496 497 _GLIBCXX_ALWAYS_INLINE __int_type 498 load(memory_order __m = memory_order_seq_cst) const noexcept 499 { 500 memory_order __b __attribute__ ((__unused__)) 501 = __m & __memory_order_mask; 502 __glibcxx_assert(__b != memory_order_release); 503 __glibcxx_assert(__b != memory_order_acq_rel); 504 505 return __atomic_load_n(&_M_i, int(__m)); 506 } 507 508 _GLIBCXX_ALWAYS_INLINE __int_type 509 load(memory_order __m = memory_order_seq_cst) const volatile noexcept 510 { 511 memory_order __b __attribute__ ((__unused__)) 512 = __m & __memory_order_mask; 513 __glibcxx_assert(__b != memory_order_release); 514 __glibcxx_assert(__b != memory_order_acq_rel); 515 516 return __atomic_load_n(&_M_i, int(__m)); 517 } 518 519 _GLIBCXX_ALWAYS_INLINE __int_type 520 exchange(__int_type __i, 521 memory_order __m = memory_order_seq_cst) noexcept 522 { 523 return __atomic_exchange_n(&_M_i, __i, int(__m)); 524 } 525 526 527 _GLIBCXX_ALWAYS_INLINE __int_type 528 exchange(__int_type __i, 529 memory_order __m = memory_order_seq_cst) volatile noexcept 530 { 531 return __atomic_exchange_n(&_M_i, __i, int(__m)); 532 } 533 534 _GLIBCXX_ALWAYS_INLINE bool 535 compare_exchange_weak(__int_type& __i1, __int_type __i2, 536 memory_order __m1, memory_order __m2) noexcept 537 { 538 __glibcxx_assert(__is_valid_cmpexch_failure_order(__m2)); 539 540 return __atomic_compare_exchange_n(&_M_i, &__i1, __i2, 1, 541 int(__m1), int(__m2)); 542 } 543 544 _GLIBCXX_ALWAYS_INLINE bool 545 compare_exchange_weak(__int_type& __i1, __int_type __i2, 546 memory_order __m1, 547 memory_order __m2) volatile noexcept 548 { 549 __glibcxx_assert(__is_valid_cmpexch_failure_order(__m2)); 550 551 return __atomic_compare_exchange_n(&_M_i, &__i1, __i2, 1, 552 int(__m1), int(__m2)); 553 } 554 555 _GLIBCXX_ALWAYS_INLINE bool 556 compare_exchange_weak(__int_type& __i1, __int_type __i2, 557 memory_order __m = memory_order_seq_cst) noexcept 558 { 559 return compare_exchange_weak(__i1, __i2, __m, 560 __cmpexch_failure_order(__m)); 561 } 562 563 _GLIBCXX_ALWAYS_INLINE bool 564 compare_exchange_weak(__int_type& __i1, __int_type __i2, 565 memory_order __m = memory_order_seq_cst) volatile noexcept 566 { 567 return compare_exchange_weak(__i1, __i2, __m, 568 __cmpexch_failure_order(__m)); 569 } 570 571 _GLIBCXX_ALWAYS_INLINE bool 572 compare_exchange_strong(__int_type& __i1, __int_type __i2, 573 memory_order __m1, memory_order __m2) noexcept 574 { 575 __glibcxx_assert(__is_valid_cmpexch_failure_order(__m2)); 576 577 return __atomic_compare_exchange_n(&_M_i, &__i1, __i2, 0, 578 int(__m1), int(__m2)); 579 } 580 581 _GLIBCXX_ALWAYS_INLINE bool 582 compare_exchange_strong(__int_type& __i1, __int_type __i2, 583 memory_order __m1, 584 memory_order __m2) volatile noexcept 585 { 586 __glibcxx_assert(__is_valid_cmpexch_failure_order(__m2)); 587 588 return __atomic_compare_exchange_n(&_M_i, &__i1, __i2, 0, 589 int(__m1), int(__m2)); 590 } 591 592 _GLIBCXX_ALWAYS_INLINE bool 593 compare_exchange_strong(__int_type& __i1, __int_type __i2, 594 memory_order __m = memory_order_seq_cst) noexcept 595 { 596 return compare_exchange_strong(__i1, __i2, __m, 597 __cmpexch_failure_order(__m)); 598 } 599 600 _GLIBCXX_ALWAYS_INLINE bool 601 compare_exchange_strong(__int_type& __i1, __int_type __i2, 602 memory_order __m = memory_order_seq_cst) volatile noexcept 603 { 604 return compare_exchange_strong(__i1, __i2, __m, 605 __cmpexch_failure_order(__m)); 606 } 607 608 #if __cpp_lib_atomic_wait 609 _GLIBCXX_ALWAYS_INLINE void 610 wait(__int_type __old, 611 memory_order __m = memory_order_seq_cst) const noexcept 612 { 613 std::__atomic_wait_address_v(&_M_i, __old, 614 [__m, this] { return this->load(__m); }); 615 } 616 617 // TODO add const volatile overload 618 619 _GLIBCXX_ALWAYS_INLINE void 620 notify_one() noexcept 621 { std::__atomic_notify_address(&_M_i, false); } 622 623 // TODO add const volatile overload 624 625 _GLIBCXX_ALWAYS_INLINE void 626 notify_all() noexcept 627 { std::__atomic_notify_address(&_M_i, true); } 628 629 // TODO add const volatile overload 630 #endif // __cpp_lib_atomic_wait 631 632 _GLIBCXX_ALWAYS_INLINE __int_type 633 fetch_add(__int_type __i, 634 memory_order __m = memory_order_seq_cst) noexcept 635 { return __atomic_fetch_add(&_M_i, __i, int(__m)); } 636 637 _GLIBCXX_ALWAYS_INLINE __int_type 638 fetch_add(__int_type __i, 639 memory_order __m = memory_order_seq_cst) volatile noexcept 640 { return __atomic_fetch_add(&_M_i, __i, int(__m)); } 641 642 _GLIBCXX_ALWAYS_INLINE __int_type 643 fetch_sub(__int_type __i, 644 memory_order __m = memory_order_seq_cst) noexcept 645 { return __atomic_fetch_sub(&_M_i, __i, int(__m)); } 646 647 _GLIBCXX_ALWAYS_INLINE __int_type 648 fetch_sub(__int_type __i, 649 memory_order __m = memory_order_seq_cst) volatile noexcept 650 { return __atomic_fetch_sub(&_M_i, __i, int(__m)); } 651 652 _GLIBCXX_ALWAYS_INLINE __int_type 653 fetch_and(__int_type __i, 654 memory_order __m = memory_order_seq_cst) noexcept 655 { return __atomic_fetch_and(&_M_i, __i, int(__m)); } 656 657 _GLIBCXX_ALWAYS_INLINE __int_type 658 fetch_and(__int_type __i, 659 memory_order __m = memory_order_seq_cst) volatile noexcept 660 { return __atomic_fetch_and(&_M_i, __i, int(__m)); } 661 662 _GLIBCXX_ALWAYS_INLINE __int_type 663 fetch_or(__int_type __i, 664 memory_order __m = memory_order_seq_cst) noexcept 665 { return __atomic_fetch_or(&_M_i, __i, int(__m)); } 666 667 _GLIBCXX_ALWAYS_INLINE __int_type 668 fetch_or(__int_type __i, 669 memory_order __m = memory_order_seq_cst) volatile noexcept 670 { return __atomic_fetch_or(&_M_i, __i, int(__m)); } 671 672 _GLIBCXX_ALWAYS_INLINE __int_type 673 fetch_xor(__int_type __i, 674 memory_order __m = memory_order_seq_cst) noexcept 675 { return __atomic_fetch_xor(&_M_i, __i, int(__m)); } 676 677 _GLIBCXX_ALWAYS_INLINE __int_type 678 fetch_xor(__int_type __i, 679 memory_order __m = memory_order_seq_cst) volatile noexcept 680 { return __atomic_fetch_xor(&_M_i, __i, int(__m)); } 681 }; 682 683 684 /// Partial specialization for pointer types. 685 template
686 struct __atomic_base<_PTp*> 687 { 688 private: 689 typedef _PTp* __pointer_type; 690 691 __pointer_type _M_p _GLIBCXX20_INIT(nullptr); 692 693 // Factored out to facilitate explicit specialization. 694 constexpr ptrdiff_t 695 _M_type_size(ptrdiff_t __d) const { return __d * sizeof(_PTp); } 696 697 constexpr ptrdiff_t 698 _M_type_size(ptrdiff_t __d) const volatile { return __d * sizeof(_PTp); } 699 700 public: 701 __atomic_base() noexcept = default; 702 ~__atomic_base() noexcept = default; 703 __atomic_base(const __atomic_base&) = delete; 704 __atomic_base& operator=(const __atomic_base&) = delete; 705 __atomic_base& operator=(const __atomic_base&) volatile = delete; 706 707 // Requires __pointer_type convertible to _M_p. 708 constexpr __atomic_base(__pointer_type __p) noexcept : _M_p (__p) { } 709 710 operator __pointer_type() const noexcept 711 { return load(); } 712 713 operator __pointer_type() const volatile noexcept 714 { return load(); } 715 716 __pointer_type 717 operator=(__pointer_type __p) noexcept 718 { 719 store(__p); 720 return __p; 721 } 722 723 __pointer_type 724 operator=(__pointer_type __p) volatile noexcept 725 { 726 store(__p); 727 return __p; 728 } 729 730 __pointer_type 731 operator++(int) noexcept 732 { return fetch_add(1); } 733 734 __pointer_type 735 operator++(int) volatile noexcept 736 { return fetch_add(1); } 737 738 __pointer_type 739 operator--(int) noexcept 740 { return fetch_sub(1); } 741 742 __pointer_type 743 operator--(int) volatile noexcept 744 { return fetch_sub(1); } 745 746 __pointer_type 747 operator++() noexcept 748 { return __atomic_add_fetch(&_M_p, _M_type_size(1), 749 int(memory_order_seq_cst)); } 750 751 __pointer_type 752 operator++() volatile noexcept 753 { return __atomic_add_fetch(&_M_p, _M_type_size(1), 754 int(memory_order_seq_cst)); } 755 756 __pointer_type 757 operator--() noexcept 758 { return __atomic_sub_fetch(&_M_p, _M_type_size(1), 759 int(memory_order_seq_cst)); } 760 761 __pointer_type 762 operator--() volatile noexcept 763 { return __atomic_sub_fetch(&_M_p, _M_type_size(1), 764 int(memory_order_seq_cst)); } 765 766 __pointer_type 767 operator+=(ptrdiff_t __d) noexcept 768 { return __atomic_add_fetch(&_M_p, _M_type_size(__d), 769 int(memory_order_seq_cst)); } 770 771 __pointer_type 772 operator+=(ptrdiff_t __d) volatile noexcept 773 { return __atomic_add_fetch(&_M_p, _M_type_size(__d), 774 int(memory_order_seq_cst)); } 775 776 __pointer_type 777 operator-=(ptrdiff_t __d) noexcept 778 { return __atomic_sub_fetch(&_M_p, _M_type_size(__d), 779 int(memory_order_seq_cst)); } 780 781 __pointer_type 782 operator-=(ptrdiff_t __d) volatile noexcept 783 { return __atomic_sub_fetch(&_M_p, _M_type_size(__d), 784 int(memory_order_seq_cst)); } 785 786 bool 787 is_lock_free() const noexcept 788 { 789 // Produce a fake, minimally aligned pointer. 790 return __atomic_is_lock_free(sizeof(_M_p), 791 reinterpret_cast
(-__alignof(_M_p))); 792 } 793 794 bool 795 is_lock_free() const volatile noexcept 796 { 797 // Produce a fake, minimally aligned pointer. 798 return __atomic_is_lock_free(sizeof(_M_p), 799 reinterpret_cast
(-__alignof(_M_p))); 800 } 801 802 _GLIBCXX_ALWAYS_INLINE void 803 store(__pointer_type __p, 804 memory_order __m = memory_order_seq_cst) noexcept 805 { 806 memory_order __b __attribute__ ((__unused__)) 807 = __m & __memory_order_mask; 808 809 __glibcxx_assert(__b != memory_order_acquire); 810 __glibcxx_assert(__b != memory_order_acq_rel); 811 __glibcxx_assert(__b != memory_order_consume); 812 813 __atomic_store_n(&_M_p, __p, int(__m)); 814 } 815 816 _GLIBCXX_ALWAYS_INLINE void 817 store(__pointer_type __p, 818 memory_order __m = memory_order_seq_cst) volatile noexcept 819 { 820 memory_order __b __attribute__ ((__unused__)) 821 = __m & __memory_order_mask; 822 __glibcxx_assert(__b != memory_order_acquire); 823 __glibcxx_assert(__b != memory_order_acq_rel); 824 __glibcxx_assert(__b != memory_order_consume); 825 826 __atomic_store_n(&_M_p, __p, int(__m)); 827 } 828 829 _GLIBCXX_ALWAYS_INLINE __pointer_type 830 load(memory_order __m = memory_order_seq_cst) const noexcept 831 { 832 memory_order __b __attribute__ ((__unused__)) 833 = __m & __memory_order_mask; 834 __glibcxx_assert(__b != memory_order_release); 835 __glibcxx_assert(__b != memory_order_acq_rel); 836 837 return __atomic_load_n(&_M_p, int(__m)); 838 } 839 840 _GLIBCXX_ALWAYS_INLINE __pointer_type 841 load(memory_order __m = memory_order_seq_cst) const volatile noexcept 842 { 843 memory_order __b __attribute__ ((__unused__)) 844 = __m & __memory_order_mask; 845 __glibcxx_assert(__b != memory_order_release); 846 __glibcxx_assert(__b != memory_order_acq_rel); 847 848 return __atomic_load_n(&_M_p, int(__m)); 849 } 850 851 _GLIBCXX_ALWAYS_INLINE __pointer_type 852 exchange(__pointer_type __p, 853 memory_order __m = memory_order_seq_cst) noexcept 854 { 855 return __atomic_exchange_n(&_M_p, __p, int(__m)); 856 } 857 858 859 _GLIBCXX_ALWAYS_INLINE __pointer_type 860 exchange(__pointer_type __p, 861 memory_order __m = memory_order_seq_cst) volatile noexcept 862 { 863 return __atomic_exchange_n(&_M_p, __p, int(__m)); 864 } 865 866 _GLIBCXX_ALWAYS_INLINE bool 867 compare_exchange_weak(__pointer_type& __p1, __pointer_type __p2, 868 memory_order __m1, 869 memory_order __m2) noexcept 870 { 871 __glibcxx_assert(__is_valid_cmpexch_failure_order(__m2)); 872 873 return __atomic_compare_exchange_n(&_M_p, &__p1, __p2, 1, 874 int(__m1), int(__m2)); 875 } 876 877 _GLIBCXX_ALWAYS_INLINE bool 878 compare_exchange_weak(__pointer_type& __p1, __pointer_type __p2, 879 memory_order __m1, 880 memory_order __m2) volatile noexcept 881 { 882 __glibcxx_assert(__is_valid_cmpexch_failure_order(__m2)); 883 884 return __atomic_compare_exchange_n(&_M_p, &__p1, __p2, 1, 885 int(__m1), int(__m2)); 886 } 887 888 _GLIBCXX_ALWAYS_INLINE bool 889 compare_exchange_strong(__pointer_type& __p1, __pointer_type __p2, 890 memory_order __m1, 891 memory_order __m2) noexcept 892 { 893 __glibcxx_assert(__is_valid_cmpexch_failure_order(__m2)); 894 895 return __atomic_compare_exchange_n(&_M_p, &__p1, __p2, 0, 896 int(__m1), int(__m2)); 897 } 898 899 _GLIBCXX_ALWAYS_INLINE bool 900 compare_exchange_strong(__pointer_type& __p1, __pointer_type __p2, 901 memory_order __m1, 902 memory_order __m2) volatile noexcept 903 { 904 __glibcxx_assert(__is_valid_cmpexch_failure_order(__m2)); 905 906 return __atomic_compare_exchange_n(&_M_p, &__p1, __p2, 0, 907 int(__m1), int(__m2)); 908 } 909 910 #if __cpp_lib_atomic_wait 911 _GLIBCXX_ALWAYS_INLINE void 912 wait(__pointer_type __old, 913 memory_order __m = memory_order_seq_cst) const noexcept 914 { 915 std::__atomic_wait_address_v(&_M_p, __old, 916 [__m, this] 917 { return this->load(__m); }); 918 } 919 920 // TODO add const volatile overload 921 922 _GLIBCXX_ALWAYS_INLINE void 923 notify_one() const noexcept 924 { std::__atomic_notify_address(&_M_p, false); } 925 926 // TODO add const volatile overload 927 928 _GLIBCXX_ALWAYS_INLINE void 929 notify_all() const noexcept 930 { std::__atomic_notify_address(&_M_p, true); } 931 932 // TODO add const volatile overload 933 #endif // __cpp_lib_atomic_wait 934 935 _GLIBCXX_ALWAYS_INLINE __pointer_type 936 fetch_add(ptrdiff_t __d, 937 memory_order __m = memory_order_seq_cst) noexcept 938 { return __atomic_fetch_add(&_M_p, _M_type_size(__d), int(__m)); } 939 940 _GLIBCXX_ALWAYS_INLINE __pointer_type 941 fetch_add(ptrdiff_t __d, 942 memory_order __m = memory_order_seq_cst) volatile noexcept 943 { return __atomic_fetch_add(&_M_p, _M_type_size(__d), int(__m)); } 944 945 _GLIBCXX_ALWAYS_INLINE __pointer_type 946 fetch_sub(ptrdiff_t __d, 947 memory_order __m = memory_order_seq_cst) noexcept 948 { return __atomic_fetch_sub(&_M_p, _M_type_size(__d), int(__m)); } 949 950 _GLIBCXX_ALWAYS_INLINE __pointer_type 951 fetch_sub(ptrdiff_t __d, 952 memory_order __m = memory_order_seq_cst) volatile noexcept 953 { return __atomic_fetch_sub(&_M_p, _M_type_size(__d), int(__m)); } 954 }; 955 956 namespace __atomic_impl 957 { 958 // Implementation details of atomic padding handling 959 960 template
961 constexpr bool 962 __maybe_has_padding() 963 { 964 #if ! __has_builtin(__builtin_clear_padding) 965 return false; 966 #elif __has_builtin(__has_unique_object_representations) 967 return !__has_unique_object_representations(_Tp) 968 && !is_same<_Tp, float>::value && !is_same<_Tp, double>::value; 969 #else 970 return true; 971 #endif 972 } 973 974 template
975 _GLIBCXX_ALWAYS_INLINE _Tp* 976 __clear_padding(_Tp& __val) noexcept 977 { 978 auto* __ptr = std::__addressof(__val); 979 #if __has_builtin(__builtin_clear_padding) 980 if _GLIBCXX17_CONSTEXPR (__atomic_impl::__maybe_has_padding<_Tp>()) 981 __builtin_clear_padding(__ptr); 982 #endif 983 return __ptr; 984 } 985 986 // Remove volatile and create a non-deduced context for value arguments. 987 template
988 using _Val = typename remove_volatile<_Tp>::type; 989 990 template
991 _GLIBCXX_ALWAYS_INLINE bool 992 __compare_exchange(_Tp& __val, _Val<_Tp>& __e, _Val<_Tp>& __i, 993 bool __is_weak, 994 memory_order __s, memory_order __f) noexcept 995 { 996 __glibcxx_assert(__is_valid_cmpexch_failure_order(__f)); 997 998 using _Vp = _Val<_Tp>; 999 1000 if _GLIBCXX17_CONSTEXPR (__atomic_impl::__maybe_has_padding<_Vp>()) 1001 { 1002 // We must not modify __e on success, so cannot clear its padding. 1003 // Copy into a buffer and clear that, then copy back on failure. 1004 alignas(_Vp) unsigned char __buf[sizeof(_Vp)]; 1005 _Vp* __exp = ::new((void*)__buf) _Vp(__e); 1006 __atomic_impl::__clear_padding(*__exp); 1007 if (__atomic_compare_exchange(std::__addressof(__val), __exp, 1008 __atomic_impl::__clear_padding(__i), 1009 __is_weak, int(__s), int(__f))) 1010 return true; 1011 __builtin_memcpy(std::__addressof(__e), __exp, sizeof(_Vp)); 1012 return false; 1013 } 1014 else 1015 return __atomic_compare_exchange(std::__addressof(__val), 1016 std::__addressof(__e), 1017 std::__addressof(__i), 1018 __is_weak, int(__s), int(__f)); 1019 } 1020 } // namespace __atomic_impl 1021 1022 #if __cplusplus > 201703L 1023 // Implementation details of atomic_ref and atomic
. 1024 namespace __atomic_impl 1025 { 1026 // Like _Val
above, but for difference_type arguments. 1027 template
1028 using _Diff = __conditional_t
, ptrdiff_t, _Val<_Tp>>; 1029 1030 template
1031 _GLIBCXX_ALWAYS_INLINE bool 1032 is_lock_free() noexcept 1033 { 1034 // Produce a fake, minimally aligned pointer. 1035 return __atomic_is_lock_free(_Size, reinterpret_cast
(-_Align)); 1036 } 1037 1038 template
1039 _GLIBCXX_ALWAYS_INLINE void 1040 store(_Tp* __ptr, _Val<_Tp> __t, memory_order __m) noexcept 1041 { 1042 __atomic_store(__ptr, __atomic_impl::__clear_padding(__t), int(__m)); 1043 } 1044 1045 template
1046 _GLIBCXX_ALWAYS_INLINE _Val<_Tp> 1047 load(const _Tp* __ptr, memory_order __m) noexcept 1048 { 1049 alignas(_Tp) unsigned char __buf[sizeof(_Tp)]; 1050 auto* __dest = reinterpret_cast<_Val<_Tp>*>(__buf); 1051 __atomic_load(__ptr, __dest, int(__m)); 1052 return *__dest; 1053 } 1054 1055 template
1056 _GLIBCXX_ALWAYS_INLINE _Val<_Tp> 1057 exchange(_Tp* __ptr, _Val<_Tp> __desired, memory_order __m) noexcept 1058 { 1059 alignas(_Tp) unsigned char __buf[sizeof(_Tp)]; 1060 auto* __dest = reinterpret_cast<_Val<_Tp>*>(__buf); 1061 __atomic_exchange(__ptr, __atomic_impl::__clear_padding(__desired), 1062 __dest, int(__m)); 1063 return *__dest; 1064 } 1065 1066 template
1067 _GLIBCXX_ALWAYS_INLINE bool 1068 compare_exchange_weak(_Tp* __ptr, _Val<_Tp>& __expected, 1069 _Val<_Tp> __desired, memory_order __success, 1070 memory_order __failure) noexcept 1071 { 1072 return __atomic_impl::__compare_exchange(*__ptr, __expected, __desired, 1073 true, __success, __failure); 1074 } 1075 1076 template
1077 _GLIBCXX_ALWAYS_INLINE bool 1078 compare_exchange_strong(_Tp* __ptr, _Val<_Tp>& __expected, 1079 _Val<_Tp> __desired, memory_order __success, 1080 memory_order __failure) noexcept 1081 { 1082 return __atomic_impl::__compare_exchange(*__ptr, __expected, __desired, 1083 false, __success, __failure); 1084 } 1085 1086 #if __cpp_lib_atomic_wait 1087 template
1088 _GLIBCXX_ALWAYS_INLINE void 1089 wait(const _Tp* __ptr, _Val<_Tp> __old, 1090 memory_order __m = memory_order_seq_cst) noexcept 1091 { 1092 std::__atomic_wait_address_v(__ptr, __old, 1093 [__ptr, __m]() { return __atomic_impl::load(__ptr, __m); }); 1094 } 1095 1096 // TODO add const volatile overload 1097 1098 template
1099 _GLIBCXX_ALWAYS_INLINE void 1100 notify_one(const _Tp* __ptr) noexcept 1101 { std::__atomic_notify_address(__ptr, false); } 1102 1103 // TODO add const volatile overload 1104 1105 template
1106 _GLIBCXX_ALWAYS_INLINE void 1107 notify_all(const _Tp* __ptr) noexcept 1108 { std::__atomic_notify_address(__ptr, true); } 1109 1110 // TODO add const volatile overload 1111 #endif // __cpp_lib_atomic_wait 1112 1113 template
1114 _GLIBCXX_ALWAYS_INLINE _Tp 1115 fetch_add(_Tp* __ptr, _Diff<_Tp> __i, memory_order __m) noexcept 1116 { return __atomic_fetch_add(__ptr, __i, int(__m)); } 1117 1118 template
1119 _GLIBCXX_ALWAYS_INLINE _Tp 1120 fetch_sub(_Tp* __ptr, _Diff<_Tp> __i, memory_order __m) noexcept 1121 { return __atomic_fetch_sub(__ptr, __i, int(__m)); } 1122 1123 template
1124 _GLIBCXX_ALWAYS_INLINE _Tp 1125 fetch_and(_Tp* __ptr, _Val<_Tp> __i, memory_order __m) noexcept 1126 { return __atomic_fetch_and(__ptr, __i, int(__m)); } 1127 1128 template
1129 _GLIBCXX_ALWAYS_INLINE _Tp 1130 fetch_or(_Tp* __ptr, _Val<_Tp> __i, memory_order __m) noexcept 1131 { return __atomic_fetch_or(__ptr, __i, int(__m)); } 1132 1133 template
1134 _GLIBCXX_ALWAYS_INLINE _Tp 1135 fetch_xor(_Tp* __ptr, _Val<_Tp> __i, memory_order __m) noexcept 1136 { return __atomic_fetch_xor(__ptr, __i, int(__m)); } 1137 1138 template
1139 _GLIBCXX_ALWAYS_INLINE _Tp 1140 __add_fetch(_Tp* __ptr, _Diff<_Tp> __i) noexcept 1141 { return __atomic_add_fetch(__ptr, __i, __ATOMIC_SEQ_CST); } 1142 1143 template
1144 _GLIBCXX_ALWAYS_INLINE _Tp 1145 __sub_fetch(_Tp* __ptr, _Diff<_Tp> __i) noexcept 1146 { return __atomic_sub_fetch(__ptr, __i, __ATOMIC_SEQ_CST); } 1147 1148 template
1149 _GLIBCXX_ALWAYS_INLINE _Tp 1150 __and_fetch(_Tp* __ptr, _Val<_Tp> __i) noexcept 1151 { return __atomic_and_fetch(__ptr, __i, __ATOMIC_SEQ_CST); } 1152 1153 template
1154 _GLIBCXX_ALWAYS_INLINE _Tp 1155 __or_fetch(_Tp* __ptr, _Val<_Tp> __i) noexcept 1156 { return __atomic_or_fetch(__ptr, __i, __ATOMIC_SEQ_CST); } 1157 1158 template
1159 _GLIBCXX_ALWAYS_INLINE _Tp 1160 __xor_fetch(_Tp* __ptr, _Val<_Tp> __i) noexcept 1161 { return __atomic_xor_fetch(__ptr, __i, __ATOMIC_SEQ_CST); } 1162 1163 template
1164 _Tp 1165 __fetch_add_flt(_Tp* __ptr, _Val<_Tp> __i, memory_order __m) noexcept 1166 { 1167 _Val<_Tp> __oldval = load(__ptr, memory_order_relaxed); 1168 _Val<_Tp> __newval = __oldval + __i; 1169 while (!compare_exchange_weak(__ptr, __oldval, __newval, __m, 1170 memory_order_relaxed)) 1171 __newval = __oldval + __i; 1172 return __oldval; 1173 } 1174 1175 template
1176 _Tp 1177 __fetch_sub_flt(_Tp* __ptr, _Val<_Tp> __i, memory_order __m) noexcept 1178 { 1179 _Val<_Tp> __oldval = load(__ptr, memory_order_relaxed); 1180 _Val<_Tp> __newval = __oldval - __i; 1181 while (!compare_exchange_weak(__ptr, __oldval, __newval, __m, 1182 memory_order_relaxed)) 1183 __newval = __oldval - __i; 1184 return __oldval; 1185 } 1186 1187 template
1188 _Tp 1189 __add_fetch_flt(_Tp* __ptr, _Val<_Tp> __i) noexcept 1190 { 1191 _Val<_Tp> __oldval = load(__ptr, memory_order_relaxed); 1192 _Val<_Tp> __newval = __oldval + __i; 1193 while (!compare_exchange_weak(__ptr, __oldval, __newval, 1194 memory_order_seq_cst, 1195 memory_order_relaxed)) 1196 __newval = __oldval + __i; 1197 return __newval; 1198 } 1199 1200 template
1201 _Tp 1202 __sub_fetch_flt(_Tp* __ptr, _Val<_Tp> __i) noexcept 1203 { 1204 _Val<_Tp> __oldval = load(__ptr, memory_order_relaxed); 1205 _Val<_Tp> __newval = __oldval - __i; 1206 while (!compare_exchange_weak(__ptr, __oldval, __newval, 1207 memory_order_seq_cst, 1208 memory_order_relaxed)) 1209 __newval = __oldval - __i; 1210 return __newval; 1211 } 1212 } // namespace __atomic_impl 1213 1214 // base class for atomic
1215 template
1216 struct __atomic_float 1217 { 1218 static_assert(is_floating_point_v<_Fp>); 1219 1220 static constexpr size_t _S_alignment = __alignof__(_Fp); 1221 1222 public: 1223 using value_type = _Fp; 1224 using difference_type = value_type; 1225 1226 static constexpr bool is_always_lock_free 1227 = __atomic_always_lock_free(sizeof(_Fp), 0); 1228 1229 __atomic_float() = default; 1230 1231 constexpr 1232 __atomic_float(_Fp __t) : _M_fp(__t) 1233 { } 1234 1235 __atomic_float(const __atomic_float&) = delete; 1236 __atomic_float& operator=(const __atomic_float&) = delete; 1237 __atomic_float& operator=(const __atomic_float&) volatile = delete; 1238 1239 _Fp 1240 operator=(_Fp __t) volatile noexcept 1241 { 1242 this->store(__t); 1243 return __t; 1244 } 1245 1246 _Fp 1247 operator=(_Fp __t) noexcept 1248 { 1249 this->store(__t); 1250 return __t; 1251 } 1252 1253 bool 1254 is_lock_free() const volatile noexcept 1255 { return __atomic_impl::is_lock_free
(); } 1256 1257 bool 1258 is_lock_free() const noexcept 1259 { return __atomic_impl::is_lock_free
(); } 1260 1261 void 1262 store(_Fp __t, memory_order __m = memory_order_seq_cst) volatile noexcept 1263 { __atomic_impl::store(&_M_fp, __t, __m); } 1264 1265 void 1266 store(_Fp __t, memory_order __m = memory_order_seq_cst) noexcept 1267 { __atomic_impl::store(&_M_fp, __t, __m); } 1268 1269 _Fp 1270 load(memory_order __m = memory_order_seq_cst) const volatile noexcept 1271 { return __atomic_impl::load(&_M_fp, __m); } 1272 1273 _Fp 1274 load(memory_order __m = memory_order_seq_cst) const noexcept 1275 { return __atomic_impl::load(&_M_fp, __m); } 1276 1277 operator _Fp() const volatile noexcept { return this->load(); } 1278 operator _Fp() const noexcept { return this->load(); } 1279 1280 _Fp 1281 exchange(_Fp __desired, 1282 memory_order __m = memory_order_seq_cst) volatile noexcept 1283 { return __atomic_impl::exchange(&_M_fp, __desired, __m); } 1284 1285 _Fp 1286 exchange(_Fp __desired, 1287 memory_order __m = memory_order_seq_cst) noexcept 1288 { return __atomic_impl::exchange(&_M_fp, __desired, __m); } 1289 1290 bool 1291 compare_exchange_weak(_Fp& __expected, _Fp __desired, 1292 memory_order __success, 1293 memory_order __failure) noexcept 1294 { 1295 return __atomic_impl::compare_exchange_weak(&_M_fp, 1296 __expected, __desired, 1297 __success, __failure); 1298 } 1299 1300 bool 1301 compare_exchange_weak(_Fp& __expected, _Fp __desired, 1302 memory_order __success, 1303 memory_order __failure) volatile noexcept 1304 { 1305 return __atomic_impl::compare_exchange_weak(&_M_fp, 1306 __expected, __desired, 1307 __success, __failure); 1308 } 1309 1310 bool 1311 compare_exchange_strong(_Fp& __expected, _Fp __desired, 1312 memory_order __success, 1313 memory_order __failure) noexcept 1314 { 1315 return __atomic_impl::compare_exchange_strong(&_M_fp, 1316 __expected, __desired, 1317 __success, __failure); 1318 } 1319 1320 bool 1321 compare_exchange_strong(_Fp& __expected, _Fp __desired, 1322 memory_order __success, 1323 memory_order __failure) volatile noexcept 1324 { 1325 return __atomic_impl::compare_exchange_strong(&_M_fp, 1326 __expected, __desired, 1327 __success, __failure); 1328 } 1329 1330 bool 1331 compare_exchange_weak(_Fp& __expected, _Fp __desired, 1332 memory_order __order = memory_order_seq_cst) 1333 noexcept 1334 { 1335 return compare_exchange_weak(__expected, __desired, __order, 1336 __cmpexch_failure_order(__order)); 1337 } 1338 1339 bool 1340 compare_exchange_weak(_Fp& __expected, _Fp __desired, 1341 memory_order __order = memory_order_seq_cst) 1342 volatile noexcept 1343 { 1344 return compare_exchange_weak(__expected, __desired, __order, 1345 __cmpexch_failure_order(__order)); 1346 } 1347 1348 bool 1349 compare_exchange_strong(_Fp& __expected, _Fp __desired, 1350 memory_order __order = memory_order_seq_cst) 1351 noexcept 1352 { 1353 return compare_exchange_strong(__expected, __desired, __order, 1354 __cmpexch_failure_order(__order)); 1355 } 1356 1357 bool 1358 compare_exchange_strong(_Fp& __expected, _Fp __desired, 1359 memory_order __order = memory_order_seq_cst) 1360 volatile noexcept 1361 { 1362 return compare_exchange_strong(__expected, __desired, __order, 1363 __cmpexch_failure_order(__order)); 1364 } 1365 1366 #if __cpp_lib_atomic_wait 1367 _GLIBCXX_ALWAYS_INLINE void 1368 wait(_Fp __old, memory_order __m = memory_order_seq_cst) const noexcept 1369 { __atomic_impl::wait(&_M_fp, __old, __m); } 1370 1371 // TODO add const volatile overload 1372 1373 _GLIBCXX_ALWAYS_INLINE void 1374 notify_one() const noexcept 1375 { __atomic_impl::notify_one(&_M_fp); } 1376 1377 // TODO add const volatile overload 1378 1379 _GLIBCXX_ALWAYS_INLINE void 1380 notify_all() const noexcept 1381 { __atomic_impl::notify_all(&_M_fp); } 1382 1383 // TODO add const volatile overload 1384 #endif // __cpp_lib_atomic_wait 1385 1386 value_type 1387 fetch_add(value_type __i, 1388 memory_order __m = memory_order_seq_cst) noexcept 1389 { return __atomic_impl::__fetch_add_flt(&_M_fp, __i, __m); } 1390 1391 value_type 1392 fetch_add(value_type __i, 1393 memory_order __m = memory_order_seq_cst) volatile noexcept 1394 { return __atomic_impl::__fetch_add_flt(&_M_fp, __i, __m); } 1395 1396 value_type 1397 fetch_sub(value_type __i, 1398 memory_order __m = memory_order_seq_cst) noexcept 1399 { return __atomic_impl::__fetch_sub_flt(&_M_fp, __i, __m); } 1400 1401 value_type 1402 fetch_sub(value_type __i, 1403 memory_order __m = memory_order_seq_cst) volatile noexcept 1404 { return __atomic_impl::__fetch_sub_flt(&_M_fp, __i, __m); } 1405 1406 value_type 1407 operator+=(value_type __i) noexcept 1408 { return __atomic_impl::__add_fetch_flt(&_M_fp, __i); } 1409 1410 value_type 1411 operator+=(value_type __i) volatile noexcept 1412 { return __atomic_impl::__add_fetch_flt(&_M_fp, __i); } 1413 1414 value_type 1415 operator-=(value_type __i) noexcept 1416 { return __atomic_impl::__sub_fetch_flt(&_M_fp, __i); } 1417 1418 value_type 1419 operator-=(value_type __i) volatile noexcept 1420 { return __atomic_impl::__sub_fetch_flt(&_M_fp, __i); } 1421 1422 private: 1423 alignas(_S_alignment) _Fp _M_fp _GLIBCXX20_INIT(0); 1424 }; 1425 #undef _GLIBCXX20_INIT 1426 1427 template
, bool = is_floating_point_v<_Tp>> 1429 struct __atomic_ref; 1430 1431 // base class for non-integral, non-floating-point, non-pointer types 1432 template
1433 struct __atomic_ref<_Tp, false, false> 1434 { 1435 static_assert(is_trivially_copyable_v<_Tp>); 1436 1437 // 1/2/4/8/16-byte types must be aligned to at least their size. 1438 static constexpr int _S_min_alignment 1439 = (sizeof(_Tp) & (sizeof(_Tp) - 1)) || sizeof(_Tp) > 16 1440 ? 0 : sizeof(_Tp); 1441 1442 public: 1443 using value_type = _Tp; 1444 1445 static constexpr bool is_always_lock_free 1446 = __atomic_always_lock_free(sizeof(_Tp), 0); 1447 1448 static constexpr size_t required_alignment 1449 = _S_min_alignment > alignof(_Tp) ? _S_min_alignment : alignof(_Tp); 1450 1451 __atomic_ref& operator=(const __atomic_ref&) = delete; 1452 1453 explicit 1454 __atomic_ref(_Tp& __t) : _M_ptr(std::__addressof(__t)) 1455 { __glibcxx_assert(((uintptr_t)_M_ptr % required_alignment) == 0); } 1456 1457 __atomic_ref(const __atomic_ref&) noexcept = default; 1458 1459 _Tp 1460 operator=(_Tp __t) const noexcept 1461 { 1462 this->store(__t); 1463 return __t; 1464 } 1465 1466 operator _Tp() const noexcept { return this->load(); } 1467 1468 bool 1469 is_lock_free() const noexcept 1470 { return __atomic_impl::is_lock_free
(); } 1471 1472 void 1473 store(_Tp __t, memory_order __m = memory_order_seq_cst) const noexcept 1474 { __atomic_impl::store(_M_ptr, __t, __m); } 1475 1476 _Tp 1477 load(memory_order __m = memory_order_seq_cst) const noexcept 1478 { return __atomic_impl::load(_M_ptr, __m); } 1479 1480 _Tp 1481 exchange(_Tp __desired, memory_order __m = memory_order_seq_cst) 1482 const noexcept 1483 { return __atomic_impl::exchange(_M_ptr, __desired, __m); } 1484 1485 bool 1486 compare_exchange_weak(_Tp& __expected, _Tp __desired, 1487 memory_order __success, 1488 memory_order __failure) const noexcept 1489 { 1490 return __atomic_impl::compare_exchange_weak(_M_ptr, 1491 __expected, __desired, 1492 __success, __failure); 1493 } 1494 1495 bool 1496 compare_exchange_strong(_Tp& __expected, _Tp __desired, 1497 memory_order __success, 1498 memory_order __failure) const noexcept 1499 { 1500 return __atomic_impl::compare_exchange_strong(_M_ptr, 1501 __expected, __desired, 1502 __success, __failure); 1503 } 1504 1505 bool 1506 compare_exchange_weak(_Tp& __expected, _Tp __desired, 1507 memory_order __order = memory_order_seq_cst) 1508 const noexcept 1509 { 1510 return compare_exchange_weak(__expected, __desired, __order, 1511 __cmpexch_failure_order(__order)); 1512 } 1513 1514 bool 1515 compare_exchange_strong(_Tp& __expected, _Tp __desired, 1516 memory_order __order = memory_order_seq_cst) 1517 const noexcept 1518 { 1519 return compare_exchange_strong(__expected, __desired, __order, 1520 __cmpexch_failure_order(__order)); 1521 } 1522 1523 #if __cpp_lib_atomic_wait 1524 _GLIBCXX_ALWAYS_INLINE void 1525 wait(_Tp __old, memory_order __m = memory_order_seq_cst) const noexcept 1526 { __atomic_impl::wait(_M_ptr, __old, __m); } 1527 1528 // TODO add const volatile overload 1529 1530 _GLIBCXX_ALWAYS_INLINE void 1531 notify_one() const noexcept 1532 { __atomic_impl::notify_one(_M_ptr); } 1533 1534 // TODO add const volatile overload 1535 1536 _GLIBCXX_ALWAYS_INLINE void 1537 notify_all() const noexcept 1538 { __atomic_impl::notify_all(_M_ptr); } 1539 1540 // TODO add const volatile overload 1541 #endif // __cpp_lib_atomic_wait 1542 1543 private: 1544 _Tp* _M_ptr; 1545 }; 1546 1547 // base class for atomic_ref
1548 template
1549 struct __atomic_ref<_Tp, true, false> 1550 { 1551 static_assert(is_integral_v<_Tp>); 1552 1553 public: 1554 using value_type = _Tp; 1555 using difference_type = value_type; 1556 1557 static constexpr bool is_always_lock_free 1558 = __atomic_always_lock_free(sizeof(_Tp), 0); 1559 1560 static constexpr size_t required_alignment 1561 = sizeof(_Tp) > alignof(_Tp) ? sizeof(_Tp) : alignof(_Tp); 1562 1563 __atomic_ref() = delete; 1564 __atomic_ref& operator=(const __atomic_ref&) = delete; 1565 1566 explicit 1567 __atomic_ref(_Tp& __t) : _M_ptr(&__t) 1568 { __glibcxx_assert(((uintptr_t)_M_ptr % required_alignment) == 0); } 1569 1570 __atomic_ref(const __atomic_ref&) noexcept = default; 1571 1572 _Tp 1573 operator=(_Tp __t) const noexcept 1574 { 1575 this->store(__t); 1576 return __t; 1577 } 1578 1579 operator _Tp() const noexcept { return this->load(); } 1580 1581 bool 1582 is_lock_free() const noexcept 1583 { 1584 return __atomic_impl::is_lock_free
(); 1585 } 1586 1587 void 1588 store(_Tp __t, memory_order __m = memory_order_seq_cst) const noexcept 1589 { __atomic_impl::store(_M_ptr, __t, __m); } 1590 1591 _Tp 1592 load(memory_order __m = memory_order_seq_cst) const noexcept 1593 { return __atomic_impl::load(_M_ptr, __m); } 1594 1595 _Tp 1596 exchange(_Tp __desired, 1597 memory_order __m = memory_order_seq_cst) const noexcept 1598 { return __atomic_impl::exchange(_M_ptr, __desired, __m); } 1599 1600 bool 1601 compare_exchange_weak(_Tp& __expected, _Tp __desired, 1602 memory_order __success, 1603 memory_order __failure) const noexcept 1604 { 1605 return __atomic_impl::compare_exchange_weak(_M_ptr, 1606 __expected, __desired, 1607 __success, __failure); 1608 } 1609 1610 bool 1611 compare_exchange_strong(_Tp& __expected, _Tp __desired, 1612 memory_order __success, 1613 memory_order __failure) const noexcept 1614 { 1615 return __atomic_impl::compare_exchange_strong(_M_ptr, 1616 __expected, __desired, 1617 __success, __failure); 1618 } 1619 1620 bool 1621 compare_exchange_weak(_Tp& __expected, _Tp __desired, 1622 memory_order __order = memory_order_seq_cst) 1623 const noexcept 1624 { 1625 return compare_exchange_weak(__expected, __desired, __order, 1626 __cmpexch_failure_order(__order)); 1627 } 1628 1629 bool 1630 compare_exchange_strong(_Tp& __expected, _Tp __desired, 1631 memory_order __order = memory_order_seq_cst) 1632 const noexcept 1633 { 1634 return compare_exchange_strong(__expected, __desired, __order, 1635 __cmpexch_failure_order(__order)); 1636 } 1637 1638 #if __cpp_lib_atomic_wait 1639 _GLIBCXX_ALWAYS_INLINE void 1640 wait(_Tp __old, memory_order __m = memory_order_seq_cst) const noexcept 1641 { __atomic_impl::wait(_M_ptr, __old, __m); } 1642 1643 // TODO add const volatile overload 1644 1645 _GLIBCXX_ALWAYS_INLINE void 1646 notify_one() const noexcept 1647 { __atomic_impl::notify_one(_M_ptr); } 1648 1649 // TODO add const volatile overload 1650 1651 _GLIBCXX_ALWAYS_INLINE void 1652 notify_all() const noexcept 1653 { __atomic_impl::notify_all(_M_ptr); } 1654 1655 // TODO add const volatile overload 1656 #endif // __cpp_lib_atomic_wait 1657 1658 value_type 1659 fetch_add(value_type __i, 1660 memory_order __m = memory_order_seq_cst) const noexcept 1661 { return __atomic_impl::fetch_add(_M_ptr, __i, __m); } 1662 1663 value_type 1664 fetch_sub(value_type __i, 1665 memory_order __m = memory_order_seq_cst) const noexcept 1666 { return __atomic_impl::fetch_sub(_M_ptr, __i, __m); } 1667 1668 value_type 1669 fetch_and(value_type __i, 1670 memory_order __m = memory_order_seq_cst) const noexcept 1671 { return __atomic_impl::fetch_and(_M_ptr, __i, __m); } 1672 1673 value_type 1674 fetch_or(value_type __i, 1675 memory_order __m = memory_order_seq_cst) const noexcept 1676 { return __atomic_impl::fetch_or(_M_ptr, __i, __m); } 1677 1678 value_type 1679 fetch_xor(value_type __i, 1680 memory_order __m = memory_order_seq_cst) const noexcept 1681 { return __atomic_impl::fetch_xor(_M_ptr, __i, __m); } 1682 1683 _GLIBCXX_ALWAYS_INLINE value_type 1684 operator++(int) const noexcept 1685 { return fetch_add(1); } 1686 1687 _GLIBCXX_ALWAYS_INLINE value_type 1688 operator--(int) const noexcept 1689 { return fetch_sub(1); } 1690 1691 value_type 1692 operator++() const noexcept 1693 { return __atomic_impl::__add_fetch(_M_ptr, value_type(1)); } 1694 1695 value_type 1696 operator--() const noexcept 1697 { return __atomic_impl::__sub_fetch(_M_ptr, value_type(1)); } 1698 1699 value_type 1700 operator+=(value_type __i) const noexcept 1701 { return __atomic_impl::__add_fetch(_M_ptr, __i); } 1702 1703 value_type 1704 operator-=(value_type __i) const noexcept 1705 { return __atomic_impl::__sub_fetch(_M_ptr, __i); } 1706 1707 value_type 1708 operator&=(value_type __i) const noexcept 1709 { return __atomic_impl::__and_fetch(_M_ptr, __i); } 1710 1711 value_type 1712 operator|=(value_type __i) const noexcept 1713 { return __atomic_impl::__or_fetch(_M_ptr, __i); } 1714 1715 value_type 1716 operator^=(value_type __i) const noexcept 1717 { return __atomic_impl::__xor_fetch(_M_ptr, __i); } 1718 1719 private: 1720 _Tp* _M_ptr; 1721 }; 1722 1723 // base class for atomic_ref
1724 template
1725 struct __atomic_ref<_Fp, false, true> 1726 { 1727 static_assert(is_floating_point_v<_Fp>); 1728 1729 public: 1730 using value_type = _Fp; 1731 using difference_type = value_type; 1732 1733 static constexpr bool is_always_lock_free 1734 = __atomic_always_lock_free(sizeof(_Fp), 0); 1735 1736 static constexpr size_t required_alignment = __alignof__(_Fp); 1737 1738 __atomic_ref() = delete; 1739 __atomic_ref& operator=(const __atomic_ref&) = delete; 1740 1741 explicit 1742 __atomic_ref(_Fp& __t) : _M_ptr(&__t) 1743 { __glibcxx_assert(((uintptr_t)_M_ptr % required_alignment) == 0); } 1744 1745 __atomic_ref(const __atomic_ref&) noexcept = default; 1746 1747 _Fp 1748 operator=(_Fp __t) const noexcept 1749 { 1750 this->store(__t); 1751 return __t; 1752 } 1753 1754 operator _Fp() const noexcept { return this->load(); } 1755 1756 bool 1757 is_lock_free() const noexcept 1758 { 1759 return __atomic_impl::is_lock_free
(); 1760 } 1761 1762 void 1763 store(_Fp __t, memory_order __m = memory_order_seq_cst) const noexcept 1764 { __atomic_impl::store(_M_ptr, __t, __m); } 1765 1766 _Fp 1767 load(memory_order __m = memory_order_seq_cst) const noexcept 1768 { return __atomic_impl::load(_M_ptr, __m); } 1769 1770 _Fp 1771 exchange(_Fp __desired, 1772 memory_order __m = memory_order_seq_cst) const noexcept 1773 { return __atomic_impl::exchange(_M_ptr, __desired, __m); } 1774 1775 bool 1776 compare_exchange_weak(_Fp& __expected, _Fp __desired, 1777 memory_order __success, 1778 memory_order __failure) const noexcept 1779 { 1780 return __atomic_impl::compare_exchange_weak(_M_ptr, 1781 __expected, __desired, 1782 __success, __failure); 1783 } 1784 1785 bool 1786 compare_exchange_strong(_Fp& __expected, _Fp __desired, 1787 memory_order __success, 1788 memory_order __failure) const noexcept 1789 { 1790 return __atomic_impl::compare_exchange_strong(_M_ptr, 1791 __expected, __desired, 1792 __success, __failure); 1793 } 1794 1795 bool 1796 compare_exchange_weak(_Fp& __expected, _Fp __desired, 1797 memory_order __order = memory_order_seq_cst) 1798 const noexcept 1799 { 1800 return compare_exchange_weak(__expected, __desired, __order, 1801 __cmpexch_failure_order(__order)); 1802 } 1803 1804 bool 1805 compare_exchange_strong(_Fp& __expected, _Fp __desired, 1806 memory_order __order = memory_order_seq_cst) 1807 const noexcept 1808 { 1809 return compare_exchange_strong(__expected, __desired, __order, 1810 __cmpexch_failure_order(__order)); 1811 } 1812 1813 #if __cpp_lib_atomic_wait 1814 _GLIBCXX_ALWAYS_INLINE void 1815 wait(_Fp __old, memory_order __m = memory_order_seq_cst) const noexcept 1816 { __atomic_impl::wait(_M_ptr, __old, __m); } 1817 1818 // TODO add const volatile overload 1819 1820 _GLIBCXX_ALWAYS_INLINE void 1821 notify_one() const noexcept 1822 { __atomic_impl::notify_one(_M_ptr); } 1823 1824 // TODO add const volatile overload 1825 1826 _GLIBCXX_ALWAYS_INLINE void 1827 notify_all() const noexcept 1828 { __atomic_impl::notify_all(_M_ptr); } 1829 1830 // TODO add const volatile overload 1831 #endif // __cpp_lib_atomic_wait 1832 1833 value_type 1834 fetch_add(value_type __i, 1835 memory_order __m = memory_order_seq_cst) const noexcept 1836 { return __atomic_impl::__fetch_add_flt(_M_ptr, __i, __m); } 1837 1838 value_type 1839 fetch_sub(value_type __i, 1840 memory_order __m = memory_order_seq_cst) const noexcept 1841 { return __atomic_impl::__fetch_sub_flt(_M_ptr, __i, __m); } 1842 1843 value_type 1844 operator+=(value_type __i) const noexcept 1845 { return __atomic_impl::__add_fetch_flt(_M_ptr, __i); } 1846 1847 value_type 1848 operator-=(value_type __i) const noexcept 1849 { return __atomic_impl::__sub_fetch_flt(_M_ptr, __i); } 1850 1851 private: 1852 _Fp* _M_ptr; 1853 }; 1854 1855 // base class for atomic_ref
1856 template
1857 struct __atomic_ref<_Tp*, false, false> 1858 { 1859 public: 1860 using value_type = _Tp*; 1861 using difference_type = ptrdiff_t; 1862 1863 static constexpr bool is_always_lock_free = ATOMIC_POINTER_LOCK_FREE == 2; 1864 1865 static constexpr size_t required_alignment = __alignof__(_Tp*); 1866 1867 __atomic_ref() = delete; 1868 __atomic_ref& operator=(const __atomic_ref&) = delete; 1869 1870 explicit 1871 __atomic_ref(_Tp*& __t) : _M_ptr(std::__addressof(__t)) 1872 { __glibcxx_assert(((uintptr_t)_M_ptr % required_alignment) == 0); } 1873 1874 __atomic_ref(const __atomic_ref&) noexcept = default; 1875 1876 _Tp* 1877 operator=(_Tp* __t) const noexcept 1878 { 1879 this->store(__t); 1880 return __t; 1881 } 1882 1883 operator _Tp*() const noexcept { return this->load(); } 1884 1885 bool 1886 is_lock_free() const noexcept 1887 { 1888 return __atomic_impl::is_lock_free
(); 1889 } 1890 1891 void 1892 store(_Tp* __t, memory_order __m = memory_order_seq_cst) const noexcept 1893 { __atomic_impl::store(_M_ptr, __t, __m); } 1894 1895 _Tp* 1896 load(memory_order __m = memory_order_seq_cst) const noexcept 1897 { return __atomic_impl::load(_M_ptr, __m); } 1898 1899 _Tp* 1900 exchange(_Tp* __desired, 1901 memory_order __m = memory_order_seq_cst) const noexcept 1902 { return __atomic_impl::exchange(_M_ptr, __desired, __m); } 1903 1904 bool 1905 compare_exchange_weak(_Tp*& __expected, _Tp* __desired, 1906 memory_order __success, 1907 memory_order __failure) const noexcept 1908 { 1909 return __atomic_impl::compare_exchange_weak(_M_ptr, 1910 __expected, __desired, 1911 __success, __failure); 1912 } 1913 1914 bool 1915 compare_exchange_strong(_Tp*& __expected, _Tp* __desired, 1916 memory_order __success, 1917 memory_order __failure) const noexcept 1918 { 1919 return __atomic_impl::compare_exchange_strong(_M_ptr, 1920 __expected, __desired, 1921 __success, __failure); 1922 } 1923 1924 bool 1925 compare_exchange_weak(_Tp*& __expected, _Tp* __desired, 1926 memory_order __order = memory_order_seq_cst) 1927 const noexcept 1928 { 1929 return compare_exchange_weak(__expected, __desired, __order, 1930 __cmpexch_failure_order(__order)); 1931 } 1932 1933 bool 1934 compare_exchange_strong(_Tp*& __expected, _Tp* __desired, 1935 memory_order __order = memory_order_seq_cst) 1936 const noexcept 1937 { 1938 return compare_exchange_strong(__expected, __desired, __order, 1939 __cmpexch_failure_order(__order)); 1940 } 1941 1942 #if __cpp_lib_atomic_wait 1943 _GLIBCXX_ALWAYS_INLINE void 1944 wait(_Tp* __old, memory_order __m = memory_order_seq_cst) const noexcept 1945 { __atomic_impl::wait(_M_ptr, __old, __m); } 1946 1947 // TODO add const volatile overload 1948 1949 _GLIBCXX_ALWAYS_INLINE void 1950 notify_one() const noexcept 1951 { __atomic_impl::notify_one(_M_ptr); } 1952 1953 // TODO add const volatile overload 1954 1955 _GLIBCXX_ALWAYS_INLINE void 1956 notify_all() const noexcept 1957 { __atomic_impl::notify_all(_M_ptr); } 1958 1959 // TODO add const volatile overload 1960 #endif // __cpp_lib_atomic_wait 1961 1962 _GLIBCXX_ALWAYS_INLINE value_type 1963 fetch_add(difference_type __d, 1964 memory_order __m = memory_order_seq_cst) const noexcept 1965 { return __atomic_impl::fetch_add(_M_ptr, _S_type_size(__d), __m); } 1966 1967 _GLIBCXX_ALWAYS_INLINE value_type 1968 fetch_sub(difference_type __d, 1969 memory_order __m = memory_order_seq_cst) const noexcept 1970 { return __atomic_impl::fetch_sub(_M_ptr, _S_type_size(__d), __m); } 1971 1972 value_type 1973 operator++(int) const noexcept 1974 { return fetch_add(1); } 1975 1976 value_type 1977 operator--(int) const noexcept 1978 { return fetch_sub(1); } 1979 1980 value_type 1981 operator++() const noexcept 1982 { 1983 return __atomic_impl::__add_fetch(_M_ptr, _S_type_size(1)); 1984 } 1985 1986 value_type 1987 operator--() const noexcept 1988 { 1989 return __atomic_impl::__sub_fetch(_M_ptr, _S_type_size(1)); 1990 } 1991 1992 value_type 1993 operator+=(difference_type __d) const noexcept 1994 { 1995 return __atomic_impl::__add_fetch(_M_ptr, _S_type_size(__d)); 1996 } 1997 1998 value_type 1999 operator-=(difference_type __d) const noexcept 2000 { 2001 return __atomic_impl::__sub_fetch(_M_ptr, _S_type_size(__d)); 2002 } 2003 2004 private: 2005 static constexpr ptrdiff_t 2006 _S_type_size(ptrdiff_t __d) noexcept 2007 { 2008 static_assert(is_object_v<_Tp>); 2009 return __d * sizeof(_Tp); 2010 } 2011 2012 _Tp** _M_ptr; 2013 }; 2014 #endif // C++2a 2015 2016 /// @endcond 2017 2018 /// @} group atomics 2019 2020 _GLIBCXX_END_NAMESPACE_VERSION 2021 } // namespace std 2022 2023 #endif
Contact us
|
About us
|
Term of use
|
Copyright © 2000-2025 MyWebUniversity.com ™