Reputation: 2408
I would like to wait for a condition for a certain amount of time.
I read the boost documentation and it seems that it is preferable to use the function wait_for
with a predicate, as described here.
Unfortunately the example is not really useful for me. How should I write the predicate? I tried to write the code reported above but the visual studio compiler is complaining: c:\boost\boost\thread\win32\condition_variable.hpp(394): error C2064: term does not evaluate to a function taking 0 arguments
This is the part of the code:
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;
}
What's the correct way of using wait_for
with predicate?
Upvotes: 3
Views: 8572
Reputation: 50134
It's recommended to use the wait
functions with predicate, because they are less error-prone compared to hand-written loops. A hand-written loop might look as follows:
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]
}
If you pass a predicate to the wait
function, it might be a function-like thing that can be invoked with no arguments and returns a type, that can be used as a bool
. For example you can use a static
member function for that purpose:
struct Foobar {
static bool isFoobar();
};
myCondition.wait_until(lock, wakeUpTime, Foobar::isFoobar);
You can't directly pass a non-static member function, because it can only be invoked with an object. However, you can use a function-object instead:
struct MyPredicateWrapper {
MyClass* _ptr;
explicit MyPredicateWrapper(MyClass* ptr) : _ptr(ptr) { }
bool operator()() const { return _ptr->myPredicate(); }
};
myCondition.wait_until(lock, wakeUpTime, MyPredicateWrapper(this));
You can do basically the same thing with boost::bind
:
myCondition.wait_until(lock, wakeUpTime, boost::bind(&MyClass::myPredicate, this));
And if you are using C++11, you can also use a lambda function:
myCondition.wait_until(lock, wakeUpTime, [this] { return myPredicate(); });
Upvotes: 9