<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
   "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=US-ASCII">
<title>C++ Timeout Specification</title>
<style type="text/css">
td { vertical-align: top; }
</style>
</head>
<body>
<h1>C++ Timeout Specification</h1>

<p>
ISO/IEC JTC1 SC22 WG21 N3128 = 10-0118 - 2010-08-19
</p>

<p>
Lawrence Crowl, crowl@google.com, Lawrence@Crowl.org
</p>

<p>
This paper revises FCD comment US 181 and its proposed resolution
based on discussions in the August 2010 meeting.
</p>

<p>
<a href="#Problem">Problem</a><br>
<a href="#Solution">Solution</a><br>
<a href="#Wording">Wording</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#time">20.10 Time utilities [time]</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#time.clock.req">20.10.1 Clock requirements [time.clock.req]</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#time.clock.system">20.10.5.1 Class <code>system_clock</code> [time.clock.system]</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#time.clock.monotonic"><del>20.10.5.2 Class <code>monotonic_clock</code> [time.clock.monotonic]</del></a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#time.clock.steady"><ins>20.10.5.2 Class <code>steady_clock</code> [time.clock.steady]</ins></a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#time.clock.hires">20.10.5.3 Class <code>high_resolution_clock</code> [time.clock.hires]</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#thread.req.timing">30.2.4 Timing specifications [thread.req.timing]</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#thread.thread.this">30.3.2 Namespace this_thread [thread.thread.this]</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#thread.timedmutex.requirements">30.4.2 TimedMutex requirements [thread.timedmutex.requirements]</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#thread.condition.condvar">30.5.1 Class condition_variable [thread.condition.condvar]</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#thread.condition.condvarany">30.5.2 Class condition_variable_any [thread.condition.condvarany]</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#futures.unique_future">30.6.6 Class template future [futures.unique_future]</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#futures.shared_future">30.6.7 Class template shared_future [futures.shared_future]</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#futures.atomic_future">30.6.8 Class template atomic_future [futures.atomic_future]</a><br>
</p>


<h2><a name="Problem">Problem</a></h2>

<p>
The meaning of clocks and timeouts
is poorly defined within the Final Committee Draft
when those clocks may be adjusted.
Clocks can be adjusted by hours
and many network protocols expect 
responses within seconds.
A task regularly scheduled for midnight GMT
should execute at midnight even though the clock has been adjusted
to eliminate accumulated error.
Failure of the standard to be precise
about this distinction makes programs effectively unportable.
</p>

<p>
The root of the problem is that the current definition
leaves open disparate implementations
that even as implementations increase their quality,
separate implementations will not converge on the same behavior.
</p>

<p>
There will necessarily be some delay
in the interrupt response, function return, and scheduling
of a thread waking from a timeout.
Implementations can reasonably strive to approach
zero delay for these activities.
So, we call this delay the "quality of implementation".
</p>

<p>
Separately, there will be some delay due to contention
for processor and memory resources.
This delay is more under the control of the application programmer
and systems administrator than it is under the implementation.
So, we call this delay the "quality of management".
The tradeoff between resources and responsiveness
is necessarily application-dependent.
</p>

<p>
We can express the actual time of a timeout
as the sum of the intended time, the quality of implementation
and the quality of management.
The remaining problem is to map the given timeout specifications
to a common intended time.
</p>

<p>
If there are no adjustments to the clock time,
the intended time may be straightforwardly determined
from the manner of specification.
In this case, we assume
that any difference in durations between reported times
and SI units is small,
and thus constitutes a measure of the quality of implementation.
</p>

<p>
The problem arises with the specification of the intended timeout
when the clock is adjusted in the middle of the timeout.
There are two plausible strategies,
the timeout is sensitive to adjustments in the clock time,
or it is not.
The <var>timeout</var>_until functions have straightforward definitions
when they are sensitive to adjustments.
The <var>timeout</var>_for functions have straightforward definitions
when they are insensitive to adjustments.
</p>


<h2><a name="Solution">Solution</a></h2>

<p>
Define <var>timeout</var>_until to respect reported clock time points
and define <var>timeout</var>_for to respect real time durations.
However, implementation constraints in the short term
make a strict definition infeasible.
So, instead we encourage such a definition.
</p>

