[英]How does std::condition_variable::wait() evaluate the given predicate?
[英]std::condition_variable::wait with predicate
在std :: condition_variable的文檔中,使用謂詞函數作為參數的wait()重載。 該函數將一直等到謂詞函數為true的第一次wake_up。
在文檔中
據說這相當於:
while (!pred()) {
wait(lock);
}
但是也:
在等待特定條件變為真時,可以使用此重載來忽略虛假喚醒。 請注意,在進入此方法之前,必須先獲取鎖,在wait(lock)退出后也必須重新獲取它,即鎖可以用作pred()訪問的保護。
我不確定要理解的是,這些嚴格地等效嗎(在這種情況下,我更喜歡普通的while循環,比我的情況下帶有lambda的重載更容易閱讀),或者重載(可能取決於實現)更有效?
為了避免測試條件為假時喚醒,實現是否可以在喚醒等待線程之前評估通知線程中的謂詞? 這里需要c ++線程大師...
謝謝
從性能的角度來看,實現可以嘗試使其比循環更好,但是我懷疑這樣做是否可行。 這是非常嚴格的,您可以檢查實現以查看完成情況。 這就是gcc 4.9.2在這里所做的:
template<typename _Predicate>
void
wait(unique_lock<mutex>& __lock, _Predicate __p)
{
while (!__p())
wait(__lock);
}
如您所見,它是完全一樣的,我懷疑是否可以在此做其他事情。 至於可讀性,它比循環更具可讀性。 但是,您可能會誤解其原因。 該循環僅用於檢查由條件保證的實變量確實確實更改為您期望的值-可能沒有。 常見的代碼片段如下所示:
cond_var.wait(lock, []() { return bool_var == true; })
據我了解,這兩個( while
循環和wait + predicate
)在功能上是等效的。 如果要使用while
循環,則應在首次進入並評估循環條件之前獲取鎖定。 每隔兩次您還將持有該鎖,因為predicate()
將在wait()
完成后執行。
內部重載的作用相同:您必須在調用wait
之前獲取鎖定,並且在wait完成之后,內部調用predicate()
來檢查是否應繼續等待(就像while循環一樣)。
對於簡單謂詞,使用while
循環返回boolean
值更加清晰,也許您是對的。 但是如果predicate
變得更復雜怎么辦? 為它定義一個專用函數並在while循環條件下使用它,還是在原處使用lambda? 如果謂詞數量增加,您將為每個謂詞定義功能嗎? 在我看來,在這種情況下使用lambda可以使代碼更清晰,因為整個事物都放在一個邏輯單元中。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.