最終更新日時:
が更新

履歴 編集

function
<condition_variable>

std::condition_variable::notify_all_at_thread_exit(C++11)

namespace std {
  void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk);
}

概要

現在のスレッド終了時に、条件変数が待っている全てのスレッドを起床させる

要件

  • lkが呼び出し元スレッドによってロック取得されていること
  • *thiscondition_variableオブジェクトが他スレッドで待機していないか、もしくは並行に待機している全てのスレッドでlockパラメータが同じミューテックスオブジェクトを参照していること

効果

lkのロック所有権を(スレッドライブラリの)内部ストレージへと移し、スレッド終了時、スレッドローカルなデータを解放した後、condを使って通知する。通知は以下のように行う:

  • C++11 :

    // ここでスレッドローカルストレージを解放
    lk.unlock();
    cond.notify_all();
    

  • C++26 :

    // ここでスレッドローカルストレージを解放
    cond.notify_all();
    lk.unlock();
    

    通知(notify_all())を先に行い、その後でロックを解放するよう順序が変更された。これにより、lkのロック解除を待っている別スレッドは、notify_all()の呼び出し完了後にはじめて起床できるため、デタッチされたスレッドでcondが破棄されてnotify_all()ダングリング参照になる競合を避けられる。

同期操作

暗黙に行われるlk.unlock()の呼び出しは、現在のスレッドに関連付けられたスレッドストレージ期間を持つ全てのオブジェクトの破棄より後に順序付けられる。

戻り値

なし

備考

ロックはスレッド終了まで保持され続けるため、デッドロックを避けるためにできるだけ早くスレッドを終了させることを推奨する。

#include <iostream>
#include <condition_variable>
#include <mutex>
#include <thread>
#include <utility>

struct ProcessData {
  std::mutex mtx_;
  std::condition_variable cond_;

  bool data_ready_;

public:
  ProcessData() : data_ready_(false) {}

  // 処理に必要なデータの準備をする
  void prepare_data_for_processing()
  {
    // ...準備処理...

    {
      std::unique_lock<std::mutex> lk(mtx_);
      data_ready_ = true;

      // このスレッドが終了したら、cond_を待機している全てのスレッドを起床させる
      std::notify_all_at_thread_exit(cond_, std::move(lk));
    }
  }

  void wait_for_data_to_process()
  {
    std::unique_lock<std::mutex> lk(mtx_);

    // データの準備ができるまで待機してから処理する
    cond_.wait(lk, [this] { return data_ready_; });
    process_data();
  }

private:
  void process_data()
  {
    // ...データを処理する...
    std::cout << std::boolalpha << "data is ready: " << data_ready_ << std::endl;
  }
};

int main()
{
  ProcessData p;

  std::thread t1([&] { p.prepare_data_for_processing(); });
  std::thread t2([&] { p.wait_for_data_to_process(); });
  std::thread t3([&] { p.wait_for_data_to_process(); });

  t1.detach(); // 準備スレッドの管理を手放す

  t2.join();
  t3.join();
}

出力

data is ready: true
data is ready: true

バージョン

言語

  • C++11

処理系

参照