<p>
A consequence of these definitions is that
<var>timeout</var>_until and <var>timeout</var>_for
are not functionally redundant.
That is, <var>timeout</var>_until(Clock::now()+3_seconds)
is generally not equivalent to <var>timeout</var>_for(3_seconds)
when the clock is adjusted in the interval.
</p>

<p>
The implementation of the <var>timeout</var> definition
necessarily depends on a <dfn>steady clock</dfn>,
one that cannot be adjusted.
A monotonic clock is not sufficient.
While one could be implicit in the standard,
below we make one explicit.
</p>

<p>
Given a steady clock,
the monotonic clock seems to be of marginal utility,
and we replace the monotonic clock with the steady clock.
</p>

<p>
[Note that considered the practice of setting clocks forward in unit tests,
and believe that continuing to do so even in <var>timeout</var>_for operations
would be reasonable because the tests operate in a virtual world,
not in the real world.
The definition of time in that world
need not be the same as the time in the real world.]
</p>


<h2><a name="Wording">Wording</a></h2>

<p>
The proposed wording changes are relative to the Final Committee Draft,
<a href="http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2010/n3092.pdf">N3092</a>.
</p>

<p>
<strong>Note to the Editor:</strong>
This paper should be consistent with N3130
under the assumption that they would both be accepted;
any inconsistencies are accidental and unintended.
</p>


<h3><a name="time">20.10 Time utilities [time]</a></h3>

<p>
Edit within the header synopsis as follows.
</p>

<blockquote><pre><code>
// Clocks
class system_clock;
<del>class monotonic_clock;</del>
<ins>class steady_clock;</ins>
class high_resolution_clock;
</code></pre></blockquote>


<h3><a name="time.clock.req">20.10.1 Clock requirements [time.clock.req]</a></h3>

<p>
Edit within table 56 as follows.
</p>

<blockquote>
<table>

<tr>
<td>....</td>
<td>....</td>
<td>....</td>
</tr>

<tr>
<td><del><code>C1::is_monotonic</code></del></td>
<td><del><code>const bool</code></del></td>
<td><del><code>true</code>
if <code>t1 &lt;= t2</code> is always <code>true</code>,
otherwise <code>false</code>.
[<i>Note:</i>
A clock that can be adjusted backwards is not monotonic.
&mdash;<i>end note</i>]
</del></td>
</tr>

<tr>
<td><ins><code>C1::is_steady</code></ins></td>
<td><ins><code>const bool</code></ins></td>
<td><ins><code>true</code> if the time between clock ticks is constant,
otherwise <code>false</code>.
</ins></td>
</tr>

<tr>
<td><code>C1::now()</code></td>
<td><code>C1::time_point</code></td>
<td>Returns a <code>time_point</code> object
representing the current point in time.
</td>
</tr>
</table>
</blockquote>

<p>
Add a new paragraph 3.
</p>

<blockquote><p>
<ins>
[<i>Note:</i>
The relative difference in durations
between those reported by the given clock
and the SI definition
is a measure of the quality of implementation.
&mdash;<i>end note</i>]
</ins>
</p></blockquote>


<h3><a name="time.clock.system">20.10.5.1 Class <code>system_clock</code> [time.clock.system]</a></h3>

<p>
Edit paragraph 1 as follows.
</p>

<blockquote><p>
Objects of class <code>system_clock</code>
represent wall clock time from the system-wide realtime clock.
</p>
<blockquote><pre><code>
class system_clock {
public:
  typedef <var>see below</var>                        rep;
  typedef ratio&lt;<var>unspecified</var>, <var>unspecified</var>&gt;  period;
  typedef chrono::duration&lt;rep, period&gt;    duration;
  typedef chrono::time_point&lt;system_clock&gt; time_point;
  <del>static const bool is_monotonic =         <var>unspecified</var>;</del>
  <ins>static const bool is_steady =            <var>unspecified</var>;</ins>

  static time_point now();

  // Map to C API
  static time_t        to_time_t(const time_point& t);
  static time_point    from_time_t(time_t t);
};
</code></pre></blockquote>
</blockquote>


