lock()
postcondition can not be generally achievedSection: 32.7 [thread.condition] Status: C++11 Submitter: Switzerland Opened: 2010-08-25 Last modified: 2016-01-28
Priority: Not Prioritized
View all other issues in [thread.condition].
View all issues with C++11 status.
Discussion:
Addresses CH-30
If lock.lock()
throws an exception, the postcondition can not be generally achieved.
[ Resolution proposed by ballot comment: ]
Either state that the postcondition might not be achieved, depending on the error condition, or state that
terminate()
is called in this case.
[ 2010-08-13 Peter Sommerlad comments and provides wording ]
32.7.4 [thread.condition.condvar], 32.7.5 [thread.condition.condvarany]
p. 13, last bullet, and corresponding paragraphs in all wait functions Problem:
Condition variable wait might fail, because the lock cannot be acquired when notified. CH-30 says: "If lock.lock() throws an exception, the postcondition can not be generally achieved." CH-30 proposes: "Either state that the postcondition might not be achieved, depending on the error condition, or state that terminate() is called in this case." The discussion in Rapperswil concluded that callingterminate()
might be too drastic in this case and a corresponding exception should be thrown/passed on and one should use a lock type that allows querying its status, whichunique_lock
allows forstd::condition_variable
We also had some additional observations while discussing in Rapperswil:
- in 32.7.4 [thread.condition.condvar]
wait
with predicate andwait_until
with predicate lack the precondition, postcondition and Error conditions sections. the lack of the precondition would allow to callpred()
without holding the lock.- in 32.7.4 [thread.condition.condvar]
wait_until
andwait_for
and 32.7.5 [thread.condition.condvarany]wait_for
still specify an error condition for a violated precondition. This should be removed.and add the following proposed solution:
[2011-02-27: Daniel adapts numbering to n3225]
Proposed resolution:
void wait(unique_lock<mutex>& lock);
[..]9 Requires:
lock
.owns_lock()
istrue
andlock.mutex()
is locked by the calling thread, and either
- no other thread is waiting on this
condition_variable
object orlock.mutex()
returns the same value for each of thelock
arguments supplied by all concurrently waiting (viawait
ortimed_wait
) threads.
[..]11 Postcondition:
lock
.owns_lock()
istrue
andlock.mutex()
is locked by the calling thread.
template <class Predicate> void wait(unique_lock<mutex>& lock, Predicate pred);
?? Requires:
lock.owns_lock()
istrue
andlock.mutex()
is locked by the calling thread, and either
- no other thread is waiting on this
condition_variable
object orlock.mutex()
returns the same value for each of thelock
arguments supplied by all concurrently waiting (viawait
ortimed_wait
) threads.
14 Effects:
while (!pred()) wait(lock);
?? Postcondition:
lock.owns_lock()
istrue
andlock.mutex()
is locked by the calling thread.
?? Throws:
std::system_error
when an exception is required (30.2.2).
?? Error conditions:
- equivalent error condition from
lock.lock()
orlock.unlock()
.
template <class Clock, class Duration> cv_status wait_until(unique_lock<mutex>& lock, const chrono::time_point<Clock, Duration>& abs_time);
15 Requires:
lock
.owns_lock()
istrue
andlock.mutex()
is locked by the calling thread, and either
- no other thread is waiting on this
condition_variable
object orlock.mutex()
returns the same value for each of thelock
arguments supplied by all concurrently waiting (viawait
,wait_for
, orwait_until
) threads.
[..]
[..]17 Postcondition:
lock
.owns_lock()
istrue
andlock.mutex()
is locked by the calling thread.
20 Error conditions:
operation_not_permitted
— if the thread does not own the lock.- equivalent error condition from
lock.lock()
orlock.unlock()
.
template <class Rep, class Period> cv_status wait_for(unique_lock<mutex>& lock, const chrono::duration<Rep, Period>& rel_time);
21 Requires:
lock
.owns_lock()
istrue
andlock.mutex()
is locked by the calling thread, and either
- no other thread is waiting on this
condition_variable
object orlock.mutex()
returns the same value for each of thelock
arguments supplied by all concurrently waiting (viawait
,wait_for
, orwait_until
) threads.
[..]
[..]24 Postcondition:
lock
.owns_lock()
istrue
andlock.mutex()
is locked by the calling thread.
26 Error conditions:
operation_not_permitted
— if the thread does not own the lock.- equivalent error condition from
lock.lock()
orlock.unlock()
.
template <class Clock, class Duration, class Predicate> bool wait_until(unique_lock<mutex>& lock, const chrono::time_point<Clock, Duration>& abs_time, Predicate pred);
?? Requires:
lock.owns_lock()
istrue
andlock.mutex()
is locked by the calling thread, and either
- no other thread is waiting on this
condition_variable
object orlock.mutex()
returns the same value for each of thelock
arguments supplied by all concurrently waiting (viawait
ortimed_wait
) threads.
27 Effects:
while (!pred()) if (wait_until(lock, abs_time) == cv_status::timeout) return pred(); return true;
28 Returns:
pred()
?? Postcondition:
lock.owns_lock()
istrue
andlock.mutex()
is locked by the calling thread.
29 [ Note: The returned value indicates whether the predicate evaluates to true regardless of whether the timeout was triggered. — end note ]
?? Throws:
std::system_error
when an exception is required (30.2.2).
?? Error conditions:
- equivalent error condition from
lock.lock()
orlock.unlock()
.
template <class Rep, class Period, class Predicate> bool wait_for(unique_lock<mutex>& lock, const chrono::duration<Rep, Period>& rel_time, Predicate pred);
30 Requires:
lock
.owns_lock()
istrue
andlock.mutex()
is locked by the calling thread, and either
- no other thread is waiting on this
condition_variable
object orlock.mutex()
returns the same value for each of thelock
arguments supplied by all concurrently waiting (viawait
,wait_for
, orwait_until
) threads.
[..]
33 Postcondition:
lock
.owns_lock()
istrue
andlock.mutex()
is locked by the calling thread.
[..]
37 Error conditions:
operation_not_permitted
— if the thread does not own the lock.- equivalent error condition from
lock.lock()
orlock.unlock()
.
template <class Lock, class Predicate> void wait(Lock& lock, Predicate pred);
[Note: if any of the wait functions exits with an exception it is indeterminate if the
Lock
is held. One can use aLock
type that allows to query that, such as theunique_lock
wrapper. — end note]
11 Effects:
while (!pred()) wait(lock);
[..]
31 Error conditions:
operation_not_permitted
— if the thread does not own the lock.- equivalent error condition from
lock.lock()
orlock.unlock()
.