786. Thread library timed waits, UTC and monotonic clocks
Section: 23.17 [time] Status: Resolved
Submitter: Christopher Kohlhoff, Jeff Garland Opened: 2008-02-03 Last modified: 2016-02-10
Priority: Not Prioritized
View all other issues in [time].
View all issues with Resolved status.
The draft C++0x thread library requires that the time points of type
system_time and returned by get_system_time() represent Coordinated
Universal Time (UTC) (section [datetime.system]). This can lead to
surprising behavior when a library user performs a duration-based wait,
such as condition_variable::timed_wait(). A complete explanation of the
problem may be found in the
Rationale for the Monotonic Clock
section in POSIX, but in summary:
Operations such as condition_variable::timed_wait() (and its POSIX
equivalent, pthread_cond_timedwait()) are specified using absolute times
to address the problem of spurious wakeups.
The typical use of the timed wait operations is to perform a relative
wait. This may be achieved by first calculating an absolute time as the
sum of the current time and the desired duration. In fact, the C++0x
thread library includes duration-based overloads of
condition_variable::timed_wait() that behave as if by calling the
corresponding absolute time overload with a time point value of
get_system_time() + rel_time.
A UTC clock may be affected by changes to the system time, such as
synchronization with an external source, leap seconds, or manual changes
to the clock.
Should the clock change during a timed wait operation, the actual
duration of the wait will not be the expected length. For example, a
user may intend a timed wait of one second duration but, due to an
adjustment of the system clock backwards by a minute, the wait instead
takes 61 seconds.
POSIX solves the problem by introducing a new monotonic clock, which is
unaffected by changes to the system time. When a condition variable is
initialized, the user may specify whether the monotonic clock is to be
used. (It is worth noting that on POSIX systems it is not possible to
use condition_variable::native_handle() to access this facility, since
the desired clock type must be specified during construction of the
condition variable object.)
In the context of the C++0x thread library, there are added dimensions
to the problem due to the need to support platforms other than POSIX:
Some environments (such as embedded systems) do not have a UTC clock, but do have a monotonic clock.
Some environments do not have a monotonic clock, but do have a UTC clock.
The Microsoft Windows API's synchronization functions use relative
timeouts based on an implied monotonic clock. A program that switches
from the Windows API to the C++0x thread library will now find itself
susceptible to clock changes.
One possible minimal solution:
Strike normative references to UTC and an epoch based on 1970-01-01.
Make the semantics of system_time and get_system_time()
implementation-defined (i.e standard library implementors may choose the
appropriate underlying clock based on the capabilities of the target
Add a non-normative note encouraging use of a monotonic clock.
Change the constructor explicit system_time(time_t secs, nanoseconds ns
= 0) to explicit system_time(nanoseconds ns).
N2661: A Foundation to Sleep On.