Параллельное программирование на С++ в действии — страница 47 из 53

В заголовке

объявлены простые атомарные типы и операции над ними, а также шаблон класса для построения атомарной версии определённого пользователем типа, удовлетворяющего некоторым условиям.

Содержимое заголовка

#define ATOMIC_BOOL_LOCK_FREE см. описание

#define ATOMIC_CHAR_LOCK_FREE см. описание

#define ATOMIC_SHORT_LOCK_FREE см. описание

#define ATOMIC_INT_LOCK_FREE см. описание

#define ATOMIC_LONG_LOCK_FREE см. описание

#define ATOMIC_LLONG_LOCK_FREE см. описание

#define ATOMIC_CHAR16_T_LOCK_FREE см. описание

#define ATOMIC_CHAR32_T_LOCK_FREE см. описание

#define ATOMIC_WCHAR_T_LOCK_FREE см. описание

#define ATOMIC_POINTER_LOCK_FREE см. описание


#define ATOMIC_VAR_INIT(value) см. описание


namespace std {

enum memory_order;

struct atomic_flag;

typedef см. описание atomic_bool;

typedef см. описание atomic_char;

typedef см. описание atomic_char16_t;

typedef см. описание atomic_char32_t;

typedef см. описание atomic_schar;

typedef см. описание atomic_uchar;

typedef см. описание atomic_short;

typedef см. описание atomic_ushort;

typedef см. описание atomic_int;

typedef см. описание atomic_uint;

typedef см. описание atomic_long;

typedef см. описание atomic_ulong;

typedef см. описание atomic_llong;

typedef см. описание atomic_ullong;

typedef см. описание atomic_wchar_t;


typedef см. описание atomic_int_least8_t;

typedef см. описание atomic_uint_least8_t;

typedef см. описание atomic_int_least16_t;

typedef см. описание atomic_uint_least16_t;

typedef см. описание atomic_int_least32_t;

typedef см. описание atomic_uint_least32_t;

typedef см. описание atomic_int_least64_t;

typedef см. описание atomic_uint_least64_t;

typedef см. описание atomic_int_fast8_t;

typedef см. описание atomic_uint_fast8_t;

typedef см. описание atomic_int_fast16_t;

typedef см. описание atomic_uint_fast16_t;

typedef см. описание atomic_int_fast32_t;

typedef см. описание atomic_uint_fast32_t;

typedef см. описание atomic_int_fast64_t;

typedef см. описание atomic_uint_fast64_t;

typedef см. описание atomic_int8_t;

typedef см. описание atomic_uint8_t;

typedef см. описание atomic_int16_t;

typedef см. описание atomic_uint16_t;

typedef см. описание atomic_int32_t;

typedef см. описание atomic_uint32_t;

typedef см. описание atomic_int64_t;

typedef см. описание atomic_uint64_t;

typedef см. описание atomic_intptr_t;

typedef см. описание atomic_uintptr_t;

typedef см. описание atomic_size_t;

typedef см. описание atomic_ssize_t;

typedef см. описание atomic_ptrdiff_t;

typedef см. описание atomic_intmax_t;

typedef см. описание atomic_uintmax_t;


template

struct atomic;


extern "C" void atomic_thread_fence(memory_order order);

extern "C" void atomic_signal_fence(memory_order order);


template

T kill_dependency(T);

}

D.3.1.
std::atomic_xxx
, псевдонимы типов

Для совместимости с ожидаемым стандартом С предоставляются псевдонимы

typedef
для атомарных целочисленных типов. Это псевдонимы либо соответствующей специализации
std::atomic
, либо базового класса этой специализации с таким же интерфейсом.


Таблица D.1. Псевдонимы атомарных типов и соответствующие им специализации

std::atomic<>

std::atomic_itype
Специализация
std::atomic<>
std::atomic_char
std::atomic
std::atomic_schar
std::atomic
std::atomic_uchar
std::atomic
std::atomic_short
std::atomic
std::atomic_ushort
std::atomic
std::atomic_int
std::atomic
std::atomic_uint
std::atomic
std::atomic_long
std::atomic
std::atomic_ulong
std::atomic
std::atomic_llong
std::atomic
std::atomic_ullong
std::atomic
std::atomic_wchar_t
std::atomic
std::atomic_char16_t
std::atomic
std::atomic_char32_t
std::atomic

D.3.2.
ATOMIC_xxx_LOCK_FREE
, макросы

Эти макросы определяют, являются ли атомарные типы, соответствующие различным встроенным типам, свободными от блокировок.

Объявления макросов

#define ATOMIC_BOOL_LOCK_FREE см. описание

#define ATOMIC_CHAR_LOCK_FREE см. описание

#define ATOMIC_SHORT_LOCK_FREE см. описание

#define ATOMIC_INT_LOCK_FREE см. описание

#define ATOMIC_LONG_LOCK_FREE см. описание

#define ATOMIC_LLONG_LOCK_FREE см. описание

#define ATOMIC_CHAR16_T_LOCK_FREE см. описание

#define ATOMIC_CHAR32_T_LOCK_FREE см. описание

#define ATOMIC_WCHAR_T_LOCK_FREE см. описание

#define ATOMIC_POINTER_LOCK_FREE см. описание

Значением

ATOMIC_xxx_LOCK_FREE
может быть 0, 1 или 2. Значение 0 означает, что операции над знаковыми и беззнаковыми атомарными типами, соответствующими типу
xxx
, никогда не свободны от блокировок; 1 — что операции могут быть свободны от блокировок для одних экземпляров этих типов и не свободны для других; 2 — что операции всегда свободны от блокировок. Например, если ATOMIC
_INT_LOCK_FREE
равно 2, то операции над любыми экземплярами
std::atomic
и
std::atomic
свободны от блокировок.

Макрос

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

D.3.3.
ATOMIC_VAR_INIT
, макрос

Макрос

ATOMIC_VAR_INIT
позволяет инициализировать атомарную переменную конкретным значением.

Объявление

#define ATOMIC_VAR_INIT(value) см. описание

Макрос расширяется в последовательность лексем, которую можно использовать в выражении следующего вида для инициализации одного из стандартных атомарных типов указанным значением:

std::atomic x = ATOMIC_VAR_INIT(val);

Указанное значение должно быть совместимо с неатомарным типом, соответствующим данной атомарной переменной, например:

std::atomic i = ATOMIC_VAR_INIT(42);

std::string s;

std::atomic p = ATOMIC_VAR_INIT(&s);

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

D.3.4.
std::memory_order
, перечисление

Перечисление