<h3><a name="time.clock.monotonic"><del>20.10.5.2 Class <code>monotonic_clock</code> [time.clock.monotonic]</del></a></h3>
<h3><a name="time.clock.steady"><ins>20.10.5.2 Class <code>steady_clock</code> [time.clock.steady]</ins></a></h3>

<p>
Delete paragraph 1.
</p>

<blockquote>
<p>
<del>
Objects of class <code>monotonic_clock</code>
represent clocks for which values of <code>time_point</code>
never decrease as physical time advances.
<code>monotonic_clock</code> may be a synonym for <code>system_clock</code>
if <code>system_clock::is_monotonic</code> is <code>true</code>.
</del>
</p>
</blockquote>

<p>
Edit paragraph 2 as follows.
</p>

<blockquote><p>
<del>The class <code>monotonic_clock</code> is conditionally supported.</del>
<ins>
Objects of class <code>steady_clock</code> represent clocks
for which values of <code>time_point</code>
advance at a steady rate relative to real time.
That is, the clock may not be adjusted.
</ins>
</p>
<blockquote><pre><code>
class <del>monotonic_clock</del> <ins>steady_clock</ins> {
public:
  typedef <var>unspecified</var>                     rep;
  typedef ratio&lt;<var>unspecified</var>, <var>unspecified</var>&gt; period;
  typedef chrono::duration&lt;rep, period&gt;   duration;
  typedef chrono::time_point&lt;<var>unspecified</var>&gt; time_point;
  <del>static const bool is_monotonic =        true;</del>
  <ins>static const bool is_steady =           true;</ins>

  static time_point now();
};
</code></pre></blockquote>
</blockquote>


<h3><a name="time.clock.hires">20.10.5.3 Class <code>high_resolution_clock</code> [time.clock.hires]</a></h3>

<p>
Edit paragraph 1 as follows.
</p>

<blockquote><p>
Objects of class <code>high_resolution_clock</code>
represent clocks with the shortest tick period.
<code>high_resolution_clock</code>
may be a synonym for <code>system_clock</code> or
<del><code>monotonic_clock</code></del>
<ins><code>steady_clock</code></ins>.
</p>
<blockquote><pre><code>
class high_resolution_clock {
 public:
  typedef <var>unspecified</var>                     rep;
  typedef ratio&lt;<var>unspecified</var>, <var>unspecified</var>&gt; period;
  typedef chrono::duration&lt;rep, period&gt;   duration;
  typedef chrono::time_point&lt;<var>unspecified</var>&gt; time_point;
  <del>static const bool is_monotonic =        <var>unspecified</var>;</del>
  <ins>static const bool is_steady =           <var>unspecified</var>;</ins>

   static time_point now();
};
</code></pre></blockquote>
</blockquote>


<h3><a name="thread.req.timing">30.2.4 Timing specifications [thread.req.timing]</a></h3>

<p>
Add a new paragraph after paragraph 1 as follows.
</p>
<blockquote><p>
Implementations necessarily have some delay in returning from a timeout.
Any overhead in interrupt response, function return, and scheduling
induces a "quality of implementation" delay, expressed as duration Di.
Ideally, this delay would be zero.
Further, any contention for processor and memory resources
induces a "quality of management" delay, expressed as duration Dm.
The delay durations may vary from timeout to timeout,
but in all cases shorter is better.
</p></blockquote>

<p>
Edit paragraph 2 as follows.
</p>

<blockquote><p>
The member functions whose names end in <code>_for</code>
take an argument that specifies a <del>relative time</del> <ins>duration</ins>.
These functions produce <dfn>relative timeouts</dfn>.
Implementations <del>should</del> <ins>should</ins>
use a <del>monotonic</del> <ins>steady</ins> clock
to measure time for these functions.
<del>
[<i>Note:</i>
Implementations are not required to use a monotonic clock
because such a clock may not be available.
&mdash;<i>end note</i>]
</del>
<ins>
[<i>Footnote:</i>
All implementations for which standard time units are meaningful
must necessarily have a steady clock within their hardware implementation.
&mdash;<i>end footnote</i>]
</ins>
<ins>
Given a duration argument Dt,
the real-time duration of the timeout is Dt+Di+Dm.
</ins>

</p></blockquote>

