Namespaces
Variants

atomic_fetch_add, atomic_fetch_add_explicit

From cppreference.net
Определено в заголовочном файле <stdatomic.h>
C atomic_fetch_add ( volatile A * obj, M arg ) ;
(1) (начиная с C11)
C atomic_fetch_add_explicit ( volatile A * obj, M arg, memory_order order ) ;
(2) (начиная с C11)

Атомарно заменяет значение, на которое указывает obj , результатом сложения arg со старым значением obj , и возвращает значение obj , которое хранилось ранее. Операция является операцией чтения-изменения-записи. Первая версия упорядочивает доступ к памяти в соответствии с memory_order_seq_cst , вторая версия упорядочивает доступ к памяти в соответствии с order .

Это обобщённая функция , определённая для всех атомарных типов объектов A . Аргументом является указатель на volatile атомарный тип для принятия адресов как не-volatile, так и volatile (например, отображаемых в памяти I/O) атомарных объектов, и семантика volatile сохраняется при применении этой операции к volatile атомарным объектам. M является либо неатомарным типом, соответствующим A , если A является атомарным целочисленным типом, либо ptrdiff_t , если A является атомарным типом указателя.

Не определено, является ли имя обобщённой функции макросом или идентификатором, объявленным с внешней линковкой. Если определение макроса подавляется для доступа к реальной функции (например, заключено в скобки как ( atomic_fetch_add ) ( ... ) ), или программа определяет внешний идентификатор с именем обобщённой функции, поведение не определено.

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

Содержание

Параметры

obj - указатель на атомарный объект для модификации
arg - значение для добавления к значению, хранящемуся в атомарном объекте
order - порядок синхронизации памяти для этой операции: допустимы все значения

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

Значение, которое ранее содержалось в атомарном объекте, на который указывает obj .

Пример

#include <stdio.h>
#include <threads.h>
#include <stdatomic.h>
atomic_int acnt;
int cnt;
int f(void* thr_data)
{
    for(int n = 0; n < 1000; ++n) {
        atomic_fetch_add_explicit(&acnt, 1, memory_order_relaxed); // atomic
        ++cnt; // undefined behavior, in practice some updates missed
    }
    return 0;
}
int main(void)
{
    thrd_t thr[10];
    for(int n = 0; n < 10; ++n)
        thrd_create(&thr[n], f, NULL);
    for(int n = 0; n < 10; ++n)
        thrd_join(thr[n], NULL);
    printf("The atomic counter is %u\n", acnt);
    printf("The non-atomic counter is %u\n", cnt);
}

Возможный вывод:

The atomic counter is 10000
The non-atomic counter is 9511

Ссылки

  • Стандарт C17 (ISO/IEC 9899:2018):
  • 7.17.7.5 Универсальные функции atomic_fetch и modify (стр. 208)
  • Стандарт C11 (ISO/IEC 9899:2011):
  • 7.17.7.5 Универсальные функции atomic_fetch и modify (стр: 284-285)

Смотрите также

атомарное вычитание
(функция)
Документация C++ для atomic_fetch_add , atomic_fetch_add_explicit