std::memory_order
применяется для задания упорядочения доступа к памяти при выполнении атомарных операций.

Объявление

typedef enum memory_order {

 memory_order_relaxed, memory_order_consume,

 memory_order_acquire, memory_order_release,

 memory_order_acq_rel, memory_order_seq_cst

} memory_order;

Операции, помеченные элементами этого перечисления, ведут себя, как описано ниже (подробное описание упорядочения доступа к памяти см. в главе 5).

STD::MEMORY_ORDER_RELAXED

Операция не обеспечивает никаких дополнительных ограничений на упорядочение.

STD::MEMORY_ORDER_RELEASE

Операция освобождения указанной ячейки памяти. Следовательно, она синхронизируется-с операцией захвата той же ячейки памяти, которая читает сохраненное значение.

STD::MEMORY_ORDER_ACQUIRE

Операция захвата указанной ячейки памяти. Если сохраненное значение было записано операцией освобождения, то сохранение синхронизируется-с этой операцией.

STD::MEMORY_ORDER_ACQ_REL

Операция чтения-модификации-записи. Ведет себя так, как будто одновременно заданы ограничения

std::memory_order_acquire
и
std::memory_order_release
для доступа к указанной ячейке памяти.

STD::MEMORY_ORDER_SEQ_CST

Операция является частью цепочки последовательно согласованных операций, на которой определено полное упорядочение. Кроме того, если это сохранение, то оно ведет себя как операция с ограничением

std::memory_order_release
, если загрузка — то как операция с ограничением
std::memory_order_acquire
, а если это операция чтения-модификации-записи, то она ведет себя как операция с обоими ограничениями
std::memory_order_acquire
и
std::memory_order_release
. Эта семантика по умолчанию подразумевается для всех операций.

STD::MEMORY_ORDER_CONSUME

Операция потребления указанной ячейки памяти.

D.3.5.
std::atomic_thread_fence
, функция

Функция

std::atomic_thread_fence()
вставляет в программу «барьер», чтобы принудительно обеспечить упорядочение доступа к памяти со стороны нескольких операций.

Объявление

extern "С" void atomic_thread_fence(std::memory_order order);

Результат

Вставляет барьер с требуемыми ограничениями на упорядочение доступа к памяти.

Барьер, для которого параметр

order
равен
std::memory_order_release
,
std::memory_order_acq_rel
или
std::memory_order_seq_cst
синхронизируется-с операцией захвата некоторой ячейки памяти, если эта операция читает значение, сохраненное атомарной операцией, следующей за барьером в том же потоке, где поставлен барьер.

Операция освобождения синхронизируется-с барьером, для которого параметр

order
равен
std::memory_order_acquire
,
std::memory_order_acq_rel
или
std::memory_order_seq_cst
, если эта операция освобождения сохраняет значение, которое читается атомарной операцией, предшествующей барьеру, в том же потоке, где поставлен барьер.

Исключения

Нет.

D.3.6.
std::atomic_signal_fence
, функция

Функция

std::atomic_signal_fence()
вставляет в программу «барьер», чтобы принудительно обеспечить упорядочение доступа к памяти со стороны операций в некотором потоке и операций в обработчике сигнала, находящемся в том же потоке.

Объявление

extern "С" void atomic_signal_fence(std::memory_order order);

Результат

Вставляет барьер с требуемыми ограничениями на упорядочение доступа к памяти. Функция эквивалентна

std::atomic_thread_fence(order)
с тем отличием, что ограничения применяются только к потоку и обработчику сигнала в том же потоке.

Исключения

Нет.

D.3.7.
std::atomic_flag
, класс

Класс

std::atomic_flag
предоставляет самый простой атомарный флаг. Это единственный тип данных в стандарте С++, который гарантированно свободен от блокировок (хотя в большинстве реализаций этим свойством обладают и многие другие атомарные типы).

Объект типа

std::atomic_flag
может находиться в одном из двух состояний: установлен или сброшен.

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

struct atomic_flag {

 atomic_flag() noexcept = default;

 atomic_flag(const atomic_flag&) = delete;

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

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

 bool test_and_set(memory_order = memory_order_seq_cst)

  volatile noexcept;

 bool test_and_set(memory_order = memory_order_seq_cst) noexcept;

 void clear(memory_order = memory_order_seq_cst)

  volatile noexcept;

 void clear(memory_order = memory_order_seq_cst) noexcept;

};

bool atomic_flag_test_and_set(volatile atomic_flag*) noexcept;

bool atomic_flag_test_and_set(atomic_flag*) noexcept;

bool atomic_flag_test_and_set_explicit(

 volatile atomic_flag*, memory_order) noexcept;

bool atomic_flag_test_and_set_explicit(

 atomic_flag*, memory_order) noexcept;

void atomic_flag_clear(volatile atomic_flag*) noexcept;

void atomic_flag_clear(atomic_flag*) noexcept;

void atomic_flag_clear_explicit(

 volatile atomic_flag*, memory_order) noexcept;

void atomic_flag_clear_explicit(

 atomic_flag*, memory_order) noexcept;


#define ATOMIC_FLAG_INIT unspecified

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

He оговаривается, в каком состоянии находится сконструированный по умолчанию экземпляр

std::atomic_flag
: установлен или сброшен. Для объектов со статическим временем жизни обеспечивается статическая инициализация.

Объявление

std::atomic_flag() noexcept = default;

Результат

Конструирует новый объект

std::atomic_flag
в неопределенном состоянии.

Исключения

Нет.

STD::ATOMIC_FLAG
, ИНИЦИАЛИЗАЦИЯ МАКРОСОМ
ATOMIC_FLAG_INIT

Экземпляр типа

std::atomic_flag
может быть инициализирован макросом
ATOMIC_FLAG_INIT
, и в таком случае его начальное состояние — сброшен. Для объектов со статическим временем жизни обеспечивается статическая инициализация.

Объявление

#define ATOMIC_FLAG_INIT unspecified

Использование

std::atomic_flag flag = ATOMIC_FLAG_INIT;

Результат

Конструирует новый объект

std::atomic_flag
в состоянии сброшен.

Исключения

Нет.

STD::ATOMIC_FLAG::TEST_AND_SET
, ФУНКЦИЯ-ЧЛЕН

Атомарно устанавливает флаг и проверяет, был ли он установлен.

Объявление

bool test_and_set(memory_order order = memory_order_seq_cst)

 volatile noexcept;

bool test_and_set(memory_order order = memory_order_seq_cst)

 noexcept;

Результат

Атомарно устанавливает флаг.

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

