Title
Thread library timed waits, UTC and monotonic clocks
Status
resolved
Section
[time]
Submitter
Christopher Kohlhoff, Jeff Garland

Created on 2008-02-03.00:00:00 last changed 171 months ago

Messages

Date: 2011-04-27.21:19:46

Rationale:

Addressed by N2661: A Foundation to Sleep On.

Date: 2008-02-03.00:00:00

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 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) to explicit system_time(nanoseconds ns).
History
Date User Action Args
2010-11-19 19:04:45adminsetstatus: nad editorial -> resolved
2010-10-21 18:28:33adminsetmessages: + msg3771
2008-02-03 00:00:00admincreate