D.3.8. Шаблон класса std::atomic

Шаблон класса std::atomic является оберткой, позволяющей строить атомарные операции для любого типа, удовлетворяющего следующим условиям.

Параметр шаблона BaseТуре должен:

• иметь тривиальный конструктор по умолчанию;

• иметь тривиальный копирующий оператор присваивания;

• иметь тривиальный деструктор;

• допускать побитовое сравнение на равенство.

По существу, это означает, что конкретизация std::atomic<некоторый-встроенный-тип> допустима, как и конкретизация std::atomic<некоторая-простая-структура>, но такие вещи, как std::atomic<std::string>, недопустимы.

Помимо основного шаблона, имеются специализации для встроенных целочисленных типов и указателей, которые предоставляют дополнительные операции, например x++.

Экземпляры std::atomic не удовлетворяют требованиям концепций CopyConstructible и CopyAssignable, потому что такие операции невозможно выполнить атомарно.

Определение класса

template<typename BaseType>

struct atomic {

 atomic() noexcept = default;

 constexpr atomic(BaseType) noexcept;

 BaseType operator=(BaseType) volatile noexcept;

 BaseType operator=(BaseType) noexcept;

 atomic(const atomic&) = delete;

 atomic& operator=(const atomic&) = delete;

 atomic& operator=(const atomic&) volatile = delete;

 bool is_lock_free() const volatile noexcept;

 bool is_lock_free() const noexcept;

 void store(BaseType, memory_order = memory_order_seq_cst)

  volatile noexcept;

 void store(BaseType, memory_order = memory_order_seq_cst)

  noexcept;

 BaseType load(memory_order = memory_order_seq_cst)

  const volatile noexcept;

 BaseType load(memory_order = memory_order_seq_cst)

  const noexcept;

 BaseType exchange(BaseType, memory_order = memory_order_seq_cst)

  volatile noexcept;

 BaseType exchange(BaseType, memory_order = memory_order_seq_cst)

  noexcept;

 bool compare_exchange_strong(

  BaseType & old_value, BaseType new_value,

  memory_order order = memory_order_seq_cst) volatile noexcept;

 bool compare_exchange_strong(

  BaseType & old_value, BaseType new_value,

  memory_order order = memory_order_seq_cst) noexcept;

 bool compare_exchange_strong(

  BaseType & old_value, BaseType new_value,

  memory_order success_order,

  memory_order failure_order) volatile noexcept;

 bool compare_exchange_strong(

  BaseType & old_value, BaseType new_value,

  memory_order success_order,

  memory_order failure_order) noexcept;

 bool compare_exchange_weak(

  BaseType & old_value, BaseType new_value,

  memory_order order = memory_order_seq_cst)

  volatile noexcept;

 bool compare_exchange_weak(

  BaseType & old_value, BaseType new_value,

  memory_order order = memory_order_seq_cst) noexcept;

 bool compare_exchange_weak(

  BaseType & old_value, BaseType new_value,

  memory_order success_order,

  memory_order failure_order) volatile noexcept;

 bool compare_exchange_weak(

  BaseType & old_value, BaseType new_value,

  memory_order success_order,

  memory_order failure_order) noexcept;

 operator BaseType() const volatile noexcept;

 operator BaseType() const noexcept;

};

template<typename BaseType>

bool atomic_is_lock_free(

 volatile const atomic<BaseType>*) noexcept;

template<typename BaseType>

 bool atomic_is_lock_free(const atomic<BaseType>*)

 noexcept;

template<typename BaseType>

void atomic_init(volatile atomic<BaseType>*, void*) noexcept;

template<typename BaseType>

void atomic_init(atomic<BaseType>*, void*) noexcept;

template<typename BaseType>

BaseType atomic_exchange(

 volatile atomic<BaseType>*, memory_order) noexcept;

template<typename BaseType>

BaseType atomic_exchange(

 atomic<BaseType>*, memory_order) noexcept;

