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
はコピー構築可能かつコピー代入可能であること is_trivially_copyable_v<T> && is_copy_constructible_v<T> && is_move_constructible_v<T> && is_copy_assignable_v<T> && is_move_assignable_v<T>
がfalse
である場合、プログラムは不適格となる- 簡潔に言うと、
memcpy()
可能な型であること
- 簡潔に言うと、
別名型
特殊化された整数型および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 |
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 |
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 |
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();
}
62
// スピンロックの実装
// 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()
出力例
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
typedef
s 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.
atomic
doesn't havevalue_type
ordifference_type
- LWG Issue 3012.
atomic
is 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で拡張浮動小数点数型もテンプレート引数として指定することが許可された