true
, если флаг был установлен в точке вызова;
false
, если флаг был сброшен.

Исключения

Нет.

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

*this
.

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

Атомарно устанавливает флаг и проверяет, был ли он установлен.

Объявление

bool atomic_flag_test_and_set(

 volatile atomic_flag* flag) noexcept;

bool atomic_flag_test_and_set(atomic_flag* flag) noexcept;

Результат

return flag->test_and_set();

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

Атомарно устанавливает флаг и проверяет, был ли он установлен.

Объявление

bool atomic_flag_test_and_set_explicit(

 volatile atomic_flag* flag, memory_order order) noexcept;

bool atomic_flag_test_and_set_explicit(

 atomic_flag* flag, memory_order order) noexcept;

Результат

return flag->test_and_set(order);

STD::ATOMIC_FLAG::CLEAR
, ФУНКЦИЯ-ЧЛЕН

Атомарно сбрасывает флаг.

Объявление

void clear(memory_order order = memory_order_seq_cst) volatile noexcept;

void clear(memory_order order = memory_order_seq_cst) noexcept;

Предусловия

Параметр order должен принимать одно из значений

std::memory_order_relaxed
,
std::memory_order_release
или
std::memory_order_seq_cst
.

Результат

Атомарно сбрасывает флаг.

Исключения

Нет.

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

*this
.

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

Атомарно сбрасывает флаг.

Объявление

void atomic_flag_clear(volatile atomic_flag* flag) noexcept;

void atomic_flag_clear(atomic_flag* flag) noexcept;

Результат

flag->clear();

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

Атомарно сбрасывает флаг.

Объявление

void atomic_flag_clear_explicit(

 volatile atomic_flag* flag, memory_order order) noexcept;

void atomic_flag_clear_explicit(

 atomic_flag* flag, memory_order order) noexcept;

Результат

return flag->clear(order);

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

Шаблон класса

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

Параметр шаблона

BaseТуре
должен:

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

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

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

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

По существу, это означает, что конкретизация

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

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

x++
.

Экземпляры

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

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

template

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

bool atomic_is_lock_free(

 volatile const atomic*) noexcept;


template

 bool atomic_is_lock_free(const atomic*)

 noexcept;


template

void atomic_init(volatile atomic*, void*) noexcept;


template

void atomic_init(atomic*, void*) noexcept;


template

BaseType atomic_exchange(

 volatile atomic*, memory_order) noexcept;


template

BaseType atomic_exchange(

 atomic*, memory_order) noexcept;


template

BaseType atomic_exchange_explicit(

 volatile atomic*, memory_order) noexcept;


template

BaseType atomic_exchange_explicit(

 atomic*, memory_order) noexcept;


template

void atomic_store(volatile atomic*, BaseType) noexcept;


template

void atomic_store(atomic*, BaseType) noexcept;


template

void atomic_store_explicit(

 volatile atomic*, BaseType, memory_order) noexcept;


template

void atomic_store_explicit(

 atomic*, BaseType, memory_order) noexcept;


template

BaseType atomic_load(volatile const atomic*) noexcept;


template

BaseType atomic_load(const atomic*) noexcept;


template

BaseType atomic_load_explicit(

 volatile const atomic*, memory_order) noexcept;


template

BaseType atomic_load_explicit(

 const atomic*, memory_order) noexcept;


template

bool atomic_compare_exchange_strong(

 volatile atomic*,

 BaseType * old_value, BaseType new_value) noexcept;


template

bool atomic_compare_exchange_strong(

 atomic*,

 BaseType * old_value, BaseType new_value) noexcept;


template

bool atomic_compare_exchange_strong_explicit(

 volatile atomic*, BaseType * old_value,

 BaseType new_value, memory_order success_order,

 memory_order failure_order) noexcept;


template

bool atomic_compare_exchange_strong_explicit(

 atomic*,

 BaseType * old_value, BaseType new_value,

 memory_order success_order,

 memory_order failure_order) noexcept;


template

bool atomic_compare_exchange_weak(

 volatile atomic*,

 BaseType * old_value, BaseType new_value) noexcept;


template

bool atomic_compare_exchange_weak(

 atomic*,

 BaseType * old_value, BaseType new_value) noexcept;


template

bool atomic_compare_exchange_weak_explicit(

 volatile atomic*,

 BaseType * old_value, BaseType new_value,

 memory_order success_order,

 memory_order failure_order) noexcept;


template

