T
fetch_add(difference_type operand,
memory_order order = memory_order_seq_cst) const noexcept; // (1) C++20
constexpr value_type
fetch_add(difference_type operand,
memory_order order = memory_order_seq_cst) const noexcept; // (1) C++26
概要
加算を行う
テンプレートパラメータ制約
std::atomic_ref<T*>
の場合、型T
がオブジェクト型であること。型T
がvoid*
や関数ポインタであってはならない- C++26 :
is_const_v<T>
がfalse
であること
効果
order
で指定されたメモリオーダーにしたがって、現在の値にoperand
を加算した値でアトミックに置き換える
戻り値
変更前の値が返される
例外
投げない
備考
- この関数は、
atomic_ref
クラスの整数型、浮動小数点数型、ポインタに対する特殊化で定義される - 整数型
- 符号付き整数型に対しては、符号なし整数型に変換されたかのようにしたあと演算が行われ、結果は符号付き整数型になる。未定義動作はない
- 浮動小数点数型
- 演算結果が、その型で表現できない値であった場合、結果は未規定値になる。ただしその操作によって未定義動作は起こらない
- 浮動小数点数型に対する操作は
std::numeric_limits<floating-point>
トレイトに準拠する - 浮動小数点数型に対するアトミック操作の浮動小数点環境は、呼び出しスレッドの浮動小数点環境とは異なる可能性がある
- ポインタ型
例
整数の例
#include <iostream>
#include <atomic>
int main()
{
int value = 3;
std::atomic_ref<int> x{value};
int before = x.fetch_add(2);
std::cout << before << std::endl;
std::cout << value << std::endl;
}
xxxxxxxxxx
#include <iostream>
#include <atomic>
int main()
{
int value = 3;
std::atomic_ref<int> x{value};
int before = x.fetch_add(2);
std::cout << before << std::endl;
std::cout << value << std::endl;
}
出力
3
5
浮動小数点数の例
#include <iostream>
#include <atomic>
int main()
{
float value = 3.14f;
std::atomic_ref<float> x{value};
float before = x.fetch_add(1.25f);
std::cout << before << std::endl;
std::cout << value << std::endl;
}
xxxxxxxxxx
#include <iostream>
#include <atomic>
int main()
{
float value = 3.14f;
std::atomic_ref<float> x{value};
float before = x.fetch_add(1.25f);
std::cout << before << std::endl;
std::cout << value << std::endl;
}
出力
3.14
4.39
複数スレッドから加算する例
#include <iostream>
#include <atomic>
#include <thread>
int main()
{
int value = 0;
// 複数スレッドで加算を呼んでも、
// 最終的に全てのスレッドでの加算が処理された値になる
std::thread t1 {[&value] {
std::atomic_ref{value}.fetch_add(1);
}};
std::thread t2 {[&value] {
std::atomic_ref{value}.fetch_add(2);
}};
t1.join();
t2.join();
std::cout << value << std::endl;
}
xxxxxxxxxx
#include <iostream>
#include <atomic>
#include <thread>
int main()
{
int value = 0;
// 複数スレッドで加算を呼んでも、
// 最終的に全てのスレッドでの加算が処理された値になる
std::thread t1 {[&value] {
std::atomic_ref{value}.fetch_add(1);
}};
std::thread t2 {[&value] {
std::atomic_ref{value}.fetch_add(2);
}};
t1.join();
t2.join();
std::cout << value << std::endl;
}
出力
3
バージョン
言語
- C++20
処理系
- Clang: 9.0 ❌
- GCC: 10.1 ✅
- Visual C++: ??
参照
- P3323R1 cv-qualified types in
atomic
andatomic_ref
- C++26でCV修飾されたテンプレート引数を受け取れるようになった
- P3309R3
constexpr atomic
andatomic_ref
- C++26で
constexpr
に対応した
- C++26で