Spec-Zone.ru › C++

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)
1,2) Инициализирует базовый shared_ptr<T> нулевым значением.
3) Инициализирует базовый shared_ptr<T> копией desired. Как инициализация любого типа std::atomic, она не является атомарной операцией.
4) Атомарные типы нельзя копировать или перемещать при конструировании.

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)
1) Атомарные типы нельзя копировать или перемещать при присваивании.
2) Присваивание значения, эквивалентное store(desired).
3) Сбрасывает атомарный shared-указатель в нулевое значение указателя. Эквивалентно 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)
1) Если базовый std::shared_ptr<T> хранит тот же T*, что и expected, и разделяет с ним владение, либо если и базовый объект, и expected пусты, выполняет присваивание desired базовому std::shared_ptr<T>, возвращает true и задаёт порядок операций с памятью согласно success; в противном случае присваивает значение базового std::shared_ptr<T> объекту expected, возвращает false и задаёт порядок операций с памятью согласно failure.
  • В случае успеха операция является атомарной операцией чтения-модификации-записи над *this, а к expected после атомарного обновления не обращаются.
  • В случае неудачи операция является атомарной операцией загрузки из *this, а expected обновляется значением, прочитанным из атомарного объекта. Это обновление expected's use_count является частью атомарной операции, хотя сама запись (и любое последующее освобождение памяти или уничтожение) не обязана быть её частью.
Поведение не определено, если failure имеет значение std::memory_order_release или std::memory_order_acq_rel.
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

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 возможность присваивания восстановлена

См. также

atomic
(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

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API