Namespaces
Variants
Views
Actions

Difference between revisions of "cpp/memory/shared ptr/atomic2"

From cppreference.com
< cpp‎ | memory‎ | shared ptr
(hope I got it right, "Associated use_count decrements [...] are not required to be part of it" from the intro vs. "The use_count update corresponding to the write to expected is part of the atomic operation." means CAS fail is an exception from that intro)
 
m (fix: order -> failure)
Line 124: Line 124:
 
}}
 
}}
 
{{dcl end}}
 
{{dcl end}}
@1@ If the underlying {{c|std::shared_ptr<T>}} stores the same {{c|T*}} as {{tt|expected}} and shares ownership with it, or if both underlying and {{tt|expected}} are empty, assigns from {{tt|desired}} to the underlying {{c|std::shared_ptr<T>}}, returns {{c|true}}, and orders memory according to {{tt|success}}, otherwise assigns from the underlying {{c|std::shared_ptr<T>}} to {{tt|expected}}, returns {{c|false}}, and orders memory according to {{tt|failure}}. The behavior is undefined if {{tt|order}} is {{lc|std::memory_order_release}} or {{lc|std::memory_order_acq_rel}}. On success, the operation is an atomic read-modify-write operation on {{c|*this}} and {{tt|expected}} is not accessed after the atomic update. On failure, the operation is an atomic load operation on {{c|*this}} and {{tt|expected}} is updated with the existing value read from the atomic object. This update to {{tt|expected}}'s use_count is part of this atomic operation, although the write itself (and any subsequent deallocation/destruction) is not required to be.
+
@1@ If the underlying {{c|std::shared_ptr<T>}} stores the same {{c|T*}} as {{tt|expected}} and shares ownership with it, or if both underlying and {{tt|expected}} are empty, assigns from {{tt|desired}} to the underlying {{c|std::shared_ptr<T>}}, returns {{c|true}}, and orders memory according to {{tt|success}}, otherwise assigns from the underlying {{c|std::shared_ptr<T>}} to {{tt|expected}}, returns {{c|false}}, and orders memory according to {{tt|failure}}. The behavior is undefined if {{tt|failure}} is {{lc|std::memory_order_release}} or {{lc|std::memory_order_acq_rel}}. On success, the operation is an atomic read-modify-write operation on {{c|*this}} and {{tt|expected}} is not accessed after the atomic update. On failure, the operation is an atomic load operation on {{c|*this}} and {{tt|expected}} is updated with the existing value read from the atomic object. This update to {{tt|expected}}'s use_count is part of this atomic operation, although the write itself (and any subsequent deallocation/destruction) is not required to be.
 
@2@ Same as {{v|1}}, but may also fail spuriously.
 
@2@ Same as {{v|1}}, but may also fail spuriously.
 
@3@ Equivalent to: {{c|return compare_exchange_strong(expected, desired, order, fail_order);}}, where {{tt|fail_order}} is the same as {{tt|order}} except that {{lc|std:memory_order_acq_rel}} is replaced by {{lc|std::memory_order_acquire}} and {{lc|std::memory_order_release}} is replaced by {{lc|std::memory_order_relaxed}}.
 
@3@ Equivalent to: {{c|return compare_exchange_strong(expected, desired, order, fail_order);}}, where {{tt|fail_order}} is the same as {{tt|order}} except that {{lc|std:memory_order_acq_rel}} is replaced by {{lc|std::memory_order_acquire}} and {{lc|std::memory_order_release}} is replaced by {{lc|std::memory_order_relaxed}}.

Revision as of 08:43, 6 January 2018

 
 
Utilities library
General utilities
Relational operators (deprecated in C++20)
 
Dynamic memory management
Uninitialized memory algorithms
Constrained uninitialized memory algorithms
Allocators
Garbage collection support
(C++11)(until C++23)
(C++11)(until C++23)
(C++11)(until C++23)
(C++11)(until C++23)
(C++11)(until C++23)
(C++11)(until C++23)



 
 
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::shraed_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.

Contents

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;
(1)
atomic(std::shared_ptr<T> desired) noexcept;
(2)
atomic(const atomic&) = delete;
(3)
1) Initializes the underlying shared_ptr<T> to default-constructed value
2) Initializes the underlying shared_ptr<T> to a copy of desired. As with any std::atomic type, initialization is not an atomic operation.
3) Atomic types are not copy/move constructible

atomic<shared_ptr<T>>::operator=

void operator=(const atomic&) = delete;
(1)
void operator=(std::shared_ptr<T> desired) noexcept;
(2)
1) Atomic types are not copy/move assignable
2) 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). Memory is ordered according to order. The behavior is undefined if order is not std::memory_order_consume, std::memory_order_acquire, or std::memory_order_acq_rel

atomic<shared_ptr<T>>::load

Atomically returns a copy of the underlying shared pointer. Memory is ordered according to order. The behavior is undefined if order is not 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) and returns a copy of the underlying std::shared_ptr<T> that it 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)
1) If the underlying std::shared_ptr<T> stores the same T* as 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.
2) Same as (1), but may also fail spuriously.
3) Equivalent to: return compare_exchange_strong(expected, desired, order, fail_order);, where 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.
4) Equivalent to: return compare_exchange_weak(expected, desired, order, fail_order); where 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.


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*/;

Example

See also

(C++11)
atomic class template and specializations for bool, integral, floating-point,(since C++20) and pointer types
(class template) [edit]