<p>
Add a new paragraph after paragraph 2 as follows.
</p>

<blockquote>
<p>
<ins>
The member functions whose names end in <code>_until</code>
take an argument that specifies a time point.
These functions produce <dfn>absolute timeouts</dfn>.
Implementations should use the clock specified in the time point
to measure time for these functions.
Given a clock time point argument Ct,
the clock time point of the return from timeout should be Ct+Di+Dm
when the clock is not adjusted during the timeout.
If the clock is adjusted to the time Ca during the timeout,
the behavior of functions with an absolute timeout
should be as follows.
</ins>
</p>
<ul>
<li>
<p>
<ins>
If Ca &gt; Ct then the waiting function should wake as soon as possible,
i.e. Ca+Di+Dm,
since the timeout is already satisfied.
[<i>Note:</i>
This specification may result in the total duration of the wait
decreasing when measured against a steady clock.
&mdash;<i>end note</i>]
</ins>
</p>
</li>
<li>
<p>
<ins>
If Ca &lt;= Ct then the waiting function should not time out
until <code>Clock::now()</code> returns a time Cn &gt;= Ct,
i.e. waking at Ct+Di+Dm.
[<i>Note:</i>
When the clock is adjusted backwards,
this specification may result in the total duration of the wait
increasing when measured against a steady clock.
When the clock is adjusted forwards,
this specification may result in the total duration of the wait
decreasing when measured against a steady clock.
&mdash;<i>end note</i>]
</ins>
</p>
</li>
</ul>
<p>
<ins>
Implementations shall return from such a timeout
at any point from the time specified above
to the time it would return from a relative timeout
on the difference between Ct
and the time point of the call to the <code>_until</code> function.
</ins>
</p>
</blockquote>


<h3><a name="thread.thread.this">30.3.2 Namespace this_thread [thread.thread.this]</a></h3>

<p>
Edit paragraph 6, regarding <code>sleep_until</code>, as follows.
</p>

<blockquote><p>
<i>Effects:</i>
Blocks the calling thread <del>at least until the time</del>
<ins>for the absolute timeout (30.2.4 [thread.req.timing])</ins>
specified by <code>abs_time</code>.
</p></blockquote>

<p>
Edit paragraph 9, regarding <code>sleep_for</code>, as follows.
</p>

<blockquote><p>
<i>Effects:</i>
Blocks the calling thread <del>for at least the time</del>
<ins>for the relative timeout (30.2.4 [thread.req.timing])</ins>
specified by <code>rel_time</code>.
</p></blockquote>


<h3><a name="thread.timedmutex.requirements">30.4.2 TimedMutex requirements [thread.timedmutex.requirements]</a></h3>

<p>
Edit paragraph 4, regarding <code>try_lock_for</code>, as follows.
</p>

<blockquote><p>
<i>Effects:</i>
The function attempts to obtain ownership of the mutex within
the <del>time</del> <ins>relative timeout (30.2.4 [thread.req.timing])</ins>
specified by <code>rel_time</code>.
If the time specified by <code>rel_time</code> is less than or equal to 0,
the function attempts to obtain ownership without blocking
(as if by calling <code>try_lock()</code>).
The function shall return within the <del>time</del> <ins>timeout</ins>
specified by <code>rel_time</code>
only if it has obtained ownership of the mutex object.
[<i>Note:</i>
As with <code>try_lock()</code>,
there is no guarantee that ownership will be obtained if the lock is available,
but implementations are expected to make a strong effort to do so.
&mdash;<i>end note</i>]
</p></blockquote>

<p>
Edit paragraph 10, regarding <code>try_lock_until</code>, as follows.
</p>

<blockquote><p>
<i>Effects:</i>
The function attempts to obtain ownership of the mutex
by the <del>time</del> <ins>absolute timeout (30.2.4 [thread.req.timing])</ins>
specified by <code>abs_time</code>.
If <code>abs_time</code> has already passed,
the function attempts to obtain ownership without blocking
(as if by calling <code>try_lock()</code>).
The function shall return before the <del>time</del> <ins>timeout</ins>
specified by <code>abs_time</code>
only if it has obtained ownership of the mutex object.
[<i>Note:</i>
As with <code>try_lock()</code>,
there is no guarantee that ownership will be obtained if the lock is available,
but implementations are expected to make a strong effort to do so.
&mdash;<i>end note</i>]
</p></blockquote>


