Note: The following applies equally to Boost.Thread and C++11 threads.
I have a condition variable which condition is actually a simple boolean variable.
// assume these are global
mutex m;
condition_variable c;
boolean b = false;
I wanted to use the wait(lock, predicate)
syntax. I could use for example a lambda:
c.wait(lock, [] () { return b; });
But I supposed there should be a more idiomatic way to wrap a variable as a callable. So I found out that reference_wrapper
provides an operator()
that retrieves the wrapped value. Therefore I tried:
c.wait(lock, cref(b));
But g++ (4.9.1) does not compile it, arguing no matching function for call to '(boost::reference_wrapper<const bool>) ()'
(if I use std::ref
the error is somewhat different, but still not compiling).
Shouldn't a reference_wrapper
qualify as a proper predicate for a condition variable? If not, why? And what would be the right wrapper for b
in this case?
EDIT: So @Praetorian has explained quite right my mistake, but, is there really nothing like this on Boost or the standard (there may be mistakes here):
template<typename T>
struct as_callable {
T &objref;
as_callable(T &r) : objref(r) {}
T &operator()() {
return objref;
}
};
std::reference_wrapper::operator()
is only available when the reference_wrapper
is storing a callable, which a plain bool
isn't. Use a lamdba for the predicate.
Also consider using std::atomic_bool
instead of a plain bool
if that boolean is being modified in a different thread from the one where your condition variable is waiting on it.
If you really want to use a wrapper instead of a lambda you could write a trivial wrapper class that overloads operator()
and returns the stored boolean value when invoked.
struct bool_wrapper
{
bool_wrapper(bool& b) : b_(&b) {}
bool *b_;
bool operator()() const noexcept { return *b_; }
};
Now you can use this class to wrap the boolean and pass it to condition_variable::wait
as
c.wait(lock, bool_wrapper(b));