atomic_fetch_add, atomic_fetch_add_explicit
提供: cppreference.com
<tbody>
</tbody>
| ヘッダ <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 アトミック型へのポインタです。
M は A がアトミック整数型の場合は A に対応する非アトミック型、 A がアトミックポインタ型の場合は ptrdiff_t です。
符号付き整数型の場合、算術は2の補数表現を用いて定義されます。 未定義の結果はありません。 ポインタ型の場合、結果が未定義のアドレスとなる場合はありますが、それ以外で演算に未定義動作はありません。
引数
| obj | - | 変更するアトミックオブジェクトを指すポインタ |
| arg | - | アトミックオブジェクトに格納されている値に加算する値 |
| order | - | この操作に対するメモリ同期順序付け。 すべての値を指定できます |
戻り値
obj の指すアトミックオブジェクトがそれまで保持していた値。
例
Run this code
#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)
関連項目
| アトミックな減算 (関数) | |
atomic_fetch_add, atomic_fetch_add_explicit の C++リファレンス
| |