<h3><a name="thread.condition.condvar">30.5.1 Class condition_variable [thread.condition.condvar]</a></h3>

<p>
Edit within paragraph 19, regarding <code>wait_until</code>, as follows.
</p>

<blockquote><p>
<p>
<i>Effects:</i>
</p>
<ul>
<li>....</li>
<li><p>
The function will unblock when signaled by
a call to <code>notify_one()</code> <del>or</del> <ins>,</ins>
a call to <code>notify_all()</code>,
<del>if <code>abs_time &lt;= Clock::now()</code></del>
<ins>expiration of the absolute timeout (30.2.4 [thread.req.timing])
specified by <code>abs_time</code></ins>,
or spuriously.
</p></li>
<li>....</li>
</ul>
</blockquote>

<p>
Edit paragraph 21, regarding <code>wait_until</code>, as follows.
</p>

<blockquote><p>
<i>Returns:</i>
<code>cv_status::timeout</code> if
<del>the function unblocked because <code>abs_time</code> was reached</del>
<ins>the absolute timeout (30.2.4 [thread.req.timing])
specified by <code>abs_time</code> expired</ins>,
otherwise <code>cv_status::no_timeout</code>.
</p></blockquote>

<p>
Edit within paragraph 25, regarding <code>wait_for</code>, as follows.
</p>

<blockquote><p>
<p>
<i>Effects:</i>
</p>
<ul>
<li>....</li>
<li><p>
The function will unblock when signaled by
a call to <code>notify_one()</code> <del>or</del> <ins>,</ins>
a call to <code>notify_all()</code>,
<del>by the elapsed time <code>rel_time passing</code></del>
<ins>expiration of the relative timeout</ins>
(30.2.4 [thread.req.timing])
<ins>specified by <code>rel_time</code></ins>,
or spuriously.
</p></li>
<li>....</li>
</ul>
</blockquote>

<p>
Edit paragraph 26, regarding <code>wait_for</code>, as follows.
</p>

<blockquote><p>
<i>Returns:</i>
<code>cv_status::timeout</code> if
<del>the function unblocked because <code>rel_time</code> elapsed</del>
<ins>the relative timeout (30.2.4 [thread.req.timing])
specified by <code>rel_time</code> expired</ins>,
otherwise <code>cv_status::no_timeout</code>.
</p></blockquote>

<p>
Edit within paragraph 34, regarding the predicate <code>wait_for</code>,
as follows.
</p>

<blockquote>
<p>
<i>Effects:</i>
</p>
<ul>
<li>....</li>
<li><p>
The function will unblock when signaled by
a call to <code>notify_one()</code> <del>or</del> <ins>,</ins>
a call to <code>notify_all()</code>,
<del>by the elapsed time <code>rel_time passing</code></del>
<ins>expiration of the relative timeout</ins>
(30.2.4 [thread.req.timing])
<ins>specified by <code>rel_time</code></ins>,
or spuriously.
</p></li>
<li>....</li>
<li><p>
The loop terminates when <code>pred()</code>
returns true or when the <del>time duration</del>
<ins>relative timeout (30.2.4 [thread.req.timing])</ins>
specified by <code>rel_time</code> has elapsed.
</p></li>
<li>....</li>
</ul>
</blockquote>


<h3><a name="thread.condition.condvarany">30.5.2 Class condition_variable_any [thread.condition.condvarany]</a></h3>

<p>
Edit within paragraph 15, regarding <code>wait_until</code>, as follows.
</p>

<blockquote><p>
<p>
<i>Effects:</i>
</p>
<ul>
<li>....</li>
<li><p>
The function will unblock when signaled by
a call to <code>notify_one()</code> <del>or</del> <ins>,</ins>
a call to <code>notify_all()</code>,
<del>if <code>abs_time &lt;= Clock::now()</code></del>
<ins>expiration of the absolute timeout (30.2.4 [thread.req.timing])
specified by <code>abs_time</code></ins>,
or spuriously.
</p></li>
<li>....</li>
</ul>
</blockquote>

