std::atomic
| ヘッダー <atomic> で定義 |
||
| template< class T > struct atomic; |
(1) | (C++11以降) |
| template< class U > struct atomic<U*>; |
(2) | (C++11以降) |
| ヘッダ <memory> で定義 |
||
| template< class U > struct atomic<std::shared_ptr<U>>; |
(3) | (C++20以降) |
| template< class U > struct atomic<std::weak_ptr<U>>; |
(4) | (C++20以降) |
| ヘッダー <stdatomic.h> で定義 |
||
| #define _Atomic(T) /* 以下を参照 */ |
(5) | (C++23から) |
std::atomic テンプレートの各インスタンス化と完全特殊化は、アトミック型を定義します。あるスレッドがアトミックオブジェクトに書き込みを行い、別のスレッドがそこから読み取る場合、その動作は明確に定義されます (データ競合の詳細はメモリーモデルを参照してください)。
さらに、アトミックオブジェクトへのアクセスは、std::memory_order で指定された通り、スレッド間同期を確立し、非アトミックメモリーアクセスを順序付けることができます。
std::atomic はコピーもムーブもできません。
|
互換性マクロ <stdatomic.h> がインクルードされたときに |
(C++23から) |
目次 |
[編集] 特殊化
[編集] プライマリテンプレート
プライマリ std::atomic テンプレートは、CopyConstructible と CopyAssignable の両方を満たす任意の TriviallyCopyable 型 T でインスタンス化できます。以下の値のいずれかが false の場合、プログラムは ill-formed です。
- std::is_trivially_copyable<T>::value
- std::is_copy_constructible<T>::value
- std::is_move_constructible<T>::value
- std::is_copy_assignable<T>::value
- std::is_move_assignable<T>::value
- std::is_same<T, typename std::remove_cv<T>::type>::value
struct Counters { int a; int b; }; // user-defined trivially-copyable type std::atomic<Counters> cnt; // specialization for the user-defined type
std::atomic<bool> はプライマリテンプレートを使用します。標準レイアウト構造体であることが保証され、トリビアルデストラクタを持ちます。
[編集] 部分特殊化
標準ライブラリは、プライマリテンプレートが持たない追加のプロパティを持つ以下の型に対して、std::atomic テンプレートの部分特殊化を提供します。
std::atomic<U*>。これらの特殊化は、標準レイアウト、トリビアルなデフォルトコンストラクタ、(C++20まで)、およびトリビアルデストラクタを持ちます。すべてのアトミック型に提供される操作に加えて、これらの特殊化は、fetch_add、fetch_sub などのポインタ型に適したアトミック算術演算もサポートします。|
3,4) std::shared_ptr および std::weak_ptr のために、部分特殊化 std::atomic<std::shared_ptr<U>> および std::atomic<std::weak_ptr<U>> が提供されます。
詳細については、std::atomic<std::shared_ptr> および std::atomic<std::weak_ptr> を参照してください。 |
(C++20以降) |
[編集] 整数型のための特殊化
以下の整数型のいずれかでインスタンス化された場合、std::atomic は、fetch_add、fetch_sub、fetch_and、fetch_or、fetch_xor などの整数型に適した追加のアトミック操作を提供します。
- 文字型: char、char8_t(C++20以降)、char16_t、char32_t、および wchar_t;
- 標準符号付き整数型: signed char、short、int、long、および long long;
- 標準符号なし整数型: unsigned char、unsigned short、unsigned int、unsigned long、および unsigned long long;
- ヘッダー <cstdint> の typedef で必要とされる追加の整数型。
さらに、結果として得られる std::atomic<Integral> 特殊化は、標準レイアウト、トリビアルなデフォルトコンストラクタ、(C++20まで)、およびトリビアルデストラクタを持ちます。符号付き整数演算は2の補数を使用するように定義されており、未定義の結果はありません。
浮動小数点型の特殊化cv-unqualified 浮動小数点型 (float、double、long double および cv-unqualified 拡張浮動小数点型(C++23以降)) のいずれかでインスタンス化された場合、 さらに、結果として得られる 結果が浮動小数点型で表現できない場合でも、未定義の動作になる操作はありません。浮動小数点環境は、呼び出しスレッドの浮動小数点環境とは異なる場合があります。 |
(C++20以降) |
[編集] メンバー型
| 型 | 定義 | ||||
value_type
|
T (特殊化されているかどうかにかかわらず) | ||||
difference_type[1] |
|
- ↑
difference_typeは、プライマリstd::atomicテンプレート、または std::shared_ptr および std::weak_ptr の部分特殊化では定義されていません。
[編集] メンバー関数
| アトミックオブジェクトを構築する (public メンバー関数) | |
| アトミックオブジェクトに値を格納する (public メンバー関数) | |
| アトミックオブジェクトがロックフリーであるかを確認する (public メンバー関数) | |
| アトミックオブジェクトの値を非アトミックな引数でアトミックに置き換える (public メンバー関数) | |
| アトミックオブジェクトの値をアトミックに取得する (public メンバー関数) | |
| アトミックオブジェクトから値をロードする (public メンバー関数) | |
| アトミックオブジェクトの値をアトミックに置き換え、以前に保持されていた値を取得する (public メンバー関数) | |
| アトミックオブジェクトの値と非アトミックな引数をアトミックに比較し、等しければアトミック交換を、そうでなければアトミックロードを実行する (public メンバー関数) | |
| (C++20) |
通知されるまで、かつアトミックな値が変更されるまでスレッドをブロックする (public member function) |
| (C++20) |
アトミックオブジェクトを待機しているスレッドを少なくとも1つ通知する (public member function) |
| (C++20) |
アトミックオブジェクトを待機してブロックされている全てのスレッドに通知する (public member function) |
定数 | |
| [static] (C++17) |
型が常にロックフリーであることを示す (public static メンバー定数) |
[編集] 特殊化されたメンバー関数
整数型、浮動小数点型(C++20以降)、およびポインタ型に特化 | |
| 引数をアトミックオブジェクトに格納された値にアトミックに加算し、以前に保持されていた値を取得する (public メンバー関数) | |
| 引数をアトミックオブジェクトに格納された値からアトミックに減算し、以前に保持されていた値を取得する (public メンバー関数) | |
| アトミック値に加算または減算する (public メンバー関数) | |
整数型とポインタ型にのみ特化 | |
| (C++26) |
引数とアトミックオブジェクトの値との間で std::max をアトミックに実行し、以前に保持されていた値を取得する (public メンバー関数) |
| (C++26) |
引数とアトミックオブジェクトの値との間で std::min をアトミックに実行し、以前に保持されていた値を取得する (public メンバー関数) |
| アトミック値を1増減させる (public メンバー関数) | |
整数型にのみ特化 | |
| 引数とアトミックオブジェクトの値との間でビット単位ANDをアトミックに実行し、以前に保持されていた値を取得する (public メンバー関数) | |
| 引数とアトミックオブジェクトの値との間でビット単位ORをアトミックに実行し、以前に保持されていた値を取得する (public メンバー関数) | |
| 引数とアトミックオブジェクトの値との間でビット単位XORをアトミックに実行し、以前に保持されていた値を取得する (public メンバー関数) | |
| アトミック値に対してビット単位AND、OR、XORを実行する (public メンバー関数) | |
[編集] 型エイリアス
上記で列挙された bool とすべての整数型について、以下のような型エイリアスが提供されます。
すべての
| |
| atomic_bool (C++11) |
std::atomic<bool> (typedef) |
| atomic_char (C++11) |
std::atomic<char> (typedef) |
| atomic_schar (C++11) |
std::atomic<signed char> (typedef) |
| atomic_uchar (C++11) |
std::atomic<unsigned char> (typedef) |
| atomic_short (C++11) |
std::atomic<short> (typedef) |
| atomic_ushort (C++11) |
std::atomic<unsigned short> (typedef) |
| atomic_int (C++11) |
std::atomic<int> (typedef) |
| atomic_uint (C++11) |
std::atomic<unsigned int> (typedef) |
| atomic_long (C++11) |
std::atomic<long> (typedef) |
| atomic_ulong (C++11) |
std::atomic<unsigned long> (typedef) |
| atomic_llong (C++11) |
std::atomic<long long> (typedef) |
| atomic_ullong (C++11) |
std::atomic<unsigned long long> (typedef) |
| atomic_char8_t (C++20) |
std::atomic<char8_t> (typedef) |
| atomic_char16_t (C++11) |
std::atomic<char16_t> (typedef) |
| atomic_char32_t (C++11) |
std::atomic<char32_t> (typedef) |
| atomic_wchar_t (C++11) |
std::atomic<wchar_t> (typedef) |
| atomic_int8_t (C++11)(任意) |
std::atomic<std::int8_t> (typedef) |
| atomic_uint8_t (C++11)(任意) |
std::atomic<std::uint8_t> (typedef) |
| atomic_int16_t (C++11)(任意) |
std::atomic<std::int16_t> (typedef) |
| atomic_uint16_t (C++11)(任意) |
std::atomic<std::uint16_t> (typedef) |
| atomic_int32_t (C++11)(任意) |
std::atomic<std::int32_t> (typedef) |
| atomic_uint32_t (C++11)(任意) |
std::atomic<std::uint32_t> (typedef) |
| atomic_int64_t (C++11)(任意) |
std::atomic<std::int64_t> (typedef) |
| atomic_uint64_t (C++11)(任意) |
std::atomic<std::uint64_t> (typedef) |
| atomic_int_least8_t (C++11) |
std::atomic<std::int_least8_t> (typedef) |
| atomic_uint_least8_t (C++11) |
std::atomic<std::uint_least8_t> (typedef) |
| atomic_int_least16_t (C++11) |
std::atomic<std::int_least16_t> (typedef) |
| atomic_uint_least16_t (C++11) |
std::atomic<std::uint_least16_t> (typedef) |
| atomic_int_least32_t (C++11) |
std::atomic<std::int_least32_t> (typedef) |
| atomic_uint_least32_t (C++11) |
std::atomic<std::uint_least32_t> (typedef) |
| atomic_int_least64_t (C++11) |
std::atomic<std::int_least64_t> (typedef) |
| atomic_uint_least64_t (C++11) |
std::atomic<std::uint_least64_t> (typedef) |
| atomic_int_fast8_t (C++11) |
std::atomic<std::int_fast8_t> (typedef) |
| atomic_uint_fast8_t (C++11) |
std::atomic<std::uint_fast8_t> (typedef) |
| atomic_int_fast16_t (C++11) |
std::atomic<std::int_fast16_t> (typedef) |
| atomic_uint_fast16_t (C++11) |
std::atomic<std::uint_fast16_t> (typedef) |
| atomic_int_fast32_t (C++11) |
std::atomic<std::int_fast32_t> (typedef) |
| atomic_uint_fast32_t (C++11) |
std::atomic<std::uint_fast32_t> (typedef) |
| atomic_int_fast64_t (C++11) |
std::atomic<std::int_fast64_t> (typedef) |
| atomic_uint_fast64_t (C++11) |
std::atomic<std::uint_fast64_t> (typedef) |
| atomic_intptr_t (C++11)(任意) |
std::atomic<std::intptr_t> (typedef) |
| atomic_uintptr_t (C++11)(任意) |
std::atomic<std::uintptr_t> (typedef) |
| atomic_size_t (C++11) |
std::atomic<std::size_t> (typedef) |
| atomic_ptrdiff_t (C++11) |
std::atomic<std::ptrdiff_t> (typedef) |
| atomic_intmax_t (C++11) |
std::atomic<std::intmax_t> (typedef) |
| atomic_uintmax_t (C++11) |
std::atomic<std::uintmax_t> (typedef) |
特殊目的型のためのエイリアス | |
| atomic_signed_lock_free (C++20) |
ロックフリーであり、待機/通知が最も効率的な符号付き整数アトミック型 (typedef) |
| atomic_unsigned_lock_free (C++20) |
ロックフリーであり、待機/通知が最も効率的な符号なし整数アトミック型 (typedef) |
std::atomic_intN_t、std::atomic_uintN_t、std::atomic_intptr_t、および std::atomic_uintptr_t は、それぞれ std::intN_t、std::uintN_t、std::intptr_t、および std::uintptr_t が定義されている場合にのみ定義されます。|
|
(C++20以降) |
[編集] 備考
std::atomic のすべてのメンバー関数には、非メンバー関数テンプレートの同等なものがあります。これらの非メンバー関数は、std::atomic の特殊化ではないがアトミシティを保証できる型のために、追加でオーバーロードされることがあります。標準ライブラリのそのような唯一の型は std::shared_ptr<U> です。
_Atomic は キーワードであり、C において アトミック型を提供するために使用されます。
実装は、すべての可能な型 T に対して、C における _Atomic(T) の表現が C++ における std::atomic<T> の表現と同じであることを保証することが推奨されます。アトミシティとメモリ順序付けを保証するために使用されるメカニズムは互換性があるべきです。
GCC および Clang では、ここで説明されている機能の一部は -latomic とのリンクが必要です。
| 機能テストマクロ | 値 | 規格 | 機能 |
|---|---|---|---|
__cpp_lib_atomic_ref |
201806L |
(C++20) | std::atomic_ref
|
__cpp_lib_constexpr_atomic |
202411L |
(C++26) | constexpr std::atomic および std::atomic_ref |
[編集] 例
#include <atomic> #include <iostream> #include <thread> #include <vector> std::atomic_int acnt; int cnt; void f() { for (auto n{10000}; n; --n) { ++acnt; ++cnt; // Note: for this example, relaxed memory order is sufficient, // e.g. acnt.fetch_add(1, std::memory_order_relaxed); } } int main() { { std::vector<std::jthread> pool; for (int n = 0; n < 10; ++n) pool.emplace_back(f); } std::cout << "The atomic counter is " << acnt << '\n' << "The non-atomic counter is " << cnt << '\n'; }
実行結果の例
The atomic counter is 100000 The non-atomic counter is 69696
[編集] 欠陥レポート
以下の動作変更を伴う欠陥報告が、以前に公開されたC++標準に遡って適用されました。
| DR | 適用対象 | 公開された動作 | 正しい動作 |
|---|---|---|---|
| LWG 2441 | C++11 | optional のアトミック版の typedef 固定幅整数型が欠落していた |
追加された |
| LWG 3012 | C++11 | std::atomic<T> は、トリビアルにコピー可能だがコピー可能ではない任意の T に対して許可されていたそのような特殊化は禁止される |
そのような特殊化は禁止される |
| LWG 3949 | C++17 | std::atomic<bool> がトリビアルデストラクタを持つことを要求する文言がC++17で誤って削除されていた C++17で誤って削除されていた |
追加された |
| LWG 4069 (P3323R1) |
C++11 | cv修飾された T のサポートに疑問があった |
T がcv修飾されることを禁止する |
| P0558R1 | C++11 | アトミック型の一部の関数に対するテンプレート引数推論が誤って失敗する可能性があった。無効なポインタ操作が提供されていた 関数が誤って失敗する可能性があった。無効なポインタ操作が提供されていた 無効なポインタ操作が提供されていた |
仕様が大幅に書き直された メンバー typedef value_typeと difference_type が追加された |
[編集] 関連項目
| (C++11) |
ロックフリーなブール型アトミック型 (クラス) |
| (C++20) |
アトミック共有ポインタ (クラステンプレート特殊化) |
| (C++20) |
アトミック弱ポインタ (クラステンプレート特殊化) |
| C ドキュメント (アトミック型)
| |