namespace std {
template<class T> struct atomic_ref; // (1) C++20
template<> struct atomic_ref<integral>; // (2) C++20
template<> struct atomic_ref<floating-point>; // (3) C++20
template<class T> struct atomic_ref<T*>; // (4) C++20
}
概要
atomic_ref
クラステンプレートは、コンストラクタで受け取ったT
型変数への参照に対してアトミック操作を適用する型である。非アトミックなオブジェクトに対して、値コピーによるstd::atomic
型変換の必要なく、アトミック操作を適用する。
オブジェクトが、多くの場面で非アトミックに使用され、競合回避のためにアトミックに振る舞う必要があるのが一部の場面である場合、オブジェクトを強制的にアトミックオブジェクトに変換してしまうことは、パフォーマンス低下につながる。atomic_ref
クラスを使用することで、そのような状況に対応し、一部の状況でのみオブジェクトをアトミックに振る舞わせることができる。
同じオブジェクトを参照する異なるatomic_ref
オブジェクトを介して行われるアトミック操作は、共通の参照するオブジェクトに対してアトミックに行われる。つまり、局所的にatomic_ref
オブジェクトに変換してアトミック操作を適用してもよい。
オブジェクトを参照してアトミック操作をするための制約として、アーキテクチャ固有のアライメント制約を満たすことが要求される。コンストラクタと代入演算子でオブジェクトを参照する際、メンバ定数としてのアライメント値required_alignment
の位置にオブジェクトが配置されていること。
atomic_ref
クラステンプレートは型T
の値をコピーではなく参照で保持するため、atomic_ref
オブジェクトより先に参照先の変数の寿命が尽きてはならない。
- (1) : プライマリテンプレート。宣言のみ
- (2) : 整数型に対する特殊化
- (3) : (CV修飾されていない) 浮動小数点数型に対する特殊化
- (C++23) : 拡張浮動小数点数型を含む
- (4) : 任意の型のポインタに対する特殊化
テンプレートパラメータ制約
- 型
T
はis_trivially_copyable_v<T> == true
であること
メンバ関数
共通メンバ関数
名前 | 説明 | 対応バージョン |
---|---|---|
(constructor) |
コンストラクタ | C++20 |
~atomic_ref() = default |
デストラクタ | C++20 |
operator= |
代入 | C++20 |
is_lock_free |
オブジェクトがロックフリーに振る舞えるかを判定する | C++20 |
store |
値を書き込む | C++20 |
load |
値を読み込む | C++20 |
operator T |
型Tへの変換演算子 | C++20 |
exchange |
値を入れ替える | C++20 |
compare_exchange_weak |
弱い比較で値を入れ替える | C++20 |
compare_exchange_strong |
強い比較で値を入れ替える | C++20 |
wait |
起床されるまで待機する | C++20 |
notify_one |
待機しているスレッドをひとつ起床させる | C++20 |
notify_all |
待機している全てのスレッドを起床させる | C++20 |
共通メンバ型
名前 | 説明 | 対応バージョン |
---|---|---|
value_type |
要素型となるテンプレートパラメータの型T |
C++20 |
共通メンバ定数
名前 | 説明 | 対応バージョン |
---|---|---|
static constexpr bool is_always_lock_free |
型T に対するアトミック操作が常にロックフリー (非ミューテックス) で動作する場合はtrue 、そうでなければfalse |
C++20 |
static constexpr size_t required_alignment |
参照するオブジェクトに要求されるアライメント。少なくともalignof(T) |
C++20 |
is_always_lock_free == true
の場合、このクラスのオブジェクトをシグナルハンドラー内で使用できる。
required_alignment
について、ハードウェアは参照するオブジェクトに対して、型T
のほかのオブジェクトよりも厳密なアライメントを持つことを要求できる。また、atomic_ref
がロックフリーかどうかは、参照するオブジェクトのアライメントに依存する。たとえばstd::complex<double>
のロックフリー操作は2 * alignof(double)
にアライメントされる場合にのみサポートされる。
atomic_ref<integral>専用メンバ関数
整数型に対する特殊化。
名前 | 説明 | 対応バージョン |
---|---|---|
fetch_add |
加算 | C++20 |
fetch_sub |
減算 | C++20 |
fetch_and |
AND演算 | C++20 |
fetch_or |
OR演算 | C++20 |
fetch_xor |
XOR演算 | C++20 |
operator++ |
インクリメント | C++20 |
operator-- |
デクリメント | C++20 |
operator+= |
加算 | C++20 |
operator-= |
減算 | C++20 |
operator&= |
AND演算 | C++20 |
operator|= |
OR演算 | C++20 |
operator^= |
XOR演算 | C++20 |
atomic_ref<integral>専用メンバ型
名前 | 説明 | 対応バージョン |
---|---|---|
difference_type |
2つの値の差を表す整数型value_type |
C++20 |
atomic_ref<floating-point>専用メンバ関数
浮動小数点数型に対する特殊化。
名前 | 説明 | 対応バージョン |
---|---|---|
fetch_add |
加算 | C++20 |
fetch_sub |
減算 | C++20 |
operator+= |
加算 | C++20 |
operator-= |
減算 | C++20 |
atomic_ref<floating-point>専用メンバ型
名前 | 説明 | 対応バージョン |
---|---|---|
difference_type |
2つの値の差を表す整数型value_type |
C++20 |
atomic_ref<T*>専用メンバ関数
ポインタ型に対する特殊化。
名前 | 説明 | 対応バージョン |
---|---|---|
fetch_add |
加算 | C++20 |
fetch_sub |
減算 | C++20 |
operator++ |
インクリメント | C++20 |
operator-- |
デクリメント | C++20 |
operator+= |
加算 | C++20 |
operator-= |
減算 | C++20 |
atomic_ref<T*>専用メンバ型
名前 | 説明 | 対応バージョン |
---|---|---|
difference_type |
2つの値の差を表す整数型ptrdiff_t |
C++20 |
例
#include <iostream>
#include <atomic>
#include <thread>
struct Info {
int value = 0;
};
int main()
{
Info info;
std::thread consumer_thread {[&info] {
std::atomic_ref<int> x{info.value};
while (true) {
if (int value = x.exchange(0); value != 0) {
std::cout << value << std::endl;
break;
}
}
}};
std::atomic_ref{info.value}.store(3); // クラステンプレートのテンプレート引数推論も使用できる (<int>省略)
consumer_thread.join();
}
xxxxxxxxxx
#include <iostream>
#include <atomic>
#include <thread>
struct Info {
int value = 0;
};
int main()
{
Info info;
std::thread consumer_thread {[&info] {
std::atomic_ref<int> x{info.value};
while (true) {
if (int value = x.exchange(0); value != 0) {
std::cout << value << std::endl;
break;
}
}
}};
std::atomic_ref{info.value}.store(3); // クラステンプレートのテンプレート引数推論も使用できる (<int>省略)
consumer_thread.join();
}
出力
3
バージョン
言語
- C++20
処理系
- Clang: 9.0 ❌
- GCC: 10.1 ✅
- Visual C++: ??
関連項目
参照
- P0019R8 Atomic Ref
- P1467R9 Extended floating-point types and standard names
- C++23で拡張浮動小数点数型もテンプレート引数として指定することが許可された