技術的な理由はありませんか?
彼が技術的な理由を与えたと私は信じているので、私はcmeerwの答えに賛成した。それを見ていきましょう。condition_variable
委員会がを待つことにしたとしましょうmutex
。その設計を使用したコードは次のとおりです。
void foo()
{
mut.lock();
// mut locked by this thread here
while (not_ready)
cv.wait(mut);
// mut locked by this thread here
mut.unlock();
}
これはまさに、を使用すべきではないcondition_variable
方法です。でマークされた地域:
// mut locked by this thread here
例外安全性の問題があり、それは深刻な問題です。これらの領域で(または単独で)例外がスローされた場合、例外cv.wait
をキャッチしてロックを解除するためにtry / catchもどこかに配置されない限り、ミューテックスのロック状態がリークされます。しかし、それはあなたがプログラマーに書くように頼んでいる単なるより多くのコードです。
プログラマーが例外安全なコードを書く方法を知っていて、unique_lock
それを達成するために使うことを知っているとしましょう。これで、コードは次のようになります。
void foo()
{
unique_lock<mutex> lk(mut);
// mut locked by this thread here
while (not_ready)
cv.wait(*lk.mutex());
// mut locked by this thread here
}
これははるかに優れていますが、それでも素晴らしい状況ではありません。インターフェースは、condition_variable
プログラマーが物事を機能させるために邪魔にならないようにしています。lk
誤ってミューテックスを参照しない場合、nullポインタの逆参照が発生する可能性があります。condition_variable::wait
そして、このスレッドがのロックを所有していることを確認する方法はありませんmut
。
ああ、覚えておいてください、プログラマーがunique_lock
ミューテックスを公開するために間違ったメンバー関数を選択するかもしれないという危険もあります。 *lk.release()
ここでは悲惨なことになります。
次に、 :を使用する実際のcondition_variable
APIを使用してコードがどのように記述されているかを見てみましょう。unique_lock<mutex>
void foo()
{
unique_lock<mutex> lk(mut);
// mut locked by this thread here
while (not_ready)
cv.wait(lk);
// mut locked by this thread here
}
- このコードは可能な限り単純です。
- 例外安全です。
wait
関数は、例外がの場合、例外をチェックしlk.owns_lock()
てスローできfalse
ます。
これらは、のAPI設計を推進した技術的な理由ですcondition_variable
。
さらに、あなたが言うように理由はcondition_variable::wait
ありません:私は破壊されるまでこのミューテックスのロックを所有しています。ただし、を呼び出すと、ミューテックスのロックが暗黙的に解放されます。そのため、アクションはユースケース/ステートメントと矛盾します。lock_guard<mutex>
lock_guard<mutex>
lock_guard<mutex>
condition_variable::wait
lock_guard
unique_lock
とにかく、関数からロックを返し、それらをコンテナーに入れ、例外安全な方法でスコープ外のパターンでミューテックスをロック/ロック解除できるようにする必要があったので、unique_lock
の自然な選択でしたcondition_variable::wait
。
アップデート
バンボンは私が対照的であると以下のコメントで提案したcondition_variable_any
ので、ここに行きます:
質問:任意のタイプをcondition_variable::wait
渡すことができるようにテンプレート化されて いないのはなぜですか?Lockable
答え:
それは本当に素晴らしい機能です。たとえば、このペーパーshared_lock
では、条件変数(posixの世界では前例のないものですが、それでも非常に便利です)で共有モードの(rwlock)を待機するコードを示します。ただし、機能はより高価です。
そこで、委員会はこの機能を備えた新しいタイプを導入しました。
`condition_variable_any`
このcondition_variable
アダプタを使用すると、ロック可能なタイプを待つことができます。メンバーがいる場合はlock()
、unlock()
行ってもいいです。の適切な実装にcondition_variable_any
は、condition_variable
データメンバーとデータメンバーが必要shared_ptr<mutex>
です。
Because this new functionality is more expensive than your basic condition_variable::wait
, and because condition_variable
is such a low level tool, this very useful but more expensive functionality was put into a separate class so that you only pay for it if you use it.