std::atomic<std::shared_ptr>
Определено в заголовке <memory> | ||
|---|---|---|
template< class T > struct std::atomic<std::shared_ptr<T>>; | (с C++20) |
Частичная шаблонная специализация std::atomic для std::shared_ptr<T> позволяет пользователям манипулировать объектами shared_ptr атомарно.
Если несколько потоков выполнения обращаются к одному и тому же объекту std::shared_ptr без синхронизации, и любое из этих обращений использует неконстантный член-функции объекта shared_ptr, то произойдёт гонка данных, если все такие обращения не выполняются через экземпляр std::atomic<std::shared_ptr> (или, устаревшее начиная с C++20, через отдельные функции для атомарного доступа к std::shared_ptr).
Связанные атомарные инкременты гарантированно являются частью атомарной операции. Связанные атомарные декременты выполняются после атомарной операции, но не обязательно являются её частью, за исключением изменения use_count при переопределении expected в случае неудачной операции CAS. Любые связанные операции удаления и выделения памяти выполняются после шага атомарного обновления и не являются частью атомарной операции.
Обратите внимание, что блок управления объектом shared_ptr защищён от одновременного доступа из разных потоков: к различным неатомарным объектам std::shared_ptr можно обращаться с помощью изменяемых операций, таких как operator= или reset, одновременно из нескольких потоков, даже если эти экземпляры являются копиями и внутренне делят один и тот же блок управления.
Тип T может быть неполным типом.
Типы членов
| Тип члена | Определение |
|---|---|
value_type | std::shared_ptr<T> |
Члены-функции
Все неспециализированные функции std::atomic также предоставляются этой специализацией, и дополнительных членов-функций нет.
atomic<shared_ptr<T>>::atomic
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) |
shared_ptr<T> значением null.shared_ptr<T> копией desired. Как и для любого типа std::atomic, инициализация не является атомарной операцией.atomic<shared_ptr<T>>::operator=
void operator=( const atomic& ) = delete; | (1) | |
void operator=( std::shared_ptr<T> desired ) noexcept; | (2) | |
void operator=( std::nullptr_t ) noexcept; | (3) |
store(desired).store(nullptr);.atomic<shared_ptr<T>>::is_lock_free
bool is_lock_free() const noexcept; |
Возвращает true если атомарные операции над всеми объектами этого типа являются блокировка-безопасными, false в противном случае.
atomic<shared_ptr<T>>::store
void store( std::shared_ptr<T> desired,
std::memory_order order = std::memory_order_seq_cst ) noexcept;
|
Атомарно заменяет значение *this значением desired как если бы это было сделано p.swap(desired), где p - это базовое std::shared_ptr<T>. Порядок памяти соответствует order. Поведение не определено, если order является std::memory_order_consume, std::memory_order_acquire, или 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; |
Атомарно возвращает копию базового shared pointer. Порядок памяти соответствует order. Поведение не определено, если order является std::memory_order_release или std::memory_order_acq_rel.
atomic<shared_ptr<T>>::operator std::shared_ptr<T>
operator std::shared_ptr<T>() const noexcept; |
Эквивалентно 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;
|
Атомарно заменяет базовый std::shared_ptr<T> на desired как если бы это было сделано p.swap(desired), где p - это базовый std::shared_ptr<T>, и возвращает копию значения, которое у p было непосредственно перед заменой. Порядок памяти соответствует order. Это атомарная операция чтения-модификации-записи.
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) |
std::shared_ptr<T> хранит то же самое T* что и expected и делит владение с ним, или если оба базового и expected пустые, присваивает значение из desired базовому std::shared_ptr<T>, возвращает true, и задаёт порядок памяти по success, в противном случае присваивает значение из базового std::shared_ptr<T> в expected, возвращает false, и задаёт порядок памяти по failure. Поведение не определено, если failure является std::memory_order_release или std::memory_order_acq_rel.return compare_exchange_strong(expected, desired, order, fail_order);, где fail_order такое же как order, за исключением того, что std::memory_order_acq_rel заменено на std::memory_order_acquire и std::memory_order_release заменено на std::memory_order_relaxed.return compare_exchange_weak(expected, desired, order, fail_order);, где fail_order такое же, как order, за исключением того, что std::memory_order_acq_rel заменено на std::memory_order_acquire и std::memory_order_release заменено на std::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;
|
Выполняет атомарную операцию ожидания.
Сравнивает load(order) с old и, если они эквивалентны, блокируется до тех пор, пока *this не будет уведомлён notify_one() или notify_all(). Это повторяется до тех пор, пока load(order) не изменится. Эта функция гарантированно возвращается только если значение изменилось, даже если лежащая в основе реализация разблокирует непредсказуемо.
Порядок памяти соответствует order. Поведение не определено, если order является std::memory_order_release или std::memory_order_acq_rel.
Примечания: два shared_ptr эквивалентны, если они хранят один и тот же указатель и либо делят владение, либо оба пусты.
atomic<shared_ptr<T>>::notify_one
void notify_one() noexcept; |
Выполняет атомарную операцию уведомления.
Если есть поток, заблокированный в атомарных операциях ожидания (т.е. wait()) на *this, то разблокируется, по крайней мере, один такой поток; в противном случае ничего не происходит.
atomic<shared_ptr<T>>::notify_all
void notify_all() noexcept; |
Выполняет атомную операцию уведомления.
Разблокирует все потоки, заблокированные в атомных операциях ожидания (т.е. wait()) на *this, если таковые имеются; в противном случае ничего не делает.
Постоянные члены
Эта специализация также предоставляет единственную стандартную std::atomic постоянную величину is_always_lock_free.
atomic<shared_ptr<T>>::is_always_lock_free
static constexpr bool is_always_lock_free = /*implementation-defined*/; |
Примечания
| Макрос проверки наличия функции | Значение | Std | Функция |
|---|---|---|---|
__cpp_lib_atomic_shared_ptr | 201711L | (C++20) |
std::atomic<std::shared_ptr> |
Пример
Отчеты об ошибках
Следующие отчеты об ошибках, изменяющих поведение, были применены ретроактивно к ранее опубликованным стандартам C++.
| DR | Применимо к | Поведение, как опубликовано | Правильное поведение |
|---|---|---|---|
| LWG 3661 | C++20 |
atomic<shared_ptr<T>> не допускалось постоянное инициализацию из nullptr | сделано допускающим постоянную инициализацию |
| LWG 3893 | C++20 |
LWG3661 сделал atomic<shared_ptr<T>> не допускающим присваивание из nullptr_t | восстановлена возможность присваивания |
См. также
|
(C++11) | Шаблон класса atomic и его специализации для bool, целых, с плавающей точкой,(с C++20) и указателей (шаблон класса) |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/cpp/memory/shared_ptr/atomic2