std::atomic<std::shared_ptr>
Defined in header <memory>
.
Declarations
template< class T >
struct std::atomic<std::shared_ptr<T>>;
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.
atomic<shared_ptr<T>>::atomic
constexpr atomic() noexcept = default; ()
constexpr atomic( std::nullptr_t ) noexcept : atomic() {} ()
atomic( std::shared_ptr<T> desired ) noexcept; ()
atomic( const atomic& ) = delete; (4)
1,2) Initializes the underlying shared_ptr<T>
to the null value.
3) Initializes the underlying shared_ptr<T>
to a copy of desired. As with any std::atomic
type, initialization is not an atomic operation.
4) Atomic types are not copy/move constructible
atomic<shared_ptr<T>>::operator=
void operator=( const atomic& ) = delete; ()
void operator=( std::shared_ptr<T> desired ) noexcept; ()
- Atomic types are not copy/move assignable
- Value assignment, equivalent to store(
desired
)
atomic<shared_ptr<T>>::is_lock_free
bool is_lock_free() const noexcept;
Returns true
if the atomic operations on all objects of this type are lock-free, false
otherwise.
atomic<shared_ptr<T>>::store
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
.
atomic<shared_ptr<T>>::load
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
.
atomic<shared_ptr<T>>::operator std::shared_ptr<T>
operator std::shared_ptr<T>() const noexcept;
Equivalent to return load();
atomic<shared_ptr<T>>::exchange
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.
atomic<shared_ptr<T>>::compare_exchange_weak, compare_exchange_strong>
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)
-
If the underlying
std::shared_ptr<T>
stores the sameT*
asexpected
and shares ownership with it, or if both underlying andexpected
are empty, assigns fromdesired
to the underlyingstd::shared_ptr<T>
, returnstrue
, and orders memory according tosuccess
, otherwise assigns from the underlyingstd::shared_ptr<T>
toexpected
, returnsfalse
, and orders memory according tofailure
. The behavior is undefined iffailure
isstd::memory_order_release
orstd::memory_order_acq_rel
. Onsuccess
, the operation is an atomic read-modify-write operation on*this
and expected is not accessed after the atomic update. Onfailure
, the operation is an atomic load operation on*this
andexpected
is updated with the existing value read from the atomic object. This update toexpected
'suse_count
is part of this atomic operation, although the write itself (and any subsequent deallocation/destruction) is not required to be. -
Same as (1), but may also fail spuriously.
-
Equivalent to:
return compare_exchange_strong(expected, desired, order, fail_order);
, wherefail_order
is the same asorder
except thatstd::memory_order_acq_rel
is replaced bystd::memory_order_acquire
andstd::memory_order_release
is replaced bystd::memory_order_relaxed
. -
Equivalent to:
return compare_exchange_weak(expected, desired, order, fail_order);
, wherefail_order
is the same asorder
except thatstd::memory_order_acq_rel
is replaced bystd::memory_order_acquire
andstd::memory_order_release
is replaced bystd::memory_order_relaxed
.
atomic<shared_ptr<T>>::wait
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_ptrs
are equivalent if they store the same pointer and either share ownership or are both empty.
atomic<shared_ptr<T>>::notify_one
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.
atomic<shared_ptr<T>>::notify_all
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.
atomic<shared_ptr<T>>::is_always_lock_free
static constexpr bool is_always_lock_free = /*implementation-defined*/;
Notes
|Feature-test macro| Value |Std |Comment|
|::|::|::|
|__cpp_lib_atomic_shared_ptr |201711L| (C++20)| std::atomic<std::shared_ptr>
|
Example
This section is incomplete
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|