ark1974
ark1974

Reputation: 655

What if the condition_variable::wait_for delay parameter changes during the wait process?

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
}

Upvotes: 2

Views: 1383

Answers (1)

Sam Varshavchik
Sam Varshavchik

Reputation: 118292

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.

Upvotes: 4

Related Questions