Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When is it appropriate to use a C++11 *_until timeout function instead of the corresponding *_for function?

Tags:

In C++11, the *_until timeout functions behave "as expected" only if a steady clock (i.e., one that moves only forward at an unchanging rate) is used. Because system_clock is not a steady clock, that means that code like this can behave quite surprisingly:

using namespace std::chrono; std::this_thread::sleep_until(system_clock::now() + seconds(10)); 

This will cause the current thread to sleep for 10 seconds unless the system clock is adjusted during the sleep period, e.g., for daylight savings time. If the clock is set back an hour during the sleep, the current thread will sleep for an hour and 10 seconds.

From what I can tell, every *_until timeout function in C++11 has a corresponding *_for function that takes a duration instead of a timepoint. For example, the above code can be rewritten as follows:

using namespace std::chrono; std::this_thread::sleep_for(seconds(10)); 

The *_for functions shouldn't have to worry about clocks that get adjusted while the function is executing, because they just say how long to wait, not what time it's supposed to be when the wait is over.

This issue affects more than sleep functions, as the same is true for timeout-based waits on futures and try_lock functions.

The only situation in which I can envision it making sense to use an *_until function with an unsteady clock would be when you want to take clock adjustments into account, e.g., you want to sleep until next Wednesday at 3:30AM, even if there's a change to or from daylight savings time between now and then. Are there other situations where *_until functions make more sense than *_for functions? If not, is it safe to say that, in general, the *_for timeout functions should be preferred over the *_until functions?

like image 482
KnowItAllWannabe Avatar asked Jun 26 '12 04:06

KnowItAllWannabe


1 Answers

The xxx_until calls are for when you have deadline. The typical use case is where you have a hard time limit for a section of code which either contains multiple waits, or where the time consumed by each step prior to the wait is unpredictable.

e.g.

void foo() {   std::chrono::steady_clock::time_point const timeout=     std::chrono::steady_clock::now()+std::chrono::milliseconds(30);    do_something_which_takes_some_time();    if(some_future.wait_until(timeout)==std::future_status::ready)     do_something_with(some_future.get()); } 

This will only process the value from some_future if it is ready within 30ms from the start, including the time taken for do_something_which_takes_some_time().

As in this example, most use cases of the xxx_until functions will use a steady clock in order to have a predictable timeout.

The only case where I can imagine using the xxx_until functions with a non-steady clock (such as std::chrono::system_clock) is where the timeout is user-visible, and depends on the value of the chosen clock. An alarm clock or reminder program is one example, a backup program that runs "at midnight" is another.

like image 52
Anthony Williams Avatar answered Oct 29 '22 07:10

Anthony Williams