Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions GLOBAL_QUALIFY_LIST.txt
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@
* identity[link /reference/functional/identity.md]
* <future>[link /reference/future.md]
* <generator>[link /reference/generator.md]
* <hazard_pointer>[link /reference/hazard_pointer.md]
* <hive>[link /reference/hive.md]
* <initializer_list>[link /reference/initializer_list.md]
* std::initializer_list[link /reference/initializer_list/initializer_list.md]
Expand Down
2 changes: 1 addition & 1 deletion lang/cpp26.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ C++26とは、2026年中に改訂される予定の、C++バージョンの通
- 文字列エンコーディングを識別するライブラリとして、[`<text_encoding>`](/reference/text_encoding.md)を追加
- 要素のメモリ位置が安定するシーケンスコンテナのライブラリとして[`<hive>`](/reference/hive.md)を追加
- 並行処理におけるデータの参照・更新を行うRCU (Read Copy Update) のライブラリとして、[`<rcu>`](/reference/rcu.md)を追加
- 並行処理において参照中のデータが更新されないよう保護するハザードポインタのライブラリとして、[`<hazard_pointer>`](/reference/hazard_pointer.md.nolink)を追加
- 並行処理において参照中のデータが更新されないよう保護するハザードポインタのライブラリとして、[`<hazard_pointer>`](/reference/hazard_pointer.md)を追加
- データ並列ライブラリとして、[`<simd>`](/reference/simd.md)を追加
- デバッグサポートのライブラリとして[`<debugging>`](/reference/debugging.md)を追加
- 線形代数ライブラリとして[`<linalg>`](/reference/linalg.md)を追加
Expand Down
2 changes: 1 addition & 1 deletion lang/cpp26/feature_test_macros.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@
|`__cpp_lib_freestanding_variant`|`202311L`||[`<variant>`](/reference/variant.md)|
|`__cpp_lib_fstream_native_handle`|`202306L`|[`std::basic_fstream`](/reference/fstream/basic_fstream.md)などのメンバに、ファイルのネイティブハンドルを追加|[`<fstream>`](/reference/fstream.md)|
|`__cpp_lib_function_ref`|`202604L`|[`<functional>`](/reference/functional.md)に[`std::function_ref`](/reference/functional/function_ref.md)を追加|[`<functional>`](/reference/functional.md)|
|`__cpp_lib_hazard_pointer`|`202306L`|ハザードポインタのライブラリ[`<hazard_pointer>`](/reference/hazard_pointer.md.nolink)を追加|[`<hazard_pointer>`](/reference/hazard_pointer.md.nolink)|
|`__cpp_lib_hazard_pointer`|`202306L`|ハザードポインタのライブラリ[`<hazard_pointer>`](/reference/hazard_pointer.md)を追加|[`<hazard_pointer>`](/reference/hazard_pointer.md)|
|`__cpp_lib_hive`|`202502L`|シーケンスコンテナのライブラリ[`<hive>`](/reference/hive.md)を追加|[`<hive>`](/reference/hive.md)|
|`__cpp_lib_indirect`|`202502L`|[`<memory>`](/reference/memory.md)に[`std::indirect`](/reference/memory/indirect.md)と[`std::polymorphic`](/reference/memory/polymorphic.md)を追加|[`<memory>`](/reference/memory.md)|
|`__cpp_lib_inplace_vector`|`202603L`|容量固定の可変長配列のライブラリ[`<inplace_vector>`](/reference/inplace_vector.md)を追加|[`<inplace_vector>`](/reference/inplace_vector.md)|
Expand Down
1 change: 1 addition & 0 deletions lang/cpp29.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ C++29とは、2029年中に改訂される予定の、C++バージョンの通
- 指定したマスクで立っている一のビットを下位に詰める[`std::simd::bit_compress()`](/reference/simd/bit_compress.md)関数
- 下位ビットを指定したマスクが立っている位置へ展開する[`std::simd::bit_expand()`](/reference/simd/bit_expand.md)関数
- 未定義動作にならないビットシフト[`std::simd::shl()`](/reference/simd/shl.md)関数と[`std::simd::shr()`](/reference/simd/shr.md)関数
- [`<hazard_pointer>`](/reference/hazard_pointer.md)に、複数のハザードポインタをまとめて構築・破棄する[`std::make_hazard_pointer_batch()`](/reference/hazard_pointer/make_hazard_pointer_batch.md)関数と[`std::clear_hazard_pointer_batch()`](/reference/hazard_pointer/clear_hazard_pointer_batch.md)関数を追加

