namespace std {
class hazard_pointer;
}
概要
hazard_pointerは、1つのハザードポインタを所有するクラスである。
このクラスのオブジェクトは、「空 (empty)」であるか、ちょうど1つのハザードポインタを所有するかのいずれかである。ハザードポインタは同時に高々1つのスレッドから所有され、その所有スレッドだけが値を設定できる。ムーブのみ可能で、コピーはできない。
オブジェクトは通常、make_hazard_pointer()関数で構築する。参照したい共有オブジェクトをprotect()メンバ関数で保護すると、その保護が解除される (デストラクタやreset_protection()メンバ関数) まで、そのオブジェクトはretire()されても回収されない。
std::hazard_pointer h = std::make_hazard_pointer();
Data* p = h.protect(shared_ptr_atomic); // 保護開始
// ... *p を安全に参照できる ...
// h のスコープ終了で保護終了
メンバ関数
| 名前 | 説明 | 対応バージョン |
|---|---|---|
(constructor) |
コンストラクタ | C++26 |
(destructor) |
デストラクタ | C++26 |
operator= |
ムーブ代入演算子 | C++26 |
empty |
空かどうかを判定する | C++26 |
protect |
オブジェクトを保護する | C++26 |
try_protect |
オブジェクトの保護を試みる | C++26 |
reset_protection |
保護を解除する | C++26 |
swap |
他のhazard_pointerオブジェクトと入れ替える |
C++26 |
非メンバ関数
| 名前 | 説明 | 対応バージョン |
|---|---|---|
swap |
2つのhazard_pointerオブジェクトを入れ替える |
C++26 |
make_hazard_pointer |
ハザードポインタを構築する | C++26 |
make_hazard_pointer_batch |
複数のハザードポインタをまとめて構築する | C++29 |
clear_hazard_pointer_batch |
複数のハザードポインタをまとめて破棄する | C++29 |
例
#include <hazard_pointer>
#include <atomic>
#include <thread>
#include <print>
struct Data : std::hazard_pointer_obj_base<Data> {
int value;
explicit Data(int v) : value(v) {}
};
// 複数スレッドから並行にアクセスされる共有データ
std::atomic<Data*> data{new Data(0)};
// 読み込み側スレッド
void reader()
{
// ハザードポインタで共有データを保護してから参照する
std::hazard_pointer h = std::make_hazard_pointer();
Data* p = h.protect(data);
// 更新側スレッドが data を差し替えて retire しても、
// このハザードポインタが保護している間は *p は回収されない
std::println("{}", p->value);
} // h のデストラクタで保護が解除される
// 更新側スレッド
void updater()
{
// 新しいデータで差し替え、取り外した古いデータを回収予約する
// (現役のオブジェクトは他スレッドが参照しうるので retire しない。
// 差し替えて取り外したものだけを retire する)
Data* old = data.exchange(new Data(1));
old->retire();
}
int main()
{
// 読み込みスレッドと更新スレッドを並行に実行する
{
std::jthread r{reader};
std::jthread w{updater};
} // 両スレッドの終了を待つ
// 最後に data が指しているオブジェクトも回収予約する
// (取り外したオブジェクトを retire し忘れると回収されずリークするので注意)
data.load()->retire();
}
出力例
0
バージョン
言語
- C++26
処理系
- Clang: ??
- GCC: ??
- ICC: ??
- Visual C++: ??
関連項目
参照
- P2530R3 Hazard Pointers for C++26
- C++26で追加された
- P2422R1 Remove
nodiscardannotations from the standard library specification- C++26で
emptyメンバ関数の[[nodiscard]]指定が削除された
- C++26で