3

我想等待一个条件一段时间。我阅读了 boost 文档,似乎最好将函数wait_for与谓词一起使用,如此所述。

不幸的是,这个例子对我来说并不是真的有用。我应该如何写谓词?我试图编写上面报告的代码,但 Visual Studio 编译器抱怨:c:\boost\boost\thread\win32\condition_variable.hpp(394): error C2064: term does not evaluate to a function taking 0 arguments

这是代码的一部分:

class MyClass{

  boost::mutex mutex;
  boost::condition_variable myCondition;
  //... 
  void foo();
  bool myPredicate();
}


void MyClass::foo(){

  boost::unique_lock<boost::mutex> lock(mutex);

  boost::chrono::microseconds period(25000);
  // ...
  boost::chrono::system_clock::time_point wakeUpTime = boost::chrono::system_clock::now() + period;
  if(myCondition.wait_until(lock,wakeUpTime,MyClass::myPredicate) == true){/...}

}

bool MyClass::myPredicate(){

  if(...)
    return true;
  else
    return true;
}

wait_for使用谓词的正确方法是什么?

4

1 回答 1

7

建议使用wait带有谓词的函数,因为与手写循环相比,它们更不容易出错。手写循环可能如下所示:

for (;;) {
    if (myPredicate()) {
        // ... [successful case]
        break;
    } else if (myCondition.wait_until(lock, wakeUpTime) == boost::cv_status::timeout) {
        // ... [timeout case]
        break;
    } // else: continue loop [spurious wakeup]
}

如果将谓词传递给wait函数,它可能是一个类似函数的东西,可以不带参数调用并返回一个类型,可以用作bool. 例如,您可以static为此目的使用成员函数:

struct Foobar {
    static bool isFoobar();
};

myCondition.wait_until(lock, wakeUpTime, Foobar::isFoobar);

你不能直接传递一个非静态成员函数,因为它只能被一个对象调用。但是,您可以改用函数对象:

struct MyPredicateWrapper {
    MyClass* _ptr;
    explicit MyPredicateWrapper(MyClass* ptr) : _ptr(ptr) { }
    bool operator()() const { return _ptr->myPredicate(); }
};

myCondition.wait_until(lock, wakeUpTime, MyPredicateWrapper(this));

您可以使用以下方法执行基本相同的操作boost::bind

myCondition.wait_until(lock, wakeUpTime, boost::bind(&MyClass::myPredicate, this));

如果您使用的是 C++11,您还可以使用lambda 函数

myCondition.wait_until(lock, wakeUpTime, [this] { return myPredicate(); });
于 2013-10-12T10:32:38.810 回答