### 非推奨化
- [`<iostream>`](/reference/iostream.md)において、`signed char` / `unsigned char`の入出力を非推奨化。[`std::int8_t`](/reference/cstdint/int8_t.md) / [`std::uint8_t`](/reference/cstdint/uint8_t.md)の別名として扱われるこれらの型の入出力で、整数型であることを期待して予期せぬ結果を招く可能性があった
1 change: 1 addition & 0 deletions lang/cpp29/feature_test_macros.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

| マクロ名 | 値 | 機能 | ヘッダ |
|----------|----|------|--------|
|`__cpp_lib_hazard_pointer`|`202606L`|[`<hazard_pointer>`](/reference/hazard_pointer.md)に、複数のハザードポインタをまとめて構築・破棄する[`std::make_hazard_pointer_batch()`](/reference/hazard_pointer/make_hazard_pointer_batch.md)関数と[`std::clear_hazard_pointer_batch()`](/reference/hazard_pointer/clear_hazard_pointer_batch.md)関数を追加|[`<hazard_pointer>`](/reference/hazard_pointer.md)|
|`__cpp_lib_simd`|`202606L`|[`<simd>`](/reference/simd.md)に、SIMDデータ用の連番を生成する[`std::simd::iota`](/reference/simd/iota.md)変数テンプレートなどを追加|[`<simd>`](/reference/simd.md)|
|`__cpp_lib_simd_bitops`|`202607L`|[`<simd>`](/reference/simd.md)に、ビット列を操作する[`bit_reverse()`](/reference/simd/bit_reverse.md)・[`bit_repeat()`](/reference/simd/bit_repeat.md)・[`bit_compress()`](/reference/simd/bit_compress.md)・[`bit_expand()`](/reference/simd/bit_expand.md)関数と、未定義動作にならないシフト[`shl()`](/reference/simd/shl.md)・[`shr()`](/reference/simd/shr.md)関数を追加|[`<simd>`](/reference/simd.md)|

Expand Down
2 changes: 1 addition & 1 deletion reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@
| [`<barrier>`](/reference/barrier.md) | バリア同期 | C++20 |
| [`<future>`](/reference/future.md) | Future | C++11 |
| [`<rcu>`](/reference/rcu.md) | データの参照・更新 | C++26 |
| [`<hazard_pointer>`](/reference/hazard_pointer.md.nolink) | ハザードポインタ | C++26 |
| [`<hazard_pointer>`](/reference/hazard_pointer.md) | ハザードポインタ | C++26 |
| [`<simd>`](/reference/simd.md) | データ並列 | C++26 |


Expand Down
45 changes: 45 additions & 0 deletions reference/hazard_pointer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# hazard_pointer
* hazard_pointer[meta header]
* cpp26[meta cpp]

`<hazard_pointer>`ヘッダは、ハザードポインタ (hazard pointer) による安全な遅延回収 (safe deferred reclamation) の機能を提供する。

ハザードポインタは、複数スレッドから並行に参照される動的オブジェクトを、参照中に破棄されないよう保護するための仕組みである。ロックフリーなデータ構造で、あるスレッドがオブジェクトを参照している間、別のスレッドがそのオブジェクトを安全に回収 (reclaim) できるようにする。

- オブジェクトを保護する側のスレッドは、[`hazard_pointer`](hazard_pointer/hazard_pointer.md)オブジェクトを取得し、参照するオブジェクトを指すよう設定する(保護)。
- オブジェクトを削除する側のスレッドは、削除したオブジェクトを[`retire()`](hazard_pointer/hazard_pointer_obj_base/retire.md)メンバ関数で回収予約する。予約されたオブジェクトは、どのハザードポインタからも指されていないことが確認された後に回収される(遅延回収)。

ハザードポインタで保護できるオブジェクトは、[`hazard_pointer_obj_base`](hazard_pointer/hazard_pointer_obj_base.md)を基底クラスとして継承する必要がある。


## クラス

| 名前 | 説明 | 対応バージョン |
|------|------|----------------|
| [`hazard_pointer_obj_base`](hazard_pointer/hazard_pointer_obj_base.md) | ハザードポインタで保護可能なオブジェクトの基底クラス (class template) | C++26 |
| [`hazard_pointer`](hazard_pointer/hazard_pointer.md) | ハザードポインタを所有するクラス (class) | C++26 |


## 関数

| 名前 | 説明 | 対応バージョン |
|------|------|----------------|
| [`make_hazard_pointer`](hazard_pointer/make_hazard_pointer.md) | ハザードポインタを構築する | C++26 |
| [`make_hazard_pointer_batch`](hazard_pointer/make_hazard_pointer_batch.md) | 複数のハザードポインタをまとめて構築する | C++29 |
| [`clear_hazard_pointer_batch`](hazard_pointer/clear_hazard_pointer_batch.md) | 複数のハザードポインタをまとめて破棄する | C++29 |