<p>
Edit paragraph 17, regarding <code>wait_until</code>, as follows.
</p>

<blockquote><p>
<i>Returns:</i>
<code>cv_status::timeout</code> if
<del>the function unblocked because <code>abs_time</code> was reached</del>
<ins>the absolute timeout (30.2.4 [thread.req.timing])
specified by <code>abs_time</code> expired</ins>,
otherwise <code>cv_status::no_timeout</code>.
</p></blockquote>

<p>
Edit within paragraph 20, regarding <code>wait_for</code>, as follows.
</p>

<blockquote><p>
<p>
<i>Effects:</i>
</p>
<ul>
<li>....</li>
<li><p>
The function will unblock when signaled by
a call to <code>notify_one()</code> <del>or</del> <ins>,</ins>
a call to <code>notify_all()</code>,
<del>by the elapsed time <code>rel_time passing</code></del>
<ins>expiration of the relative timeout</ins>
(30.2.4 [thread.req.timing])
<ins>specified by <code>rel_time</code></ins>,
or spuriously.
</p></li>
<li>....</li>
</ul>
</blockquote>

<p>
Edit paragraph 21, regarding <code>wait_for</code>, as follows.
</p>

<blockquote><p>
<i>Returns:</i>
<code>cv_status::timeout</code> if
<del>the function unblocked because <code>rel_time</code> elapsed</del>
<ins>the relative timeout (30.2.4 [thread.req.timing])
specified by <code>rel_time</code> expired</ins>,
otherwise <code>cv_status::no_timeout</code>.
</p></blockquote>

<p>
Edit within paragraph 28, regarding the predicate <code>wait_for</code>,
as follows.
</p>

<blockquote>
<p>
<i>Effects:</i>
</p>
<ul>
<li>....</li>
<li><p>
The function will unblock when signaled by
a call to <code>notify_one()</code> <del>or</del> <ins>,</ins>
a call to <code>notify_all()</code>,
<del>by the elapsed time <code>rel_time passing</code></del>
<ins>expiration of the relative timeout</ins>
(30.2.4 [thread.req.timing])
<ins>specified by <code>rel_time</code></ins>,
or spuriously.
</p></li>
<li>....</li>
<li><p>
The loop terminates when <code>pred()</code>
returns true or when the <del>time duration</del>
<ins>relative timeout (30.2.4 [thread.req.timing])</ins>
specified by <code>rel_time</code> has elapsed.
</p></li>
<li>....</li>
</ul>
</blockquote>


<h3><a name="futures.unique_future">30.6.6 Class template future [futures.unique_future]</a></h3>

<p>
Edit within paragraph 22, regarding <code>wait_for</code>, as follows.
</p>

<blockquote><p>
<i>Effects:</i>
blocks until the associated asynchronous state is ready
or until
<ins>the relative timeout (30.2.4 [thread.req.timing])</ins>
specified by <code>rel_time</code> has <del>elapsed</del> <ins>expired</ins>.
</p></blockquote>


<p>
Edit within paragraph 23, regarding <code>wait_for</code>, as follows.
</p>

<blockquote>
<p>
<i>Returns:</i>
</p>
<ul>
<li>....</li>
<li><p>
<code>future_status::timeout</code> if the function is returning
because the <del>time period</del>
<ins>relative timeout (30.2.4 [thread.req.timing])</ins>
specified by <code>rel_time</code> has <del>elapsed</del> <ins>expired</ins>.
</p></li>
<li>....</li>
</ul>
</blockquote>

<p>
Edit within paragraph 25, regarding <code>wait_until</code>, as follows.
</p>

<blockquote><p>
<i>Effects:</i>
blocks until the associated asynchronous state is ready
or until
<del>the current time exceeds</del>
<ins>the absolute timeout (30.2.4 [thread.req.timing])</ins>
specified by <code>abs_time</code> <ins>has expired</ins>.
</p></blockquote>

<p>
Edit within paragraph 26, regarding <code>wait_until</code>, as follows.
</p>