template<typename BaseType>

BaseType atomic_exchange_explicit(

 volatile atomic<BaseType>*, memory_order) noexcept;

template<typename BaseType>

BaseType atomic_exchange_explicit(

 atomic<BaseType>*, memory_order) noexcept;

template<typename BaseType>

void atomic_store(volatile atomic<BaseType>*, BaseType) noexcept;

template<typename BaseType>

void atomic_store(atomic<BaseType>*, BaseType) noexcept;

template<typename BaseType>

void atomic_store_explicit(

 volatile atomic<BaseType>*, BaseType, memory_order) noexcept;

template<typename BaseType>

void atomic_store_explicit(

 atomic<BaseType>*, BaseType, memory_order) noexcept;

template<typename BaseType>

BaseType atomic_load(volatile const atomic<BaseType>*) noexcept;

template<typename BaseType>

BaseType atomic_load(const atomic<BaseType>*) noexcept;

template<typename BaseType>

BaseType atomic_load_explicit(

 volatile const atomic<BaseType>*, memory_order) noexcept;

template<typename BaseType>

BaseType atomic_load_explicit(

 const atomic<BaseType>*, memory_order) noexcept;

template<typename BaseType>

bool atomic_compare_exchange_strong(

 volatile atomic<BaseType>*,

 BaseType * old_value, BaseType new_value) noexcept;

template<typename BaseType>

bool atomic_compare_exchange_strong(

 atomic<BaseType>*,

 BaseType * old_value, BaseType new_value) noexcept;

template<typename BaseType>

bool atomic_compare_exchange_strong_explicit(

 volatile atomic<BaseType>*, BaseType * old_value,

 BaseType new_value, memory_order success_order,

 memory_order failure_order) noexcept;

template<typename BaseType>

bool atomic_compare_exchange_strong_explicit(

 atomic<BaseType>*,

 BaseType * old_value, BaseType new_value,

 memory_order success_order,

 memory_order failure_order) noexcept;

template<typename BaseType>

bool atomic_compare_exchange_weak(

 volatile atomic<BaseType>*,

 BaseType * old_value, BaseType new_value) noexcept;

template<typename BaseType>

bool atomic_compare_exchange_weak(

 atomic<BaseType>*,

 BaseType * old_value, BaseType new_value) noexcept;

template<typename BaseType>

bool atomic_compare_exchange_weak_explicit(

 volatile atomic<BaseType>*,

 BaseType * old_value, BaseType new_value,

 memory_order success_order,

 memory_order failure_order) noexcept;

template<typename BaseType>

bool atomic_compare_exchange_weak_explicit(

 atomic<BaseType>*,

 BaseType * old_value, BaseType new_value,

 memory_order success_order,

 memory_order failure_order) noexcept;

Примечание. Хотя функции, не являющиеся членами класса, определены как шаблоны, они могут быть предоставлены в виде набора перегруженных функций, поэтому задавать явную спецификацию аргументов шаблона не следует.

STD::ATOMIC , КОНСТРУКТОР ПО УМОЛЧАНИЮ

Конструирует экземпляр std::atomic со значением, инициализированным по умолчанию.

Объявление

atomic() noexcept;

Результат

Конструирует новый объект std::atomic со значением, инициализированным по умолчанию. Для объектов со статическим временем жизни обеспечивается статическая инициализация.

Примечание. Если время жизни объекта std::atomic не статическое, то значение, которое будет иметь объект, инициализированный конструктором по умолчанию, непредсказуемо.

Исключения

Нет.

STD::ATOMIC_INIT , ФУНКЦИЯ, НЕ ЯВЛЯЮЩАЯСЯ ЧЛЕНОМ КЛАССА

Неатомарно сохраняет указанное значение в объекте типа std::atomic<BaseType>.

Объявление

template<typename BaseType>

void atomic_init(

 atomic<BaseType> volatile* p, BaseType v) noexcept;

template<typename BaseType>

