1498. Unclear specification for [thread.condition]

Section: 33.5 [thread.condition] Status: Resolved Submitter: Switzerland Opened: 2010-08-25 Last modified: 2016-02-10

Priority: Not Prioritized

View all other issues in [thread.condition].

View all issues with Resolved status.

Discussion:

Addresses CH-29

It is unclear if a spurious wake-up during the loop and reentering of the blocked state due to a repeated execution of the loop will adjust the timer of the blocking with the respect to the previously specified rel_time value.

[ Resolution proposed by ballot comment: ]

Make it clear (e.g. by a note) that when reexecuting the loop the waiting time when blocked will be adjusted with respect to the elapsed time of the previous loop executions.

[ 2010-08-13 Peter Sommerlad comments and provides wording: ]

Problem: It is unclear if a spurious wake-up during the loop and re-entering of the blocked state due to a repeated execution of the loop will adjust the timer of the blocking with the respect to the previously specified rel_time value.

Proposed Resolution from CH29:

Make it clear (e.g. by a note) that when re-executing the loop the waiting time when blocked will be adjusted with respect to the elapsed time of the previous loop executions.

Discussion in Rapperswil:

Assuming the introduction of a mandatory steady_clock proposed by US-181 to the FCD the specification of condition_variable::wait_for can be defined in terms of wait_until using the steady_clock. This is also interleaving with US-181, because that touches the same paragraph (30.5.1 p 25, p34 and 30.5.2 p 20, p 28 in n3092.pdf)

(The "as if" in the proposed solutions should be confirmed by the standardization terminology experts)

[ 2010-11 Batavia: Resolved by applying n3191 ]

  1. Change 33.5.3 [thread.condition.condvar] paragraph 25, wait_for Effects as indicated:
    template <class Rep, class Period>
    cv_status wait_for(unique_lock<mutex>& lock,
      const chrono::duration<Rep, Period>& rel_time);
    

    [..]

    25 Effects: as if

    return wait_until(lock, chrono::steady_clock::now() + rel_time);
    
    • Atomically calls lock.unlock() and blocks on *this.
    • When unblocked, calls lock.lock() (possibly blocking on the lock), then returns.
    • The function will unblock when signaled by a call to notify_one() or a call to notify_all(), by the elapsed time rel_time passing (30.2.4), or spuriously.
    • If the function exits via an exception, lock.lock() shall be called prior to exiting the function scope.
  2. Change 33.5.3 [thread.condition.condvar] paragraph 34, wait_for with predicate Effects as indicated:
    template <class Rep, class Period, class Predicate>
    bool wait_for(unique_lock<mutex>& lock,
      const chrono::duration<Rep, Period>& rel_time,
      Predicate pred);
    

    [..]

    34 Effects: as if

    return wait_until(lock, chrono::steady_clock::now() + rel_time, std::move(pred));
    
    • Executes a loop: Within the loop the function first evaluates pred() and exits the loop if the result is true.
    • Atomically calls lock.unlock() and blocks on *this.
    • When unblocked, calls lock.lock() (possibly blocking on the lock).
    • The function will unblock when signaled by a call to notify_one() or a call to notify_all(), by the elapsed time rel_time passing (30.2.4), or spuriously.
    • If the function exits via an exception, lock.lock() shall be called prior to exiting the function scope.
    • The loop terminates when pred() returns true or when the time duration specified by rel_time has elapsed.
  3. Change 33.5.4 [thread.condition.condvarany] paragraph 20, wait_for Effects as indicated:
    template <class Lock, class Rep, class Period>
    cv_status wait_for(Lock& lock, const chrono::duration<Rep, Period>& rel_time);
    

    20 Effects: as if

    return wait_until(lock, chrono::steady_clock::now() + rel_time);
    
    • Atomically calls lock.unlock() and blocks on *this.
    • When unblocked, calls lock.lock() (possibly blocking on the lock), then returns.
    • The function will unblock when signaled by a call to notify_one() or a call to notify_all(), by the elapsed time rel_time passing (30.2.4), or spuriously.
    • If the function exits via an exception, lock.unlock() shall be called prior to exiting the function scope.
  4. Change 33.5.4 [thread.condition.condvarany] paragraph 28, wait_for with predicate Effects as indicated:
    template <class Lock, class Rep, class Period, class Predicate>
    bool wait_for(Lock& lock, const chrono::duration<Rep, Period>& rel_time, Predicate pred);
    

    28 Effects: as if

    return wait_until(lock, chrono::steady_clock::now() + rel_time, std::move(pred));
    
    • Executes a loop: Within the loop the function first evaluates pred() and exits the loop if the result is true.
    • Atomically calls lock.unlock() and blocks on *this.
    • When unblocked, calls lock.lock() (possibly blocking on the lock).
    • The function will unblock when signaled by a call to notify_one() or a call to notify_all(), by the elapsed time rel_time passing (30.2.4), or spuriously.
    • If the function exits via an exception, lock.unlock() shall be called prior to exiting the function scope.
    • The loop terminates when pred() returns true or when the time duration specified by rel_time has elapsed.

Proposed resolution:

Resolved by n3191.