使用reference_wrapper作为condition_variable谓词

时间:2014-09-15 18:31:07

标签: c++ multithreading c++11 boost reference-wrapper

注意:以下内容同样适用于Boost.Thread和C ++ 11线程。

我有一个条件变量,该条件实际上是一个简单的布尔变量。

// assume these are global
mutex m;
condition_variable c;
boolean b = false;

我想使用wait(lock, predicate)语法。我可以使用例如lambda:

c.wait(lock, [] () { return b; });

但我认为应该有一种更惯用的方式将变量包装为可调用的。所以我发现reference_wrapper提供了一个operator()来检索包装的值。所以我试过了:

c.wait(lock, cref(b));

但是g ++(4.9.1)没有编译它,争论no matching function for call to '(boost::reference_wrapper<const bool>) ()'(如果我使用std::ref错误有些不同,但仍然没有编译)。

reference_wrapper不应该有资格作为条件变量的正确谓词吗?如果没有,为什么?在这种情况下,b的正确包装是什么?

编辑:所以@Praetorian已经解释了我的错误,但是,在Boost或标准上真的没有这样的(这里可能有错误):

template<typename T>
struct as_callable {
    T &objref;
    as_callable(T &r) : objref(r) {}
    T &operator()() {
        return objref;
    }
};

2 个答案:

答案 0 :(得分:1)

std::reference_wrapper::operator()仅在reference_wrapper存储可调用时才可用,而bool不是{\ n}。使用lamdba作为谓词。

如果在与条件变量等待的线程不同的线程中修改布尔值,也可以考虑使用std::atomic_bool而不是普通的bool


如果你真的想使用包装器而不是lambda,你可以编写一个重载operator()的简单包装类,并在调用时返回存储的布尔值。

struct bool_wrapper
{
    bool_wrapper(bool& b) : b_(&b) {}
    bool *b_;

    bool operator()() const noexcept { return *b_; }
};

现在您可以使用此类来包装布尔值并将其作为

传递给condition_variable::wait
c.wait(lock, bool_wrapper(b));

Live demo

答案 1 :(得分:1)

除了恰当地解释出现问题的另一个答案之外,我想我可能能够解释 你是如何做出错误的期望的。

瞧,还有Boost Phoenix的版本ref()cref(),令人惊讶地将这个参考作为凤凰懒惰演员提供。即:phx::ref()phx::cref()仿函数

这意味着你可以简单地使用

c.wait(lock, phx::cref(b));

你可能在过去的某个地方遇到过它。