bool atomic_compare_exchange_weak_explicit(

 atomic*,

 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
.

Объявление

template

void atomic_init(

 atomic volatile* p, BaseType v) noexcept;


template

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

Результат

Неатомарно сохраняет значение

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

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

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

bool atomic_is_lock_free(

 volatile const atomic* p) noexcept;

template

bool atomic_is_lock_free(const atomic* 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

BaseType atomic_load(volatile const atomic* p) noexcept;

template

BaseType atomic_load(const atomic* p) noexcept;

Результат

return p->load();

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

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

std::atomic
.

Объявление

template

BaseType atomic_load_explicit(

 volatile const atomic* p,

 memory_order order) noexcept;

template

BaseType atomic_load_explicit(

 const atomic* 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
.

Объявление

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
.

Объявление

template

void atomic_store(

 volatile atomic* p, BaseType new_value) noexcept;

template

void atomic_store(

 atomic* p, BaseType new_value) noexcept;

Результат

p->store(new_value);

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

Атомарно сохраняет новое значение в объекте

atomic
.

Объявление

template

void atomic_store_explicit(

 volatile atomic* p, BaseType new_value,

 memory_order order) noexcept;

template

void atomic_store_explicit(

 atomic* 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
и читает предыдущее значение.

Объявление

template

BaseType atomic_exchange(

 volatile atomic* p, BaseType new_value) noexcept;

template

BaseType atomic_exchange(

 atomic* p, BaseType new_value) noexcept;

Результат

return p->exchange(new_value);

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

Атомарно сохраняет новое значение в объекте

atomic
и читает предыдущее значение.

Объявление

template

BaseType atomic_exchange_explicit(

 volatile atomic* p,

 BaseType new_value, memory_order order)

 noexcept;

template

BaseType atomic_exchange_explicit(

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

bool atomic_compare_exchange_strong(

 volatile atomic* p,

 BaseType * old_value, BaseType new_value) noexcept;

template

bool atomic_compare_exchange_strong(

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

bool atomic_compare_exchange_strong_explicit(

 volatile atomic* p,

 BaseType * old_value, BaseType new_value,

 memory_order success_order, memory_order failure_order)

 noexcept;

template

bool atomic_compare_exchange_strong_explicit(

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

bool atomic_compare_exchange_weak(

 volatile atomic* p,

 BaseType * old_value, BaseType new_value) noexcept;

template

bool atomic_compare_exchange_weak(

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

bool atomic_compare_exchange_weak_explicit(

 volatile atomic* p,

 BaseType * old_value, BaseType new_value,

 memory_order success_order,

 memory_order failure_order) noexcept;

template

bool atomic_compare_exchange_weak_explicit(

 atomic* 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);

D.3.9. Специализации шаблона
std::atomic

Предоставляются специализации шаблона

std::atomic
для целочисленных и указательных типов. Для целочисленных типов специализации обеспечивают атомарные операции сложения, вычитания и поразрядные в дополнение к имеющимся в основном шаблоне. Для указательных типов в дополнение к основному шаблону предоставляются арифметические операции над указателями.

Имеются специализации для следующих целочисленных типов:

std::atomic

std::atomic

std::atomic

std::atomic

std::atomic

std::atomic

std::atomic

std::atomic

std::atomic

std::atomic

std::atomic

std::atomic

std::atomic

std::atomic

std::atomic

а также для типа

std::atomic
при любом типе
T
.

D.3.10. Специализации
std::atomic<integral-type>

Специализации

std::atomic<integral-type>
шаблона класса
std::atomic
дают атомарный целочисленный тип для каждого фундаментального целочисленного типа, с полным набором операций.

Ниже перечислены все такие специализации шаблона

std::atomic<>
:

std::atomic

std::atomic

std::atomic

std::atomic

std::atomic

std::atomic

std::atomic

std::atomic

std::atomic

std::atomic

std::atomic

std::atomic

std::atomic

std::atomic

Экземпляры этих специализаций не удовлетворяют требованиям концепций

CopyConstructible
и
CopyAssignable
, поскольку такие операции невозможно выполнить атомарно.

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

template<>

struct atomic<integral-type> {

 atomic() noexcept = default;

 constexpr atomic(integral-type) noexcept;

 bool operator=(integral-type) volatile 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(

  integral-type, memory_order = memory_order_seq_cst)

  volatile noexcept;

 void store(

  integral-type, memory_order = memory_order_seq_cst) noexcept;

 integral-type load(memory_order = memory_order_seq_cst)

  const volatile noexcept;

 integral-type load(

  memory_order = memory_order_seq_cst) const noexcept;

 integral-type exchange(

  integral-type,

  memory_order = memory_order_seq_cst) volatile noexcept;

 integral-type exchange(

  integral-type, memory_order = memory_order_seq_cst) noexcept;


 bool compare_exchange_strong(

  integral-type& old_value, integral-type new_value,

  memory_order order = memory_order_seq_cst)

  volatile noexcept;

 bool compare_exchange_strong(

  integral-type& old_value, integral-type new_value,

  memory_order order = memory_order_seq_cst) noexcept;

 bool compare_exchange_strong(

  integral-type& old_value, integral-type new_value,

  memory_order success_order, memory_order failure_order)

  volatile noexcept;

 bool compare_exchange_strong(

  integral-type& old_value, integral-type new_value,

  memory_order success_order,

  memory_order failure_order) noexcept;

 bool compare_exchange_weak(

  integral-type& old_value, integral-type new_value,

  memory_order order = memory_order_seq_cst) volatile noexcept;

 bool compare_exchange_weak(

  integral-type& old_value, integral-type new_value,

  memory_order order = memory_order_seq_cst) noexcept;

 bool compare_exchange_weak(

  integral-type& old_value, integral-type new_value,

  memory_order success_order, memory_order failure_order)

  volatile noexcept;

 bool compare_exchange_weak(

  integral-type& old_value, integral-type new_value,

  memory_order success_order,

  memory_order failure_order) noexcept;


 operator integral-type() const volatile noexcept;

 operator integral-type() const noexcept;

 integral-type fetch_add(

  integral-type, memory_order = memory_order_seq_cst)

  volatile noexcept;

 integral-type fetch_add(

  integral-type, memory_order = memory_order_seq_cst) noexcept;

 integral-type fetch_sub(

  integral-type, memory_order = memory_order_seq_cst)

  volatile noexcept;

 integral-type fetch_sub(

  integral-type, memory_order = memory_order_seq_cst) noexcept;

 integral-type fetch_and(

  integral-type, memory_order = memory_order_seq_cst)

  volatile noexcept;

 integral-type fetch_and(

  integral-type, memory_order = memory_order_seq_cst) noexcept;

 integral-type fetch_or(

  integral-type, memory_order = memory_order_seq_cst)

  volatile noexcept;

 integral-type fetch_or(

  integral-type, memory_order = memory_order_seq_cst) noexcept;

 integral-type fetch_xor(

  integral-type, memory_order = memory_order_seq_cst)

  volatile noexcept;

 integral-type fetch_xor(

  integral-type, memory_order = memory_order_seq_cst) noexcept;

 integral-type operator++() volatile noexcept;

 integral-type operator++() noexcept;

 integral-type operator++(int) volatile noexcept;

 integral-type operator++(int) noexcept;

 integral-type operator--() volatile noexcept;

 integral-type operator--() noexcept;

 integral-type operator--(int) volatile noexcept;

 integral-type operator--(int) noexcept;


 integral-type operator+=(integral-type) volatile noexcept;

 integral-type operator+=(integral-type) noexcept;

 integral-type operator-=(integral-type) volatile noexcept;

 integral-type operator-=(integral-type) noexcept;

 integral-type operator&=(integral-type) volatile noexcept;

 integral-type operator&=(integral-type) noexcept;

 integral-type operator|=(integral-type) volatile noexcept;

 integral-type operator|=(integral-type) noexcept;

 integral-type operator^=(integral-type) volatile noexcept;

 integral-type operator^=(integral-type) noexcept;

};


bool atomic_is_lock_free(

 volatile const atomic<integral-type>*) noexcept;

bool atomic_is_lock_free(const atomic<integral-type>*) noexcept;

void atomic_init(

 volatile atomic<integral-type>*, integral-type) noexcept;

void atomic_init(atomic<integral-type>*, integral-type) noexcept;

integral-type atomic_exchange(

 volatile atomic<integral-type>*, integral-type) noexcept;

integral-type atomic_exchange(

 atomic<integral-type>*, integral-type) noexcept;


integral-type atomic_exchange_explicit(

 volatile atomic<integral-type>*, integral-type, memory_order)

 noexcept;

integral-type atomic_exchange_explicit(

 atomic<integral-type>*, integral-type, memory_order) noexcept;

void atomic_store(

 volatile atomic<integral-type>*, integral-type) noexcept;

void atomic_store(

 atomic<integral-type>*, integral-type) noexcept;

void atomic_store_explicit(

 volatile atomic<integral-type>*,

 integral-type, memory_order) noexcept;

void atomic_store_explicit(

 atomic<integral-type>*, integral-type, memory_order) noexcept;

integral-type atomic_load(

 volatile const atomic<integral-type>*) noexcept;

integral-type atomic_load(

 const atomic<integral-type>*) noexcept;

integral-type atomic_load_explicit(

 volatile const atomic<integral-type>*, memory_order) noexcept;

integral-type atomic_load_explicit(

 const atomic<integral-type>*, memory_order) noexcept;

bool atomic_compare_exchange_strong(

 volatile atomic<integral-type>*, integral-type * old_value,

 integral-type new_value) noexcept;

bool atomic_compare_exchange_strong(

 atomic<integral-type>*,

 integral-type * old_value, integral-type new_value) noexcept;

bool atomic_compare_exchange_strong_explicit(

 volatile atomic<integral-type>*,

 integral-type * old_value, integral-type new_value,

 memory_order success_order,

 memory_order failure_order) noexcept;

bool atomic_compare_exchange_strong_explicit(

 atomic<integral-type>*,

 integral-type * old_value, integral-type new_value,

 memory_order success_order,

 memory_order failure_order) noexcept;

bool atomic_compare_exchange_weak(

 volatile atomic<integral-type>*,

 integral-type * old_value, integral-type new_value) noexcept;

bool atomic_compare_exchange_weak(

 atomic<integral-type>*,

 integral-type * old_value, integral-type new_value) noexcept;

bool atomic_compare_exchange_weak_explicit(

 volatile atomic<integral-type>*,

integral-type * old_value, integral-type new_value,

 memory_order success_order,

 memory_order failure_order) noexcept;

bool atomic_compare_exchange_weak_explicit(

 atomic<integral-type>*,

 integral-type * old_value, integral-type new_value,

 memory_order success_order,

 memory_order failure_order) noexcept;

 integral-type atomic_fetch_add(

 volatile atomic<integral-type>*, integral-type) noexcept;

integral-type atomic_fetch_add(

 atomic<integral-type>*, integral-type) noexcept;

integral-type atomic_fetch_add_explicit(

 volatile atomic<integral-type>*, integral-type,

 memory_order) noexcept;

integral-type atomic_fetch_add_explicit(

 atomic<integral-type>*, integral-type, memory_order) noexcept;

integral-type atomic_fetch_sub(

 volatile atomic<integral-type>*, integral-type) noexcept;

integral-type atomic_fetch_sub(

 atomic<integral-type>*, integral-type) noexcept;

integral-type atomic_fetch_sub_explicit(

 volatile atomic<integral-type>*,

 integral-type, memory_order) noexcept;

integral-type atomic_fetch_sub_explicit(

 atomic<integral-type>*, integral-type, memory_order) noexcept;

integral-type atomic_fetch_and(

 volatile atomic<integral-type>*, integral-type) noexcept;

integral-type atomic_fetch_and(

 atomic<integral-type>*, integral-type) noexcept;

integral-type atomic_fetch_and_explicit(

 volatile atomic<integral-type>*,

 integral-type, memory_order) noexcept;

integral-type atomic_fetch_and_explicit(

 atomic<integral-type>*, integral-type, memory_order) noexcept;

integral-type atomic_fetch_or(

 volatile atomic<integral-type>*, integral-type) noexcept;

integral-type atomic_fetch_or(

 atomic<integral-type>*, integral-type) noexcept;

integral-type atomic_fetch_or_explicit(

 volatile atomic<integral-type>*,

 integral-type, memory_order) noexcept;

integral-type atomic_fetch_or_explicit(

 atomic<integral-type>*, integral-type, memory_order) noexcept;

integral-type atomic_fetch_xor(

 volatile atomic<integral-type>*, integral-type) noexcept;

integral-type atomic_fetch_xor(

 atomic<integral-type>*, integral-type) noexcept;

integral-type atomic_fetch_xor_explicit(

 volatile atomic<integral-type>*,

 integral-type, memory_order) noexcept;

integral-type atomic_fetch_xor_explicit(

 atomic<integral-type>*, integral-type, memory_order) noexcept;

Те операции, которые предоставляются также основным шаблоном (см. D.3.8), имеют точно такую же семантику.

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

Атомарно загружает значение и заменяет его суммой его самого и аргумента

i
.

Объявление

fetch_add(

 integral-type i, memory_order order = memory_order_seq_cst)

 volatile noexcept;

integral-type fetch_add(

 integral-type i, memory_order order = memory_order_seq_cst)

 noexcept;

Результат

Атомарно возвращает прежнее значение

*this
и сохраняет в
*this
значение
old-value + i
.

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

Значение

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

Исключения

Нет.

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

*this
.

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

Атомарно читает значение из экземпляра

atomic<integral-type>
и заменяет его суммой этого значения и аргумента
i
.

Объявление

integral-type atomic_fetch_add(

 volatile atomic<integral-type>* p, integral-type i) noexcept;

integral-type atomic_fetch_add(

 atomic<integral-type>* p, integral-type i) noexcept;

Результат

return p->fetch_add(i);

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

КЛАССА

Атомарно читает значение из экземпляра

atomic<integral-type>
и заменяет его суммой этого значения и аргумента
i
.

Объявление

integral-type atomic_fetch_add_explicit(

 volatile atomic<integral-type>* p, integral-type i,

 memory_order order) noexcept;

integral-type atomic_fetch_add_explicit(

 atomic<integral-type>* p, integral-type i,

 memory_order order) noexcept;

Результат

return p->fetch_add(i,order);

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

Атомарно читает значение и заменяет его разностью этого значения и аргумента

i
.

Объявление

integral-type fetch_sub(

 integral-type i,

 memory_order order = memory_order_seq_cst) volatile noexcept;

integral-type fetch_sub(

 integral-type i,

 memory_order order = memory_order_seq_cst) noexcept;

Результат

Атомарно возвращает прежнее значение

*this
и сохраняет в
*this
значение
old-value - i
.

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

Значение

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

Исключения

Нет.

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

*this
.

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

Атомарно читает значение из экземпляра

atomic<integral-type>
и заменяет его разностью этого значения и аргумента
i
.

Объявление

integral-type atomic_fetch_sub(

 volatile atomic<integral-type>* p, integral-type i) noexcept;

integral-type atomic_fetch_sub(

 atomic<integral-type>* p, integral-type i) noexcept;

Результат

return p->fetch_sub(i);

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

Атомарно читает значение из экземпляра

atomic<integral-type>
и заменяет его разностью этого значения и аргумента
i
.

Объявление

integral-type atomic_fetch_sub_explicit(

 volatile atomic<integral-type>* p,

 integral-type i, memory_order order) noexcept;

integral-type atomic_fetch_sub_explicit(

 atomic<integral-type>* p,

 integral-type i, memory_order order) noexcept;

Результат

return p->fetch_sub(i, order);

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

Атомарно загружает значение и заменяет его результатом операции поразрядное-и между этим значением и аргументом

i
.

Объявление

integral-type fetch_and(

 integral-type i, memory_order order = memory_order_seq_cst)

 volatile noexcept;

integral-type fetch_and(

 integral-type i, memory_order order = memory_order_seq_cst)

 noexcept;

Результат

Атомарно возвращает прежнее значение

*this
и сохраняет в
*this
значение
old-value & i
.

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

Значение

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

Исключения

Нет.

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

*this
.

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

Атомарно читает значение из экземпляра

atomic<integral-type>
и заменяет его результатом операции поразрядное-и между этим значением и аргументом
i
. Объявление

integral-type atomic_fetch_and(

 volatile atomic<integral-type>* p, integral-type i) noexcept;

integral-type atomic_fetch_and(

 atomic<integral-type>* p, integral-type i) noexcept;

Результат

return p->fetch_and(i);

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

Атомарно читает значение из экземпляра

atomic<integral-type>
и заменяет его результатом операции поразрядное-и между этим значением и аргументом
i
.

Объявление

integral-type atomic_fetch_and_explicit(

 volatile atomic<integral-type>* p,

 integral-type i, memory_order order) noexcept;

integral-type atomic_fetch_and_explicit(

 atomic<integral-type>* p,

 integral-type i, memory_order order) noexcept;

Результат

return p->fetch_and(i,order);

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

Атомарно загружает значение и заменяет его результатом операции поразрядное-или между этим значением и аргументом

i
.

Объявление

integral-type fetch_or(

 integral-type i, memory_order order = memory_order_seq_cst)

volatile noexcept;

integral-type fetch_or(

 integral-type i, memory_order order = memory_order_seq_cst)

 noexcept;

Результат

Атомарно возвращает прежнее значение

*this
и сохраняет в
*this
значение
old-value | i
.

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

Значение

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

Исключения

Нет.

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

*this
.

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

Атомарно читает значение из экземпляра

atomic<integral-type>
и заменяет его результатом операции поразрядное-или между этим значением и аргументом
i
.

Объявление

integral-type atomic_fetch_or(

 volatile atomic<integral-type>* p, integral-type i) noexcept;

integral-type atomic_fetch_or(

 atomic<integral-type>* p, integral-type i) noexcept;

Результат

return p->fetch_or(i);

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

Атомарно читает значение из экземпляра

atomic<integral-type>
и заменяет его результатом операции поразрядное-или между этим значением и аргументом i.

Объявление

integral-type atomic_fetch_or_explicit(

 volatile atomic<integral-type>* p,

 integral-type i, memory_order order) noexcept;

integral-type atomic_fetch_or_explicit(

 atomic<integral-type>* p,

 integral-type i, memory_order order) noexcept;

Результат

return p->fetch_or(i, order);

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

Атомарно загружает значение и заменяет его результатом операции поразрядное исключающее-или между этим значением и аргументом i.

Объявление

integral-type fetch_xor(

 integral-type i, memory_order order = memory_order_seq_cst)

 volatile noexcept;

integral-type fetch_xor(

 integral-type i, memory_order order = memory_order_seq_cst)

 noexcept;

Результат

Атомарно возвращает прежнее значение

*this
и сохраняет в
*this
значение
old-value ^ i
.

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

Значение

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

Исключения

Нет.

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

*this
.

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

Атомарно читает значение из экземпляра

atomic<integral-type>
и заменяет его результатом операции поразрядное исключающее-или между этим значением и аргументом
i
.

Объявление

integral-type atomic_fetch_xor(

 volatile atomic<integral-type>* p, integral-type i) noexcept;

integral-type atomic_fetch_xor(

 atomic<integral-type>* p, integral-type i) noexcept;

Результат

return p->fetch_xor(i);

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

Атомарно читает значение из экземпляра

atomic<integral-type>
и заменяет его результатом операции поразрядное исключающее-или между этим значением и аргументом
i
.

Объявление

integral-type atomic_fetch_xor_explicit(

 volatile atomic<integral-type>* p,

 integral-type i, memory_order order) noexcept;

integral-type atomic_fetch_xor_explicit(

 atomic<integral-type>* p,

 integral-type i, memory_order order) noexcept;

Результат

return p->fetch_xor(i,order);

STD::ATOMIC::OPERATOR++
, ОПЕРАТОР ПРЕДИНКРЕМЕНТА

Атомарно инкрементирует значение, хранящееся в

*this
, и возвращает новое значение.

Объявление

integral-type operator++() volatile noexcept;

integral-type operator++() noexcept;

Результат

return this->fetch_add(1) + 1;

STD::ATOMIC::OPERATOR++
, ОПЕРАТОР ПОСТИНКРЕМЕНТА

Атомарно инкрементирует значение, хранящееся в

*this
, и возвращает старое значение.

Объявление

integral-type operator++(int) volatile noexcept;

integral-type operator++(int) noexcept;

Результат

return this->fetch_add(1);

STD::ATOMIC::OPERATOR--
, ОПЕРАТОР ПРЕДЕКРЕМЕНТА

Атомарно декрементирует значение, хранящееся в

*this
, и возвращает новое значение.

Объявление

integral-type operator--() volatile noexcept;

integral-type operator--() noexcept;

Результат

return this->fetch_sub(1) - 1;

STD::ATOMIC::OPERATOR--
, ОПЕРАТОР ПОСТДЕКРЕМЕНТА

Атомарно декрементирует значение, хранящееся в

*this
, и возвращает старое значение.

Объявление

integral-type operator--(int) volatile noexcept;

integral-type operator--(int) noexcept;

Результат

return this->fetch_sub(1);

STD::ATOMIC::OPERATOR+=
, СОСТАВНОЙ ОПЕРАТОР ПРИСВАИВАНИЯ

Атомарно складывает значение аргумента со значением, хранящимся в

*this
, и возвращает новое значение.

Объявление

integral-type operator+=(integral-type i) volatile noexcept;

integral-type operator+=(integral-type i) noexcept;

Результат

return this->fetch_add(i) + i;

STD::ATOMIC::OPERATOR-=
, СОСТАВНОЙ ОПЕРАТОР ПРИСВАИВАНИЯ

Атомарно вычитает значение аргумента из значения, хранящегося в

*this
, и возвращает новое значение.

Объявление

integral-type operator-=(integral-type i) volatile noexcept;

integral-type operator-=(integral-type i) noexcept;

Результат

return this->fetch_sub(i, std::memory_order_seq_cst) - i;

STD::ATOMIC::OPERATOR&=
, СОСТАВНОЙ ОПЕРАТОР ПРИСВАИВАНИЯ

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

*this
, результатом операции поразрядное-и между этим значением и значением аргумента и возвращает новое значение.

Объявление

integral-type operator&=(integral-type i) volatile noexcept;

integral-type operator&=(integral-type i) noexcept;

Результат

return this->fetch_and(i) & i;

STD::ATOMIC::OPERATOR|=
, СОСТАВНОЙ ОПЕРАТОР ПРИСВАИВАНИЯ

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

*this
, результатом операции поразрядное-или между этим значением и значением аргумента и возвращает новое значение.

Объявление

integral-type operator|=(integral-type i) volatile noexcept;

integral-type operator|=(integral-type i) noexcept;

Результат

return this->fetch_or(i, std::memory_order_seq_cst) | i;

STD::ATOMIC::OPERATOR^=
, СОСТАВНОЙ ОПЕРАТОР ПРИСВАИВАНИЯ

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

*this
, результатом операции поразрядное исключающее-или между этим значением и значением аргумента и возвращает новое значение.

Объявление

integral-type operator^=(integral-type i) volatile noexcept;

integral-type operator^=(integral-type i) noexcept;

Результат

return this->fetch_xor(i, std::memory_order_seq_cst) ^ i;

STD::ATOMIC
, ЧАСТИЧНАЯ СПЕЦИАЛИЗАЦИЯ

Частичная специализация

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

Экземпляры

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

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

template

struct atomic {

 atomic() noexcept = default;

 constexpr atomic(T*) noexcept;

 bool operator=(T*) volatile;

 bool operator=(T*);


 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(T*, memory_order = memory_order_seq_cst)

  volatile noexcept;

 void store(T*, memory_order = memory_order_seq_cst) noexcept;

 T* load(memory_order = memory_order_seq_cst)

  const volatile noexcept;

 T* load(memory_order = memory_order_seq_cst) const noexcept;

 T* exchange(T*, memory_order = memory_order_seq_cst)

  volatile noexcept;

 T* exchange(T*, memory_order = memory_order_seq_cst) noexcept;


 bool compare_exchange_strong(

  T* & old_value, T* new_value,

  memory_order order = memory_order_seq_cst)

  volatile noexcept;

 bool compare_exchange_strong(

  T* & old_value, T* new_value,

  memory_order order = memory_order_seq_cst) noexcept;

 bool compare_exchange_strong(

  T* & old_value, T* new_value,

  memory_order success_order, memory_order failure_order)

  volatile noexcept;

 bool compare_exchange_strong(

  T* & old_value, T* new_value,

  memory_order success_order,

  memory_order failure_order) noexcept;

 bool compare_exchange_weak(

  T* & old_value, T* new_value,

  memory_order order = memory_order_seq_cst) volatile noexcept;

 bool compare_exchange_weak(

  T* & old_value, T* new_value,

  memory_order order = memory_order_seq_cst) noexcept;

 bool compare_exchange_weak(

  T* & old_value, T* new_value,

  memory_order success_order, memory_order failure_order)

  volatile noexcept;

 bool compare_exchange_weak(

  T* & old_value, T* new_value,

  memory_order success_order,

  memory_order failure_order) noexcept;


 operator T*() const volatile noexcept;

 operator T*() const noexcept;


 T* fetch_add(

  ptrdiff_t, memory_order = memory_order_seq_cst)

  volatile noexcept;

 T* fetch_add(

  ptrdiff_t, memory_order = memory_order_seq_cst) noexcept;

 T* fetch_sub(

  ptrdiff_t, memory_order = memory_order_seq_cst)

  volatile noexcept;

 T* fetch_sub(

  ptrdiff_t, memory_order = memory_order_seq_cst) noexcept;

 T* operator++() volatile noexcept;

 T* operator++() noexcept;

 T* operator++(int) volatile noexcept;

 T* operator++(int) noexcept;

 T* operator--() volatile noexcept;

 T* operator--() noexcept;

 T* operator--(int) volatile noexcept;

 T* operator--(int) noexcept;

 T* operator+=(ptrdiff_t) volatile noexcept;

 T* operator+=(ptrdiff_t) noexcept;

 T* operator-=(ptrdiff_t) volatile noexcept;

 T* operator-=(ptrdiff_t) noexcept;

};


bool atomic_is_lock_free(volatile const atomic*) noexcept;

bool atomic_is_lock_free(const atomic*) noexcept;

void atomic_init(volatile atomic*, T*) noexcept;

void atomic_init(atomic*, T*) noexcept;

T* atomic_exchange(volatile atomic*, T*) noexcept;

T* atomic_exchange(atomic*, T*) noexcept;

T* atomic_exchange_explicit(

 volatile atomic*, T*, memory_order) noexcept;

T* atomic_exchange_explicit(

 atomic*, T*, memory_order) noexcept;

void atomic_store(volatile atomic*, T*) noexcept;

void atomic_store(atomic*, T*) noexcept;

void atomic_store_explicit(

 volatile atomic*, T*, memory_order) noexcept;

void atomic_store_explicit(

 atomic*, T*, memory_order) noexcept;

T* atomic_load(volatile const atomic*) noexcept;

T* atomic_load(const atomic*) noexcept;

T* atomic_load_explicit(

 volatile const atomic*, memory_order) noexcept;

T* atomic_load_explicit(

 const atomic*, memory_order) noexcept;

bool atomic_compare_exchange_strong(

 volatile atomic*, T** old_value, T* new_value) noexcept;

bool atomic_compare_exchange_strong(

 volatile atomic*, T** old_value, T* new_value) noexcept;

bool atomic_compare_exchange_strong_explicit(

 atomic*, T** old_value, T* new_value,

 memory_order success_order,

 memory_order failure_order) noexcept;

bool atomic_compare_exchange_strong_explicit(

 atomic*, T** old_value, T* new_value,

 memory_order success_order,

 memory_order failure_order) noexcept;

bool atomic_compare_exchange_weak(

 volatile atomic*, T** old_value, T* new_value) noexcept;

bool atomic_compare_exchange_weak(

 atomic*, T** old_value, T* new_value) noexcept;

bool atomic_compare_exchange_weak_explicit(

 volatile atomic*,

 T** old_value, T* new_value,

 memory_order success_order,

 memory_order failure_order) noexcept;

bool atomic_compare_exchange_weak_explicit(

 atomic*, T** old_value, T* new_value,

 memory_order success_order,

 memory_order failure_order) noexcept;

T* atomic_fetch_add(volatile atomic*, ptrdiff_t) noexcept;

T* atomic_fetch_add(atomic*, ptrdiff_t) noexcept;

T* atomic_fetch_add_explicit(

 volatile atomic*, ptrdiff_t, memory_order) noexcept;

T* atomic_fetch_add_explicit(

 atomic*, ptrdiff_t, memory_order) noexcept;

T* atomic_fetch_sub(volatile atomic*, ptrdiff_t) noexcept;

T* atomic_fetch_sub(atomic*, ptrdiff_t) noexcept;

T* atomic_fetch_sub_explicit(

 volatile atomic*, ptrdiff_t, memory_order) noexcept;

T* atomic_fetch_sub_explicit(

 atomic*, ptrdiff_t, memory_order) noexcept;

Те операции, которые предоставляются также основным шаблоном (см. приложение D.3.8), имеют точно такую же семантику.

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

Атомарно загружает значение, заменяет его суммой этого значения и аргумента

i
, применяя стандартные правила арифметики указателей, и возвращает старое значение.

Объявление

T* fetch_add(

 ptrdiff_t i, memory_order order = memory_order_seq_cst)

 volatile noexcept;

T* fetch_add(

 ptrdiff_t i, memory_order order = memory_order_seq_cst) noexcept;

Результат

Атомарно возвращает текущее значение

*this
и сохраняет в
*this
значение
old-value + i
.

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

Значение

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

Исключения

Нет.

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

*this
.

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

Атомарно читает значение из экземпляра

atomic
и заменяет его суммой этого значения и аргумента
i
, применяя стандартные правила арифметики указателей.

Объявление

T* atomic_fetch_add_explicit(

 volatile atomic* p, ptrdiff_t i, memory_order order)

 noexcept;

T* atomic_fetch_add_explicit(

 atomic* p, ptrdiff_t i, memory_order order) noexcept;

Результат

return p->fetch_add(i, order);

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

Атомарно загружает значение, заменяет его разностью этого значения и аргумента

i
, применяя стандартные правила арифметики указателей, и возвращает старое значение.

Объявление

T* fetch_sub(

 ptrdiff_t i, memory_order order = memory_order_seq_cst)

 volatile noexcept;

T* fetch_sub(

 ptrdiff_t i, memory_order order = memory_order_seq_cst)

 noexcept;

Результат

Атомарно возвращает текущее значение

*this
и сохраняет в
*this
значение
old-value - i
.

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

Значение

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

Исключения

Нет.

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

*this
.

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

Атомарно читает значение из экземпляра

atomic
и заменяет его разностью этого значения и аргумента
i
, применяя стандартные правила арифметики указателей.

Объявление

T* atomic_fetch_sub(

 volatile atomic* p, ptrdiff_t i) noexcept;

T* atomic_fetch_sub(atomic* p, ptrdiff_t i) noexcept;

Результат

return p->fetch_sub(i);

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

Атомарно читает значение из экземпляра

atomic
и заменяет его разностью этого значения и аргумента
i
, применяя стандартные правила арифметики указателей.

Объявление

T* atomic_fetch_sub_explicit(

 volatile atomic* p, ptrdiff_t i, memory_order order)

 noexcept;

T* atomic_fetch_sub_explicit(

 atomic* p, ptrdiff_t i, memory_order order) noexcept;

Результат

return p->fetch_sub(i, order);

STD::ATOMIC::OPERATOR++
, ОПЕРАТОР ПРЕДИНКРЕМЕНТА

Атомарно инкрементирует значение, хранящееся в

*this
, применяя стандартные правила арифметики указателей, и возвращает новое значение.

Объявление

T* operator++() volatile noexcept;

T* operator++() noexcept;

Результат

return this->fetch_add(1) + 1;

STD::ATOMIC::OPERATOR++
, ОПЕРАТОР ПОСТИНКРЕМЕНТА

Атомарно инкрементирует значение, хранящееся в

*this
, и возвращает старое значение.

Объявление

T* operator++(int) volatile noexcept;

T* operator++(int) noexcept;

Результат

return this->fetch_add(1);

STD::ATOMIC::OPERATOR--
, ОПЕРАТОР ПРЕДЕКРЕМЕНТА

Атомарно декрементирует значение, хранящееся в

*this
, применяя стандартные правила арифметики указателей, и возвращает новое значение.

Объявление

T* operator--() volatile noexcept;

T* operator--() noexcept;

Результат

return this->fetch_sub(1) - 1;

STD::ATOMIC::OPERATOR--
, ОПЕРАТОР ПОСТДЕКРЕМЕНТА

Атомарно декрементирует значение, хранящееся в

*this
, применяя стандартные правила арифметики указателей, и возвращает старое значение.

Объявление

T* operator--(int) volatile noexcept;

T* operator--(int) noexcept;

Результат

return this->fetch_sub(1);

STD::ATOMIC::OPERATOR+=
, СОСТАВНОЙ ОПЕРАТОР ПРИСВАИВАНИЯ

Атомарно складывает значение аргумента со значением, хранящимся в

*this
, применяя стандартные правила арифметики указателей, и возвращает новое значение.

Объявление

T* operator+=(ptrdiff_t i) volatile noexcept;

T* operator+=(ptrdiff_t i) noexcept;

Результат

return this->fetch_add(i) + i;

STD::ATOMIC::OPERATOR-=
, СОСТАВНОЙ ОПЕРАТОР ПРИСВАИВАНИЯ

Атомарно вычитает значение аргумента из значения, хранящегося в

*this
, применяя стандартные правила арифметики указателей, и возвращает новое значение.

Объявление

T* operator-=(ptrdiff_t i) volatile noexcept;

T* operator-=(ptrdiff_t i) noexcept;

Результат

return this->fetch_sub(i) - i;

D.4. Заголовок