std::condition_variable_any::wait
From cppreference.com
< cpp | thread | condition variable any
| template< class Lock > void wait( Lock& lock ); |
(1) | (C++11以降) |
| template< class Lock, class Predicate > void wait( Lock& lock, Predicate pred ); |
(2) | (C++11以降) |
| template< class Lock, class Predicate > bool wait( Lock& lock, std::stop_token stoken, Predicate pred ); |
(3) | (C++20以降) |
wait は、条件変数に通知されるか、または偽のウェイクアップが発生するまで、現在のスレッドをブロックさせます。pred は、偽のウェイクアップを検出するためにオプションで提供できます。
1) lock.unlock() をアトミックに呼び出し、*this でブロックします。
スレッドは、notify_all() または notify_one() が実行されたときにアンブロックされます。また、偽にアンブロックされることもあります。
解除されると、lock.lock() を呼び出し(ロックでブロックする可能性があります)、その後返します。
2,3) 特定の条件が真になるのを待機します。偽のウェイクアップを無視するために使用できます。
2) 同値:
while (!pred())
wait(lock);
wait(lock);
3) この呼び出しの間、*this を登録し、stoken の関連付けられた stop-state で停止要求が行われた場合に通知されるようにします。その後、これは次のものと同等です。
while (!stoken.stop_requested())
{
if (pred())
return true;
wait(lock);
}
return pred();
{
if (pred())
return true;
wait(lock);
}
return pred();
wait が返された直後、lock は呼び出しスレッドによってロックされます。この後条件が満たされない場合[1]、std::terminate が呼び出されます。
- ↑ これは、ミューテックスの再ロックが例外をスローした場合に発生する可能性があります。
目次 |
[編集] パラメータ
| lock | - | 呼び出しスレッドによってロックされる必要があるロック |
| stoken | - | 割り込みを登録するためのストップトークン |
| pred | - | 待機が完了できるかどうかをチェックする述語 |
| 型要件 | ||
-Lock は BasicLockable の要件を満たす必要があります。 | ||
-Predicate は FunctionObject の要件を満たす必要があります。 | ||
| -pred() は有効な式であり、その型と値カテゴリは BooleanTestable の要件を満たす必要があります。 | ||
[編集] 戻り値
1,2) (なし)
3) 返される前に pred() の最新の結果。
[編集] 例外
1) スローしません。
2,3) pred によってスローされる例外。
[編集] 注記
オーバーロード (3) の返り値は、停止要求があったかどうかに関わらず、pred が true と評価されたかどうかを示します。
notify_one()/notify_all() と、wait()/wait_for()/wait_until() の 3 つのアトミック部分(アンロック+待機、ウェイクアップ、ロック)の効果は、単一の全順序で発生します。これは、アトミック変数の一連の 変更順序 と見なすことができます。この順序は、この個別の条件変数に固有のものです。これにより、例えば、notify_one() の呼び出しが行われた直後に待機を開始したスレッドを解除するために notify_one() が遅延することは不可能になります。
[編集] 例
このコードを実行
#include <chrono> #include <condition_variable> #include <iostream> #include <thread> std::condition_variable_any cv; std::mutex cv_m; // This mutex is used for three purposes: // 1) to synchronize accesses to i // 2) to synchronize accesses to std::cerr // 3) for the condition variable cv int i = 0; void waits() { std::unique_lock<std::mutex> lk(cv_m); std::cerr << "Waiting... \n"; cv.wait(lk, []{ return i == 1; }); std::cerr << "...finished waiting. i == 1\n"; } void signals() { std::this_thread::sleep_for(std::chrono::seconds(1)); { std::lock_guard<std::mutex> lk(cv_m); std::cerr << "Notifying...\n"; } cv.notify_all(); std::this_thread::sleep_for(std::chrono::seconds(1)); { std::lock_guard<std::mutex> lk(cv_m); i = 1; std::cerr << "Notifying again...\n"; } cv.notify_all(); } int main() { std::thread t1(waits), t2(waits), t3(waits), t4(signals); t1.join(); t2.join(); t3.join(); t4.join(); }
実行結果の例
Waiting... Waiting... Waiting... Notifying... Notifying again... ...finished waiting. i == 1 ...finished waiting. i == 1 ...finished waiting. i == 1
[編集] 不具合報告
以下の動作変更を伴う欠陥報告が、以前に公開されたC++標準に遡って適用されました。
| DR | 適用対象 | 公開された動作 | 正しい動作 |
|---|---|---|---|
| LWG 2114 (P2167R3) |
C++11 | bool への変換可能性は、実装の期待を反映するには弱すぎた | 要件が強化された |
| LWG 2135 | C++11 | lock.lock() が例外をスローした場合の動作が不明確だった | この場合、std::terminate を呼び出す |
[編集] 関連項目
| 指定されたタイムアウト期間後、または条件変数(condition variable)が起動されるまで、現在のスレッドをブロックする。 (public member function) | |
| 指定された時刻に達するか、または条件変数(condition variable)が起動されるまで、現在のスレッドをブロックする。 (public member function) | |
| C ドキュメント cnd_wait
| |
[編集] 外部リンク
| The Old New Thing 記事: Win32 条件変数における偽のウェイクアップ。 |