This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of Resolved status.
786. Thread library timed waits, UTC and monotonic clocks
Section: 30 [time] Status: Resolved Submitter: Christopher Kohlhoff, Jeff Garland Opened: 2008-02-03 Last modified: 2016-01-28
Priority: Not Prioritized
View all other issues in [time].
View all issues with Resolved status.
Discussion:
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 ofget_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_timeandget_system_time()implementation-defined (i.e standard library implementors may choose the appropriate underlying clock based on the capabilities of the target platform). - Add a non-normative note encouraging use of a monotonic clock.
-
Remove
system_time::seconds_since_epoch(). -
Change the constructor
explicit system_time(time_t secs, nanoseconds ns = 0)toexplicit system_time(nanoseconds ns).
Proposed resolution:
Rationale:
Addressed by N2661: A Foundation to Sleep On.
