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