◐ Shell
clean mode source ↗

std::atomic<std::shared_ptr> — cppreference.com

Материал из cppreference.com

<tbody> </tbody>

Определено в заголовочном файле <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 гарантированно являются частью атомарной операции. Связанные декременты use_count следуют за атомарной операцией, но не обязаны быть её частью, за исключением изменения use_count при переопределении expected в неудачном CAS. Любое связанное удаление и освобождение выполняются после шага атомарного обновления и не являются частью атомарной операции.

Обратите внимание, что блок управления shared_ptr является потокобезопасным: доступ к различным неатомарным объектам std::shared_ptr можно получить с помощью mutable операций, таких как operator = или reset одновременно нескольким потокам, даже если эти экземпляры являются копиями и совместно используют один и тот же внутренний блок управления.

Тип T может быть неполным типом.

Типы элементы

Тип элемент Определение
value_type std::shared_ptr<T>

Функции-элементы

Все неспециализированные функции std::atomic также предоставляются этой специализацией и не содержат дополнительных функций-элементов.

atomic<shared_ptr<T>>::atomic

<tbody> </tbody>

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)

1,2) Инициализирует базовый shared_ptr<T> нулевым значением.

3) Инициализирует базовый shared_ptr<T> копией desired. Как и в случае любого типа std::atomic, инициализация не является атомарной операцией.

4) Атомарные типы нельзя копировать/перемещать

atomic<shared_ptr<T>>::operator=

<tbody> </tbody>

void operator=( const atomic& ) = delete;

(1)

void operator=( std::shared_ptr<T> desired ) noexcept;

(2)

void operator=( std::nullptr_t ) noexcept;

(3)

1) Атомарные типы нельзя копировать\перемещать присваиванием

2) Присваивание значения эквивалентно store(desired)

3) Сбрасывает атомарный общий указатель к нулевому значению указателя. Эквивалентно store(nullptr);.

atomic<shared_ptr<T>>::is_lock_free

<tbody> </tbody>

bool is_lock_free() const noexcept;

Возвращает true, если атомарные операции над всеми объектами этого типа не блокируются, иначе false.

atomic<shared_ptr<T>>::store

<tbody> </tbody>

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

<tbody> </tbody>

std::shared_ptr<T> load( std::memory_order order = std::memory_order_seq_cst ) const noexcept;

Атомарно возвращает копию базового общего указателя. Память упорядочена в соответствии с order. Поведение не определено, если order равно std::memory_order_release или std::memory_order_acq_rel.

atomic<shared_ptr<T>>::operator std::shared_ptr<T>

<tbody> </tbody>

operator std::shared_ptr<T>() const noexcept;

Эквивалентно return load();

atomic<shared_ptr<T>>::exchange

<tbody> </tbody>

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

<tbody> </tbody>

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) Если базовый 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. В случае успеха операция является атомарной операцией чтения-изменения-записи для *this, а доступ к expected после атомарного обновления невозможен. В случае сбоя операция представляет собой атомарную операцию загрузки *this, а expected обновляется существующим значением, считанным из атомарного объекта. Это обновление use_count для expected является частью этой атомарной операции, хотя сама запись (и любое последующее освобождение/уничтожение) не требуется.

2) То же, что и (1), но также может привести к ложному сбою.

3) Эквивалентно: 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.

4) Эквивалентно: 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

<tbody> </tbody>

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

<tbody> </tbody>

void notify_one() noexcept;

Выполняет атомарную операцию уведомления.

Если есть поток, заблокированный в атомарных операциях ожидания (т.е. wait()) для *this, разблокирует по крайней мере один такой поток; иначе ничего не делает.

atomic<shared_ptr<T>>::notify_all

<tbody> </tbody>

void notify_all() noexcept;

Выполняет атомарную операцию уведомления.

Разблокирует все потоки, заблокированные в атомарных операциях ожидания (т.е. wait()) для *this, если таковые имеются; иначе ничего не делает.

Константы элементы

Единственная стандартная константа-элемент std::atomic это is_always_lock_free, также предоставляемая этой специализацией.

atomic<shared_ptr<T>>::is_always_lock_free

<tbody> </tbody>

static constexpr bool is_always_lock_free = /*определено-реализацией*/;

Примечание

Макрос Тестирования функциональности Значение Стандарт Функциональность
__cpp_lib_atomic_shared_ptr 201711L (C++20) 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
возможность присваивания восстановлена

Смотри также

шаблон класса atomic и его специализации для bool, целочисленных типов и указателей
(шаблон класса) [править]