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. T может быть неполным типом.
Если несколько потоков выполнения обращаются к одному и тому же объекту std::shared_ptr без синхронизации, и хотя бы одно из таких обращений использует неконстантную функцию-член shared_ptr, возникнет гонка данных, если только все такие обращения не выполняются через экземпляр std::atomic<std::shared_ptr> (или, начиная с C++20, через устаревшие отдельные функции атомарного доступа к std::shared_ptr).
Связанные увеличения use_count гарантированно являются частью атомарной операции. Связанные уменьшения use_count упорядочены после атомарной операции, но не обязательно являются её частью, за исключением изменения use_count при переопределении expected в неудачном CAS. Любые связанные удаление и освобождение памяти упорядочены после шага атомарного обновления и не являются частью атомарной операции.
Обратите внимание, что управляющий блок shared_ptr является потокобезопасным: разные неатомарные объекты std::shared_ptr могут одновременно изменяться несколькими потоками с помощью изменяющих операций, таких как operator= или reset, даже если эти экземпляры являются копиями и внутренне используют общий управляющий блок.
Вложенные типы
| Тип | Определение |
|---|---|
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) | (constexpr начиная с C++26) |
atomic( const atomic& ) = delete; | (4) |
desired. Как инициализация любого типа std::atomic, она не является атомарной операцией.atomic<shared_ptr<T>>::operator=
void operator=( const atomic& ) = delete; | (1) | |
void operator=( std::shared_ptr<T> desired ) noexcept; | (2) | (constexpr начиная с C++26) |
void operator=( std::nullptr_t ) noexcept; | (3) | (constexpr начиная с C++26) |
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;
| (constexpr начиная с C++26) |
Атомарно заменяет значение *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;
| (constexpr начиная с C++26) |
Атомарно возвращает копию базового shared-указателя. Порядок операций с памятью определяется согласно 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; | (constexpr начиная с C++26) |
Эквивалентно 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;
| (constexpr начиная с C++26) |
Атомарно заменяет базовый 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) | (constexpr начиная с C++26) |
bool compare_exchange_weak
( std::shared_ptr<T>& expected, std::shared_ptr<T> desired,
std::memory_order success, std::memory_order failure ) noexcept;
| (2) | (constexpr начиная с C++26) |
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) | (constexpr начиная с C++26) |
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) | (constexpr начиная с C++26) |
expected, и разделяет с ним владение, либо если и базовый объект, и expected пусты, выполняет присваивание desired базовому std::shared_ptr<T>, возвращает true и задаёт порядок операций с памятью согласно success; в противном случае присваивает значение базового std::shared_ptr<T> объекту expected, возвращает false и задаёт порядок операций с памятью согласно failure. - В случае успеха операция является атомарной операцией чтения-модификации-записи над
*this, а кexpectedпосле атомарного обновления не обращаются. - В случае неудачи операция является атомарной операцией загрузки из
*this, аexpectedобновляется значением, прочитанным из атомарного объекта. Это обновлениеexpected'suse_countявляется частью атомарной операции, хотя сама запись (и любое последующее освобождение памяти или уничтожение) не обязана быть её частью.
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;
| (constexpr начиная с C++26) |
Выполняет атомарное ожидание.
Сравнивает 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; | (constexpr начиная с C++26) |
Выполняет атомарное уведомление.
Если какой-либо поток заблокирован в ожидании атомарной операции (то есть выполняет wait()) на *this, разблокирует как минимум один такой поток; в противном случае ничего не делает.
atomic<shared_ptr<T>>::notify_all
void notify_all() noexcept; | (constexpr начиная с C++26) |
Выполняет атомарное уведомление.
Разблокирует все потоки, заблокированные в ожидании атомарной операции (то есть выполняющие 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 */; |
Примечания
| Макрос проверки поддержки возможности | Значение | Стандарт | Возможность |
|---|---|---|---|
__cpp_lib_atomic_shared_ptr | 201711L | (C++20) |
std::atomic<std::shared_ptr> |
__cpp_lib_constexpr_memory | 202506L | (C++26) | Возможность constexpr std::atomic<std::shared_ptr> |
Пример
Отчёты об ошибках
Следующие отчёты об ошибках, изменяющие поведение, были применены задним числом к ранее опубликованным стандартам C++.
| Отчёт об ошибке | Применён к | Поведение в опубликованной версии | Исправленное поведение |
|---|---|---|---|
| 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/cpp/memory/shared_ptr/atomic2