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