This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of Resolved status.
Section: 32.6 [thread.mutex] Status: Resolved Submitter: Anthony Williams Opened: 2009-11-17 Last modified: 2016-01-28
Priority: Not Prioritized
View all other issues in [thread.mutex].
View all issues with Resolved status.
Discussion:
The Mutex requirements in 32.6.4 [thread.mutex.requirements] and
32.6.4.3 [thread.timedmutex.requirements] confuse the requirements on the
behaviour of std::mutex et al with the requirements on
Lockable types for use with std::unique_lock,
std::lock_guard and std::condition_variable_any.
[ 2010 Pittsburgh: ]
Concepts of threads chapter and issue presentation are: Lockable < Mutex < TimedMutex and Lockable < TimedLockable < TimedMutex.
Typo in failed deletion of Mutex in 30.4.4 p4 edits.
Lockable requirements are too weak for condition_variable_any, but the Mutex requirements are too strong.
Need subset of Lockable requirements for condition_variable_any that does not include try_lock. E.g. CvLockable < Lockable.
Text needs updating to recent draft changes.
Needs to specify exception behavior in Lockable.
The current standard is fine for what it says, but it places requirements that are too strong on authors of mutexes and locks.
Move to open status. Suggest Anthony look at condition_variable_any requirements. Suggest Anthony refine requirements/concepts categories.
[ 2010-03-28 Daniel synced with N3092. ]
[ 2010-10-25 Daniel adds: ]
Accepting n3130 would solve this issue.
[ 2010-11 Batavia: ]
Resolved by adopting n3197.
Proposed resolution:
Add a new section to 32.2 [thread.req] after 32.2.4 [thread.req.timing] as follows:
30.2.5 Requirements for Lockable types
The standard library templates
unique_lock(32.6.5.4 [thread.lock.unique]),lock_guard(32.6.5.2 [thread.lock.guard]),lock,try_lock(32.6.6 [thread.lock.algorithm]) andcondition_variable_any(32.7.5 [thread.condition.condvarany]) all operate on user-suppliedLockableobjects. Such an object must support the member functions specified for either theLockableRequirements or theTimedLockablerequirements as appropriate to acquire or release ownership of alockby a giventhread. [Note: the nature of any lock ownership and any synchronization it may entail are not part of these requirements. — end note]30.2.5.1 Lockable Requirements
In order to qualify as a
Lockabletype, the following expressions must be supported, with the specified semantics, wheremdenotes a value of typeLthat supports theLockable:The expression
m.lock()shall be well-formed and have the following semantics:
- Effects:
- Block until a lock can be acquired for the current thread.
- Return type:
voidThe expression
m.try_lock()shall be well-formed and have the following semantics:
- Effects:
- Attempt to acquire a lock for the current thread without blocking.
- Return type:
bool- Returns:
trueif the lock was acquired,falseotherwise.The expression
m.unlock()shall be well-formed and have the following semantics:
- Effects:
- Release a lock on
mheld by the current thread.- Return type:
void- Throws:
- Nothing if the current thread holds a lock on
m.30.2.5.2
TimedLockableRequirementsFor a type to qualify as
TimedLockableit must meet theLockablerequirements, and additionally the following expressions must be well-formed, with the specified semantics, wheremis an instance of a typeTLthat supports theTimedLockablerequirements,rel_timedenotes instantiation ofduration(30.5 [time.duration]) andabs_timedenotes an instantiation oftime_point(30.6 [time.point])The expression
m.try_lock_for(rel_time)shall be well-formed and have the following semantics:
- Effects:
- Attempt to acquire a lock for the current thread within the specified time period.
- Return type:
bool- Returns:
trueif the lock was acquired,falseotherwise.The expression
m.try_lock_until(abs_time)shall be well-formed and have the following semantics:
- Effects:
- Attempt to acquire a lock for the current thread before the specified point in time.
- Return type:
bool- Returns:
trueif the lock was acquired,falseotherwise.
Replace 32.6.4 [thread.mutex.requirements] paragraph 2 with the following:
2 This section describes requirements on
template argument types used to instantiate templates defined inthe C++ standard library.The template definitions in the C++ standard library referThese types shall conform to the namedMutexrequirements whose details are set out below. In this description,mis an object ofa.Mutextype
Add the following paragraph after 32.6.4 [thread.mutex.requirements] paragraph 2:
Replace 32.6.4.3 [thread.timedmutex.requirements] paragraph 1 with the following:
Ashall meet the requirements for aTimedMutextypeMutextype. In addition,itshall meet the requirements set outin this Clause 30.4.2, whererel_timedenotes an instantiation ofduration(30.5 [time.duration]) andabs_timedenotes an instantiation oftime_point(30.6 [time.point]).
Add the following paragraph after 32.6.4.3 [thread.timedmutex.requirements] paragraph 1:
Add the following paragraph following 32.6.5.2 [thread.lock.guard] paragraph 1:
Add the following paragraph following 32.6.5.4 [thread.lock.unique] paragraph 1:
Replace the use of "mutex" or "mutex object" with "lockable object" throughout clause 32.6.5 [thread.lock] paragraph 1:
1 A lock is an object that holds a reference to a
mutexand may unlock themutexduring the lock's destruction (such as when leaving block scope). A thread of execution may use a lock to aid in managingmutexownership in an exception safe manner. A lock is said to own amutexif it is currently managing the ownership of thatmutexfor a thread of execution. A lock does not manage the lifetime of themutexit references. [ Note: Locks are intended to ease the burden of unlocking themutexunder both normal and exceptional circumstances. — end note ]
32.6.5 [thread.lock] paragaph 2:
2 Some lock constructors take tag types which describe what should be done with the
mutexobject during the lock's constuction.
32.6.5.2 [thread.lock.guard] paragaph 1:
1 An object of type
lock_guardcontrols the ownership of amutexobject within a scope. Alock_guardobject maintains ownership of amutexobject throughout thelock_guardobject's lifetime. The behavior of a program is undefined if themutexreferenced bypmdoes not exist for the entire lifetime (3.8) of thelock_guardobject.
32.6.5.4 [thread.lock.unique] paragaph 1:
1 An object of type
unique_lockcontrols the ownership of amutexwithin a scope.Mutexownership may be acquired at construction or after construction, and may be transferred, after acquisition, to anotherunique_lockobject. Objects of typeunique_lockare not copyable but are movable. The behavior of a program is undefined if the contained pointerpmis not null and the mutex pointed to bypmdoes not exist for the entire remaining lifetime (3.8) of theunique_lockobject.
Add the following to the precondition of unique_lock(mutex_type&
m, const chrono::time_point<Clock, Duration>& abs_time) in
32.6.5.4.2 [thread.lock.unique.cons] paragraph 18:
template <class Clock, class Duration> unique_lock(mutex_type& m, const chrono::time_point<Clock, Duration>& abs_time);18 Requires: If
mutex_typeis not a recursive mutex the calling thread does not own the mutex.
Add the following to the precondition of unique_lock(mutex_type&
m,
const chrono::duration<Rep, Period>& rel_time) in
32.6.5.4.2 [thread.lock.unique.cons]
paragraph 22
22 Requires: If
mutex_typeis not a recursive mutex the calling thread does not own the mutex.
Add the following as a precondition of bool try_lock_until(const
chrono::time_point<Clock, Duration>& abs_time) before
32.6.5.4.3 [thread.lock.unique.locking] paragraph 8
template <class Clock, class Duration> bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
Add the following as a precondition of bool try_lock_for(const
chrono::duration<Rep, Period>& rel_time) before
32.6.5.4.3 [thread.lock.unique.locking] paragraph 12
template <class Rep, class Period> bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
Replace 32.6.6 [thread.lock.algorithm] p1 with the following:
template <class L1, class L2, class... L3> int try_lock(L1&, L2&, L3&...);1 Requires: Each template parameter type shall meet the
requirementsMutex, except that a call to[Note: Thetry_lock()may throw an exception.unique_lockclass template meets these requirements when suitably instantiated. — end note]
Replace 32.6.6 [thread.lock.algorithm] p4 with the following:
template <class L1, class L2, class... L3> void lock(L1&, L2&, L3&...);4 Requires: Each template parameter type shall meet the
MutexrequirementsMutex, except that a call to[Note: Thetry_lock()may throw an exception.unique_lockclass template meets these requirements when suitably instantiated. — end note]
Replace 32.7.5 [thread.condition.condvarany] paragraph 1 with:
1 A
Locktype shall meet therequirements for a, except thatMutextypetry_lockis not required. [Note: All of the standard mutex types meet this requirement. — end note]