std:: atomic_fetch_add, std:: atomic_fetch_add_explicit
|
ヘッダーで定義
<atomic>
|
||
|
template
<
class
T
>
T atomic_fetch_add
(
std::
atomic
<
T
>
*
obj,
|
(1) | (C++11以降) |
|
template
<
class
T
>
T atomic_fetch_add
(
volatile
std::
atomic
<
T
>
*
obj,
|
(2) | (C++11以降) |
|
template
<
class
T
>
T atomic_fetch_add_explicit
(
std::
atomic
<
T
>
*
obj,
|
(3) | (C++11以降) |
|
template
<
class
T
>
T atomic_fetch_add_explicit
(
volatile
std::
atomic
<
T
>
*
obj,
|
(4) | (C++11以降) |
アトミック加算を実行します。 arg を obj が指す値にアトミックに加算し、 obj が以前保持していた値を返します。この操作は以下のコードが実行されたかのように行われます:
std::atomic<T>
が
fetch_add
メンバーを持たない場合(このメンバーは
整数型
、
浮動小数点型
(C++20以降)
および
ポインタ型
に対してのみ提供されます、
bool
を除く)、プログラムは不適格です。
目次 |
パラメータ
| obj | - | 変更対象のアトミックオブジェクトへのポインタ |
| arg | - | アトミックオブジェクトに格納されている値に加算する値 |
| order | - | メモリ同期順序 |
戻り値
この関数の効果が適用される直前の値、 modification order における * obj の値。
例
シングルライター/マルチリーダーロックは
std::atomic_fetch_add
で実装できます。この単純な実装はロックアウトフリーではないことに注意してください。
#include <atomic> #include <chrono> #include <iostream> #include <string> #include <thread> #include <vector> using namespace std::chrono_literals; // meaning of cnt: // 5: readers and writer are in race. There are no active readers or writers. // 4...0: there are 1...5 active readers, The writer is blocked. // -1: writer won the race and readers are blocked. const int N = 5; // four concurrent readers are allowed std::atomic<int> cnt(N); std::vector<int> data; void reader(int id) { for (;;) { // lock while (std::atomic_fetch_sub(&cnt, 1) <= 0) std::atomic_fetch_add(&cnt, 1); // read if (!data.empty()) std::cout << ("reader " + std::to_string(id) + " sees " + std::to_string(*data.rbegin()) + '\n'); if (data.size() == 25) break; // unlock std::atomic_fetch_add(&cnt, 1); // pause std::this_thread::sleep_for(1ms); } } void writer() { for (int n = 0; n < 25; ++n) { // lock while (std::atomic_fetch_sub(&cnt, N + 1) != N) std::atomic_fetch_add(&cnt, N + 1); // write data.push_back(n); std::cout << "writer pushed back " << n << '\n'; // unlock std::atomic_fetch_add(&cnt, N + 1); // pause std::this_thread::sleep_for(1ms); } } int main() { std::vector<std::thread> v; for (int n = 0; n < N; ++n) v.emplace_back(reader, n); v.emplace_back(writer); for (auto& t : v) t.join(); }
出力:
writer pushed back 0 reader 2 sees 0 reader 3 sees 0 reader 1 sees 0 <...> reader 2 sees 24 reader 4 sees 24 reader 1 sees 24
不具合報告
以下の動作変更の欠陥報告書は、以前に公開されたC++規格に対して遡及的に適用されました。
| DR | 適用対象 | 公開時の動作 | 正しい動作 |
|---|---|---|---|
| P0558R1 | C++11 |
厳密な型一致が要求されていた。これは
T
が複数の引数から推論されていたため
|
T
は
obj からのみ推論される |
関連項目
|
アトミックオブジェクトに格納された値に引数を加算し、以前に保持されていた値を取得する
(
std::atomic<T>
の公開メンバ関数)
|
|
|
(C++11)
(C++11)
|
アトミックオブジェクトから非アトミック値を減算し、アトミックの以前の値を取得する
(関数テンプレート) |
|
Cドキュメント
for
atomic_fetch_add
,
atomic_fetch_add_explicit
|
|