最終更新日時: 2025年07月09日 17時52分14秒 (JST)
Akira Takahashi が更新

履歴 編集

class template
<rcu>

# std::rcu_obj_base(C++26)

    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 jt{[] {
        for (int i = 0; i < 3; i++) {
          reader();
        }
      }};
      updater();
    }

### 出力例

    0 0
    1 2
    1 2

## バージョン

### 言語

- C++26

### 処理系

- Clang: ??
- GCC: ??
- ICC: ??
- Visual C++: ??

## 関連項目

- `rcu_domain`

## 参照

- P2545R4 Read-Copy Update(RCU)