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