namespace std {
template<class T> struct atomic; // (1) C++11
template<> struct atomic<integral>; // (2) C++11
template<> struct atomic<floating-point>; // (3) C++20
template<class T> struct atomic<T*>; // (4) C++11
}
概要
atomicクラステンプレートは、型Tをアトミック操作するためのクラステンプレートである。組み込み型に対する特殊化が提供されており、それぞれに特化した演算が用意されている。
- (1) : プライマリテンプレート。宣言のみ
- (2) : 整数型に対する特殊化
- (3) : (CV修飾されていない) 浮動小数点数型に対する特殊化
- (C++23) : 拡張浮動小数点数型を含む
- (4) : 任意の型のポインタに対する特殊化
これらのほか、<memory>ヘッダでstd::shared_ptrとstd::weak_ptrに対するatomicクラスの特殊化が定義される。
テンプレートパラメータ制約
- 型
Tはコピー構築可能かつコピー代入可能であること - 以下のいずれかが
falseである場合、プログラムは不適格となる:is_trivially_copyable_v<T>- 簡潔に言うと、
memcpy()可能な型であること
- 簡潔に言うと、
is_copy_constructible_v<T>is_move_constructible_v<T>is_copy_assignable_v<T>is_move_assignable_v<T>- C++26:
same_as<T, remove_cv_t<T>>- CV修飾された
Tは許可しない
- CV修飾された
別名型
特殊化された整数型およびbool型には、それぞれatomic_Tという型の別名が提供される。
| 名前付きアトミック型 | テンプレート引数となる整数型 | 対応バージョン |
|---|---|---|
atomic_char |
char |
C++11 |
atomic_schar |
signed char |
C++11 |
atomic_uchar |
unsigned char |
C++11 |
atomic_short |
short |
C++11 |
atomic_ushort |
unsigned short |
C++11 |
atomic_int |
int |
C++11 |
atomic_uint |
unsigned int |
C++11 |
atomic_long |
long |
C++11 |
atomic_ulong |
unsigned long |
C++11 |
atomic_llong |
long long |
C++11 |
atomic_ullong |
unsigned long long |
C++11 |
atomic_char8_t |
char8_t |
C++20 |
atomic_char16_t |
char16_t |
C++11 |
atomic_char32_t |
char32_t |
C++11 |
atomic_wchar_t |
wchar_t |
C++11 |
atomic_bool |
bool |
C++11 |
浮動小数点数型に対する別名は定義されていない。
また、<cstdint>で定義される整数型に対する以下の別名も提供される。
| 名前付きアトミック型 | テンプレート引数となる整数型 | 対応バージョン |
|---|---|---|
atomic_int_least8_t |
int_least8_t |
C++11 |
atomic_uint_least8_t |
uint_least8_t |
C++11 |
atomic_int_least16_t |
int_least16_t |
C++11 |
atomic_uint_least16_t |
uint_least16_t |
C++11 |
atomic_int_least32_t |
int_least32_t |
C++11 |
atomic_uint_least32_t |
uint_least32_t |
C++11 |
atomic_int_least64_t |
int_least64_t |
C++11 |
atomic_uint_least64_t |
uint_least64_t |
C++11 |
atomic_int_fast8_t |
int_fast8_t |
C++11 |
atomic_uint_fast8_t |
uint_fast8_t |
C++11 |
atomic_int_fast16_t |
int_fast16_t |
C++11 |
atomic_uint_fast16_t |
uint_fast16_t |
C++11 |
atomic_int_fast32_t |
int_fast32_t |
C++11 |
atomic_uint_fast32_t |
uint_fast32_t |
C++11 |
atomic_int_fast64_t |
int_fast64_t |
C++11 |
atomic_uint_fast64_t |
uint_fast64_t |
C++11 |
atomic_size_t |
size_t |
C++11 |
atomic_ptrdiff_t |
ptrdiff_t |
C++11 |
atomic_intmax_t |
intmax_t |
C++11 |
atomic_uintmax_t |
uintmax_t |
C++11 |
以下の整数型に対する別名は、整数型に対するatomic型の特殊化だが、その中でも以下の特性を持つものである:
is_always_lock_freeプロパティがtrueである- wait/notify操作が最も効率的に行える整数アトミック型
ただし、フリースタンディング環境において、これらの型は定義されない場合がある。
| 名前付きアトミック型 | 説明 | 対応バージョン |
|---|---|---|
atomic_signed_lock_free |
is_always_lock_free == trueかつwait/notify操作が最も効率的に行える符号付き整数のアトミック型 |
C++20 |
atomic_unsigned_lock_free |
is_always_lock_free == trueかつwait/notify操作が最も効率的に行える符号なし整数のアトミック型 |
C++20 |
<cstdint>で定義される整数型に対する以下の別名は、元の整数型が定義される場合のみ定義される。
| 名前付きアトミック型 | テンプレート引数となる整数型 | 対応バージョン |
|---|---|---|
atomic_int8_t |
int8_t |
C++17 |
atomic_uint8_t |
uint8_t |
C++17 |
atomic_int16_t |
int16_t |
C++17 |
atomic_uint16_t |
uint16_t |
C++17 |
atomic_int32_t |
int32_t |
C++17 |
atomic_uint32_t |
uint32_t |
C++17 |
atomic_int64_t |
int64_t |
C++17 |
atomic_uint64_t |
uint64_t |
C++17 |
atomic_intptr_t |
intptr_t |
C++11 |
atomic_uintptr_t |
uintptr_t |
C++11 |
メンバ関数
共通メンバ関数
| 名前 | 説明 | 対応バージョン |
|---|---|---|
(constructor) |
コンストラクタ | C++11 |
~atomic() = default |
デストラクタ | C++11 |
operator= |
代入演算子 | C++11 |
is_lock_free |
オブジェクトがロックフリーに振る舞えるかを判定する | C++11 |
store |
値を書き込む | C++11 |
load |
値を読み込む | C++11 |
operator T |
型Tへの変換演算子 | C++11 |
exchange |
値を入れ替える | C++11 |
compare_exchange_weak |
弱い比較で値を入れ替える | C++11 |
compare_exchange_strong |
強い比較で値を入れ替える | C++11 |
wait |
起床されるまで待機する | C++20 |
notify_one |
待機しているスレッドをひとつ起床させる | C++20 |
notify_all |
待機している全てのスレッドを起床させる | C++20 |
共通メンバ型
| 名前 | 説明 | 対応バージョン |
|---|---|---|
value_type |
要素型となるテンプレートパラメータの型T |
C++17 |
共通メンバ定数
| 名前 | 説明 | 対応バージョン |
|---|---|---|
static constexpr bool is_always_lock_free |
型Tに対するアトミック操作が常にロックフリー (非ミューテックス) で動作する場合はtrue、そうでなければfalse |
C++17 |
is_always_lock_free == trueの場合、このクラスのオブジェクトをシグナルハンドラー内で使用できる。
atomic<integral>専用メンバ関数
整数型に対する特殊化。
| 名前 | 説明 | 対応バージョン |
|---|---|---|
fetch_add |
加算 | C++11 |
fetch_sub |
減算 | C++11 |
fetch_and |
AND演算 | C++11 |
fetch_or |
OR演算 | C++11 |
fetch_xor |
XOR演算 | C++11 |
fetch_max |
最大値を設定・取得 | C++26 |
fetch_min |
最小値を設定・取得 | C++26 |
store_add |
値を読み込まずに加算 | C++26 |
store_sub |
値を読み込まずに減算 | C++26 |
store_and |
値を読み込まずにAND演算 | C++26 |
store_or |
値を読み込まずにOR演算 | C++26 |
store_xor |
値を読み込まずにXOR演算 | C++26 |
store_max |
値を読み込まずに最大値を設定 | C++26 |
store_min |
値を読み込まずに最小値を設定 | C++26 |
operator++ |
インクリメント | C++11 |
operator-- |
デクリメント | C++11 |
operator+= |
加算 | C++11 |
operator-= |
減算 | C++11 |
operator&= |
AND演算 | C++11 |
operator|= |
OR演算 | C++11 |
operator^= |
XOR演算 | C++11 |
atomic<integral>専用メンバ型
| 名前 | 説明 | 対応バージョン |
|---|---|---|
difference_type |
2つの値の差を表す整数型value_type |
C++17 |
atomic<floating-point>専用メンバ関数
浮動小数点数型に対する特殊化。
| 名前 | 説明 | 対応バージョン |
|---|---|---|
fetch_add |
加算 | C++20 |
fetch_sub |
減算 | C++20 |
fetch_max |
最大値を設定・取得 | C++26 |
fetch_min |
最小値を設定・取得 | C++26 |
fetch_fmaximum |
最大値を設定・取得 (-0.0と+0.0では+0.0、NaNと値ではNaNを返す) |
C++26 |
fetch_fminimum |
最小値を設定・取得 (-0.0と+0.0では-0.0、NaNと値ではNaNを返す) |
C++26 |
fetch_fmaximum_num |
最大値を設定・取得 (-0.0と+0.0では+0.0、NaNと値では数値を返す) |
C++26 |
fetch_fminimum_num |
最小値を設定・取得 (-0.0と+0.0では-0.0、NaNと値では数値を返す) |
C++26 |
store_add |
値を読み込まずに加算 | C++26 |
store_sub |
値を読み込まずに減算 | C++26 |
store_and |
値を読み込まずにAND演算 | C++26 |
store_or |
値を読み込まずにOR演算 | C++26 |
store_xor |
値を読み込まずにXOR演算 | C++26 |
store_max |
値を読み込まずに最大値を設定 | C++26 |
store_min |
値を読み込まずに最小値を設定 | C++26 |
store_fmaximum |
値を読み込まずに最大値を設定 (-0.0と+0.0では+0.0、NaNと値ではNaNを返す) |
C++26 |
store_fminimum |
値を読み込まずに最小値を設定 (-0.0と+0.0では-0.0、NaNと値ではNaNを返す) |
C++26 |
store_fmaximum_num |
値を読み込まずに最大値を設定 (-0.0と+0.0では+0.0、NaNと値では数値を返す) |
|
store_fminimum_num |
値を読み込まずに最小値を設定 (-0.0と+0.0では-0.0、NaNと値では数値を返す) |
C++26 |
operator+= |
加算 | C++20 |
operator-= |
減算 | C++20 |
atomic<floating-point>専用メンバ型
| 名前 | 説明 | 対応バージョン |
|---|---|---|
difference_type |
2つの値の差を表す型value_type |
C++20 |
atomic<T*>専用メンバ関数
ポインタ型に対する特殊化。
| 名前 | 説明 | 対応バージョン |
|---|---|---|
fetch_add |
加算 | C++11 |
fetch_sub |
減算 | C++11 |
fetch_max |
最大値を設定・取得 | C++26 |
fetch_min |
最小値を設定・取得 | C++26 |
store_add |
値を読み込まずに加算 | C++26 |
store_sub |
値を読み込まずに減算 | C++26 |
store_max |
値を読み込まずに最大値を設定 | C++26 |
store_min |
値を読み込まずに最小値を設定 | C++26 |
operator++ |
インクリメント | C++11 |
operator-- |
デクリメント | C++11 |
operator+= |
加算 | C++11 |
operator-= |
減算 | C++11 |
atomic<T*>専用メンバ型
| 名前 | 説明 | 対応バージョン |
|---|---|---|
difference_type |
2つの値の差を表す整数型ptrdiff_t |
C++17 |
例
// スピンロックの実装
// Boost Atomic Library - Usage Example
// http://www.boost.org/doc/libs/1_53_0/doc/html/atomic/usage_examples.html#boost_atomic.usage_examples.example_spinlock
#include <iostream>
#include <atomic>
#include <thread>
#include <mutex>
class spinlock {
private:
enum LockState {Locked, Unlocked};
std::atomic<LockState> state_;
public:
spinlock() : state_(Unlocked) {}
void lock()
{
// 現在の状態をLockedと入れ替える
while (state_.exchange(Locked, std::memory_order_acquire) == Locked) {
// busy-wait...アンロックされるまで待機
}
}
void unlock()
{
// 値をUnlockedに更新
state_.store(Unlocked, std::memory_order_release);
}
};
namespace {
spinlock lock;
}
template <class T>
void print(const T& x)
{
std::lock_guard<spinlock> lk(lock);
std::cout << x << std::endl;
}
void f()
{
print(1);
}
void g()
{
print(2);
}
int main()
{
std::thread t1(f);
std::thread t2(g);
t1.join();
t2.join();
}
出力例
2
1
バージョン
言語
- C++11
処理系
- Clang: 3.2 ✅
- GCC: 4.7.0 ✅
- Visual C++: 2012 ✅, 2013 ✅
備考
- GCC 4.9.2まで、アライメントがおかしくなってセグメンテーションフォルトになるバグがあった。GCC 5.1で修正された。(Bug 65147)
関連項目
参照
- N2145 C++ Atomic Types and Operations
- N2547 Allow atomics use in signal handlers
- アトミックオブジェクトを含むクラスのコピーとムーブ - Faith and Brave - C++で遊ぼう
- LWG Issue 2441. Exact-width atomic
typedefs should be provided - P0558R1 Resolving
atomic<T>named base class inconsistencies - P0152R1
constexpr atomic<T>::is_always_lock_free - P0020R6 Floating Point Atomic
- LWG Issue 3045.
atomicdoesn't havevalue_typeordifference_type - LWG Issue 3012.
atomicis unimplementable for non-is_trivially_copy_constructible T - Correctly implementing a spinlock in C++
- P1135R6 The C++20 Synchronization Library
- C++20での
atomic_signed_lock_freeとatomic_unsigned_lock_freeの追加
- C++20での
- P1467R9 Extended floating-point types and standard names
- C++23で拡張浮動小数点数型もテンプレート引数として指定することが許可された
- P3323R1 cv-qualified types in
atomicandatomic_ref- C++26でCV修飾されたテンプレートパラメータが明確に禁止された