void atomic_init(atomic<BaseType>* p, BaseType v) noexcept;

Результат

Неатомарно сохраняет значение v в *p. Вызов atomic_init() с передачей в качестве аргумента объекта atomic<BaseType>, который не был сконструирован по умолчанию или над которым производились какие-нибудь операции после конструирования, является неопределенным поведением.

Примечание. Поскольку эта операция сохранения неатомарна, то одновременный доступ к объекту, на который указывает p, из другого потока (даже с помощью атомарной операции) представляет собой гонку за данными.

Исключения

Нет.

STD::ATOMIC , КОНВЕРТИРУЮЩИЙ КОНСТРУКТОР

Конструирует экземпляр std::atomic из переданного значения типа BaseType.

Объявление

constexpr atomic(BaseType b) noexcept;

Результат

Конструирует новый объект std::atomic из значения b. Для объектов со статическим временем жизни обеспечивается статическая инициализация.

Исключения

Нет.

STD::ATOMIC , КОНВЕРТИРУЮЩИЙ ОПЕРАТОР ПРИСВАИВАНИЯ

Сохраняет новое значение в *this.

Объявление

BaseType operator=(BaseType b) volatile noexcept;

BaseType operator=(BaseType b) noexcept;

Результат

return this->store(b);

STD::ATOMIC::IS_LOCK_FREE , ФУНКЦИЯ-ЧЛЕН

Сообщает, являются ли операции над *this свободными от блокировок.

Объявление

bool is_lock_free() const volatile noexcept;

bool is_lock_free() const noexcept;

Возвращаемое значение

true, если операции над *this свободны от блокировок, иначе false.

Исключения

Нет.

STD::ATOMIC_IS_LOCK_FREE , ФУНКЦИЯ, НЕ ЯВЛЯЮЩАЯСЯ ЧЛЕНОМ КЛАССА

Сообщает, являются ли операции над *this свободными от блокировок.

Объявление

template<typename BaseType>

bool atomic_is_lock_free(

 volatile const atomic<BaseType>* p) noexcept;

template<typename BaseType>

bool atomic_is_lock_free(const atomic<BaseType>* p) noexcept;

Результат

return p->is_lock_free();

STD::ATOMIC::LOAD , ФУНКЦИЯ-ЧЛЕН

Атомарно загружает текущее значение объекта std::atomic.

Объявление

BaseType load(memory_order order = memory_order_seq_cst)

 const volatile noexcept;

BaseType load(

 memory_order order = memory_order_seq_cst) const noexcept;

Предусловия

Параметр order должен принимать одно из значений std::memory_order_relaxed, std::memory_order_acquire, std: :memory_order_consume или std::memory_order_seq_cst.

Результат

Атомарно загружает текущее, хранящееся в *this.

Возвращаемое значение

Значение, хранящееся в *this, в точке вызова.

Исключения

Нет.

Примечание. Это атомарная операция загрузки для ячейки памяти, содержащей *this.

STD::ATOMIC_LOAD , ФУНКЦИЯ, НЕ ЯВЛЯЮЩАЯСЯ ЧЛЕНОМ КЛАССА

Атомарно загружает текущее значение объекта std::atomic.

Объявление

template<typename BaseType>

BaseType atomic_load(volatile const atomic<BaseType>* p) noexcept;

template<typename BaseType>

BaseType atomic_load(const atomic<BaseType>* p) noexcept;

Результат

return p->load();

STD::ATOMIC_LOAD_EXPLICIT , ФУНКЦИЯ, HE ЯВЛЯЮЩАЯСЯ ЧЛЕНОМ КЛАССА

Атомарно загружает текущее значение объекта std::atomic.

Объявление

template<typename BaseType>

BaseType atomic_load_explicit(

 volatile const atomic<BaseType>* p,

 memory_order order) noexcept;

template<typename BaseType>

BaseType atomic_load_explicit(

 const atomic<BaseType>* p, memory_order order) noexcept;

