Skip to content

Commit 9a152c2

Browse files
committed
rcu: 非メンバ関数群 (#1183)
1 parent eda1e0c commit 9a152c2

File tree

8 files changed

+310
-11
lines changed

8 files changed

+310
-11
lines changed

reference/rcu.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ RCU同期メカニズムは、複数スレッド間で共有されるデータ
1212
| [`rcu_obj_base`](rcu/rcu_obj_base.md) | RCU対象オブジェクトの基底クラス(class template) | C++26 |
1313
| [`rcu_domain`](rcu/rcu_domain.md) | RCUドメイン(class) | C++26 |
1414
| [`rcu_default_domain`](rcu/rcu_default_domain.md) | デフォルトのRCUドメイン取得(function) | C++26 |
15-
| [`rcu_synchronize`](rcu/rcu_synchronize.md.nolink) | RCUドメインのアンロック完了を待機(function) | C++26 |
16-
| [`rcu_barrier`](rcu/rcu_barrier.md.nolink) | メモリ解放操作完了を待機(function) | C++26 |
17-
| [`rcu_retire`](rcu/rcu_barrier.md.nolink) | メモリ解放操作をスケジュル(function template) | C++26 |
15+
| [`rcu_synchronize`](rcu/rcu_synchronize.md) | RCUドメインのアンロック完了を待機(function) | C++26 |
16+
| [`rcu_barrier`](rcu/rcu_barrier.md) | メモリ回収操作完了を待機(function) | C++26 |
17+
| [`rcu_retire`](rcu/rcu_retire.md) | メモリ回収操作をスケジュール(function template) | C++26 |
1818

1919

2020
## バージョン

reference/rcu/rcu_barrier.md

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# rcu_barrier
2+
* rcu[meta header]
3+
* function[meta id-type]
4+
* std[meta namespace]
5+
* cpp26[meta cpp]
6+
7+
```cpp
8+
namespace std {
9+
void rcu_barrier(rcu_domain& dom = rcu_default_domain()) noexcept;
10+
}
11+
```
12+
* rcu_domain[link rcu_domain.md]
13+
* rcu_default_domain[link rcu_default_domain.md]
14+
15+
## 概要
16+
スケジュールされたメモリ回収操作の完了を待機する。
17+
18+
19+
## 効果
20+
RCUドメイン`dom`上でスケジュールされた回収操作を評価する可能性がある。
21+
`rcu_barrier`呼び出しよりも前に発生する評価で、かつ`dom`上での操作`E`をスケジュールする評価については、`E`が評価されるまでブロックする。
22+
23+
24+
## 同期操作
25+
`E`のあらゆる評価は、`rcu_barrier`からの戻りよりも確実に前に発生する。
26+
27+
28+
## 戻り値
29+
なし
30+
31+
32+
## 例外
33+
投げない
34+
35+
36+
## 備考
37+
`rcu_barrier`呼び出しは、暗黙に[`rcu_synchronize`](rcu_synchronize.md)を呼ばない。
38+
39+
40+
## バージョン
41+
### 言語
42+
- C++26
43+
44+
### 処理系
45+
- [Clang](/implementation.md#clang): ??
46+
- [GCC](/implementation.md#gcc): ??
47+
- [ICC](/implementation.md#icc): ??
48+
- [Visual C++](/implementation.md#visual_cpp): ??
49+
50+
51+
## 関連項目
52+
- [`rcu_retire`](rcu_retire.md)
53+
- [`rcu_obj_base::retire`](rcu_obj_base/retire.md)
54+
55+
56+
## 参照
57+
- [P2545R4 Read-Copy Update(RCU)](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2545r4.pdf)

reference/rcu/rcu_domain.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ namespace std {
1414
RCU同期メカニズムで保護する共有データに対応付ける、RCUドメインを表現する。
1515
1616
`rcu_domain`クラスは Cpp17Lockable 要件を満たし、共有データの読み取りをおこなうRCU保護区間を表現する。
17-
RCU保護区間は`lock`呼び出しから`unlock()`呼び出しのまでの区間であり、RCUドメインに対して同一スレッド上でのRCU保護区間は入れ子になってもよい。
17+
RCU保護区間は[`lock`](rcu_domain/lock.md)呼び出しから[`unlock`](rcu_domain/unlock.md)呼び出しのまでの区間であり、RCUドメインに対して同一スレッド上でのRCU保護区間は入れ子になってもよい。
1818
1919
2020
## メンバ関数
@@ -67,7 +67,7 @@ int main()
6767

6868
## 関連項目
6969
- [`rcu_default_domain`](rcu_default_domain.md)
70-
- [`rcu_retire`](rcu_retire.md.nolink)
70+
- [`rcu_retire`](rcu_retire.md)
7171
- [`rcu_obj_base::retire`](rcu_obj_base/retire.md)
7272

7373

reference/rcu/rcu_domain/unlock.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ RCU機構により保護される共有データの読み取り終了を宣言
1919

2020
## 効果
2121
直近に開かれたRCU保護区間を閉じる。
22-
`*this`上でスケジュールされた再利用操作を呼び出す可能性がある
22+
`*this`上でスケジュールされた回収操作を呼び出す可能性がある
2323

2424

2525
## 戻り値
@@ -43,8 +43,8 @@ RCU機構により保護される共有データの読み取り終了を宣言
4343

4444
## 関連項目
4545
- [`lock`](lock.md)
46-
- [`rcu_retire`](../rcu_retire.md.nolink)
47-
- [`rcu_obj_base::retire`](../rcu_rcu_obj_base/retire.md.nolink)
46+
- [`rcu_retire`](../rcu_retire.md)
47+
- [`rcu_obj_base::retire`](../rcu_obj_base/retire.md)
4848

4949

5050
## 参照

reference/rcu/rcu_obj_base.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ RCU機構の保護対象とする型の基底クラス。
3131
| [`(constructor)`](rcu_obj_base/op_constructor.md) | コンストラクタ | C++26 |
3232
| `(destructor)` | デストラクタ | C++26 |
3333
| [`operator=`](rcu_obj_base/op_assign.md) | 代入演算子 | C++26 |
34-
| [`retire`](rcu_obj_base/retire.md) | オブジェクト再利用をスケジュールする | C++26 |
34+
| [`retire`](rcu_obj_base/retire.md) | オブジェクト回収をスケジュールする | C++26 |
3535
3636
3737
## 例
@@ -64,7 +64,7 @@ void updater()
6464
Data *old_data = data.exchange(newdata);
6565
6666
// 古いデータを読み取り中のスレッドがなくなったタイミングで
67-
// データ領域の再利用(メモリ解放)を行うようスケジューリングする
67+
// データ領域の回収(メモリ解放)を行うようスケジューリングする
6868
old_data->retire();
6969
}
7070

reference/rcu/rcu_obj_base/retire.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ void retire(D d = D(),
1313
* rcu_default_domain[link ../rcu_default_domain.md]
1414
1515
## 概要
16-
RCU機構により保護されるオブジェクト再利用をスケジュールする
16+
RCU機構により保護されるオブジェクト回収をスケジュールする
1717
1818
1919
## 適格要件
@@ -50,6 +50,7 @@ RCU機構により保護されるオブジェクト再利用をスケジュー
5050
5151
## 関連項目
5252
- [`rcu_domain::unlock`](../rcu_domain/unlock.md)
53+
- [`rcu_retire`](../rcu_retire.md)
5354
5455
5556
## 参照

reference/rcu/rcu_retire.md

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
# rcu_retire
2+
* rcu[meta header]
3+
* function template[meta id-type]
4+
* std[meta namespace]
5+
* cpp26[meta cpp]
6+
7+
```cpp
8+
namespace std{
9+
template<class T, class D = default_delete<T>>
10+
void rcu_retire(T* p,
11+
D d = D(),
12+
rcu_domain& dom = rcu_default_domain());
13+
}
14+
```
15+
* default_delete[link /reference/memory/default_delete.md]
16+
* rcu_domain[link rcu_domain.md]
17+
* rcu_default_domain[link rcu_default_domain.md]
18+
19+
## 概要
20+
RCU機構により保護されるオブジェクト回収をスケジュールする。
21+
22+
23+
## 適格要件
24+
[`is_move_constructible_v`](/reference/type_traits/is_move_constructible.md)`<D> == true`、かつ式`d(p)`が妥当であること。
25+
26+
27+
## 事前条件
28+
`D`はCpp17MoveCosntructible要件およびCpp17Destructible要件をみたすこと。
29+
30+
31+
## 効果
32+
- メモリを確保する可能性がある。
33+
- メモリ確保が`operator new`を呼び出すか否かは未規定である。
34+
- `D`型のオブジェクト`d1``std::move(d)`で初期化する。
35+
- RCUドメイン`dom`に対して式`d1(p)`の評価をスケジュールする。
36+
- 評価が例外で終了した場合は未定義の動作を引き起こす。
37+
- `dom`に対してスケジュールされた評価を呼び出す可能性がある。
38+
39+
40+
## 戻り値
41+
なし
42+
43+
44+
## 例外
45+
[`bad_alloc`](/reference/new/bad_alloc.md)、または`d1`初期化中に送出された例外。
46+
47+
48+
##
49+
```cpp example
50+
#include <atomic>
51+
#include <mutex>
52+
#include <thread>
53+
#include <rcu>
54+
55+
struct Data {
56+
int m1, m2;
57+
};
58+
59+
// 共有データを指すポインタ
60+
std::atomic<Data*> data;
61+
62+
void reader()
63+
{
64+
std::scoped_lock slk{std::rcu_default_domain()};
65+
// 共有データを読み取り(Read)
66+
Data *p = data;
67+
68+
std::println("{} {}", p->m1, p->m2);
69+
}
70+
71+
void updater()
72+
{
73+
Data *newdata = new Data{1, 2};
74+
// 新しいデータで共有データを更新(Update)
75+
Data *old_data = data.exchange(newdata);
76+
77+
// 古いデータを読み取り中のスレッドがなくなったタイミングで
78+
// データ領域の回収(メモリ解放)を行うようスケジューリングする
79+
std::rcu_retire(old_data);
80+
}
81+
82+
int main()
83+
{
84+
// 共有データ初期化
85+
Data *newdata = new Data{0, 0};
86+
data.store(newdata);
87+
88+
// 共有データへ並行アクセス
89+
std::jthread th{[] {
90+
for (int i = 0; i < 3; i++) {
91+
reader();
92+
}
93+
}};
94+
updater();
95+
}
96+
```
97+
* std::rcu_retire[color ff0000]
98+
* std::rcu_default_domain[link rcu_default_domain.md]
99+
* std::scoped_lock[link /reference/mutex/scoped_lock.md]
100+
101+
### 出力例
102+
```
103+
0 0
104+
1 2
105+
1 2
106+
```
107+
108+
## バージョン
109+
### 言語
110+
- C++26
111+
112+
### 処理系
113+
- [Clang](/implementation.md#clang): ??
114+
- [GCC](/implementation.md#gcc): ??
115+
- [ICC](/implementation.md#icc): ??
116+
- [Visual C++](/implementation.md#visual_cpp): ??
117+
118+
119+
## 関連項目
120+
- [`rcu_domain::unlock`](rcu_domain/unlock.md)
121+
- [`rcu_obj_base::retire`](rcu_obj_base/retire.md)
122+
123+
124+
## 参照
125+
- [P2545R4 Read-Copy Update(RCU)](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2545r4.pdf)

reference/rcu/rcu_synchronize.md

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
# rcu_synchronize
2+
* rcu[meta header]
3+
* function[meta id-type]
4+
* std[meta namespace]
5+
* cpp26[meta cpp]
6+
7+
```cpp
8+
namespace std {
9+
void rcu_synchronize(rcu_domain& dom = rcu_default_domain()) noexcept;
10+
}
11+
```
12+
* rcu_domain[link rcu_domain.md]
13+
* rcu_default_domain[link rcu_default_domain.md]
14+
15+
## 概要
16+
RCUドメインのアンロック完了を待機する。
17+
18+
19+
## 効果
20+
もし`rcu_synchronize`呼び出しが`dom`上のRCU保護区間`R`のロックを開く操作よりも確実に前に発生するのでなければ、`R`を閉じる[`unlock`](rcu_domain/unlock.md)まで現スレッドをブロックする。
21+
22+
23+
## 同期操作
24+
`R`を閉じる[`unlock`](rcu_domain/unlock.md)は、`rcu_synchronize`からの戻りよりも確実に前に発生する。
25+
26+
27+
## 戻り値
28+
なし
29+
30+
31+
## 例外
32+
投げない
33+
34+
35+
## 備考
36+
`rcu_synchronize`呼び出しは、暗黙に[`rcu_barrier`](rcu_barrier.md)を呼ばない。
37+
38+
39+
## 例
40+
```cpp example
41+
#include <atomic>
42+
#include <mutex>
43+
#include <thread>
44+
#include <rcu>
45+
46+
struct Data {
47+
int m1, m2;
48+
};
49+
50+
// 共有データを指すポインタ
51+
std::atomic<Data*> data;
52+
53+
void reader()
54+
{
55+
std::scoped_lock slk{std::rcu_default_domain()};
56+
// 共有データを読み取り(Read)
57+
Data *p = data;
58+
59+
std::println("{} {}", p->m1, p->m2);
60+
}
61+
62+
void updater()
63+
{
64+
Data *newdata = new Data{1, 2};
65+
// 新しいデータで共有データを更新(Update)
66+
Data *old_data = data.exchange(newdata);
67+
68+
// 古いデータを読み取り中のスレッドがなくるまで待機する
69+
std::rcu_synchronize();
70+
delete old_data;
71+
}
72+
73+
int main()
74+
{
75+
// 共有データ初期化
76+
Data *newdata = new Data{0, 0};
77+
data.store(newdata);
78+
79+
// 共有データへ並行アクセス
80+
std::jthread th{[] {
81+
for (int i = 0; i < 3; i++) {
82+
reader();
83+
}
84+
}};
85+
updater();
86+
}
87+
```
88+
* std::rcu_synchronize[color ff0000]
89+
* std::rcu_default_domain[link rcu_default_domain.md]
90+
* std::scoped_lock[link /reference/mutex/scoped_lock.md]
91+
92+
### 出力例
93+
```
94+
0 0
95+
1 2
96+
1 2
97+
```
98+
99+
100+
## バージョン
101+
### 言語
102+
- C++26
103+
104+
### 処理系
105+
- [Clang](/implementation.md#clang): ??
106+
- [GCC](/implementation.md#gcc): ??
107+
- [ICC](/implementation.md#icc): ??
108+
- [Visual C++](/implementation.md#visual_cpp): ??
109+
110+
111+
## 関連項目
112+
- [`rcu_domain`](rcu_domain.md)
113+
114+
115+
## 参照
116+
- [P2545R4 Read-Copy Update(RCU)](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2545r4.pdf)

0 commit comments

Comments
 (0)