最終更新日時:
が更新

履歴 編集

function
<hazard_pointer>

std::hazard_pointer_obj_base::retire(C++26)

void retire(D d = D()) noexcept;

概要

ハザードポインタで保護されるオブジェクトの回収 (reclamation) をスケジュールする。

このオブジェクトを削除済みとして登録し、どのハザードポインタからも指されていないことが確認された時点で、削除器dによって回収 (破棄) されるようにする。

適格要件

  • クラステンプレートパラメータTが、ハザードポインタで保護可能 (hazard-protectable) な型であること。すなわち、
    • hazard_pointer_obj_base<T, D>型を唯一の基底クラスとして持ち、かつ
    • その基底は公開 (public) かつ非仮想基底クラスであり、かつ
    • T2, D2の他の組合せに対してhazard_pointer_obj_base<T2, D2>型を基底クラスとして持たないこと。

事前条件

  • *thisが型Tのオブジェクトxの基底クラスサブオブジェクトであること。
  • xが回収予約されていないこと。任意のオブジェクトの回収予約は高々1回だけ行える。
  • D型の説明用メンバ変数deleterへのdのムーブ代入が例外で終了しないこと。

効果

  • deleter = std::move(d)を評価してxの削除器として設定し、xを回収予約する。
  • 回収可能となったオブジェクトを回収する可能性がある。

回収は、削除器にxへのポインタを渡して呼び出すことで行われる。この呼び出しが例外で終了した場合の動作は未定義である。

戻り値

なし

例外

投げない

備考

  • ライブラリが回収 (破棄) するのは、retire()に渡されたオブジェクトだけである。データ構造から取り外したオブジェクトをretire()し忘れると、そのオブジェクトは回収されずメモリリークになるので注意すること。ガベージコレクションのように未参照オブジェクトが自動的に回収されるわけではない。
  • 回収は、このretire()の呼び出し時に即座に行われるとは限らない。実際の回収 (削除器の呼び出し) は、どのハザードポインタからも指されていないことが確認できたオブジェクトに対して、後続のretire()make_hazard_pointer()などのライブラリ呼び出しの中で、まとめて (償却的に) 行われうる。遅くともプログラムの終了までには回収される。

#include <hazard_pointer>
#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(1)};

int main()
{
  // 新しいデータで差し替え、古いデータを回収予約する
  Data* old = data.exchange(new Data(2));
  old->retire(); // 保護しているスレッドがいなくなったら回収される

  std::println("{}", data.load()->value);

  // 最後に残ったオブジェクトも回収予約する
  data.load()->retire();
}

出力

2

バージョン

言語

  • C++26

処理系

関連項目

参照