Результат

return p->load(order);

STD::ATOMIC::OPERATOR , ОПЕРАТОР ПРЕОБРАЗОВАНИЯ В ТИП BASETYPE

Загружает значение, хранящееся в *this.

Объявление

operator BaseType() const volatile noexcept;

operator BaseType() const noexcept;

Результат

return this->load();

STD::ATOMIC::STORE , ФУНКЦИЯ-ЧЛЕН

Атомарно сохраняет новое значение в объекте atomic<BaseType>.

Объявление

void store(

 BaseType new_value, memory_order order = memory_order_seq_cst)

 volatile noexcept;

void store(

 BaseType new_value, memory_order order = memory_order_seq_cst)

 noexcept;

Предусловия

Параметр order должен принимать одно из значений std::memory_order_relaxed, std::memory_order_release или std::memory_order_seq_cst.

Результат

Атомарно сохраняет значение new_value в *this.

Исключения

Нет.

Примечание. Это атомарная операция сохранения для ячейки памяти, содержащей *this.

STD::ATOMIC_STORE , ФУНКЦИЯ, НЕ ЯВЛЯЮЩАЯСЯ ЧЛЕНОМ КЛАССА

Атомарно сохраняет новое значение в объекте atomic<BaseType>.

Объявление

template<typename BaseType>

void atomic_store(

 volatile atomic<BaseType>* p, BaseType new_value) noexcept;

template<typename BaseType>

void atomic_store(

 atomic<BaseType>* p, BaseType new_value) noexcept;

Результат

p->store(new_value);

STD::ATOMIC_STORE_EXPLICIT , ФУНКЦИЯ, HE ЯВЛЯЮЩАЯСЯ ЧЛЕНОМ КЛАССА

Атомарно сохраняет новое значение в объекте atomic<BaseType>.

Объявление

template<typename BaseType>

void atomic_store_explicit(

 volatile atomic<BaseType>* p, BaseType new_value,

 memory_order order) noexcept;

template<typename BaseType>

void atomic_store_explicit(

 atomic<BaseType>* p, BaseType new_value,

 memory_order order) noexcept;

Результат

p->store(new_value, order);

STD::ATOMIC::EXCHANGE , ФУНКЦИЯ-ЧЛЕН

Атомарно сохраняет новое значение и читает старое.

Объявление

BaseType exchange(

BaseType new_value,

 memory_order order = memory_order_seq_cst) volatile noexcept;

Результат

Атомарно сохраняет значение new_value в *this и извлекает прежнее значение *this.

Возвращаемое значение

Значение *this непосредственно перед сохранением.

Исключения

Нет.

Примечание. Это атомарная операция чтения-модификации-записи для ячейки памяти, содержащей *this.

STD::ATOMIC_EXCHANGE , ФУНКЦИЯ, НЕ ЯВЛЯЮЩАЯСЯ ЧЛЕНОМ КЛАССА

Атомарно сохраняет новое значение в объекте atomic<BaseType> и читает предыдущее значение.

Объявление

template<typename BaseType>

BaseType atomic_exchange(

 volatile atomic<BaseType>* p, BaseType new_value) noexcept;

template<typename BaseType>

BaseType atomic_exchange(

 atomic<BaseType>* p, BaseType new_value) noexcept;

Результат

return p->exchange(new_value);

STD::ATOMIC_EXCHANGE_EXPLICIT , ФУНКЦИЯ, HE ЯВЛЯЮЩАЯСЯ ЧЛЕНОМ КЛАССА

Атомарно сохраняет новое значение в объекте atomic<BaseType> и читает предыдущее значение.

Объявление

template<typename BaseType>

BaseType atomic_exchange_explicit(

 volatile atomic<BaseType>* p,

 BaseType new_value, memory_order order)

 noexcept;

template<typename BaseType>

BaseType atomic_exchange_explicit(

 atomic<BaseType>* p,

 BaseType new_value, memory_order order) noexcept;

