Difference between revisions of "cpp/memory/shared ptr/atomic2"
m |
m (rv) |
||
Line 1: | Line 1: | ||
− | {{cpp/title | atomic<small> | + | {{cpp/title | atomic<small>(std::shared_ptr)</small>}} |
{{cpp/memory/shared_ptr/navbar}} | {{cpp/memory/shared_ptr/navbar}} | ||
{{dcl begin}} | {{dcl begin}} |
Revision as of 15:15, 23 February 2020
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.
Member types
Member type | Definition |
value_type
|
std::shared_ptr<T> |
Member functions
All non-specialized std::atomic functions are also provided by this specialization, and no additional member functions.
constexpr atomic() noexcept = default; |
(1) | |
atomic(std::shared_ptr<T> desired) noexcept; |
(2) | |
atomic(const atomic&) = delete; |
(3) | |
shared_ptr<T>
to default-constructed valueshared_ptr<T>
to a copy of desired
. As with any std::atomic type, initialization is not an atomic operation. void operator=(const atomic&) = delete; |
(1) | |
void operator=(std::shared_ptr<T> desired) noexcept; |
(2) | |
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) | |
expected
and shares ownership with it, or if both underlying and expected
are empty, assigns from desired
to the underlying std::shared_ptr<T>, returns true, and orders memory according to success
, otherwise assigns from the underlying std::shared_ptr<T> to expected
, returns false, and orders memory according to failure
. The behavior is undefined if failure
is std::memory_order_release or std::memory_order_acq_rel. On success, the operation is an atomic read-modify-write operation on *this and expected
is not accessed after the atomic update. On failure, the operation is an atomic load operation on *this and expected
is updated with the existing value read from the atomic object. This update to expected
's 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 load(order) changes or *this is notified by notify_one()
or notify_all()
. This functions is allowed to unblock spuriously, i.e. returns due to reasons other than value change or notification.
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.
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*/; |
||
Example
This section is incomplete Reason: no example |
See also
(C++11) |
atomic class template and specializations for bool, integral, floating-point,(since C++20) and pointer types (class template) |