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