<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 2093: Throws clause of condition_variable::wait with predicate</title>
<meta property="og:title" content="Issue 2093: Throws clause of condition_variable::wait with predicate">
<meta property="og:description" content="C++ library issue. Status: C++14">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue2093.html">
<meta property="og:type" content="website">
<meta property="og:image" content="http://cplusplus.github.io/LWG/images/cpp_logo.png">
<meta property="og:image:alt" content="C++ logo">
<style>
  p {text-align:justify}
  li {text-align:justify}
  pre code.backtick::before { content: "`" }
  pre code.backtick::after { content: "`" }
  blockquote.note
  {
    background-color:#E0E0E0;
    padding-left: 15px;
    padding-right: 15px;
    padding-top: 1px;
    padding-bottom: 1px;
  }
  ins {background-color:#A0FFA0}
  del {background-color:#FFA0A0}
  table.issues-index { border: 1px solid; border-collapse: collapse; }
  table.issues-index th { text-align: center; padding: 4px; border: 1px solid; }
  table.issues-index td { padding: 4px; border: 1px solid; }
  table.issues-index td:nth-child(1) { text-align: right; }
  table.issues-index td:nth-child(2) { text-align: left; }
  table.issues-index td:nth-child(3) { text-align: left; }
  table.issues-index td:nth-child(4) { text-align: left; }
  table.issues-index td:nth-child(5) { text-align: center; }
  table.issues-index td:nth-child(6) { text-align: center; }
  table.issues-index td:nth-child(7) { text-align: left; }
  table.issues-index td:nth-child(5) span.no-pr { color: red; }
  @media (prefers-color-scheme: dark) {
     html {
        color: #ddd;
        background-color: black;
     }
     ins {
        background-color: #225522
     }
     del {
        background-color: #662222
     }
     a {
        color: #6af
     }
     a:visited {
        color: #6af
     }
     blockquote.note
     {
        background-color: rgba(255, 255, 255, .10)
     }
  }
</style>
</head>
<body>
<hr>
<p><em>This page is a snapshot from the LWG issues list, see the <a href="lwg-active.html">Library Active Issues List</a> for more information and the meaning of <a href="lwg-active.html#C++14">C++14</a> status.</em></p>
<h3 id="2093"><a href="lwg-defects.html#2093">2093</a>. Throws clause of <code>condition_variable::wait</code> with predicate</h3>
<p><b>Section:</b> 32.7.4 <a href="https://wg21.link/thread.condition.condvar">[thread.condition.condvar]</a> <b>Status:</b> <a href="lwg-active.html#C++14">C++14</a>
 <b>Submitter:</b> Alberto Ganesh Barbati <b>Opened:</b> 2011-10-27 <b>Last modified:</b> 2015-10-20</p>
<p><b>Priority: </b>Not Prioritized
</p>
<p><b>View other</b> <a href="lwg-index-open.html#thread.condition.condvar">active issues</a> in [thread.condition.condvar].</p>
<p><b>View all other</b> <a href="lwg-index.html#thread.condition.condvar">issues</a> in [thread.condition.condvar].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#C++14">C++14</a> status.</p>
<p><b>Discussion:</b></p>

<p>
the Throws: clause of <code>condition_variable::wait&#47;wait_xxx</code> functions that 
take a predicate argument is:
</p>
<blockquote><p>
<i>Throws</i>: <code>system_error</code> when an exception is required (32.2.2 <a href="https://wg21.link/thread.req.exception">[thread.req.exception]</a>).
</p></blockquote>
<p>
If executing the predicate throws an exception, I would expect such exception to propagate unchanged 
to the caller, but the throws clause seems to indicate that it gets mutated into a <code>system_error</code>.
That's because of 16.3.2.4 <a href="https://wg21.link/structure.specifications">[structure.specifications]</a>&#47;4:
<p/>
"If <code>F</code>'s semantics contains a Throws:, Postconditions:, or Complexity: element, then that supersedes 
any occurrences of that element in the code sequence."
<p/>
Is my interpretation correct? Does it match the intent?
<p/>
Daniel comments:
<p/>
I don't think that this interpretation is entirely correct, the wording does not say that 
<code>std::system_error</code> or a derived class must be thrown, it simply is underspecified 
in this regard (The extreme interpretation is that the behaviour would be undefined, but 
that would be too far reaching I think). We have better wording for this in 
32.6.7.2 <a href="https://wg21.link/thread.once.callonce">[thread.once.callonce]</a> p4, where it says:
<p/>
"<i>Throws</i>: <code>system_error</code> when an exception is required (32.2.2 <a href="https://wg21.link/thread.req.exception">[thread.req.exception]</a>), 
or any exception thrown by <code>func</code>."
<p/>
or in 32.4.5 <a href="https://wg21.link/thread.thread.this">[thread.thread.this]</a> p6&#47;p9:
<p/>
"<i>Throws</i>: Nothing if <code>Clock</code> satisfies the <code>TrivialClock</code> requirements 
(30.3 <a href="https://wg21.link/time.clock.req">[time.clock.req]</a>) and operations of <code>Duration</code> do not throw exceptions. 
[ <i>Note</i>: instantiations of time point types and clocks supplied by the implementation 
as specified in 30.7 <a href="https://wg21.link/time.clock">[time.clock]</a> do not throw exceptions. &mdash; <i>end note</i> ]"
<p/>
So, the here discussed Throws elements should add lines along the lines of
<p/>
"Any exception thrown by operations of <code>pred</code>."
<p/>
and similar wording for time-related operations:
<p/>
"Any exception thrown by operations of <code>Duration</code>",
<p/>
"Any exception thrown by operations of <code>chrono::duration&lt;Rep, Period&gt;</code>"
</p>

<p><i>[2011-11-28: Ganesh comments and suggests wording]</i></p>


<p>
As for the discussion about the exception thrown by the manipulation of time-related objects, 
I believe the argument applies to all functions declared in 32 <a href="https://wg21.link/thread">[thread]</a>. Therefore, 
instead of adding wording to each member, I would simply move those requirements from 
32.4.5 <a href="https://wg21.link/thread.thread.this">[thread.thread.this]</a> p6&#47;p9 to a new paragraph in 32.2.4 <a href="https://wg21.link/thread.req.timing">[thread.req.timing]</a>. 
<p/>
As for 32.7.5 <a href="https://wg21.link/thread.condition.condvarany">[thread.condition.condvarany]</a>, the member functions <code>wait()</code> and 
<code>wait_until()</code> are described only in terms of the Effects: clause (so strictly speaking, 
they need no changes), however, <code>wait_for()</code> is described with a full set of clauses 
including Throws: and Error conditions:. Either we should add those clauses to <code>wait&#47;wait_until</code> 
with changes similar to the one above, or remove paragraphs 29 to 34 entirely. By the way, 
even paragraph 26 could be removed IMHO.
</p>

<p><i>[2012, Kona]</i></p>

<p>
We like the idea behind the proposed resolution.
<p/>
Modify the first addition to read instead: "Functions that specify a timeout, will throw if an operation 
on a clock, time point, or time duration throws an exception." 
<p/>
In the note near the bottom change "even if the timeout has already expired" to "or if the timeout has 
already expired". (This is independent, but the original doesn't seem to make sense.) 
<p/>
Move to Review.
</p>

<p><i>[2012, Portland]</i></p>

<p>
Concurrency move to Ready with slightly ammended wording.
</p>

<p><i>[2013-04-20 Bristol]</i></p>



<p id="res-2093"><b>Proposed resolution:</b></p>
<p>This wording is relative to N3337.</p>

<ol>
<li><p>Add a new paragraph at the end of 32.2.4 <a href="https://wg21.link/thread.req.timing">[thread.req.timing]</a>:</p>

<blockquote>
<p>
[&hellip;]
<p/>
-6- The resolution of timing provided by an implementation depends on both operating system and hardware.
The finest resolution provided by an implementation is called the <i>native resolution</i>.
<p/>
-7- Implementation-provided clocks that are used for these functions shall meet the <code>TrivialClock</code> 
requirements (30.3 <a href="https://wg21.link/time.clock.req">[time.clock.req]</a>).
<p/>

<ins>-?- Functions that specify a timeout, will throw if, during the execution of this function,
a clock, time point, or time duration throws an exception. [ <i>Note</i>: instantiations of clock,
time point and duration types supplied by the implementation as specified in 30.7 <a href="https://wg21.link/time.clock">[time.clock]</a>
do not throw exceptions. &mdash; <i>end note</i>]</ins>
</p>
</blockquote>
</li>


<li><p>Change 32.4.5 <a href="https://wg21.link/thread.thread.this">[thread.thread.this]</a> as indicated:</p>

<blockquote><pre>
template &lt;class Clock, class Duration&gt;
  void sleep_until(const chrono::time_point&lt;Clock, Duration&gt;&amp; abs_time);;
</pre><blockquote>
<p>
-4- <i>Effects</i>: Blocks the calling thread for the absolute timeout (32.2.4 <a href="https://wg21.link/thread.req.timing">[thread.req.timing]</a>) specified by <code>abs_time</code>.
<p/>
-5- <i>Synchronization</i>: None.
<p/>
-6- <i>Throws</i>: <ins>timeout-related exceptions (32.2.4 <a href="https://wg21.link/thread.req.timing">[thread.req.timing]</a>).</ins><del>Nothing if 
<code>Clock</code> satisfies the <code>TrivialClock</code> requirements (30.3 <a href="https://wg21.link/time.clock.req">[time.clock.req]</a>) and 
operations of <code>Duration</code> do not throw exceptions. [ <i>Note</i>: instantiations of time point types 
and clocks supplied by the implementation as specified in 30.7 <a href="https://wg21.link/time.clock">[time.clock]</a> do not throw 
exceptions. &mdash; <i>end note</i>]</del>
</p>
</blockquote></blockquote>

<blockquote><pre>
template &lt;class Rep, class Period&gt;
  void sleep_for(const chrono::duration&lt;Rep, Period&gt;&amp; rel_time);;
</pre><blockquote>
<p>
-7- <i>Effects</i>: Blocks the calling thread for the relative timeout (32.2.4 <a href="https://wg21.link/thread.req.timing">[thread.req.timing]</a>) specified by <code>rel_time</code>.
<p/>
-8- <i>Synchronization</i>: None.
<p/>
-9- <i>Throws</i>: <ins>timeout-related exceptions (32.2.4 <a href="https://wg21.link/thread.req.timing">[thread.req.timing]</a>).</ins><del>Nothing 
if operations of <code>chrono::duration&lt;Rep, Period&gt;</code> do not throw exceptions. 
[ <i>Note</i>: instantiations of time point types and clocks supplied by the implementation
as specified in 30.7 <a href="https://wg21.link/time.clock">[time.clock]</a> do not throw exceptions. &mdash; <i>end note</i>]</del>
</p>
</blockquote></blockquote>

</li>

<li><p>Change 32.6.4.3 <a href="https://wg21.link/thread.timedmutex.requirements">[thread.timedmutex.requirements]</a> as indicated:</p>

<p>
-3- The expression <code>m.try_lock_for(rel_time)</code> shall be well-formed and have the following semantics:
<p/>
[&hellip;]
<p/>
-5- <i>Effects</i>: The function attempts to obtain ownership of the mutex within the relative timeout (32.2.4 <a href="https://wg21.link/thread.req.timing">[thread.req.timing]</a>)
specified by <code>rel_time</code>. If the time specified by <code>rel_time</code> is less than or equal to <code>rel_time.zero()</code>, the
function attempts to obtain ownership without blocking (as if by calling <code>try_lock()</code>). The function
shall return within the timeout 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/>
[&hellip;]
<p/>
-8- <i>Synchronization</i>: If <code>try_lock_for()</code> returns <code>true</code>, prior <code>unlock()</code> operations on the same object
<i>synchronize with</i> (6.10.2 <a href="https://wg21.link/intro.multithread">[intro.multithread]</a>) this operation.
<p/>
-9- <i>Throws</i>: <ins>timeout-related exceptions (32.2.4 <a href="https://wg21.link/thread.req.timing">[thread.req.timing]</a>).</ins><del>Nothing</del>.
<p/>
-10- The expression <code>m.try_lock_until(abs_time)</code> shall be well-formed and have the following semantics:
<p/>
[&hellip;]
<p/>
-12- <i>Effects</i>: The function attempts to obtain ownership of the mutex. 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 absolute timeout (32.2.4 <a href="https://wg21.link/thread.req.timing">[thread.req.timing]</a>) 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/>
[&hellip;]
<p/>
-15- <i>Synchronization</i>: If <code>try_lock_until()</code> returns true, prior <code>unlock()</code> operations on the same object
<i>synchronize with</i> (6.10.2 <a href="https://wg21.link/intro.multithread">[intro.multithread]</a>) this operation.
<p/>
-16- <i>Throws</i>: <ins>timeout-related exceptions (32.2.4 <a href="https://wg21.link/thread.req.timing">[thread.req.timing]</a>).</ins><del>Nothing</del>.
</p>
</li>

<li><p>Change 32.7.4 <a href="https://wg21.link/thread.condition.condvar">[thread.condition.condvar]</a> as indicated:</p>

<blockquote><pre>
template &lt;class Predicate&gt;
  void wait(unique_lock&lt;mutex&gt;&amp; lock, Predicate pred);
</pre><blockquote>
<p>
[&hellip;]
<p/>
-15- <i>Effects</i>: <ins>Equivalent to:</ins>
</p>
<blockquote><pre>
while (!pred())
  wait(lock);
</pre></blockquote>
<p>
[&hellip;]
<p/>
-17- <i>Throws</i>: <code>std::system_error</code> when an exception is required (32.2.2 <a href="https://wg21.link/thread.req.exception">[thread.req.exception]</a>)<ins>, 
timeout-related exceptions (32.2.4 <a href="https://wg21.link/thread.req.timing">[thread.req.timing]</a>), or any exception thrown by <code>pred</code></ins>.
<p/>
[&hellip;]
</p>
</blockquote></blockquote>

<blockquote><pre>
template &lt;class Clock, class Duration&gt;
  cv_status wait_until(unique_lock&lt;mutex&gt;&amp; lock,
                       const chrono::time_point&lt;Clock, Duration&gt;&amp; abs_time);
</pre><blockquote>
<p>
[&hellip;]
<p/>
-23- <i>Throws</i>: <code>system_error</code> when an exception is required (32.2.2 <a href="https://wg21.link/thread.req.exception">[thread.req.exception]</a>)
<ins>or timeout-related exceptions (32.2.4 <a href="https://wg21.link/thread.req.timing">[thread.req.timing]</a>)</ins>.
<p/>
[&hellip;]
</p>
</blockquote></blockquote>

<blockquote><pre>
template &lt;class Rep, class Period&gt;
  cv_status wait_for(unique_lock&lt;mutex&gt;&amp; lock,
                     const chrono::duration&lt;Rep, Period&gt;&amp; rel_time);
</pre><blockquote>
<p>
[&hellip;]
<p/>
-26- <i>Effects</i>: <del>as if</del><ins>Equivalent to:</ins>
</p>
<blockquote><pre>
return wait_until(lock, chrono::steady_clock::now() + rel_time);
</pre></blockquote>
<p>
[&hellip;]
<p/>
-29- <i>Throws</i>: <code>system_error</code> when an exception is required (32.2.2 <a href="https://wg21.link/thread.req.exception">[thread.req.exception]</a>)
<ins>or timeout-related exceptions (32.2.4 <a href="https://wg21.link/thread.req.timing">[thread.req.timing]</a>)</ins>.
<p/>
[&hellip;]
</p>
</blockquote></blockquote>

<blockquote><pre>
template &lt;class Clock, class Duration, class Predicate&gt;
  bool wait_until(unique_lock&lt;mutex&gt;&amp; lock,
                  const chrono::time_point&lt;Clock, Duration&gt;&amp; abs_time,
                  Predicate pred);
</pre><blockquote>
<p>
[&hellip;]
<p/>
-32- <i>Effects</i>: <ins>Equivalent to:</ins>
</p>
<blockquote><pre>
while (!pred())
  if (wait_until(lock, abs_time) == cv_status::timeout)
    return pred();
return true;
</pre></blockquote>
<p>
<del>-33- <i>Returns</i>: <code>pred()</code></del>
<p/>
[&hellip;]
<p/>
-36- <i>Throws</i>: <code>std::system_error</code> when an exception is required (32.2.2 <a href="https://wg21.link/thread.req.exception">[thread.req.exception]</a>)<ins>, 
timeout-related exceptions (32.2.4 <a href="https://wg21.link/thread.req.timing">[thread.req.timing]</a>), or any exception thrown by <code>pred</code></ins>.
<p/>
[&hellip;]
</p>
</blockquote></blockquote>

<blockquote><pre>
template &lt;class Rep, class Period, class Predicate&gt;
  bool wait_for(unique_lock&lt;mutex&gt;&amp; lock,
                const chrono::duration&lt;Rep, Period&gt;&amp; rel_time,
                Predicate pred);
</pre><blockquote>
<p>
[&hellip;]
<p/>
-39- <i>Effects</i>: <del>as if</del><ins>Equivalent to:</ins>
</p>
<blockquote><pre>
return wait_until(lock, chrono::steady_clock::now() + rel_time, std::move(pred));
</pre></blockquote>
<p>
[&hellip;]
<p/>
<del>-42- <i>Returns</i>: <code>pred()</code></del>
<p/>
[&hellip;]
<p/>
-44- <i>Throws</i>: <code>system_error</code> when an exception is required (32.2.2 <a href="https://wg21.link/thread.req.exception">[thread.req.exception]</a>)<ins>, 
timeout-related exceptions (32.2.4 <a href="https://wg21.link/thread.req.timing">[thread.req.timing]</a>), or any exception thrown by <code>pred</code></ins>.
<p/>
[&hellip;]
</p>
</blockquote></blockquote>

</li>

<li><p>Change 32.7.5 <a href="https://wg21.link/thread.condition.condvarany">[thread.condition.condvarany]</a> as indicated:</p>

<blockquote><pre>
template &lt;class Lock, class Predicate&gt;
  void wait(Lock&amp; lock, Predicate pred);
</pre><blockquote>
<p>
-14- <i>Effects</i>: <ins>Equivalent to:</ins>
</p>
<blockquote><pre>
while (!pred())
  wait(lock);
</pre></blockquote>
</blockquote></blockquote>

<blockquote><pre>
template &lt;class Lock, class Clock, class Duration&gt;
  cv_status wait_until(Lock&amp; lock, const chrono::time_point&lt;Clock, Duration&gt;&amp; abs_time);
</pre><blockquote>
<p>
[&hellip;]
<p/>
-18- <i>Throws</i>: <code>system_error</code> when an exception is required (32.2.2 <a href="https://wg21.link/thread.req.exception">[thread.req.exception]</a>)
<ins>or any timeout-related exceptions (32.2.4 <a href="https://wg21.link/thread.req.timing">[thread.req.timing]</a>)</ins>.
<p/>
[&hellip;]
</p>
</blockquote></blockquote>

<blockquote><pre>
template &lt;class Lock, class Rep, class Period&gt;
  cv_status wait_for(Lock&amp; lock, const chrono::duration&lt;Rep, Period&gt;&amp; rel_time);
</pre><blockquote>
<p>
[&hellip;]
<p/>
-20- <i>Effects</i>: <del>as if</del><ins>Equivalent to:</ins>
</p>
<blockquote><pre>
return wait_until(lock, chrono::steady_clock::now() + rel_time);
</pre></blockquote>
<p>
[&hellip;]
<p/>
-23- <i>Throws</i>: <code>system_error</code> when an exception is required (32.2.2 <a href="https://wg21.link/thread.req.exception">[thread.req.exception]</a>)
<ins>or any timeout-related exceptions (32.2.4 <a href="https://wg21.link/thread.req.timing">[thread.req.timing]</a>)</ins>.
<p/>
[&hellip;]
</p>
</blockquote></blockquote>

<blockquote><pre>
template &lt;class Lock, class Clock, class Duration, class Predicate&gt;
  bool wait_until(Lock&amp; lock, const chrono::time_point&lt;Clock, Duration&gt;&amp; abs_time, Predicate pred);
</pre><blockquote>
<p>
-25- <i>Effects</i>: <ins>Equivalent to:</ins>
</p>
<blockquote><pre>
while (!pred())
  if (wait_until(lock, abs_time) == cv_status::timeout)
    return pred();
return true;
</pre></blockquote>
<p>
-26- <del><i>Returns</i>: <code>pred()</code></del><ins>[<i>Note</i>: There is no blocking if <code>pred()</code> is initially <code>true</code>, 
or if the timeout has already expired. &mdash; <i>end note</i>]</ins>
<p/>
-27- [<i>Note</i>: The returned value indicates whether the predicate evaluates to <code>true</code> regardless of whether the
timeout was triggered. <i>end note</i>]
</p>
</blockquote></blockquote>

<blockquote><pre>
template &lt;class Lock, class Rep, class Period, class Predicate&gt;
  bool wait_for(Lock&amp; lock, const chrono::duration&lt;Rep, Period&gt;&amp; rel_time, Predicate pred);
</pre><blockquote>
<p>
-28- <i>Effects</i>: <del>as if</del><ins>Equivalent to:</ins>
</p>
<blockquote><pre>
return wait_until(lock, chrono::steady_clock::now() + rel_time, std::move(pred));
</pre></blockquote>
<p>
<del>-29- [<i>Note</i>: There is no blocking if <code>pred()</code> is initially <code>true</code>, 
even if the timeout has already expired. &mdash; <i>end note</i>]</del>
<del>-30- <i>Postcondition</i>: <code>lock</code> is locked by the calling thread.</del>
<p/>
<del>-31- <i>Returns</i>: <code>pred()</code></del>
<p/>
<del>-32- [<i>Note</i>: The returned value indicates whether the predicate evaluates to <code>true</code> 
regardless of whether the timeout was triggered. &mdash; <i>end note</i>]</del>
<p/>
<del>-33- <i>Throws</i>: <code>system_error</code> when an exception is required (32.2.2 <a href="https://wg21.link/thread.req.exception">[thread.req.exception]</a>).</del>
<p/>
<del>-34- <i>Error conditions</i>:</del>
</p>
<ul>
<li><del>equivalent error condition from <code>lock.lock()</code> or <code>lock.unlock()</code>.</del></li>
</ul>
</blockquote></blockquote>

</li>
</ol>





</body>
</html>
