1 // -*- C++ -*- header. 2 3 // Copyright (C) 2008-2018 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 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 <bits/c++config.h> 36 #include <stdint.h> 37 #include <bits/atomic_lockfree_defines.h> 38 39 #ifndef _GLIBCXX_ALWAYS_INLINE 40 #define _GLIBCXX_ALWAYS_INLINE inline __attribute__((__always_inline__)) 41 #endif 42 43 namespace std _GLIBCXX_VISIBILITY(default) 44 { 45 _GLIBCXX_BEGIN_NAMESPACE_VERSION 46 47 /** 48 * @defgroup atomics Atomics 49 * 50 * Components for performing atomic operations. 51 * @{ 52 */ 53 54 /// Enumeration for memory_order 55 typedef enum memory_order 56 { 57 memory_order_relaxed, 58 memory_order_consume, 59 memory_order_acquire, 60 memory_order_release, 61 memory_order_acq_rel, 62 memory_order_seq_cst 63 } memory_order; 64 65 enum __memory_order_modifier 66 { 67 __memory_order_mask = 0x0ffff, 68 __memory_order_modifier_mask = 0xffff0000, 69 __memory_order_hle_acquire = 0x10000, 70 __memory_order_hle_release = 0x20000 71 }; 72 73 constexpr memory_order 74 operator|(memory_order __m, __memory_order_modifier __mod) 75 { 76 return memory_order(__m | int(__mod)); 77 } 78 79 constexpr memory_order 80 operator&(memory_order __m, __memory_order_modifier __mod) 81 { 82 return memory_order(__m & int(__mod)); 83 } 84 85 // Drop release ordering as per [atomics.types.operations.req]/21 86 constexpr memory_order 87 __cmpexch_failure_order2(memory_order __m) noexcept 88 { 89 return __m == memory_order_acq_rel ? memory_order_acquire 90 : __m == memory_order_release ? memory_order_relaxed : __m; 91 } 92 93 constexpr memory_order 94 __cmpexch_failure_order(memory_order __m) noexcept 95 { 96 return memory_order(__cmpexch_failure_order2(__m & __memory_order_mask) 97 | (__m & __memory_order_modifier_mask)); 98 } 99 100 _GLIBCXX_ALWAYS_INLINE void 101 atomic_thread_fence(memory_order __m) noexcept 102 { __atomic_thread_fence(__m); } 103 104 _GLIBCXX_ALWAYS_INLINE void 105 atomic_signal_fence(memory_order __m) noexcept 106 { __atomic_signal_fence(__m); } 107 108 /// kill_dependency 109 template<typename _Tp> 110 inline _Tp 111 kill_dependency(_Tp __y) noexcept 112 { 113 _Tp __ret(__y); 114 return __ret; 115 } 116 117 118 // Base types for atomics. 119 template<typename _IntTp> 120 struct __atomic_base; 121 122 123 #define ATOMIC_VAR_INIT(_VI) { _VI } 124 125 template<typename _Tp> 126 struct atomic; 127 128 template<typename _Tp> 129 struct atomic<_Tp*>; 130 131 /* The target's "set" value for test-and-set may not be exactly 1. */ 132 #if __GCC_ATOMIC_TEST_AND_SET_TRUEVAL == 1 133 typedef bool __atomic_flag_data_type; 134 #else 135 typedef unsigned char __atomic_flag_data_type; 136 #endif 137 138 /** 139 * @brief Base type for atomic_flag. 140 * 141 * Base type is POD with data, allowing atomic_flag to derive from 142 * it and meet the standard layout type requirement. In addition to 143 * compatibility with a C interface, this allows different 144 * implementations of atomic_flag to use the same atomic operation 145 * functions, via a standard conversion to the __atomic_flag_base 146 * argument. 147 */ 148 _GLIBCXX_BEGIN_EXTERN_C 149 150 struct __atomic_flag_base 151 { 152 __atomic_flag_data_type _M_i; 153 }; 154 155 _GLIBCXX_END_EXTERN_C 156 157 #define ATOMIC_FLAG_INIT { 0 } 158 159 /// atomic_flag 160 struct atomic_flag : public __atomic_flag_base 161 { 162 atomic_flag() noexcept = default; 163 ~atomic_flag() noexcept = default; 164 atomic_flag(const atomic_flag&) = delete; 165 atomic_flag& operator=(const atomic_flag&) = delete; 166 atomic_flag& operator=(const atomic_flag&) volatile = delete; 167 168 // Conversion to ATOMIC_FLAG_INIT. 169 constexpr atomic_flag(bool __i) noexcept 170 : __atomic_flag_base{ _S_init(__i) } 171 { } 172 173 _GLIBCXX_ALWAYS_INLINE bool 174 test_and_set(memory_order __m = memory_order_seq_cst) noexcept 175 { 176 return __atomic_test_and_set (&_M_i, __m); 177 } 178 179 _GLIBCXX_ALWAYS_INLINE bool 180 test_and_set(memory_order __m = memory_order_seq_cst) volatile noexcept 181 { 182 return __atomic_test_and_set (&_M_i, __m); 183 } 184 185 _GLIBCXX_ALWAYS_INLINE void 186 clear(memory_order __m = memory_order_seq_cst) noexcept 187 { 188 memory_order __b = __m & __memory_order_mask; 189 __glibcxx_assert(__b != memory_order_consume); 190 __glibcxx_assert(__b != memory_order_acquire); 191 __glibcxx_assert(__b != memory_order_acq_rel); 192 193 __atomic_clear (&_M_i, __m); 194 } 195 196 _GLIBCXX_ALWAYS_INLINE void 197 clear(memory_order __m = memory_order_seq_cst) volatile noexcept 198 { 199 memory_order __b = __m & __memory_order_mask; 200 __glibcxx_assert(__b != memory_order_consume); 201 __glibcxx_assert(__b != memory_order_acquire); 202 __glibcxx_assert(__b != memory_order_acq_rel); 203 204 __atomic_clear (&_M_i, __m); 205 } 206 207 private: 208 static constexpr __atomic_flag_data_type 209 _S_init(bool __i) 210 { return __i ? __GCC_ATOMIC_TEST_AND_SET_TRUEVAL : 0; } 211 }; 212 213 214 /// Base class for atomic integrals. 215 // 216 // For each of the integral types, define atomic_[integral type] struct 217 // 218 // atomic_bool bool 219 // atomic_char char 220 // atomic_schar signed char 221 // atomic_uchar unsigned char 222 // atomic_short short 223 // atomic_ushort unsigned short 224 // atomic_int int 225 // atomic_uint unsigned int 226 // atomic_long long 227 // atomic_ulong unsigned long 228 // atomic_llong long long 229 // atomic_ullong unsigned long long 230 // atomic_char16_t char16_t 231 // atomic_char32_t char32_t 232 // atomic_wchar_t wchar_t 233 // 234 // NB: Assuming _ITp is an integral scalar type that is 1, 2, 4, or 235 // 8 bytes, since that is what GCC built-in functions for atomic 236 // memory access expect. 237 template<typename _ITp> 238 struct __atomic_base 239 { 240 private: 241 typedef _ITp __int_type; 242 243 static constexpr int _S_alignment = 244 sizeof(_ITp) > alignof(_ITp) ? sizeof(_ITp) : alignof(_ITp); 245 246 alignas(_S_alignment) __int_type _M_i; 247 248 public: 249 __atomic_base() noexcept = default; 250 ~__atomic_base() noexcept = default; 251 __atomic_base(const __atomic_base&) = delete; 252 __atomic_base& operator=(const __atomic_base&) = delete; 253 __atomic_base& operator=(const __atomic_base&) volatile = delete; 254 255 // Requires __int_type convertible to _M_i. 256 constexpr __atomic_base(__int_type __i) noexcept : _M_i (__i) { } 257 258 operator __int_type() const noexcept 259 { return load(); } 260 261 operator __int_type() const volatile noexcept 262 { return load(); } 263 264 __int_type 265 operator=(__int_type __i) noexcept 266 { 267 store(__i); 268 return __i; 269 } 270 271 __int_type 272 operator=(__int_type __i) volatile noexcept 273 { 274 store(__i); 275 return __i; 276 } 277 278 __int_type 279 operator++(int) noexcept 280 { return fetch_add(1); } 281 282 __int_type 283 operator++(int) volatile noexcept 284 { return fetch_add(1); } 285 286 __int_type 287 operator--(int) noexcept 288 { return fetch_sub(1); } 289 290 __int_type 291 operator--(int) volatile noexcept 292 { return fetch_sub(1); } 293 294 __int_type 295 operator++() noexcept 296 { return __atomic_add_fetch(&_M_i, 1, memory_order_seq_cst); } 297 298 __int_type 299 operator++() volatile noexcept 300 { return __atomic_add_fetch(&_M_i, 1, memory_order_seq_cst); } 301 302 __int_type 303 operator--() noexcept 304 { return __atomic_sub_fetch(&_M_i, 1, memory_order_seq_cst); } 305 306 __int_type 307 operator--() volatile noexcept 308 { return __atomic_sub_fetch(&_M_i, 1, memory_order_seq_cst); } 309 310 __int_type 311 operator+=(__int_type __i) noexcept 312 { return __atomic_add_fetch(&_M_i, __i, memory_order_seq_cst); } 313 314 __int_type 315 operator+=(__int_type __i) volatile noexcept 316 { return __atomic_add_fetch(&_M_i, __i, memory_order_seq_cst); } 317 318 __int_type 319 operator-=(__int_type __i) noexcept 320 { return __atomic_sub_fetch(&_M_i, __i, memory_order_seq_cst); } 321 322 __int_type 323 operator-=(__int_type __i) volatile noexcept 324 { return __atomic_sub_fetch(&_M_i, __i, memory_order_seq_cst); } 325 326 __int_type 327 operator&=(__int_type __i) noexcept 328 { return __atomic_and_fetch(&_M_i, __i, memory_order_seq_cst); } 329 330 __int_type 331 operator&=(__int_type __i) volatile noexcept 332 { return __atomic_and_fetch(&_M_i, __i, memory_order_seq_cst); } 333 334 __int_type 335 operator|=(__int_type __i) noexcept 336 { return __atomic_or_fetch(&_M_i, __i, memory_order_seq_cst); } 337 338 __int_type 339 operator|=(__int_type __i) volatile noexcept 340 { return __atomic_or_fetch(&_M_i, __i, memory_order_seq_cst); } 341 342 __int_type 343 operator^=(__int_type __i) noexcept 344 { return __atomic_xor_fetch(&_M_i, __i, memory_order_seq_cst); } 345 346 __int_type 347 operator^=(__int_type __i) volatile noexcept 348 { return __atomic_xor_fetch(&_M_i, __i, memory_order_seq_cst); } 349 350 bool 351 is_lock_free() const noexcept 352 { 353 // Use a fake, minimally aligned pointer. 354 return __atomic_is_lock_free(sizeof(_M_i), 355 reinterpret_cast<void *>(-__alignof(_M_i))); 356 } 357 358 bool 359 is_lock_free() const volatile noexcept 360 { 361 // Use a fake, minimally aligned pointer. 362 return __atomic_is_lock_free(sizeof(_M_i), 363 reinterpret_cast<void *>(-__alignof(_M_i))); 364 } 365 366 _GLIBCXX_ALWAYS_INLINE void 367 store(__int_type __i, memory_order __m = memory_order_seq_cst) noexcept 368 { 369 memory_order __b = __m & __memory_order_mask; 370 __glibcxx_assert(__b != memory_order_acquire); 371 __glibcxx_assert(__b != memory_order_acq_rel); 372 __glibcxx_assert(__b != memory_order_consume); 373 374 __atomic_store_n(&_M_i, __i, __m); 375 } 376 377 _GLIBCXX_ALWAYS_INLINE void 378 store(__int_type __i, 379 memory_order __m = memory_order_seq_cst) volatile noexcept 380 { 381 memory_order __b = __m & __memory_order_mask; 382 __glibcxx_assert(__b != memory_order_acquire); 383 __glibcxx_assert(__b != memory_order_acq_rel); 384 __glibcxx_assert(__b != memory_order_consume); 385 386 __atomic_store_n(&_M_i, __i, __m); 387 } 388 389 _GLIBCXX_ALWAYS_INLINE __int_type 390 load(memory_order __m = memory_order_seq_cst) const noexcept 391 { 392 memory_order __b = __m & __memory_order_mask; 393 __glibcxx_assert(__b != memory_order_release); 394 __glibcxx_assert(__b != memory_order_acq_rel); 395 396 return __atomic_load_n(&_M_i, __m); 397 } 398 399 _GLIBCXX_ALWAYS_INLINE __int_type 400 load(memory_order __m = memory_order_seq_cst) const volatile noexcept 401 { 402 memory_order __b = __m & __memory_order_mask; 403 __glibcxx_assert(__b != memory_order_release); 404 __glibcxx_assert(__b != memory_order_acq_rel); 405 406 return __atomic_load_n(&_M_i, __m); 407 } 408 409 _GLIBCXX_ALWAYS_INLINE __int_type 410 exchange(__int_type __i, 411 memory_order __m = memory_order_seq_cst) noexcept 412 { 413 return __atomic_exchange_n(&_M_i, __i, __m); 414 } 415 416 417 _GLIBCXX_ALWAYS_INLINE __int_type 418 exchange(__int_type __i, 419 memory_order __m = memory_order_seq_cst) volatile noexcept 420 { 421 return __atomic_exchange_n(&_M_i, __i, __m); 422 } 423 424 _GLIBCXX_ALWAYS_INLINE bool 425 compare_exchange_weak(__int_type& __i1, __int_type __i2, 426 memory_order __m1, memory_order __m2) noexcept 427 { 428 memory_order __b2 = __m2 & __memory_order_mask; 429 memory_order __b1 = __m1 & __memory_order_mask; 430 __glibcxx_assert(__b2 != memory_order_release); 431 __glibcxx_assert(__b2 != memory_order_acq_rel); 432 __glibcxx_assert(__b2 <= __b1); 433 434 return __atomic_compare_exchange_n(&_M_i, &__i1, __i2, 1, __m1, __m2); 435 } 436 437 _GLIBCXX_ALWAYS_INLINE bool 438 compare_exchange_weak(__int_type& __i1, __int_type __i2, 439 memory_order __m1, 440 memory_order __m2) volatile noexcept 441 { 442 memory_order __b2 = __m2 & __memory_order_mask; 443 memory_order __b1 = __m1 & __memory_order_mask; 444 __glibcxx_assert(__b2 != memory_order_release); 445 __glibcxx_assert(__b2 != memory_order_acq_rel); 446 __glibcxx_assert(__b2 <= __b1); 447 448 return __atomic_compare_exchange_n(&_M_i, &__i1, __i2, 1, __m1, __m2); 449 } 450 451 _GLIBCXX_ALWAYS_INLINE bool 452 compare_exchange_weak(__int_type& __i1, __int_type __i2, 453 memory_order __m = memory_order_seq_cst) noexcept 454 { 455 return compare_exchange_weak(__i1, __i2, __m, 456 __cmpexch_failure_order(__m)); 457 } 458 459 _GLIBCXX_ALWAYS_INLINE bool 460 compare_exchange_weak(__int_type& __i1, __int_type __i2, 461 memory_order __m = memory_order_seq_cst) volatile noexcept 462 { 463 return compare_exchange_weak(__i1, __i2, __m, 464 __cmpexch_failure_order(__m)); 465 } 466 467 _GLIBCXX_ALWAYS_INLINE bool 468 compare_exchange_strong(__int_type& __i1, __int_type __i2, 469 memory_order __m1, memory_order __m2) noexcept 470 { 471 memory_order __b2 = __m2 & __memory_order_mask; 472 memory_order __b1 = __m1 & __memory_order_mask; 473 __glibcxx_assert(__b2 != memory_order_release); 474 __glibcxx_assert(__b2 != memory_order_acq_rel); 475 __glibcxx_assert(__b2 <= __b1); 476 477 return __atomic_compare_exchange_n(&_M_i, &__i1, __i2, 0, __m1, __m2); 478 } 479 480 _GLIBCXX_ALWAYS_INLINE bool 481 compare_exchange_strong(__int_type& __i1, __int_type __i2, 482 memory_order __m1, 483 memory_order __m2) volatile noexcept 484 { 485 memory_order __b2 = __m2 & __memory_order_mask; 486 memory_order __b1 = __m1 & __memory_order_mask; 487 488 __glibcxx_assert(__b2 != memory_order_release); 489 __glibcxx_assert(__b2 != memory_order_acq_rel); 490 __glibcxx_assert(__b2 <= __b1); 491 492 return __atomic_compare_exchange_n(&_M_i, &__i1, __i2, 0, __m1, __m2); 493 } 494 495 _GLIBCXX_ALWAYS_INLINE bool 496 compare_exchange_strong(__int_type& __i1, __int_type __i2, 497 memory_order __m = memory_order_seq_cst) noexcept 498 { 499 return compare_exchange_strong(__i1, __i2, __m, 500 __cmpexch_failure_order(__m)); 501 } 502 503 _GLIBCXX_ALWAYS_INLINE bool 504 compare_exchange_strong(__int_type& __i1, __int_type __i2, 505 memory_order __m = memory_order_seq_cst) volatile noexcept 506 { 507 return compare_exchange_strong(__i1, __i2, __m, 508 __cmpexch_failure_order(__m)); 509 } 510 511 _GLIBCXX_ALWAYS_INLINE __int_type 512 fetch_add(__int_type __i, 513 memory_order __m = memory_order_seq_cst) noexcept 514 { return __atomic_fetch_add(&_M_i, __i, __m); } 515 516 _GLIBCXX_ALWAYS_INLINE __int_type 517 fetch_add(__int_type __i, 518 memory_order __m = memory_order_seq_cst) volatile noexcept 519 { return __atomic_fetch_add(&_M_i, __i, __m); } 520 521 _GLIBCXX_ALWAYS_INLINE __int_type 522 fetch_sub(__int_type __i, 523 memory_order __m = memory_order_seq_cst) noexcept 524 { return __atomic_fetch_sub(&_M_i, __i, __m); } 525 526 _GLIBCXX_ALWAYS_INLINE __int_type 527 fetch_sub(__int_type __i, 528 memory_order __m = memory_order_seq_cst) volatile noexcept 529 { return __atomic_fetch_sub(&_M_i, __i, __m); } 530 531 _GLIBCXX_ALWAYS_INLINE __int_type 532 fetch_and(__int_type __i, 533 memory_order __m = memory_order_seq_cst) noexcept 534 { return __atomic_fetch_and(&_M_i, __i, __m); } 535 536 _GLIBCXX_ALWAYS_INLINE __int_type 537 fetch_and(__int_type __i, 538 memory_order __m = memory_order_seq_cst) volatile noexcept 539 { return __atomic_fetch_and(&_M_i, __i, __m); } 540 541 _GLIBCXX_ALWAYS_INLINE __int_type 542 fetch_or(__int_type __i, 543 memory_order __m = memory_order_seq_cst) noexcept 544 { return __atomic_fetch_or(&_M_i, __i, __m); } 545 546 _GLIBCXX_ALWAYS_INLINE __int_type 547 fetch_or(__int_type __i, 548 memory_order __m = memory_order_seq_cst) volatile noexcept 549 { return __atomic_fetch_or(&_M_i, __i, __m); } 550 551 _GLIBCXX_ALWAYS_INLINE __int_type 552 fetch_xor(__int_type __i, 553 memory_order __m = memory_order_seq_cst) noexcept 554 { return __atomic_fetch_xor(&_M_i, __i, __m); } 555 556 _GLIBCXX_ALWAYS_INLINE __int_type 557 fetch_xor(__int_type __i, 558 memory_order __m = memory_order_seq_cst) volatile noexcept 559 { return __atomic_fetch_xor(&_M_i, __i, __m); } 560 }; 561 562 563 /// Partial specialization for pointer types. 564 template<typename _PTp> 565 struct __atomic_base<_PTp*> 566 { 567 private: 568 typedef _PTp* __pointer_type; 569 570 __pointer_type _M_p; 571 572 // Factored out to facilitate explicit specialization. 573 constexpr ptrdiff_t 574 _M_type_size(ptrdiff_t __d) const { return __d * sizeof(_PTp); } 575 576 constexpr ptrdiff_t 577 _M_type_size(ptrdiff_t __d) const volatile { return __d * sizeof(_PTp); } 578 579 public: 580 __atomic_base() noexcept = default; 581 ~__atomic_base() noexcept = default; 582 __atomic_base(const __atomic_base&) = delete; 583 __atomic_base& operator=(const __atomic_base&) = delete; 584 __atomic_base& operator=(const __atomic_base&) volatile = delete; 585 586 // Requires __pointer_type convertible to _M_p. 587 constexpr __atomic_base(__pointer_type __p) noexcept : _M_p (__p) { } 588 589 operator __pointer_type() const noexcept 590 { return load(); } 591 592 operator __pointer_type() const volatile noexcept 593 { return load(); } 594 595 __pointer_type 596 operator=(__pointer_type __p) noexcept 597 { 598 store(__p); 599 return __p; 600 } 601 602 __pointer_type 603 operator=(__pointer_type __p) volatile noexcept 604 { 605 store(__p); 606 return __p; 607 } 608 609 __pointer_type 610 operator++(int) noexcept 611 { return fetch_add(1); } 612 613 __pointer_type 614 operator++(int) volatile noexcept 615 { return fetch_add(1); } 616 617 __pointer_type 618 operator--(int) noexcept 619 { return fetch_sub(1); } 620 621 __pointer_type 622 operator--(int) volatile noexcept 623 { return fetch_sub(1); } 624 625 __pointer_type 626 operator++() noexcept 627 { return __atomic_add_fetch(&_M_p, _M_type_size(1), 628 memory_order_seq_cst); } 629 630 __pointer_type 631 operator++() volatile noexcept 632 { return __atomic_add_fetch(&_M_p, _M_type_size(1), 633 memory_order_seq_cst); } 634 635 __pointer_type 636 operator--() noexcept 637 { return __atomic_sub_fetch(&_M_p, _M_type_size(1), 638 memory_order_seq_cst); } 639 640 __pointer_type 641 operator--() volatile noexcept 642 { return __atomic_sub_fetch(&_M_p, _M_type_size(1), 643 memory_order_seq_cst); } 644 645 __pointer_type 646 operator+=(ptrdiff_t __d) noexcept 647 { return __atomic_add_fetch(&_M_p, _M_type_size(__d), 648 memory_order_seq_cst); } 649 650 __pointer_type 651 operator+=(ptrdiff_t __d) volatile noexcept 652 { return __atomic_add_fetch(&_M_p, _M_type_size(__d), 653 memory_order_seq_cst); } 654 655 __pointer_type 656 operator-=(ptrdiff_t __d) noexcept 657 { return __atomic_sub_fetch(&_M_p, _M_type_size(__d), 658 memory_order_seq_cst); } 659 660 __pointer_type 661 operator-=(ptrdiff_t __d) volatile noexcept 662 { return __atomic_sub_fetch(&_M_p, _M_type_size(__d), 663 memory_order_seq_cst); } 664 665 bool 666 is_lock_free() const noexcept 667 { 668 // Produce a fake, minimally aligned pointer. 669 return __atomic_is_lock_free(sizeof(_M_p), 670 reinterpret_cast<void *>(-__alignof(_M_p))); 671 } 672 673 bool 674 is_lock_free() const volatile noexcept 675 { 676 // Produce a fake, minimally aligned pointer. 677 return __atomic_is_lock_free(sizeof(_M_p), 678 reinterpret_cast<void *>(-__alignof(_M_p))); 679 } 680 681 _GLIBCXX_ALWAYS_INLINE void 682 store(__pointer_type __p, 683 memory_order __m = memory_order_seq_cst) noexcept 684 { 685 memory_order __b = __m & __memory_order_mask; 686 687 __glibcxx_assert(__b != memory_order_acquire); 688 __glibcxx_assert(__b != memory_order_acq_rel); 689 __glibcxx_assert(__b != memory_order_consume); 690 691 __atomic_store_n(&_M_p, __p, __m); 692 } 693 694 _GLIBCXX_ALWAYS_INLINE void 695 store(__pointer_type __p, 696 memory_order __m = memory_order_seq_cst) volatile noexcept 697 { 698 memory_order __b = __m & __memory_order_mask; 699 __glibcxx_assert(__b != memory_order_acquire); 700 __glibcxx_assert(__b != memory_order_acq_rel); 701 __glibcxx_assert(__b != memory_order_consume); 702 703 __atomic_store_n(&_M_p, __p, __m); 704 } 705 706 _GLIBCXX_ALWAYS_INLINE __pointer_type 707 load(memory_order __m = memory_order_seq_cst) const noexcept 708 { 709 memory_order __b = __m & __memory_order_mask; 710 __glibcxx_assert(__b != memory_order_release); 711 __glibcxx_assert(__b != memory_order_acq_rel); 712 713 return __atomic_load_n(&_M_p, __m); 714 } 715 716 _GLIBCXX_ALWAYS_INLINE __pointer_type 717 load(memory_order __m = memory_order_seq_cst) const volatile noexcept 718 { 719 memory_order __b = __m & __memory_order_mask; 720 __glibcxx_assert(__b != memory_order_release); 721 __glibcxx_assert(__b != memory_order_acq_rel); 722 723 return __atomic_load_n(&_M_p, __m); 724 } 725 726 _GLIBCXX_ALWAYS_INLINE __pointer_type 727 exchange(__pointer_type __p, 728 memory_order __m = memory_order_seq_cst) noexcept 729 { 730 return __atomic_exchange_n(&_M_p, __p, __m); 731 } 732 733 734 _GLIBCXX_ALWAYS_INLINE __pointer_type 735 exchange(__pointer_type __p, 736 memory_order __m = memory_order_seq_cst) volatile noexcept 737 { 738 return __atomic_exchange_n(&_M_p, __p, __m); 739 } 740 741 _GLIBCXX_ALWAYS_INLINE bool 742 compare_exchange_strong(__pointer_type& __p1, __pointer_type __p2, 743 memory_order __m1, 744 memory_order __m2) noexcept 745 { 746 memory_order __b2 = __m2 & __memory_order_mask; 747 memory_order __b1 = __m1 & __memory_order_mask; 748 __glibcxx_assert(__b2 != memory_order_release); 749 __glibcxx_assert(__b2 != memory_order_acq_rel); 750 __glibcxx_assert(__b2 <= __b1); 751 752 return __atomic_compare_exchange_n(&_M_p, &__p1, __p2, 0, __m1, __m2); 753 } 754 755 _GLIBCXX_ALWAYS_INLINE bool 756 compare_exchange_strong(__pointer_type& __p1, __pointer_type __p2, 757 memory_order __m1, 758 memory_order __m2) volatile noexcept 759 { 760 memory_order __b2 = __m2 & __memory_order_mask; 761 memory_order __b1 = __m1 & __memory_order_mask; 762 763 __glibcxx_assert(__b2 != memory_order_release); 764 __glibcxx_assert(__b2 != memory_order_acq_rel); 765 __glibcxx_assert(__b2 <= __b1); 766 767 return __atomic_compare_exchange_n(&_M_p, &__p1, __p2, 0, __m1, __m2); 768 } 769 770 _GLIBCXX_ALWAYS_INLINE __pointer_type 771 fetch_add(ptrdiff_t __d, 772 memory_order __m = memory_order_seq_cst) noexcept 773 { return __atomic_fetch_add(&_M_p, _M_type_size(__d), __m); } 774 775 _GLIBCXX_ALWAYS_INLINE __pointer_type 776 fetch_add(ptrdiff_t __d, 777 memory_order __m = memory_order_seq_cst) volatile noexcept 778 { return __atomic_fetch_add(&_M_p, _M_type_size(__d), __m); } 779 780 _GLIBCXX_ALWAYS_INLINE __pointer_type 781 fetch_sub(ptrdiff_t __d, 782 memory_order __m = memory_order_seq_cst) noexcept 783 { return __atomic_fetch_sub(&_M_p, _M_type_size(__d), __m); } 784 785 _GLIBCXX_ALWAYS_INLINE __pointer_type 786 fetch_sub(ptrdiff_t __d, 787 memory_order __m = memory_order_seq_cst) volatile noexcept 788 { return __atomic_fetch_sub(&_M_p, _M_type_size(__d), __m); } 789 }; 790 791 // @} group atomics 792 793 _GLIBCXX_END_NAMESPACE_VERSION 794 } // namespace std 795 796 #endif 797