std::atomic<std::shared_ptr>
Defined in header <memory>
|
||
template< class T > struct std::atomic<std::shared_ptr<T>>; |
(since C++20) | |
The partial template specialization of std::atomic for std::shared_ptr<T> allows users to manipulate shared_ptr
objects atomically.
If multiple threads of execution access the same std::shared_ptr object without synchronization and any of those accesses uses a non-const member function of shared_ptr then a data race will occur unless all such access is performed through an instance of std::atomic<std::shared_ptr> (or, deprecated as of C++20, through the standalone functions for atomic access to std::shared_ptr).
Associated use_count
increments are guaranteed to be part of the atomic operation. Associated use_count
decrements are sequenced after the atomic operation, but are not required to be part of it, except for the use_count
change when overriding expected in a failed CAS. Any associated deletion and deallocation are sequenced after the atomic update step and are not part of the atomic operation.
Note that the control block of a shared_ptr
is thread-safe: different non-atomic std::shared_ptr objects can be accessed using mutable operations, such as operator= or reset, simultaneously by multiple threads, even when these instances are copies, and share the same control block internally.
The type T may be an incomplete type.
[edit] Member types
Member type | Definition |
value_type
|
std::shared_ptr<T> |
[edit] Member functions
All non-specialized std::atomic functions are also provided by this specialization, and no additional member functions.
constexpr atomic() noexcept = default; |
(1) | |
constexpr atomic( std::nullptr_t ) noexcept : atomic() {} |
(2) | |
atomic( std::shared_ptr<T> desired ) noexcept; |
(3) | |
atomic( const atomic& ) = delete; |
(4) | |
void operator=( const atomic& ) = delete; |
(1) | |
void operator=( std::shared_ptr<T> desired ) noexcept; |
(2) | |
void operator=( std::nullptr_t ) noexcept; |
(3) | |
bool is_lock_free() const noexcept; |
||
Returns true if the atomic operations on all objects of this type are lock-free, false otherwise.
void store( std::shared_ptr<T> desired, std::memory_order order = std::memory_order_seq_cst ) noexcept; |
||
Atomically replaces the value of *this with the value of desired as if by p.swap(desired) where p is the underlying std::shared_ptr<T>. Memory is ordered according to order. The behavior is undefined if order is std::memory_order_consume, std::memory_order_acquire, or std::memory_order_acq_rel.
std::shared_ptr<T> load( std::memory_order order = std::memory_order_seq_cst ) const noexcept; |
||
Atomically returns a copy of the underlying shared pointer. Memory is ordered according to order. The behavior is undefined if order is std::memory_order_release or std::memory_order_acq_rel.
std::shared_ptr<T> exchange( std::shared_ptr<T> desired, std::memory_order order = std::memory_order_seq_cst ) noexcept; |
||
Atomically replaces the underlying std::shared_ptr<T> with desired as if by p.swap(desired) where p is the underlying std::shared_ptr<T> and returns a copy of the value that p had immediately before the swap. Memory is ordered according to order. This is an atomic read-modify-write operation.
bool compare_exchange_strong( std::shared_ptr<T>& expected, std::shared_ptr<T> desired, std::memory_order success, std::memory_order failure ) noexcept; |
(1) | |
bool compare_exchange_weak( std::shared_ptr<T>& expected, std::shared_ptr<T> desired, std::memory_order success, std::memory_order failure ) noexcept; |
(2) | |
bool compare_exchange_strong( std::shared_ptr<T>& expected, std::shared_ptr<T> desired, std::memory_order order = std::memory_order_seq_cst ) noexcept; |
(3) | |
bool compare_exchange_weak( std::shared_ptr<T>& expected, std::shared_ptr<T> desired, std::memory_order order = std::memory_order_seq_cst ) noexcept; |
(4) | |
use_count
is part of this atomic operation, although the write itself (and any subsequent deallocation/destruction) is not required to be.fail_order
is the same as order except that std::memory_order_acq_rel is replaced by std::memory_order_acquire and std::memory_order_release is replaced by std::memory_order_relaxed.fail_order
is the same as order except that std::memory_order_acq_rel is replaced by std::memory_order_acquire and std::memory_order_release is replaced by std::memory_order_relaxed.
void wait( std::shared_ptr<T> old, std::memory_order order = std::memory_order_seq_cst ) const noexcept; |
||
Performs an atomic waiting operation.
Compares load(order) with old and if they are equivalent then blocks until *this is notified by notify_one()
or notify_all()
. This is repeated until load(order) changes. This function is guaranteed to return only if value has changed, even if underlying implementation unblocks spuriously.
Memory is ordered according to order. The behavior is undefined if order is std::memory_order_release or std::memory_order_acq_rel.
Notes: two shared_ptr
s are equivalent if they store the same pointer and either share ownership or are both empty.
void notify_one() noexcept; |
||
Performs an atomic notifying operation.
If there is a thread blocked in atomic waiting operations (i.e. wait()
) on *this, then unblocks at least one such thread; otherwise does nothing.
void notify_all() noexcept; |
||
Performs an atomic notifying operation.
Unblocks all threads blocked in atomic waiting operations (i.e. wait()
) on *this, if there are any; otherwise does nothing.
[edit] Member constants
The only standard std::atomic member constant is_always_lock_free
is also provided by this specialization.
static constexpr bool is_always_lock_free = /*implementation-defined*/; |
||
[edit] Notes
Feature-test macro | Value | Std | Feature |
---|---|---|---|
__cpp_lib_atomic_shared_ptr |
201711L | (C++20) | std::atomic<std::shared_ptr>
|
[edit] Example
This section is incomplete Reason: no example |
[edit] Defect reports
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
DR | Applied to | Behavior as published | Correct behavior |
---|---|---|---|
LWG 3661 | C++20 | atomic<shared_ptr<T>> was not constant-initializable from nullptr
|
made constant-initializable |
LWG 3893 | C++20 | LWG3661 made atomic<shared_ptr<T>> not assignable from nullptr_t
|
assignability restored |
[edit] See also
(C++11) |
atomic class template and specializations for bool, integral, floating-point,(since C++20) and pointer types (class template) |