<blockquote>
<p>
<ins>
<i>Returns:</i>
</ins>
</p>
<ul>
<li>....</li>
<li><p>
<code>future_status::timeout</code> if the function is returning
because the <del>the time point</del>
<ins>absolute timeout (30.2.4 [thread.req.timing])</ins>
specified by <code>rel_time</code> has <del>been reached</del>
<ins>expired</ins>.
</p></li>
<li>....</li>
</ul>
</blockquote>


<h3><a name="futures.shared_future">30.6.7 Class template shared_future [futures.shared_future]</a></h3>

<p>
Edit within paragraph 27, regarding <code>wait_for</code>, as follows.
</p>

<blockquote><p>
<i>Effects:</i>
blocks until the associated asynchronous state is ready
or until
<ins>the relative timeout (30.2.4 [thread.req.timing])</ins>
specified by <code>rel_time</code> has <del>elapsed</del> <ins>expired</ins>.
</p></blockquote>

<p>
Edit within paragraph 28, regarding <code>wait_for</code>, as follows.
</p>

<blockquote>
<p>
<i>Returns:</i>
</p>
<ul>
<li>....</li>
<li><p>
<code>future_status::timeout</code> if the function is returning
because the <del>time period</del>
<ins>relative timeout (30.2.4 [thread.req.timing])</ins>
specified by <code>rel_time</code> has <del>elapsed</del> <ins>expired</ins>.
</p></li>
<li>....</li>
</ul>
</blockquote>

<p>
Edit within paragraph 30, regarding <code>wait_until</code>, as follows.
</p>

<blockquote><p>
<i>Effects:</i>
blocks until the associated asynchronous state is ready
or until
<del>the current time exceeds</del>
<ins>the absolute timeout (30.2.4 [thread.req.timing])</ins>
specified by <code>abs_time</code> <ins>has expired</ins>.
</p></blockquote>

<p>
Edit within paragraph 31, regarding <code>wait_until</code>, as follows.
</p>

<blockquote>
<p>
<i>Returns:</i>
</p>
<ul>
<li>....</li>
<li><p>
<code>future_status::timeout</code> if the function is returning
because the <del>the time point</del>
<ins>absolute timeout (30.2.4 [thread.req.timing])</ins>
specified by <code>rel_time</code> has <del>been reached</del>
<ins>expired</ins>.
</p></li>
<li>....</li>
</ul>
</blockquote>


<h3><a name="futures.atomic_future">30.6.8 Class template atomic_future [futures.atomic_future]</a></h3>

<p>
Edit within paragraph 23, regarding <code>wait_for</code>, as follows.
</p>

<blockquote><p>
<i>Effects:</i>
blocks until the associated asynchronous state is ready
or until
<ins>the relative timeout (30.2.4 [thread.req.timing])</ins>
specified by <code>rel_time</code> has <del>elapsed</del> <ins>expired</ins>.
</p></blockquote>

<p>
Edit within paragraph 24, regarding <code>wait_for</code>, as follows.
</p>

<blockquote>
<p>
<i>Returns:</i>
</p>
<ul>
<li>....</li>
<li><p>
<code>future_status::timeout</code> if the function is returning
because the <del>time period</del>
<ins>relative timeout (30.2.4 [thread.req.timing])</ins>
specified by <code>rel_time</code> has <del>elapsed</del> <ins>expired</ins>.
</p></li>
<li>....</li>
</ul>
</blockquote>

<p>
Edit within paragraph 27, regarding <code>wait_until</code>, as follows.
</p>

<blockquote><p>
<i>Effects:</i>
blocks until the associated asynchronous state is ready
or until
<del>the current time exceeds</del>
<ins>the absolute timeout (30.2.4 [thread.req.timing])</ins>
specified by <code>abs_time</code> <ins>has expired</ins>.
</p></blockquote>

<p>
Edit within paragraph 28, regarding <code>wait_until</code>, as follows.
</p>

<blockquote>
<p>
<i>Returns:</i>
</p>
<ul>
<li>....</li>
<li><p>
<code>future_status::timeout</code> if the function is returning
because the <del>the time point</del>
<ins>absolute timeout (30.2.4 [thread.req.timing])</ins>
specified by <code>rel_time</code> has <del>been reached</del>
<ins>expired</ins>.
</p></li>
<li>....</li>
</ul>
</blockquote>

</body>
</html>
