namespace std {
template<class T, class D = default_delete<T>>
class rcu_obj_base;
}
概要
RCU機構の保護対象とする型の基底クラス。
使用するときは、T
でrcu_obj_base
を公開継承した上で派生クラスT
をrcu_obj_base
のテンプレート引数にする(CRTP)。
適格要件
T
は不完全型でもよいが、特殊化されたrcu_obj_base
のメンバが参照されるまでに完全型とすること。D
は関数オブジェクト型であり、D
型の値d
とT*
型の値ptr
に対して式d(ptr)
が有効であること。D
型は要件 Cpp17DefaultConstructible およ Cpp17MoveAssignable を満たすこと。
メンバ関数
名前 | 説明 | 対応バージョン |
---|---|---|
(constructor) |
コンストラクタ | C++26 |
(destructor) |
デストラクタ | C++26 |
operator= |
代入演算子 | C++26 |
retire |
オブジェクト回収をスケジュールする | C++26 |
例
#include <atomic>
#include <mutex>
#include <thread>
#include <rcu>
struct Data : std::rcu_obj_base<Data> {
int m1, m2;
};
// 共有データを指すポインタ
std::atomic<Data*> data;
void reader()
{
std::scoped_lock slk{std::rcu_default_domain()};
// 共有データを読み取り(Read)
Data *p = data;
std::println("{} {}", p->m1, p->m2);
}
void updater()
{
Data *newdata = new Data{1, 2};
// 新しいデータで共有データを更新(Update)
Data *old_data = data.exchange(newdata);
// 古いデータを読み取り中のスレッドがなくなったタイミングで
// データ領域の回収(メモリ解放)を行うようスケジューリングする
old_data->retire();
}
int main()
{
// 共有データ初期化
Data *newdata = new Data{0, 0};
data.store(newdata);
// 共有データへ並行アクセス
std::jthread th{[] {
for (int i = 0; i < 3; i++) {
reader();
}
}};
updater();
}
47
#include <atomic>
#include <mutex>
#include <thread>
#include <rcu>
struct Data : std::rcu_obj_base<Data> {
int m1, m2;
};
// 共有データを指すポインタ
std::atomic<Data*> data;
void reader()
{
std::scoped_lock slk{std::rcu_default_domain()};
// 共有データを読み取り(Read)
Data *p = data;
出力例
0 0
1 2
1 2
バージョン
言語
- C++26
処理系
- Clang: ??
- GCC: ??
- ICC: ??
- Visual C++: ??