Результат

return p->exchange(new_value, order);

STD::ATOMIC::COMPARE_EXCHANGE_STRONG , ФУНКЦИЯ-ЧЛЕН

Атомарно сравнивает значение с ожидаемым и, если они равны, сохраняет новое значение. Если значения не равны, то заменяет ожидаемое значение прочитанным.

Объявление

bool compare_exchange_strong(

 BaseType& expected, BaseType new_value,

 memory_order order = std::memory_order_seq_cst)

 volatile noexcept;

bool compare_exchange_strong(

 BaseType& expected, BaseType new_value,

 memory_order order = std::memory_order_seq_cst) noexcept;

bool compare_exchange_strong(

 BaseType& expected, BaseType new_value,

 memory_order success_order, memory_order failure_order)

 volatile noexcept;

bool compare_exchange_strong(

 BaseType& expected, BaseType new_value,

 memory_order success_order,

 memory_order failure_order) noexcept;

Предусловия

Параметр failure_order не должен быть равен std::memory_order_release или std::memory_order_acq_rel.

Результат

Атомарно сравнивает expected со значением, хранящимся в *this, применяя побитовое сравнение, и сохраняет new_value в *this, если значения равны. В противном случае записывает в expected прочитанное значение.

Возвращаемое значение

true, если значение, хранящееся в *this, совпало с expected. В противном случае false.

Исключения

Нет.

Примечание. Этот перегруженный вариант функции с тремя параметрами эквивалентен перегруженному варианту с четырьмя параметрами, где success_order == order и failure_order == order, с тем отличием, что если order равно std::memory_order_acq_rel, то failure_order равно std::memory_order_acquire, а если order равно std::memory_order_release, то failure_order равно std::memory_order_relaxed.

Примечание. Если результат равен true, то это атомарная операция чтения-модификации-записи для ячейки памяти, содержащей *this, с упорядочением доступа к памяти success_order; в противном случае это атомарная операция загрузки для ячейки памяти, содержащей *this, с упорядочением доступа к памяти failure_order.

STD::ATOMIC_COMPARE_EXCHANGE_STRONG , ФУНКЦИЯ, HE ЯВЛЯЮЩАЯСЯ ЧЛЕНОМ КЛАССА

Атомарно сравнивает значение с ожидаемым и, если они равны, сохраняет новое значение. Если значения не равны, то заменяет ожидаемое значение прочитанным.

Объявление

template<typename BaseType>

bool atomic_compare_exchange_strong(

 volatile atomic<BaseType>* p,

 BaseType * old_value, BaseType new_value) noexcept;

template<typename BaseType>

bool atomic_compare_exchange_strong(

 atomic<BaseType>* p,

 BaseType * old_value, BaseType new_value) noexcept;

Результат

return p->compare_exchange_strong(*old_value, new_value);

STD::ATOMIC_COMPARE_EXCHANGE_STRONG_EXPLICIT , ФУНКЦИЯ, HE ЯВЛЯЮЩАЯСЯ ЧЛЕНОМ КЛАССА

Атомарно сравнивает значение с ожидаемым и, если они равны, сохраняет новое значение. Если значения не равны, то заменяет ожидаемое значение прочитанным.

Объявление

template<typename BaseType>

bool atomic_compare_exchange_strong_explicit(

 volatile atomic<BaseType>* p,

 BaseType * old_value, BaseType new_value,

 memory_order success_order, memory_order failure_order)

 noexcept;

template<typename BaseType>

bool atomic_compare_exchange_strong_explicit(

 atomic<BaseType>* p,

 BaseType * old_value, BaseType new_value,

 memory_order success_order, memory_order failure_order)

 noexcept;

Результат

return p->compare_exchange_strong(

*old_value, new_value, success_order, failure_order) noexcept;

STD::ATOMIC::COMPARE_EXCHANGE_WEAK , ФУНКЦИЯ-ЧЛЕН

