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-suppliedLockable
objects. Such an object must support the member functions specified for either theLockable
Requirements or theTimedLockable
requirements as appropriate to acquire or release ownership of alock
by 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
Lockable
type, the following expressions must be supported, with the specified semantics, wherem
denotes a value of typeL
that 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:
void
The 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:
true
if the lock was acquired,false
otherwise.The expression
m.unlock()
shall be well-formed and have the following semantics:
- Effects:
- Release a lock on
m
held by the current thread.- Return type:
void
- Throws:
- Nothing if the current thread holds a lock on
m
.30.2.5.2
TimedLockable
RequirementsFor a type to qualify as
TimedLockable
it must meet theLockable
requirements, and additionally the following expressions must be well-formed, with the specified semantics, wherem
is an instance of a typeTL
that supports theTimedLockable
requirements,rel_time
denotes instantiation ofduration
(30.5 [time.duration]) andabs_time
denotes 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:
true
if the lock was acquired,false
otherwise.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:
true
if the lock was acquired,false
otherwise.
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 mutex types supplied by the C++ standard library.The template definitions in the C++ standard library referThese types shall conform to the namedMutex
requirements whose details are set out below. In this description,m
is an object ofaone of the standard library mutex typesMutex
typestd::mutex
,std::recursive_mutex
,std::timed_mutex
orstd::recursive_timed_mutex
..
Add the following paragraph after 32.6.4 [thread.mutex.requirements] paragraph 2:
A
Mutex
type shall conform to theLockable
requirements (30.2.5.1).
Replace 32.6.4.3 [thread.timedmutex.requirements] paragraph 1 with the following:
The C++ standard library
TimedMutex
typesstd::timed_mutex
andstd::recursive_timed_mutex
Ashall meet the requirements for aTimedMutex
typeMutex
type. In addition,itthey shall meet the requirements set outin this Clause 30.4.2below, whererel_time
denotes an instantiation ofduration
(30.5 [time.duration]) andabs_time
denotes an instantiation oftime_point
(30.6 [time.point]).
Add the following paragraph after 32.6.4.3 [thread.timedmutex.requirements] paragraph 1:
A
TimedMutex
type shall conform to theTimedLockable
requirements (30.2.5.1).
Add the following paragraph following 32.6.5.2 [thread.lock.guard] paragraph 1:
The supplied
Mutex
type shall meet theLockable
requirements (30.2.5.1).
Add the following paragraph following 32.6.5.4 [thread.lock.unique] paragraph 1:
The supplied
Mutex
type shall meet theLockable
requirements (30.2.5.1).unique_lock<Mutex>
meets theLockable
requirements. IfMutex
meets theTimedLockable
requirements (30.2.5.2) thenunique_lock<Mutex>
also meets theTimedLockable
requirements.
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
mutexlockable object and may unlock themutexlockable object during the lock's destruction (such as when leaving block scope). A thread of execution may use a lock to aid in managingmutexownership of a lockable object in an exception safe manner. A lock is said to own amutexlockable object if it is currently managing the ownership of thatmutexlockable object for a thread of execution. A lock does not manage the lifetime of themutexlockable object it references. [ Note: Locks are intended to ease the burden of unlocking themutexlockable object under 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
mutexlockable object during the lock's constuction.
32.6.5.2 [thread.lock.guard] paragaph 1:
1 An object of type
lock_guard
controls the ownership of amutexlockable object within a scope. Alock_guard
object maintains ownership of amutexlockable object throughout thelock_guard
object's lifetime. The behavior of a program is undefined if themutexlockable object referenced bypm
does not exist for the entire lifetime (3.8) of thelock_guard
object.Mutex
shall meet theLockable
requirements (30.2.5.1).
32.6.5.4 [thread.lock.unique] paragaph 1:
1 An object of type
unique_lock
controls the ownership of amutexlockable object within a scope.MutexoOwnership of the lockable object may be acquired at construction or after construction, and may be transferred, after acquisition, to anotherunique_lock
object. Objects of typeunique_lock
are not copyable but are movable. The behavior of a program is undefined if the contained pointerpm
is not null and the mutex pointed to bypm
does not exist for the entire remaining lifetime (3.8) of theunique_lock
object.Mutex
shall meet theLockable
requirements (30.2.5.1).
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_type
is not a recursive mutex the calling thread does not own the mutex. The suppliedmutex_type
type shall meet theTimedLockable
requirements (30.2.5.2).
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_type
is not a recursive mutex the calling thread does not own the mutex. The suppliedmutex_type
type shall meet theTimedLockable
requirements (30.2.5.2).
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);Requires: The supplied
mutex_type
type shall meet theTimedLockable
requirements (30.2.5.2).
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);Requires: The supplied
mutex_type
type shall meet theTimedLockable
requirements (30.2.5.2).
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
requirements (30.2.5.1).
MutexLockable, except that a call to[Note: Thetry_lock()
may throw an exception.unique_lock
class 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
Mutex
requirements (30.2.5.1).MutexLockable, except that a call to[Note: Thetry_lock()
may throw an exception.unique_lock
class template meets these requirements when suitably instantiated. — end note]
Replace 32.7.5 [thread.condition.condvarany] paragraph 1 with:
1 A
Lock
type shall meet therequirements for aMutex
typeLockable
requirements (30.2.5.1), except thattry_lock
is not required. [Note: All of the standard mutex types meet this requirement. — end note]