2

I prefer using condition_variable::wait_for as a timer over chrono based timer since I can override the wait condition by specifying a predicate. So I wrote a test program to check what if the delay duration changes once the wait process has already started. The condition_variable::wait_for seems to ignore the change and instead comes out of the wait process entirely. Why is this? Can I ever change it in the middle of a wait process?

enum STATE {START,STOP,NONE};

STATE  state ;
condition_variable cv;
mutex mu;
chrono::milliseconds delay;

void cv_wait_thread()
{
    {
        unique_lock<mutex> lock(mu);
        cv.wait(lock, [](){ return state == START; });
    }

    chrono::time_point<chrono::high_resolution_clock> start_time = chrono::high_resolution_clock::now();

    {
        unique_lock<mutex> lock(mu);
        cv.wait_for(lock, delay);       
    }

    auto diff = chrono::duration_cast<chrono::milliseconds>(chrono::high_resolution_clock::now() - start_time);


    cout << "Conditional_wait:  "<< diff.count() << " milliseconds" << endl;

}


void main()
{
    thread thread1([](){ cv_wait_thread(); });

    state = NONE;   

    this_thread::sleep_for(chrono::seconds(1));

    delay = chrono::milliseconds(3000);

    state = START;
    cv.notify_all(); // ask thread to sleep for 3 sec

    this_thread::sleep_for(chrono::milliseconds(2000)); // let cv_wait thread start the wait process for at least 2 sec already

    delay = chrono::milliseconds(5000); // ask thread to correct and sleep for 5 sec instead

    cv.notify_all();

    thread1.join(); // thread prints 2000 milli
}
0

1 Answer 1

4

As you can see in the specification of the wait_for() method, the delay interval is specified as a const parameter:

template< class Rep, class Period >
std::cv_status wait_for( std::unique_lock<std::mutex>& lock,
                         const std::chrono::duration<Rep, Period>& rel_time);

Furthermore, there's nothing in the specification of wait_for() that indicates that any changes to the parameter will be observable by the thread that's executing the wait_for().

In fact, the only sequencing here comes as an indirect result of releasing and re-acquiring the underlying mutex. Note, however, that this will not occur until after the specified timeout expires. As such, any changes made to the delay parameter by another thread will not be sequenced until that time, and will not be observable by the thread that's executing the wait_for() call.

Note, that if the thread in question was doing something other than locking the mutex and executing wait_for(), unless the main execution thread explicitly does something that sequences its change to delay with respect to the other thread, the other thread is not guaranteed to observe the new value of delay ever.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for the comprehensive reply. But still that don't answer why the wait process breaks after the delay parameter value had changed.Why the original if not not the second value was not taken at all?
Because that's what your code told it to do. wait_for() returns when the condition variable has been notify()-ed, or the timeout expires, whichever comes first. Your code notify()-ed the condition variable, so wait_for() returned. Whether or not the delay value was changed is completely irrelevant.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.