std::condition_variable:: wait_until
|
template
<
class
Clock,
class
Duration
>
std::
cv_status
|
(1) | (C++11以降) |
|
template
<
class
Clock,
class
Duration,
class
Predicate
>
bool
wait_until
(
std::
unique_lock
<
std::
mutex
>
&
lock,
|
(2) | (C++11以降) |
wait_until
は、条件変数が通知されるか、指定された時間ポイントに到達するか、偽のウェイクアップが発生するまで、現在のスレッドをブロックします。
pred
はオプションで提供され、偽のウェイクアップを検出するために使用できます。
if ( wait_until ( lock, abs_time ) == std:: cv_status :: timeout )
return pred ( ) ;
return true ; .
wait_until
が戻った直後、
lock.
owns_lock
(
)
は
true
であり、かつ
lock.
mutex
(
)
は呼び出しスレッドによってロックされています。これらの事後条件が満たせない場合
[1]
、
std::terminate
を呼び出します。
以下のいずれかの条件が満たされる場合、動作は未定義です:
- lock. owns_lock ( ) が false である。
- lock. mutex ( ) が呼び出しスレッドによってロックされていない。
-
他のスレッドが
*
this
で待機中の場合、
lock.
mutex
(
)
がそれらのスレッドが
*
this
で呼び出した待機関数(
wait
、
wait_for
および
wait_until)によってアンロックされたミューテックスと異なる。
- ↑ これはミューテックスの再ロックが例外をスローした場合に発生する可能性があります。
目次 |
パラメータ
| lock | - | 呼び出しスレッドによってロックされなければならないロック |
| abs_time | - | 待機が期限切れとなる時間ポイント |
| pred | - | 待機が完了できるかどうかをチェックする述語 |
| 型要件 | ||
-
Predicate
は
FunctionObject
の要件を満たさなければならない。
|
||
|
-
|
||
戻り値
例外
注記
標準では、
abs_time
に関連付けられたクロックを使用して時間を計測することが推奨されています。このクロックは単調増加クロックである必要はありません。クロックが不連続に調整された場合のこの関数の動作については保証されていませんが、既存の実装では
abs_time
を
Clock
から
std::chrono::system_clock
に変換し、POSIXの
pthread_cond_timedwait
に委譲するため、システムクロックの調整は尊重されますが、ユーザー提供の
Clock
の調整は尊重されません。いずれの場合も、スケジューリングやリソース競合による遅延のため、
abs_time
が経過した後も関数が待機を継続する可能性があります。
使用中のクロックが std::chrono::steady_clock または他の単調増加クロックであっても、システムクロックの調整によって偽のウェイクアップが発生する可能性があります。
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 cv; std::mutex cv_m; // このミューテックスは3つの目的で使用されます: // 1) iへのアクセスを同期するため // 2) std::cerrへのアクセスを同期するため // 3) 条件変数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 2093 | C++11 | タイムアウト関連の例外が仕様に記載されていなかった | これらの例外を明記 |
|
LWG 2114
( P2167R3 ) |
C++11 | bool への変換可能性が実装の期待を反映するには弱すぎた | 要件を強化 |
| LWG 2135 | C++11 | lock. lock ( ) が例外をスローした場合の動作が不明確だった | この場合 std::terminate を呼び出す |
関連項目
|
条件変数が通知されるまで現在のスレッドをブロックする
(公開メンバ関数) |
|
|
条件変数が通知されるか、指定されたタイムアウト時間が経過するまで現在のスレッドをブロックする
(公開メンバ関数) |