Where Online Learning is simpler!
The C and C++ Include Header Files
/usr/include/c++/13/bits/shared_ptr_atomic.h
$ cat -n /usr/include/c++/13/bits/shared_ptr_atomic.h 1 // shared_ptr atomic access -*- C++ -*- 2 3 // Copyright (C) 2014-2023 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/shared_ptr_atomic.h 26 * This is an internal header file, included by other library headers. 27 * Do not attempt to use it directly. @headername{memory} 28 */ 29 30 #ifndef _SHARED_PTR_ATOMIC_H 31 #define _SHARED_PTR_ATOMIC_H 1 32 33 #include <bits/atomic_base.h> 34 35 // Annotations for the custom locking in atomic<shared_ptr<T>>. 36 #if defined _GLIBCXX_TSAN && __has_include(<sanitizer/tsan_interface.h>) 37 #include <sanitizer/tsan_interface.h> 38 #define _GLIBCXX_TSAN_MUTEX_DESTROY(X) \ 39 __tsan_mutex_destroy(X, __tsan_mutex_not_static) 40 #define _GLIBCXX_TSAN_MUTEX_TRY_LOCK(X) \ 41 __tsan_mutex_pre_lock(X, __tsan_mutex_not_static|__tsan_mutex_try_lock) 42 #define _GLIBCXX_TSAN_MUTEX_TRY_LOCK_FAILED(X) __tsan_mutex_post_lock(X, \ 43 __tsan_mutex_not_static|__tsan_mutex_try_lock_failed, 0) 44 #define _GLIBCXX_TSAN_MUTEX_LOCKED(X) \ 45 __tsan_mutex_post_lock(X, __tsan_mutex_not_static, 0) 46 #define _GLIBCXX_TSAN_MUTEX_PRE_UNLOCK(X) __tsan_mutex_pre_unlock(X, 0) 47 #define _GLIBCXX_TSAN_MUTEX_POST_UNLOCK(X) __tsan_mutex_post_unlock(X, 0) 48 #define _GLIBCXX_TSAN_MUTEX_PRE_SIGNAL(X) __tsan_mutex_pre_signal(X, 0) 49 #define _GLIBCXX_TSAN_MUTEX_POST_SIGNAL(X) __tsan_mutex_post_signal(X, 0) 50 #else 51 #define _GLIBCXX_TSAN_MUTEX_DESTROY(X) 52 #define _GLIBCXX_TSAN_MUTEX_TRY_LOCK(X) 53 #define _GLIBCXX_TSAN_MUTEX_TRY_LOCK_FAILED(X) 54 #define _GLIBCXX_TSAN_MUTEX_LOCKED(X) 55 #define _GLIBCXX_TSAN_MUTEX_PRE_UNLOCK(X) 56 #define _GLIBCXX_TSAN_MUTEX_POST_UNLOCK(X) 57 #define _GLIBCXX_TSAN_MUTEX_PRE_SIGNAL(X) 58 #define _GLIBCXX_TSAN_MUTEX_POST_SIGNAL(X) 59 #endif 60 61 namespace std _GLIBCXX_VISIBILITY(default) 62 { 63 _GLIBCXX_BEGIN_NAMESPACE_VERSION 64 65 /** 66 * @addtogroup pointer_abstractions 67 * @relates shared_ptr 68 * @{ 69 */ 70 71 /// @cond undocumented 72 73 struct _Sp_locker 74 { 75 _Sp_locker(const _Sp_locker&) = delete; 76 _Sp_locker& operator=(const _Sp_locker&) = delete; 77 78 #ifdef __GTHREADS 79 explicit 80 _Sp_locker(const void*) noexcept; 81 _Sp_locker(const void*, const void*) noexcept; 82 ~_Sp_locker(); 83 84 private: 85 unsigned char _M_key1; 86 unsigned char _M_key2; 87 #else 88 explicit _Sp_locker(const void*, const void* = nullptr) { } 89 #endif 90 }; 91 92 /// @endcond 93 94 /** 95 * @brief Report whether shared_ptr atomic operations are lock-free. 96 * @param __p A non-null pointer to a shared_ptr object. 97 * @return True if atomic access to @c *__p is lock-free, false otherwise. 98 * @{ 99 */ 100 template<typename _Tp, _Lock_policy _Lp> 101 inline bool 102 atomic_is_lock_free(const __shared_ptr<_Tp, _Lp>*) 103 { 104 #ifdef __GTHREADS 105 return __gthread_active_p() == 0; 106 #else 107 return true; 108 #endif 109 } 110 111 template<typename _Tp> 112 inline bool 113 atomic_is_lock_free(const shared_ptr<_Tp>* __p) 114 { return std::atomic_is_lock_free<_Tp, __default_lock_policy>(__p); } 115 116 /// @} 117 118 /** 119 * @brief Atomic load for shared_ptr objects. 120 * @param __p A non-null pointer to a shared_ptr object. 121 * @return @c *__p 122 * 123 * The memory order shall not be `memory_order_release` or 124 * `memory_order_acq_rel`. 125 * @{ 126 */ 127 template<typename _Tp> 128 inline shared_ptr<_Tp> 129 atomic_load_explicit(const shared_ptr<_Tp>* __p, memory_order) 130 { 131 _Sp_locker __lock{__p}; 132 return *__p; 133 } 134 135 template<typename _Tp> 136 inline shared_ptr<_Tp> 137 atomic_load(const shared_ptr<_Tp>* __p) 138 { return std::atomic_load_explicit(__p, memory_order_seq_cst); } 139 140 template<typename _Tp, _Lock_policy _Lp> 141 inline __shared_ptr<_Tp, _Lp> 142 atomic_load_explicit(const __shared_ptr<_Tp, _Lp>* __p, memory_order) 143 { 144 _Sp_locker __lock{__p}; 145 return *__p; 146 } 147 148 template<typename _Tp, _Lock_policy _Lp> 149 inline __shared_ptr<_Tp, _Lp> 150 atomic_load(const __shared_ptr<_Tp, _Lp>* __p) 151 { return std::atomic_load_explicit(__p, memory_order_seq_cst); } 152 /// @} 153 154 /** 155 * @brief Atomic store for shared_ptr objects. 156 * @param __p A non-null pointer to a shared_ptr object. 157 * @param __r The value to store. 158 * 159 * The memory order shall not be `memory_order_acquire` or 160 * `memory_order_acq_rel`. 161 * @{ 162 */ 163 template<typename _Tp> 164 inline void 165 atomic_store_explicit(shared_ptr<_Tp>* __p, shared_ptr<_Tp> __r, 166 memory_order) 167 { 168 _Sp_locker __lock{__p}; 169 __p->swap(__r); // use swap so that **__p not destroyed while lock held 170 } 171 172 template<typename _Tp> 173 inline void 174 atomic_store(shared_ptr<_Tp>* __p, shared_ptr<_Tp> __r) 175 { std::atomic_store_explicit(__p, std::move(__r), memory_order_seq_cst); } 176 177 template<typename _Tp, _Lock_policy _Lp> 178 inline void 179 atomic_store_explicit(__shared_ptr<_Tp, _Lp>* __p, 180 __shared_ptr<_Tp, _Lp> __r, 181 memory_order) 182 { 183 _Sp_locker __lock{__p}; 184 __p->swap(__r); // use swap so that **__p not destroyed while lock held 185 } 186 187 template<typename _Tp, _Lock_policy _Lp> 188 inline void 189 atomic_store(__shared_ptr<_Tp, _Lp>* __p, __shared_ptr<_Tp, _Lp> __r) 190 { std::atomic_store_explicit(__p, std::move(__r), memory_order_seq_cst); } 191 /// @} 192 193 /** 194 * @brief Atomic exchange for shared_ptr objects. 195 * @param __p A non-null pointer to a shared_ptr object. 196 * @param __r New value to store in `*__p`. 197 * @return The original value of `*__p` 198 * @{ 199 */ 200 template<typename _Tp> 201 inline shared_ptr<_Tp> 202 atomic_exchange_explicit(shared_ptr<_Tp>* __p, shared_ptr<_Tp> __r, 203 memory_order) 204 { 205 _Sp_locker __lock{__p}; 206 __p->swap(__r); 207 return __r; 208 } 209 210 template<typename _Tp> 211 inline shared_ptr<_Tp> 212 atomic_exchange(shared_ptr<_Tp>* __p, shared_ptr<_Tp> __r) 213 { 214 return std::atomic_exchange_explicit(__p, std::move(__r), 215 memory_order_seq_cst); 216 } 217 218 template<typename _Tp, _Lock_policy _Lp> 219 inline __shared_ptr<_Tp, _Lp> 220 atomic_exchange_explicit(__shared_ptr<_Tp, _Lp>* __p, 221 __shared_ptr<_Tp, _Lp> __r, 222 memory_order) 223 { 224 _Sp_locker __lock{__p}; 225 __p->swap(__r); 226 return __r; 227 } 228 229 template<typename _Tp, _Lock_policy _Lp> 230 inline __shared_ptr<_Tp, _Lp> 231 atomic_exchange(__shared_ptr<_Tp, _Lp>* __p, __shared_ptr<_Tp, _Lp> __r) 232 { 233 return std::atomic_exchange_explicit(__p, std::move(__r), 234 memory_order_seq_cst); 235 } 236 /// @} 237 238 /** 239 * @brief Atomic compare-and-swap for shared_ptr objects. 240 * @param __p A non-null pointer to a shared_ptr object. 241 * @param __v A non-null pointer to a shared_ptr object. 242 * @param __w A non-null pointer to a shared_ptr object. 243 * @return True if `*__p` was equivalent to `*__v`, false otherwise. 244 * 245 * The memory order for failure shall not be `memory_order_release` or 246 * `memory_order_acq_rel`. 247 * @{ 248 */ 249 template<typename _Tp> 250 bool 251 atomic_compare_exchange_strong_explicit(shared_ptr<_Tp>* __p, 252 shared_ptr<_Tp>* __v, 253 shared_ptr<_Tp> __w, 254 memory_order, 255 memory_order) 256 { 257 shared_ptr<_Tp> __x; // goes out of scope after __lock 258 _Sp_locker __lock{__p, __v}; 259 owner_less<shared_ptr<_Tp>> __less; 260 if (*__p == *__v && !__less(*__p, *__v) && !__less(*__v, *__p)) 261 { 262 __x = std::move(*__p); 263 *__p = std::move(__w); 264 return true; 265 } 266 __x = std::move(*__v); 267 *__v = *__p; 268 return false; 269 } 270 271 template<typename _Tp> 272 inline bool 273 atomic_compare_exchange_strong(shared_ptr<_Tp>* __p, shared_ptr<_Tp>* __v, 274 shared_ptr<_Tp> __w) 275 { 276 return std::atomic_compare_exchange_strong_explicit(__p, __v, 277 std::move(__w), memory_order_seq_cst, memory_order_seq_cst); 278 } 279 280 template<typename _Tp> 281 inline bool 282 atomic_compare_exchange_weak_explicit(shared_ptr<_Tp>* __p, 283 shared_ptr<_Tp>* __v, 284 shared_ptr<_Tp> __w, 285 memory_order __success, 286 memory_order __failure) 287 { 288 return std::atomic_compare_exchange_strong_explicit(__p, __v, 289 std::move(__w), __success, __failure); 290 } 291 292 template<typename _Tp> 293 inline bool 294 atomic_compare_exchange_weak(shared_ptr<_Tp>* __p, shared_ptr<_Tp>* __v, 295 shared_ptr<_Tp> __w) 296 { 297 return std::atomic_compare_exchange_weak_explicit(__p, __v, 298 std::move(__w), memory_order_seq_cst, memory_order_seq_cst); 299 } 300 301 template<typename _Tp, _Lock_policy _Lp> 302 bool 303 atomic_compare_exchange_strong_explicit(__shared_ptr<_Tp, _Lp>* __p, 304 __shared_ptr<_Tp, _Lp>* __v, 305 __shared_ptr<_Tp, _Lp> __w, 306 memory_order, 307 memory_order) 308 { 309 __shared_ptr<_Tp, _Lp> __x; // goes out of scope after __lock 310 _Sp_locker __lock{__p, __v}; 311 owner_less<__shared_ptr<_Tp, _Lp>> __less; 312 if (*__p == *__v && !__less(*__p, *__v) && !__less(*__v, *__p)) 313 { 314 __x = std::move(*__p); 315 *__p = std::move(__w); 316 return true; 317 } 318 __x = std::move(*__v); 319 *__v = *__p; 320 return false; 321 } 322 323 template<typename _Tp, _Lock_policy _Lp> 324 inline bool 325 atomic_compare_exchange_strong(__shared_ptr<_Tp, _Lp>* __p, 326 __shared_ptr<_Tp, _Lp>* __v, 327 __shared_ptr<_Tp, _Lp> __w) 328 { 329 return std::atomic_compare_exchange_strong_explicit(__p, __v, 330 std::move(__w), memory_order_seq_cst, memory_order_seq_cst); 331 } 332 333 template<typename _Tp, _Lock_policy _Lp> 334 inline bool 335 atomic_compare_exchange_weak_explicit(__shared_ptr<_Tp, _Lp>* __p, 336 __shared_ptr<_Tp, _Lp>* __v, 337 __shared_ptr<_Tp, _Lp> __w, 338 memory_order __success, 339 memory_order __failure) 340 { 341 return std::atomic_compare_exchange_strong_explicit(__p, __v, 342 std::move(__w), __success, __failure); 343 } 344 345 template<typename _Tp, _Lock_policy _Lp> 346 inline bool 347 atomic_compare_exchange_weak(__shared_ptr<_Tp, _Lp>* __p, 348 __shared_ptr<_Tp, _Lp>* __v, 349 __shared_ptr<_Tp, _Lp> __w) 350 { 351 return std::atomic_compare_exchange_weak_explicit(__p, __v, 352 std::move(__w), memory_order_seq_cst, memory_order_seq_cst); 353 } 354 /// @} 355 356 /// @} group pointer_abstractions 357 358 #if __cplusplus >= 202002L 359 # define __cpp_lib_atomic_shared_ptr 201711L 360 template<typename _Tp> 361 struct atomic; 362 363 /** 364 * @addtogroup pointer_abstractions 365 * @relates shared_ptr 366 * @{ 367 */ 368 369 template<typename _Up> 370 static constexpr bool __is_shared_ptr = false; 371 template<typename _Up> 372 static constexpr bool __is_shared_ptr<shared_ptr<_Up>> = true; 373 374 template<typename _Tp> 375 class _Sp_atomic 376 { 377 using value_type = _Tp; 378 379 friend struct atomic<_Tp>; 380 381 // An atomic version of __shared_count<> and __weak_count<>. 382 // Stores a _Sp_counted_base<>* but uses the LSB as a lock. 383 struct _Atomic_count 384 { 385 // Either __shared_count<> or __weak_count<> 386 using __count_type = decltype(_Tp::_M_refcount); 387 388 // _Sp_counted_base<>* 389 using pointer = decltype(__count_type::_M_pi); 390 391 // Ensure we can use the LSB as the lock bit. 392 static_assert(alignof(remove_pointer_t<pointer>) > 1); 393 394 constexpr _Atomic_count() noexcept = default; 395 396 explicit 397 _Atomic_count(__count_type&& __c) noexcept 398 : _M_val(reinterpret_cast<uintptr_t>(__c._M_pi)) 399 { 400 __c._M_pi = nullptr; 401 } 402 403 ~_Atomic_count() 404 { 405 auto __val = _M_val.load(memory_order_relaxed); 406 _GLIBCXX_TSAN_MUTEX_DESTROY(&_M_val); 407 __glibcxx_assert(!(__val & _S_lock_bit)); 408 if (auto __pi = reinterpret_cast<pointer>(__val)) 409 { 410 if constexpr (__is_shared_ptr<_Tp>) 411 __pi->_M_release(); 412 else 413 __pi->_M_weak_release(); 414 } 415 } 416 417 _Atomic_count(const _Atomic_count&) = delete; 418 _Atomic_count& operator=(const _Atomic_count&) = delete; 419 420 // Precondition: Caller does not hold lock! 421 // Returns the raw pointer value without the lock bit set. 422 pointer 423 lock(memory_order __o) const noexcept 424 { 425 // To acquire the lock we flip the LSB from 0 to 1. 426 427 auto __current = _M_val.load(memory_order_relaxed); 428 while (__current & _S_lock_bit) 429 { 430 #if __cpp_lib_atomic_wait 431 __detail::__thread_relax(); 432 #endif 433 __current = _M_val.load(memory_order_relaxed); 434 } 435 436 _GLIBCXX_TSAN_MUTEX_TRY_LOCK(&_M_val); 437 438 while (!_M_val.compare_exchange_strong(__current, 439 __current | _S_lock_bit, 440 __o, 441 memory_order_relaxed)) 442 { 443 _GLIBCXX_TSAN_MUTEX_TRY_LOCK_FAILED(&_M_val); 444 #if __cpp_lib_atomic_wait 445 __detail::__thread_relax(); 446 #endif 447 __current = __current & ~_S_lock_bit; 448 _GLIBCXX_TSAN_MUTEX_TRY_LOCK(&_M_val); 449 } 450 _GLIBCXX_TSAN_MUTEX_LOCKED(&_M_val); 451 return reinterpret_cast<pointer>(__current); 452 } 453 454 // Precondition: caller holds lock! 455 void 456 unlock(memory_order __o) const noexcept 457 { 458 _GLIBCXX_TSAN_MUTEX_PRE_UNLOCK(&_M_val); 459 _M_val.fetch_sub(1, __o); 460 _GLIBCXX_TSAN_MUTEX_POST_UNLOCK(&_M_val); 461 } 462 463 // Swaps the values of *this and __c, and unlocks *this. 464 // Precondition: caller holds lock! 465 void 466 _M_swap_unlock(__count_type& __c, memory_order __o) noexcept 467 { 468 if (__o != memory_order_seq_cst) 469 __o = memory_order_release; 470 auto __x = reinterpret_cast<uintptr_t>(__c._M_pi); 471 _GLIBCXX_TSAN_MUTEX_PRE_UNLOCK(&_M_val); 472 __x = _M_val.exchange(__x, __o); 473 _GLIBCXX_TSAN_MUTEX_POST_UNLOCK(&_M_val); 474 __c._M_pi = reinterpret_cast<pointer>(__x & ~_S_lock_bit); 475 } 476 477 #if __cpp_lib_atomic_wait 478 // Precondition: caller holds lock! 479 void 480 _M_wait_unlock(memory_order __o) const noexcept 481 { 482 _GLIBCXX_TSAN_MUTEX_PRE_UNLOCK(&_M_val); 483 auto __v = _M_val.fetch_sub(1, memory_order_relaxed); 484 _GLIBCXX_TSAN_MUTEX_POST_UNLOCK(&_M_val); 485 _M_val.wait(__v & ~_S_lock_bit, __o); 486 } 487 488 void 489 notify_one() noexcept 490 { 491 _GLIBCXX_TSAN_MUTEX_PRE_SIGNAL(&_M_val); 492 _M_val.notify_one(); 493 _GLIBCXX_TSAN_MUTEX_POST_SIGNAL(&_M_val); 494 } 495 496 void 497 notify_all() noexcept 498 { 499 _GLIBCXX_TSAN_MUTEX_PRE_SIGNAL(&_M_val); 500 _M_val.notify_all(); 501 _GLIBCXX_TSAN_MUTEX_POST_SIGNAL(&_M_val); 502 } 503 #endif 504 505 private: 506 mutable __atomic_base<uintptr_t> _M_val{0}; 507 static constexpr uintptr_t _S_lock_bit{1}; 508 }; 509 510 typename _Tp::element_type* _M_ptr = nullptr; 511 _Atomic_count _M_refcount; 512 513 static typename _Atomic_count::pointer 514 _S_add_ref(typename _Atomic_count::pointer __p) 515 { 516 if (__p) 517 { 518 if constexpr (__is_shared_ptr<_Tp>) 519 __p->_M_add_ref_copy(); 520 else 521 __p->_M_weak_add_ref(); 522 } 523 return __p; 524 } 525 526 constexpr _Sp_atomic() noexcept = default; 527 528 explicit 529 _Sp_atomic(value_type __r) noexcept 530 : _M_ptr(__r._M_ptr), _M_refcount(std::move(__r._M_refcount)) 531 { } 532 533 ~_Sp_atomic() = default; 534 535 _Sp_atomic(const _Sp_atomic&) = delete; 536 void operator=(const _Sp_atomic&) = delete; 537 538 value_type 539 load(memory_order __o) const noexcept 540 { 541 __glibcxx_assert(__o != memory_order_release 542 && __o != memory_order_acq_rel); 543 // Ensure that the correct value of _M_ptr is visible after locking., 544 // by upgrading relaxed or consume to acquire. 545 if (__o != memory_order_seq_cst) 546 __o = memory_order_acquire; 547 548 value_type __ret; 549 auto __pi = _M_refcount.lock(__o); 550 __ret._M_ptr = _M_ptr; 551 __ret._M_refcount._M_pi = _S_add_ref(__pi); 552 _M_refcount.unlock(memory_order_relaxed); 553 return __ret; 554 } 555 556 void 557 swap(value_type& __r, memory_order __o) noexcept 558 { 559 _M_refcount.lock(memory_order_acquire); 560 std::swap(_M_ptr, __r._M_ptr); 561 _M_refcount._M_swap_unlock(__r._M_refcount, __o); 562 } 563 564 bool 565 compare_exchange_strong(value_type& __expected, value_type __desired, 566 memory_order __o, memory_order __o2) noexcept 567 { 568 bool __result = true; 569 auto __pi = _M_refcount.lock(memory_order_acquire); 570 if (_M_ptr == __expected._M_ptr 571 && __pi == __expected._M_refcount._M_pi) 572 { 573 _M_ptr = __desired._M_ptr; 574 _M_refcount._M_swap_unlock(__desired._M_refcount, __o); 575 } 576 else 577 { 578 _Tp __sink = std::move(__expected); 579 __expected._M_ptr = _M_ptr; 580 __expected._M_refcount._M_pi = _S_add_ref(__pi); 581 _M_refcount.unlock(__o2); 582 __result = false; 583 } 584 return __result; 585 } 586 587 #if __cpp_lib_atomic_wait 588 void 589 wait(value_type __old, memory_order __o) const noexcept 590 { 591 auto __pi = _M_refcount.lock(memory_order_acquire); 592 if (_M_ptr == __old._M_ptr && __pi == __old._M_refcount._M_pi) 593 _M_refcount._M_wait_unlock(__o); 594 else 595 _M_refcount.unlock(memory_order_relaxed); 596 } 597 598 void 599 notify_one() noexcept 600 { 601 _M_refcount.notify_one(); 602 } 603 604 void 605 notify_all() noexcept 606 { 607 _M_refcount.notify_all(); 608 } 609 #endif 610 }; 611 612 template<typename _Tp> 613 struct atomic<shared_ptr<_Tp>> 614 { 615 public: 616 using value_type = shared_ptr<_Tp>; 617 618 static constexpr bool is_always_lock_free = false; 619 620 bool 621 is_lock_free() const noexcept 622 { return false; } 623 624 constexpr atomic() noexcept = default; 625 626 // _GLIBCXX_RESOLVE_LIB_DEFECTS 627 // 3661. constinit atomic<shared_ptr<T>> a(nullptr); should work 628 constexpr atomic(nullptr_t) noexcept : atomic() { } 629 630 atomic(shared_ptr<_Tp> __r) noexcept 631 : _M_impl(std::move(__r)) 632 { } 633 634 atomic(const atomic&) = delete; 635 void operator=(const atomic&) = delete; 636 637 shared_ptr<_Tp> 638 load(memory_order __o = memory_order_seq_cst) const noexcept 639 { return _M_impl.load(__o); } 640 641 operator shared_ptr<_Tp>() const noexcept 642 { return _M_impl.load(memory_order_seq_cst); } 643 644 void 645 store(shared_ptr<_Tp> __desired, 646 memory_order __o = memory_order_seq_cst) noexcept 647 { _M_impl.swap(__desired, __o); } 648 649 void 650 operator=(shared_ptr<_Tp> __desired) noexcept 651 { _M_impl.swap(__desired, memory_order_seq_cst); } 652 653 // _GLIBCXX_RESOLVE_LIB_DEFECTS 654 // 3893. LWG 3661 broke atomic<shared_ptr<T>> a; a = nullptr; 655 void 656 operator=(nullptr_t) noexcept 657 { store(nullptr); } 658 659 shared_ptr<_Tp> 660 exchange(shared_ptr<_Tp> __desired, 661 memory_order __o = memory_order_seq_cst) noexcept 662 { 663 _M_impl.swap(__desired, __o); 664 return __desired; 665 } 666 667 bool 668 compare_exchange_strong(shared_ptr<_Tp>& __expected, 669 shared_ptr<_Tp> __desired, 670 memory_order __o, memory_order __o2) noexcept 671 { 672 return _M_impl.compare_exchange_strong(__expected, __desired, __o, __o2); 673 } 674 675 bool 676 compare_exchange_strong(value_type& __expected, value_type __desired, 677 memory_order __o = memory_order_seq_cst) noexcept 678 { 679 memory_order __o2; 680 switch (__o) 681 { 682 case memory_order_acq_rel: 683 __o2 = memory_order_acquire; 684 break; 685 case memory_order_release: 686 __o2 = memory_order_relaxed; 687 break; 688 default: 689 __o2 = __o; 690 } 691 return compare_exchange_strong(__expected, std::move(__desired), 692 __o, __o2); 693 } 694 695 bool 696 compare_exchange_weak(value_type& __expected, value_type __desired, 697 memory_order __o, memory_order __o2) noexcept 698 { 699 return compare_exchange_strong(__expected, std::move(__desired), 700 __o, __o2); 701 } 702 703 bool 704 compare_exchange_weak(value_type& __expected, value_type __desired, 705 memory_order __o = memory_order_seq_cst) noexcept 706 { 707 return compare_exchange_strong(__expected, std::move(__desired), __o); 708 } 709 710 #if __cpp_lib_atomic_wait 711 void 712 wait(value_type __old, 713 memory_order __o = memory_order_seq_cst) const noexcept 714 { 715 _M_impl.wait(std::move(__old), __o); 716 } 717 718 void 719 notify_one() noexcept 720 { 721 _M_impl.notify_one(); 722 } 723 724 void 725 notify_all() noexcept 726 { 727 _M_impl.notify_all(); 728 } 729 #endif 730 731 private: 732 _Sp_atomic<shared_ptr<_Tp>> _M_impl; 733 }; 734 735 template<typename _Tp> 736 struct atomic<weak_ptr<_Tp>> 737 { 738 public: 739 using value_type = weak_ptr<_Tp>; 740 741 static constexpr bool is_always_lock_free = false; 742 743 bool 744 is_lock_free() const noexcept 745 { return false; } 746 747 constexpr atomic() noexcept = default; 748 749 atomic(weak_ptr<_Tp> __r) noexcept 750 : _M_impl(move(__r)) 751 { } 752 753 atomic(const atomic&) = delete; 754 void operator=(const atomic&) = delete; 755 756 weak_ptr<_Tp> 757 load(memory_order __o = memory_order_seq_cst) const noexcept 758 { return _M_impl.load(__o); } 759 760 operator weak_ptr<_Tp>() const noexcept 761 { return _M_impl.load(memory_order_seq_cst); } 762 763 void 764 store(weak_ptr<_Tp> __desired, 765 memory_order __o = memory_order_seq_cst) noexcept 766 { _M_impl.swap(__desired, __o); } 767 768 void 769 operator=(weak_ptr<_Tp> __desired) noexcept 770 { _M_impl.swap(__desired, memory_order_seq_cst); } 771 772 weak_ptr<_Tp> 773 exchange(weak_ptr<_Tp> __desired, 774 memory_order __o = memory_order_seq_cst) noexcept 775 { 776 _M_impl.swap(__desired, __o); 777 return __desired; 778 } 779 780 bool 781 compare_exchange_strong(weak_ptr<_Tp>& __expected, 782 weak_ptr<_Tp> __desired, 783 memory_order __o, memory_order __o2) noexcept 784 { 785 return _M_impl.compare_exchange_strong(__expected, __desired, __o, __o2); 786 } 787 788 bool 789 compare_exchange_strong(value_type& __expected, value_type __desired, 790 memory_order __o = memory_order_seq_cst) noexcept 791 { 792 memory_order __o2; 793 switch (__o) 794 { 795 case memory_order_acq_rel: 796 __o2 = memory_order_acquire; 797 break; 798 case memory_order_release: 799 __o2 = memory_order_relaxed; 800 break; 801 default: 802 __o2 = __o; 803 } 804 return compare_exchange_strong(__expected, std::move(__desired), 805 __o, __o2); 806 } 807 808 bool 809 compare_exchange_weak(value_type& __expected, value_type __desired, 810 memory_order __o, memory_order __o2) noexcept 811 { 812 return compare_exchange_strong(__expected, std::move(__desired), 813 __o, __o2); 814 } 815 816 bool 817 compare_exchange_weak(value_type& __expected, value_type __desired, 818 memory_order __o = memory_order_seq_cst) noexcept 819 { 820 return compare_exchange_strong(__expected, std::move(__desired), __o); 821 } 822 823 #if __cpp_lib_atomic_wait 824 void 825 wait(value_type __old, 826 memory_order __o = memory_order_seq_cst) const noexcept 827 { 828 _M_impl.wait(std::move(__old), __o); 829 } 830 831 void 832 notify_one() noexcept 833 { 834 _M_impl.notify_one(); 835 } 836 837 void 838 notify_all() noexcept 839 { 840 _M_impl.notify_all(); 841 } 842 #endif 843 844 private: 845 _Sp_atomic<weak_ptr<_Tp>> _M_impl; 846 }; 847 /// @} group pointer_abstractions 848 #endif // C++20 849 850 _GLIBCXX_END_NAMESPACE_VERSION 851 } // namespace 852 853 #endif // _SHARED_PTR_ATOMIC_H
Welcome to MyWebUniversity on May 26, 2025.
Contact us
|
About us
|
Term of use
|
Copyright © 2000-2025 MyWebUniversity.com ™