名前空間
変種
操作

atomic_fetch_add, atomic_fetch_add_explicit

提供: cppreference.com
< c‎ | atomic
ヘッダ <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 がそれまで保持していた値を返します。 この操作は読み込み-変更-書き込み操作です。 1つめのバージョンは memory_order_seq_cst に従ってメモリアクセスを順序付けし、 2つめのバージョンは order に従ってメモリアクセスを順序付けします。

これはすべてのアトミックオブジェクト型 A に対して定義される総称関数です。 引数は非 volatile と volatile (メモリマップド I/O など) 両方のアトミック変数のアドレスを受理するための volatile アトミック型へのポインタです。 MA がアトミック整数型の場合は A に対応する非アトミック型、 A がアトミックポインタ型の場合は ptrdiff_t です。

符号付き整数型の場合、算術は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

[編集] 参考文献

  • C11 standard (ISO/IEC 9899:2011):
  • 7.17.7.5 The atomic_fetch and modify generic functions (p: 284-285)

[編集] 関連項目

アトミックな減算
(関数) [edit]
atomic_fetch_add, atomic_fetch_add_explicitC++リファレンス