Атомарно сравнивает значение с ожидаемым и, если они равны и обновление может быть произведено атомарно, то сохраняет новое значение. Если значения не равны или обновление не может быть произведено атомарно, то заменяет ожидаемое значение прочитанным.

Объявление

bool compare_exchange_weak(

 BaseType& expected, BaseType new_value,

 memory_order order = std::memory_order_seq_cst)

 volatile noexcept;

bool compare_exchange_weak(

 BaseType& expected, BaseType new_value,

 memory_order order = std::memory_order_seq_cst) noexcept;

bool compare_exchange_weak(

 BaseType& expected, BaseType new_value,

 memory_order success_order, memory_order failure_order)

 volatile noexcept;

bool compare_exchange_weak(

 BaseType& expected, BaseType new_value,

 memory_order success_order,

 memory_order failure_order) noexcept;

Предусловия

Параметр failure_order не должен быть равен std::memory_order_release или std::memory_order_acq_rel.

Результат

Атомарно сравнивает expected со значением, хранящимся в *this, применяя побитовое сравнение, и сохраняет new_value в *this, если значения равны. Если значения не равны или обновление не может быть произведено атомарно, записывает в expected прочитанное значение.

Возвращаемое значение

true, если значение, хранящееся в *this, совпало с expected и new_value успешно сохранено в *this. В противном случае false.

Исключения

Нет.

Примечание. Этот перегруженный вариант функции с тремя параметрами эквивалентен перегруженному варианту с четырьмя параметрами, где success_order == order и failure_order == order, с тем отличием, что если order равно std::memory_order_acq_rel, то failure_order равно std::memory_order_acquire, а если order равно std::memory_order_release, то failure_order равно std::memory_order_relaxed.

Примечание. Если результат равен true, то это атомарная операция чтения-модификации-записи для ячейки памяти, содержащей *this, с упорядочением доступа к памяти success_order; в противном случае это атомарная операция загрузки для ячейки памяти, содержащей *this, с упорядочением доступа к памяти failure_order.

STD::ATOMIC_COMPARE_EXCHANGE_WEAK , ФУНКЦИЯ, HE ЯВЛЯЮЩАЯСЯ ЧЛЕНОМ КЛАССА

Атомарно сравнивает значение с ожидаемым и, если они равны и обновление может быть произведено атомарно, то сохраняет новое значение. Если значения не равны или обновление не может быть произведено атомарно, то заменяет ожидаемое значение прочитанным.

Объявление

template<typename BaseType>

bool atomic_compare_exchange_weak(

 volatile atomic<BaseType>* p,

 BaseType * old_value, BaseType new_value) noexcept;

template<typename BaseType>

bool atomic_compare_exchange_weak(

 atomic<BaseType>* p,

 BaseType * old_value, BaseType new_value) noexcept;

Результат

return p->compare_exchange_weak(*old_value, new_value);

STD::ATOMIC_COMPARE_EXCHANGE_WEAK_EXPLICIT , ФУНКЦИЯ, HE ЯВЛЯЮЩАЯСЯ ЧЛЕНОМ КЛАССА

Атомарно сравнивает значение с ожидаемым и, если они равны и обновление может быть произведено атомарно, то сохраняет новое значение. Если значения не равны или обновление не может быть произведено атомарно, то заменяет ожидаемое значение прочитанным.

template<typename BaseType>

bool atomic_compare_exchange_weak_explicit(

 volatile atomic<BaseType>* p,

 BaseType * old_value, BaseType new_value,

 memory_order success_order,

 memory_order failure_order) noexcept;

template<typename BaseType>

bool atomic_compare_exchange_weak_explicit(

 atomic<BaseType>* p,

 BaseType * old_value, BaseType new_value,

 memory_order success_order,

 memory_order failure_order) noexcept;

Результат

return p->compare_exchange_weak(

 *old_value, new_value, success_order, failure_order);