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 が指す値を、 obj の元の値に arg を加算した結果で原子的に置き換え、 obj が以前保持していた値を返します。この操作はread-modify-write操作です。最初のバージョンはメモリアクセスを memory_order_seq_cst に従って順序付けし、2番目のバージョンはメモリアクセスを order に従って順序付けします。

これはすべての generic function に対して定義された atomic object types A です。引数はvolatile atomic型へのポインタであり、非volatileと volatile (例:メモリマップドI/O)の両方のatomicオブジェクトのアドレスを受け入れます。また、volatile atomicオブジェクトにこの操作を適用する際にはvolatileセマンティクスが保持されます。 M は、 A がatomic integer型の場合には A に対応する非atomic型、または A がatomic pointer型の場合には ptrdiff_t のいずれかです。

ジェネリック関数の名前がマクロであるか、外部リンケージで宣言された識別子であるかは未規定である。実際の関数にアクセスするために(例えば括弧で囲んで ( atomic_fetch_add ) ( ... ) のように)マクロ定義が抑制された場合、またはプログラムがジェネリック関数の名前で外部識別子を定義した場合、動作は未定義である。

符号付き整数型の場合、算術演算は2の補数表現を使用するように定義されています。未定義の結果はありません。ポインタ型の場合、結果は未定義のアドレスになる可能性がありますが、それ以外の操作には未定義動作はありません。

目次

パラメータ

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汎用関数 (p: 208)
  • C11 standard (ISO/IEC 9899:2011):
  • 7.17.7.5 The atomic_fetch and modify generic functions (p: 284-285)

関連項目

アトミック減算
(関数)
C++ ドキュメント for atomic_fetch_add , atomic_fetch_add_explicit