Search code examples
c++c++11boostcondition-variable

How does bool version of boost::condition_variable::wait_until using a predicate behave?


Trying to use the:

bool
wait_until(
    unique_lock<mutex>& lock,
    const chrono::time_point<Clock, Duration>& t,
    Predicate pred);

form of boost::condition_variable::wait_until (long story why not std). The documentation states that the effects of this are "As-if:"

while(!pred())
{
    if(!wait_until(lock,abs_time))
    {
        return pred();
    }
}
return true;

But the wait_until(lock,abs_time) form of wait_until actually returns a cv_status type defined as:

enum class cv_status;
{
  no_timeout,
  timeout
};

Since the cv_status type can't be implicitly cast to a bool (right?), what does the if(!wait_until(lock,abs_time)) conditional from the "As-if" imply exactly? I imagine it's saying "if the wait times out, return the value of the predicate" but I don't get that from the form of the if statement and the cv_status return type of that wait_until.

Now, the std documentation "Equivalent to" seems to be exactly what I'd expect:

while (!pred()) {
    if (wait_until(lock, abs_time) == std::cv_status::timeout) {
        return pred();
    }
}
return true;

So is it safe to assume the boost documentation is just a little off and the implementation is as-stated in the std documentation?


Solution

  • You might be mixing up documentation¹.

    In this sample code: Live On Coliru (output: "Nay")

    #include <boost/thread.hpp>
    #include <iostream>
    
    int main()
    {
        boost::mutex m;
        boost::condition_variable cv;
    
        boost::unique_lock<boost::mutex> lk(m);
        if (cv.wait_until(lk,
                boost::chrono::high_resolution_clock::now() + boost::chrono::seconds(1), 
                [] { return false; }))
        {
            std::cout << "Yay\n";
        } else {
            std::cout << "Nay\n";
        }
    }
    

    The return type of wait_until is actually bool. The implementation of that call is actually:

        template <class Clock, class Duration, class Predicate>
        bool
        wait_until(
                unique_lock<mutex>& lock,
                const chrono::time_point<Clock, Duration>& t,
                Predicate pred)
        {
            while (!pred())
            {
                if (wait_until(lock, t) == cv_status::timeout)
                    return pred();
            }
            return true;
        }
    

    As you can see, it deals with the cv_status type explicitly.

    Other than that it does look as if [sic] the "As-if" code is pseudo-code that assumes a bool-kind of return value. I agree this is technically "incorrect".


    ¹ See enter image description here