Reputation: 655
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
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