![](/img/trans.png)
[英]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.