N3961: A proposal to add shared_mutex (untimed)
Gor Nishanov (gorn@microsoft.com)
2014-02-25
At the Issaquah ISO C++ meeting of 2014 shared_mutex was renamed to shared_timed_mutex per proposal N3891 to follow the naming precedent set by timed_mutex and recursive_timed_mutex and to leave room for an untimed shared_mutex which can be more efficient on some platforms than shared_timed_mutex.
This paper introduces shared_mutex without timed locking requirement. This paper only includes the proposed wording. For background for shared locking please refer to N3568, N3659 and N3891.
Proposed wording is relative to the C++ draft that incorporated SG1 motions available in branch motions-2014-02-sg1+2.
Modify shared_mutex synopsis of [thread.mutex] as follows:
Header <shared_mutex> synopsis
namespace std {
class shared_mutex;
class shared_timed_mutex;
template <class Mutex> class shared_lock;
template <class Mutex>
void swap(shared_lock<Mutex>& x, shared_lock<Mutex>& y) noexcept;
}
Modify [thread.mutex.requirements.mutex] as follows:
Mutex types [thread.mutex.requirements.mutex]
1 The mutex types are the standard library types std::mutex, std::recursive_mutex, std::timed_mutex, std::recursive_timed_mutex, std::shared_mutex, and std::shared_timed_mutex. They shall meet the requirements set out in this section. In this description, m denotes an object of a mutex type.
6 The expression m.lock() shall be well-formed and have the following semantics:
7 Requires: If m is of type std::mutex, std::timed_mutex, std::shared_mutex, or std::shared_timed_mutex the calling thread does not own the mutex.
14 The expression m.try_lock() shall be well-formed and have the following semantics:
15 Requires: If m is of type std::mutex, std::timed_mutex, std::shared_mutex, or std::shared_timed_mutex, the calling thread does not own the mutex.
Insert a new section 30.4.1.4
[thread.sharedmutex.requirements]
30.4.1.4 Shared
mutex types [thread.sharedmutex.requirements]
1 The standard library types std::shared_mutex and std::shared_timed_mutex are shared mutex types. Shared mutex types shall meet the requirements of mutex types (30.4.1.2), and additionally shall meet the requirements set out below. In this description, m denotes an object of a mutex type.
Note to Editor: please move clauses 2-23 from [thread.sharedtimedmutex.requirements] to this point.
Excerpt from clauses 2 23 presented here for convenience of the reviewer.
2 In addition to the exclusive lock ownership mode specified in 30.4.1.2, shared
mutex types provide a shared
lock ownership mode. Multiple execution agents can simultaneously hold a shared lock ownership of a shared
mutex type. But no execution agent shall hold a shared lock while another execution agent holds an exclusive lock on the same shared mutex type, and vice-versa. The maximum number of execution agents which can
share a shared lock on a single shared mutex type is unspecified, but shall be at least 10000. If more than
the maximum number of execution agents attempt to obtain a shared lock, the excess execution agents shall
block until the number of shared locks are reduced below the maximum amount by other execution agents
releasing their shared lock.
3 The expression m.lock_shared() shall be well-formed and have the following semantics:
11 The expression m.unlock_shared() shall be well-formed and have the following semantics:
17 The expression m.try_lock_shared() shall be well-formed and have the following semantics:
23 Throws: Nothing.
Insert a new section 30.4.1.4.1 [thread.sharedmutex.class]
30.4.1.4.1 Class shared_mutex [thread.sharedmutex.class]
namespace std {
class shared_mutex {
public:
shared_mutex();
~shared_mutex();
shared_mutex(const shared_mutex&) = delete;
shared_mutex& operator=(const shared_mutex&) = delete;
// Exclusive ownership
void lock(); // blocking
bool try_lock();
// Shared ownership
void lock_shared(); // blocking
bool try_lock_shared();
void unlock_shared();
};
}
1 The class shared_mutex provides a non-recursive mutex with shared ownership semantics.
2 The class shared_mutex shall satisfy all of the requirements for shared mutexes (30.4.1.4). It shall
be a standard-layout class (Clause 9).
3 The behavior of a program is undefined if:
it destroys a shared_mutex object owned by any thread,
a thread attempts to recursively gain any ownership of a shared_mutex.
a thread terminates while possessing any ownership of a shared_mutex.
4 shared_mutex may be a synonym for shared_timed_mutex
Modify section [thread.sharedtimedmutex.requirements] as follows
30.4.1.4.2 Shared timed mutex types [thread.sharedtimedmutex.requirements]
1 The standard library type std::shared_timed_mutex is a shared timed mutex type. Shared timed mutex
types shall meet the requirements of timed mutex types (30.4.1.3), shared mutex types (30.4.1.4), and additionally shall meet the requirements set out below. In this description, m denotes an object of a mutex type, rel_type denotes an object of an instantiation of duration (20.12.5), and abs_time denotes an object of an instantiation of time_point (20.12.6).
Note to Editor, Clauses 2-23 were moved to section [thread.sharedmutex.requirements] per earlier edits, clauses 24 37 remains here properly renumbered.
Excerpt from clauses 24 37 presented here for convenience of the reviewer.
24 The expression m.try_lock_shared_for(rel_time)
shall be
well-formed and have the following semantics:
30 Throws: Timeout-related exceptions (30.2.4).
31 The expression m.try_lock_shared_until(abs_time) shall be well-formed and have the following semantics:
37
Throws: Timeout-related exceptions (30.2.4).
Modify section 30.4.1.4.1 [thread.sharedtimedmutex.class] as follows:
30.4.1.4.13 Class
shared_timed_mutex
[thread.sharedtimedmutex.class]
2 The class shared_timed_mutex
shall
satisfy all of the SharedTimedMutex requirements (30.4.1.4).
requirements for shared timed mutexes (30.4.1.4.2). It shall be a standard-layout class (Clause 9).
Many thanks to Artur Laksberg, James McNellis and Stephan T. Lavavej for their feedback and review.