Spec-Zone.ru › C

atomic_fetch_add, atomic_fetch_add_explicit

Определено в заголовке <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. Аргумент — указатель на изменчивый атомный тип для приема адресов как неизменчивых, так и изменчивых (например, отображаемых в памяти) атомных объектов, и семантика изменчивости сохраняется при применении этой операции к изменчивым атомным объектам. 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 и модификации (стр: 208)
  • Стандарт C11 (ISO/IEC 9899:2011):
    • 7.17.7.5 Общие функции atomic_fetch и модификации (стр: 284-285)

См. также

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

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/c/atomic/atomic_fetch_add

Spec-Zone.ru

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