## バージョン
### 言語
- C++26


## 関連項目
- [`<atomic>`](atomic.md)


## 参照
- [P2530R3 Hazard Pointers for C++26](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2530r3.pdf)
- C++26で`<hazard_pointer>`ヘッダが追加された
- [P2422R1 Remove `nodiscard` annotations from the standard library specification](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2422r1.html)
- C++26で`[[nodiscard]]`指定が削除された
102 changes: 102 additions & 0 deletions reference/hazard_pointer/clear_hazard_pointer_batch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
# clear_hazard_pointer_batch
* hazard_pointer[meta header]
* std[meta namespace]
* function[meta id-type]
* cpp29[meta cpp]

```cpp
namespace std {
void clear_hazard_pointer_batch(span<hazard_pointer> batch) noexcept; // C++29
}
```
* span[link /reference/span/span.md]
* hazard_pointer[link hazard_pointer.md]

## 概要
複数のハザードポインタを、まとめて破棄する。

`batch`に含まれる非空の[`hazard_pointer`](hazard_pointer.md)オブジェクトそれぞれが所有するハザードポインタを破棄し、その要素を空にする。個別に破棄するよりも、複数のハザードポインタをまとめて破棄することでレイテンシを低減できる。

[`make_hazard_pointer_batch()`](make_hazard_pointer_batch.md)で構築したハザードポインタ群をまとめて破棄する用途に使用する。


## 効果
`batch`の各要素`e`について、`e.`[`empty()`](hazard_pointer/empty.md)が`false`であるものは、`e`が所有するハザードポインタを破棄し、`e`を空にする。

破棄されたハザードポインタが保護していたオブジェクトは、他に保護しているハザードポインタがなければ回収可能となる。


## 戻り値
なし


## 例外
投げない


## 備考
- 既に空の要素は変更されない。


## 例
```cpp example
#include <hazard_pointer>
#include <array>
#include <atomic>
#include <print>

struct Data : std::hazard_pointer_obj_base<Data> {
int value;
explicit Data(int v) : value(v) {}
};

std::atomic<Data*> data{new Data(42)};

int main()
{
// ハザードポインタ群をまとめて構築する
std::array<std::hazard_pointer, 2> hp;
std::make_hazard_pointer_batch(hp);

Data* p = hp[0].protect(data);
std::println("{}", p->value);

// 使い終わったハザードポインタ群をまとめて破棄する
std::clear_hazard_pointer_batch(hp);

// 後始末: 共有データを回収予約する
data.load()->retire();
}
```
* std::clear_hazard_pointer_batch[color ff0000]
* std::hazard_pointer_obj_base[link hazard_pointer_obj_base.md]
* std::make_hazard_pointer_batch[link make_hazard_pointer_batch.md]
* hp[0].protect[link hazard_pointer/protect.md]
* load[link /reference/atomic/atomic/load.md]
* retire()[link hazard_pointer_obj_base/retire.md]

### 出力
```
42
```


## バージョン
### 言語
- C++29

