std::notify_all_at_thread_exit
From cppreference.com
| ヘッダ <condition_variable> で定義 |
||
| void notify_all_at_thread_exit( std::condition_variable& cond, std::unique_lock<std::mutex> lk ); |
(C++11以降) | |
notify_all_at_thread_exit は、指定されたスレッドが、すべての thread_local オブジェクトの破棄を含めて、完全に終了したことを他のスレッドに通知するメカニズムを提供します。これは次のように動作します。
- 事前に取得されたロック lk の所有権は、内部ストレージに転送されます。
- 実行環境は、現在のスレッドが終了したときに、あたかも lk.unlock();
cond.notify_all(); であるかのように、条件変数 cond が通知されるように変更されます。
暗黙的な lk.unlock() は、現在のスレッドに関連付けられた スレッドローカルストレージ期間 を持つすべてのオブジェクトの破棄の 後 に順序付けられます。
次のいずれかの条件が満たされる場合、動作は未定義です。
- lk は呼び出し元のスレッドによってロックされていません。
- 他のスレッドも cond を待機している場合、lk.mutex() は、それらのスレッドによって cond に対して呼び出された待機関数(
wait、wait_for、wait_until)によってアンロックされるミューテックスとは異なります。
目次 |
[編集] 注記
std::promise または std::packaged_task によって提供される機能を使用して、同等の効果を得ることができます。
指定されたロック lk は、スレッドが終了するまで保持されます。この関数が呼び出されたら、cond を待機するために同じロックをさらに取得することはできません。一部のスレッドがこの条件変数で待機している場合は、lk のロックを保持している間に待機されている条件が満たされていることを確認し、このロックが notify_all_at_thread_exit を呼び出す前に解放および再取得されないことを確認してください。これにより、他のスレッドでの誤ったウェイクアップによる混乱を避けることができます。
典型的な使用例では、この関数はデタッチされたスレッドによって最後に呼び出されるものです。
[編集] パラメータ
| cond | - | スレッド終了時に通知する条件変数 |
| lk | - | 条件変数 cond に関連付けられたロック |
[編集] 戻り値
(なし)
[編集] 例
この部分的なコードフラグメントは、notify_all_at_thread_exit を使用して、スレッドローカルオブジェクトが破棄されている最中に、それらに依存するデータにアクセスすることを避ける方法を示しています。
このコードを実行
#include <cassert> #include <condition_variable> #include <mutex> #include <string> #include <thread> std::mutex m; std::condition_variable cv; bool ready = false; std::string result; // some arbitrary type void thread_func() { thread_local std::string thread_local_data = "42"; std::unique_lock<std::mutex> lk(m); // assign a value to result using thread_local data result = thread_local_data; ready = true; std::notify_all_at_thread_exit(cv, std::move(lk)); } // 1. destroy thread_locals; // 2. unlock mutex; // 3. notify cv. int main() { std::thread t(thread_func); t.detach(); // do other work // ... // wait for the detached thread std::unique_lock<std::mutex> lk(m); cv.wait(lk, []{ return ready; }); // result is ready and thread_local destructors have finished, no UB assert(result == "42"); }
[編集] 不具合報告
以下の動作変更を伴う欠陥報告が、以前に公開されたC++標準に遡って適用されました。
| DR | 適用対象 | 公開された動作 | 正しい動作 |
|---|---|---|---|
| LWG 2140 | C++11 | notify_all_at_thread_exit の呼び出しcond で待機する関数への呼び出しと同期 |
同期を更新しました 要件 |
[編集] 関連項目
| スレッド終了時のみ通知を配信し、結果を特定の値に設定する ( std::promise<R> の public member function) | |
| 現在のスレッドが終了するまで結果を準備しない関数を実行します。 ( std::packaged_task<R(Args...)> の public member function) |