### 処理系
- [Clang](/implementation.md#clang): ??
- [GCC](/implementation.md#gcc): ??
- [ICC](/implementation.md#icc): ??
- [Visual C++](/implementation.md#visual_cpp): ??


## 関連項目
- [`std::make_hazard_pointer_batch`](make_hazard_pointer_batch.md)
- [`std::hazard_pointer`](hazard_pointer.md)


## 参照
- [P3428R4 Hazard Pointer Batches](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3428r4.pdf)
- C++29で追加された
137 changes: 137 additions & 0 deletions reference/hazard_pointer/hazard_pointer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
# hazard_pointer
* hazard_pointer[meta header]
* class[meta id-type]
* std[meta namespace]
* cpp26[meta cpp]

```cpp
namespace std {
class hazard_pointer;
}
```

## 概要
`hazard_pointer`は、1つのハザードポインタを所有するクラスである。

このクラスのオブジェクトは、「空 (empty)」であるか、ちょうど1つのハザードポインタを所有するかのいずれかである。ハザードポインタは同時に高々1つのスレッドから所有され、その所有スレッドだけが値を設定できる。ムーブのみ可能で、コピーはできない。

オブジェクトは通常、[`make_hazard_pointer()`](make_hazard_pointer.md)関数で構築する。参照したい共有オブジェクトを[`protect()`](hazard_pointer/protect.md)メンバ関数で保護すると、その保護が解除される (デストラクタや[`reset_protection()`](hazard_pointer/reset_protection.md)メンバ関数) まで、そのオブジェクトは[`retire()`](hazard_pointer_obj_base/retire.md)されても回収されない。

```cpp
std::hazard_pointer h = std::make_hazard_pointer();
Data* p = h.protect(shared_ptr_atomic); // 保護開始
// ... *p を安全に参照できる ...
// h のスコープ終了で保護終了
```


## メンバ関数

| 名前 | 説明 | 対応バージョン |
|------|------|----------------|
| [`(constructor)`](hazard_pointer/op_constructor.md) | コンストラクタ | C++26 |
| [`(destructor)`](hazard_pointer/op_destructor.md) | デストラクタ | C++26 |
| [`operator=`](hazard_pointer/op_assign.md) | ムーブ代入演算子 | C++26 |
| [`empty`](hazard_pointer/empty.md) | 空かどうかを判定する | C++26 |
| [`protect`](hazard_pointer/protect.md) | オブジェクトを保護する | C++26 |
| [`try_protect`](hazard_pointer/try_protect.md) | オブジェクトの保護を試みる | C++26 |
| [`reset_protection`](hazard_pointer/reset_protection.md) | 保護を解除する | C++26 |
| [`swap`](hazard_pointer/swap.md) | 他の`hazard_pointer`オブジェクトと入れ替える | C++26 |


## 非メンバ関数

| 名前 | 説明 | 対応バージョン |
|------|------|----------------|
| [`swap`](hazard_pointer/swap_free.md) | 2つの`hazard_pointer`オブジェクトを入れ替える | C++26 |
| [`make_hazard_pointer`](make_hazard_pointer.md) | ハザードポインタを構築する | C++26 |
| [`make_hazard_pointer_batch`](make_hazard_pointer_batch.md) | 複数のハザードポインタをまとめて構築する | C++29 |
| [`clear_hazard_pointer_batch`](clear_hazard_pointer_batch.md) | 複数のハザードポインタをまとめて破棄する | C++29 |


## 例
```cpp example
#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();
}
```
* std::hazard_pointer[color ff0000]
* std::hazard_pointer_obj_base[link hazard_pointer_obj_base.md]
* std::make_hazard_pointer[link make_hazard_pointer.md]
* h.protect[link hazard_pointer/protect.md]
* old->retire()[link hazard_pointer_obj_base/retire.md]
* exchange[link /reference/atomic/atomic/exchange.md]
* data.load()[link /reference/atomic/atomic/load.md]
* std::jthread[link /reference/thread/jthread.md]

### 出力例
```
0
```


## バージョン
### 言語
- C++26

### 処理系
- [Clang](/implementation.md#clang): ??
- [GCC](/implementation.md#gcc): ??
- [ICC](/implementation.md#icc): ??
- [Visual C++](/implementation.md#visual_cpp): ??


## 関連項目
- [`std::hazard_pointer_obj_base`](hazard_pointer_obj_base.md)
- [`std::make_hazard_pointer`](make_hazard_pointer.md)


## 参照
- [P2530R3 Hazard Pointers for C++26](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2530r3.pdf)
- C++26で追加された
- [P2422R1 Remove `nodiscard` annotations from the standard library specification](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2422r1.html)
- C++26で`empty`メンバ関数の`[[nodiscard]]`指定が削除された
42 changes: 42 additions & 0 deletions reference/hazard_pointer/hazard_pointer/empty.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# empty
* hazard_pointer[meta header]
* function[meta id-type]
* std[meta namespace]
* hazard_pointer[meta class]
* cpp26[meta cpp]

```cpp
bool empty() const noexcept;
```

## 概要
`*this`が空である(ハザードポインタを所有していない)かどうかを判定する。


## 戻り値
`*this`が空である場合にのみ`true`を返す。


## 例外
投げない


## 備考
- 空の`hazard_pointer`オブジェクトは、非関連 (unassociated) 状態のハザードポインタを所有する`hazard_pointer`オブジェクトとは異なる。空のオブジェクトはハザードポインタを1つも所有していない。


## バージョン
### 言語
- C++26

### 処理系
- [Clang](/implementation.md#clang): ??
- [GCC](/implementation.md#gcc): ??
- [ICC](/implementation.md#icc): ??
- [Visual C++](/implementation.md#visual_cpp): ??


## 参照
- [P2530R3 Hazard Pointers for C++26](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2530r3.pdf)
- [P2422R1 Remove `nodiscard` annotations from the standard library specification](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2422r1.html)
- C++26で`[[nodiscard]]`指定が削除された
Loading
Loading