<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html><head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">


<title>N3197: Lockable Requirements for C++0x</title>
<style type="text/css">
p {text-align:justify}
li {text-align:justify}
blockquote.note
{
    background-color:#E0E0E0;
    padding-left: 15px;
    padding-right: 15px;
    padding-top: 1px;
    padding-bottom: 1px;
}
ins, .inserted
{
    color: black;
    background: #a0ffa0;
    text-decoration: underline;
}
del
{
    color: black;
    background: #ffa0a0;
    text-decoration: line-through;
}
</style>
</head><body>
<table>
<tr><td>Document Number:</td><td>N3197=10-0187</td></tr>
<tr><td>Date:</td><td>2010-11-12</td></tr>
<tr><td>Author:</td><td><a href="mailto:anthony@justsoftwaresolutions.co.uk">Anthony
      Williams</a><br>Just Software Solutions Ltd</td></tr>
</table>
    <h1>N3197: Lockable requirements for C++0x</h1>

    <p>This paper revises N3130.
    It provides a proposed resolution
    for <a href="http://home.roadrunner.com/~hinnant/issue_review/lwg-active.html#1268">LWG
    issue 1268</a>, and comments GB 138, CH 26, CH27 and US 188 on the
    FCD (see N3102). The basic premise of LWG issue 1268 and GB 138 is
    that the "Mutex requirements" from the current working draft are
    worded as if they are requirements on all lockable types,
    including user-defined mutexes and instantiations
    of <code>unique_lock</code>. However, the requirements really only
    need apply to the standard mutex types such
    as <code>std::mutex</code>, and are too strong when applied to
    user-defined mutex types. Also, the requirements are worded in
    terms of threads, when they could apply equally for other
    asynchronous agents.</p>

    <p>This paper therefore proposes to separate the existing
    requirements on the standard mutex types from the general
    requirements on all lockable types. Note to editor: this paper
    should be consistent with N3128 under the assumption that they
    would both be accepted; any inconsistencies are accidental and
    unintended.</p>

    <h2>Proposed wording</h2>
<p>
Add a new section to 30.2 [thread.req] after 30.2.4 [thread.req.timing] 
as follows:
</p>

<blockquote class="inserted">
<p>
30.2.5 Requirements for Lockable types
</p>

<p>An <em>execution agent</em> is an entity, such as a thread,
that may perform work in parallel with other execution agents.
[<i>Note:</i>
Implementations or users may introduce other kinds of agents,
such as processes or thread-pool tasks.
&mdash;<i>end note</i>]
The calling agent is determined by context,
e.g. the calling thread that contains the call,
etc.</p>

<p>[<i>Note:</i>
Some lockable objects are “agent-oblivious” in that they
work for any execution-agent model because they do not determine or
store the agent’s ID (e.g., an ordinary spin-lock).
&mdash;<i>end note</i>]</p>

<p>
The standard library templates <code>unique_lock</code> (30.4.3.2 
[thread.lock.unique]), <code>lock_guard</code> (30.4.3.1 
[thread.lock.guard]), <code>lock</code>, <code>try_lock</code> (30.4.4 
[thread.lock.algorithm]) and <code>condition_variable_any</code> (30.5.2 
[thread.condition.condvarany]) all operate on user-supplied
lockable objects. Such an object must support the member
functions specified for either the <code>BasicLockable</code>
requirements, the <code>Lockable</code> requirements or the
<code>TimedLockable</code> requirements as appropriate to acquire or
release ownership of a <code>lock</code> by a given execution
agent. [<i>Note:</i> the nature of any lock ownership and any
synchronization it may entail are not part of these
requirements. — <i>end note</i>]
</p>

<p>
30.2.5.1  BasicLockable Requirements
</p>

<p>In order for a type <code>L</code> to qualify as
a <code>BasicLockable</code> type, the following expressions must be
supported, with the specified semantics, where <code>m</code> denotes a
value of type <code>L</code>:
</p>

<p>
The expression <code>m.lock()</code> shall be well-formed and have the
following semantics:
</p>

<dl>
  <dt>Effects:</dt><dd>Block until a lock can be acquired for the
  current execution agent. If an exception is thrown then a lock shall not
  have been acquired for the current execution agent.</dd>
</dl>

<p>
The expression <code>m.unlock()</code> shall be well-formed and have the
following semantics:
</p>

<dl>
  <dt>Requires:</dt><dd>The current execution agent shall hold  a lock on <code>m</code>.</dd>
  <dt>Effects:</dt><dd>Release a lock on <code>m</code> held by the current execution agent.</dd>
  <dt>Throws:</dt><dd>Nothing.</dd>
</dl>

<p>
30.2.5.2  Lockable Requirements
</p>

<p>In order for a type <code>L</code> to qualify as a <code>Lockable</code>
  type, it must meet the <code>BasicLockable</code> requirements. In
  addition, the following expressions must be supported, with the
  specified semantics, where <code>m</code> denotes a value of
  type <code>L</code>:
</p>

<p>
The expression <code>m.try_lock()</code> shall be well-formed and have the
following semantics:
</p>

<dl>
  <dt>Effects:</dt><dd>Attempt to acquire a lock for the current
  execution agent without blocking. If an exception is thrown then a lock shall
  not have been acquired for the current execution agent.</dd>
  <dt>Return type:</dt><dd><code>bool</code></dd>
  <dt>Returns:</dt><dd><code>true</code> if the lock was
  acquired, <code>false</code> otherwise.</dd>
</dl>


<p>
30.2.5.3 <code>TimedLockable</code> Requirements
</p>

<p>
For a type <code>TL</code> to qualify as <code>TimedLockable</code> it must meet the
<code>Lockable</code> requirements, and additionally the following
expressions must be well-formed, with the specified semantics,
where <code>m</code> is an instance of a
type <code>TL</code>, <code>rel_time</code> denotes instantiation
of <code>duration</code> (20.10.3 [time.duration]) and <code>abs_time</code>
denotes an instantiation of <code>time_point</code> (20.10.4 [time.point])

</p>

<p>
The expression <code>m.try_lock_for(rel_time)</code> shall be well-formed and have the
following semantics:
</p>

<dl>
  <dt>Effects:</dt><dd>Attempt to acquire a lock for the current
  execution agent within the relative timeout (30.2.4
  [thread.req.timing]) specified by <code>rel_time</code>. The
  function shall return within the timeout specified by <code>rel_time</code>
  only if it has obtained a lock on <code>m</code> for the current
  execution agent. If an exception is
  thrown then a lock shall not have been acquired for the current
  execution agent.</dd>
  <dt>Return type:</dt><dd><code>bool</code></dd>
  <dt>Returns:</dt><dd><code>true</code> if the lock was
  acquired, <code>false</code> otherwise.</dd>
</dl>

<p>
The expression <code>m.try_lock_until(abs_time)</code> shall be well-formed and have the
following semantics:
</p>

<dl>
  <dt>Effects:</dt><dd>Attempt to acquire a lock for the current
  execution agent before the absolute timeout (30.2.4
  [thread.req.timing]) specified by <code>abs_time</code>.  The
  function shall return before the timeout specified by <code>abs_time</code>
  only if it has obtained a lock on <code>m</code> for the current
  execution agent. If an exception is
  thrown then a lock shall not have been acquired for the current
  execution agent.</dd>
  <dt>Return type:</dt><dd><code>bool</code></dd>
  <dt>Returns:</dt><dd><code>true</code> if the lock was
  acquired, <code>false</code> otherwise.</dd>
</dl>
</blockquote>

<p>
Replace 30.4.1 [thread.mutex.requirements] paragraph 1 with the
following:
</p>

<blockquote><p>
1 A mutex object facilitates protection against data races and allows
<del>thread-</del>safe synchronization of data
between <del>threads</del><ins>execution agents
(30.2.5)</ins>. A <del>thread</del><ins>execution agent</ins> owns a
mutex from the time it successfully calls one of the lock functions
until it calls unlock. Mutexes may be either recursive or
non-recursive, and may grant simultaneous ownership to one or many
<del>threads</del><ins>execution agents</ins>. The mutex types
supplied by the standard library provide exclusive ownership semantics
for threads: only one thread may own the mutex at a time. Both
recursive and non-recursive mutexes are supplied.
</p></blockquote>


<p>
Replace 30.4.1 [thread.mutex.requirements] paragraph 2 with the
following:
</p>

<blockquote><p>
2 This section describes requirements on <del>template argument types
used to instantiate templates defined in</del> <ins>the mutex types
supplied by</ins> the C++ standard library. <del>The template
definitions in the C++ standard library refer</del> These types shall
conform to the <del>named <code>Mutex</code></del> requirements whose details are set
out below.  In this description, <code>m</code> is an object
of <del>a <code>Mutex</code> type</del>
<ins>one of the standard library mutex types <code>std::mutex</code>,
<code>std::recursive_mutex</code>, <code>std::timed_mutex</code> or
<code>std::recursive_timed_mutex</code>.</ins>.
</p></blockquote>

<p>
Add the following paragraph after 30.4.1 [thread.mutex.requirements]
paragraph 2:
</p>

<blockquote><p><ins>
A mutex type shall conform to the <code>Lockable</code>
requirements (30.2.5.2).
</ins></p></blockquote>

<p>Insert a new paragraph before 30.4.1 [thread.mutex.requirements]
  paragraph 7:</p>

<blockquote><p><ins><i>Requires:</i> If <code>m</code> is of
    type <code>std::mutex</code> or <code>std::timed_mutex</code> then
the calling thread does not own the mutex.</ins>
</p></blockquote>

<p>Insert a new paragraph before 30.4.1 [thread.mutex.requirements]
  paragraph 14:</p>

<blockquote><p><ins><i>Requires:</i> If <code>m</code> is of
    type <code>std::mutex</code> or <code>std::timed_mutex</code> then
the calling thread does not own the mutex.</ins>
</p></blockquote>

<p>
Replace 30.4.2 [thread.timedmutex.requirements] paragraph 1 with the
following:
</p>

<blockquote><p>
<ins>In addition to the requirements set out in
  [thread.mutex.requirements] (30.4.1), the C++ standard library
  types <code>std::timed_mutex</code>
  and <code>std::recursive_timed_mutex</code> (the <em>timed mutex
  types</em>)</ins>
<del>A <code>TimedMutex</code> type shall meet the requirements for
a <code>Mutex</code> type. In addition, it</del> shall
meet the requirements set out <del>in this Clause 30.4.2</del><ins>below</ins>,
where <code>rel_time</code> denotes an instantiation of <code>duration</code>
(20.10.3 [time.duration]) and <code>abs_time</code> denotes an instantiation
of <code>time_point</code> (20.10.4 [time.point]).
</p></blockquote>

<p>
Add the following paragraph after 30.4.2
[thread.timedmutex.requirements] paragraph 1:
</p>

<blockquote><p><ins>
A timed mutex type shall conform to the <code>TimedLockable</code>
requirements (30.2.5.3).
</ins></p></blockquote>

<p>Modify 30.4.2 [thread.mutex.requirements]
  paragraph 3 as follows:</p>

<blockquote><p><i>Requires:</i> If the tick period
of <code>rel_time</code> is not exactly convertible to the native tick
period, the duration shall be rounded up to the nearest native tick
period. <ins>If <code>m</code> is of
    type <code>std::timed_mutex</code> then
the calling thread does not own the mutex.</ins>
</p></blockquote>

<p>Insert a new paragraph before 30.4.2 [thread.mutex.requirements]
  paragraph 10 as follows:</p>

<blockquote><p><ins><i>Requires:</i> If <code>m</code> is of
    type <code>std::timed_mutex</code> then
the calling thread does not own the mutex.</ins>
</p></blockquote>

<p>
Add the following paragraph following 30.4.3.1 [thread.lock.guard]
paragraph 1:
</p>

<blockquote><p><ins> The supplied <code>Mutex</code> type shall meet
the <code>Lockable</code> requirements (30.2.5.2).
</ins></p></blockquote>

<p>
Add the following paragraph following 30.4.3.2 [thread.lock.unique]
paragraph 1:
</p>

<blockquote><p><ins>
The supplied <code>Mutex</code> type shall meet the <code>Lockable</code> 
requirements
(30.2.5.2). <code>unique_lock&lt;Mutex&gt;</code> meets the <code>Lockable</code>
requirements. If <code>Mutex</code> meets the <code>TimedLockable</code> 
requirements
(30.2.5.3) then <code>unique_lock&lt;Mutex&gt;</code> also meets the
<code>TimedLockable</code> requirements.
</ins></p></blockquote>

<p>
Replace the use of "mutex" or "mutex object" with "lockable object"
throughout clause 30.4.3. 30.4.3 [thread.mutex.locks] paragraph 1:
</p>

<blockquote><p>
1 A lock is an object that holds a reference to
a <del>mutex</del><ins>lockable object</ins> and may unlock
the <del>mutex</del><ins>lockable object</ins> during the lock’s
destruction (such as when leaving block scope). A <del>thread of
execution</del><ins>execution agent</ins> may use a lock to aid in
managing <del>mutex</del> ownership <ins>of a lockable object</ins> in
an exception safe manner. A lock is said to own
a <del>mutex</del><ins>lockable object</ins> if it is currently
managing the ownership of that <del>mutex</del><ins>lockable
object</ins> for a <del>thread of execution</del><ins>execution
agent</ins>. A lock does not manage the lifetime of
the <del>mutex</del><ins>lockable object</ins> it references.  [ Note:
Locks are intended to ease the burden of unlocking
the <del>mutex</del><ins>lockable object</ins> under both normal and
exceptional circumstances. — end note ]
</p></blockquote>

<p>30.4.3 [thread.lock] paragraph 2:</p>

<blockquote><p>
2 Some lock constructors take tag types which describe what should be
done with the <del>mutex</del><ins>lockable</ins> object during the
lock’s constuction.
</p></blockquote>

<p>30.4.3.1 [thread.lock.guard] paragraph 1:</p>

<blockquote><p>
1 An object of type <code>lock_guard</code> controls the ownership of a
  <del>mutex</del><ins>lockable</ins> object within a scope. A
<code>lock_guard</code> object maintains ownership of
a <del>mutex</del><ins>lockable</ins> object throughout
the <code>lock_guard</code> object’s lifetime. The behavior of a program
is undeﬁned if the <del>mutex</del><ins>lockable object</ins>
referenced by <code>pm</code> does not exist for the entire lifetime (3.8)
of the <code>lock_guard</code> object. <ins><code>Mutex</code> shall meet
  the <code>BasicLockable</code> requirements (30.2.5.2).</ins>
</p></blockquote>

<p>30.4.3.2 [thread.lock.unique] paragraph 1:</p>

<blockquote><p>
1 An object of type <code>unique_lock</code> controls the ownership of
a <del>mutex</del><ins>lockable object</ins> within a
scope. <Del>Mutex</Del> <del>o</del><ins>O</ins>wnership <Ins>of the
lockable object</Ins> may be acquired at construction or after
construction, and may be transferred, after acquisition, to
another <code>unique_lock</code> object. Objects of
type <code>unique_lock</code> are not copyable but are movable. The
behavior of a program is undefined if the contained
pointer <code>pm</code> is not null and the mutex pointed to
by <code>pm</code> does not exist for the entire remaining lifetime (3.8)
of the <code>unique_lock</code> object. <ins><code>Mutex</code> shall meet
the <code>Lockable</code> requirements (30.2.5.2).</ins>
</p></blockquote>


<p>
Add the following to the precondition of <code>unique_lock(mutex_type&amp;
 m,
const chrono::time_point&lt;Clock, Duration&gt;&amp; abs_time)</code> in 
30.4.3.2.1 [thread.lock.unique.cons] paragraph 18:
</p>

<blockquote><pre>template &lt;class Clock, class Duration&gt;
  unique_lock(mutex_type&amp; m, const chrono::time_point&lt;Clock, Duration&gt;&amp; abs_time);
</pre>

<blockquote><p>
18 <i>Requires:</i> If <code>mutex_type</code> is not a recursive mutex 
the
calling thread does not own the mutex. <ins>The supplied <code>mutex_type</code>
type shall meet the <code>TimedLockable</code> requirements (30.2.5.3).</ins>
</p></blockquote>
</blockquote>

<p>
Add the following to the precondition of <code>unique_lock(mutex_type&amp;
 m,
const chrono::duration&lt;Rep, Period&gt;&amp; rel_time)</code> in 
30.4.3.2.1 [thread.lock.unique.cons]
paragraph 22
</p>

<blockquote><p>
22  <i>Requires:</i> If <code>mutex_type</code> is not a recursive mutex
 the
calling thread does not own the mutex. <ins>The supplied <code>mutex_type</code>
type shall meet the <code>TimedLockable</code> requirements (30.2.5.3).</ins>
</p></blockquote>

<p>
Add the following as a precondition of <code>bool try_lock_until(const
chrono::time_point&lt;Clock, Duration&gt;&amp; abs_time)</code> before
30.4.3.2.2 [thread.lock.unique.locking] paragraph 10
</p>

<blockquote><pre>template &lt;class Clock, class Duration&gt;
  bool try_lock_until(const chrono::time_point&lt;Clock, Duration&gt;&amp; abs_time);
</pre>
<blockquote><p><ins>
<i>Requires:</i> The supplied <code>mutex_type</code> type shall meet the
<code>TimedLockable</code> requirements (30.2.5.3).
</ins></p></blockquote>
</blockquote>

<p>
Add the following as a precondition of <code>bool try_lock_for(const
chrono::duration&lt;Rep, Period&gt;&amp; rel_time)</code> before 
30.4.3.2.2 [thread.lock.unique.locking] paragraph 15
</p>

<blockquote><pre>template &lt;class Rep, class Period&gt;
  bool try_lock_for(const chrono::duration&lt;Rep, Period&gt;&amp; rel_time);
</pre>
<blockquote><p><ins>
<i>Requires:</i> The supplied <code>mutex_type</code> type shall meet the
<code>TimedLockable</code> requirements (30.2.5.3).
</ins></p></blockquote>
</blockquote>

<p>
Replace 30.4.4 [thread.lock.algorithm] p1 with the following:
</p>

<blockquote><pre>template &lt;class L1, class L2, class... L3&gt; int try_lock(L1&amp;, L2&amp;, L3&amp;...);
</pre>
<blockquote><p>
1 <i>Requires:</i> Each template parameter type shall meet the
<code><del>Mutex</del> <ins>Lockable</ins></code> requirements
<ins>(30.2.5.2).</ins><del>, except that a call to <code>try_lock()</code> 
may throw
an exception.</del> [<i>Note:</i> The <code>unique_lock</code> class 
template meets
these requirements when suitably instantiated. — <i>end note</i>]
</p></blockquote>
</blockquote>

<p>
Replace 30.4.4 [thread.lock.algorithm] p4 with the following:
</p>

<blockquote><pre>template &lt;class L1, class L2, class... L3&gt; void lock(L1&amp;, L2&amp;, L3&amp;...);
</pre>
<blockquote><p>
4 <i>Requires:</i> Each template parameter type shall meet the
<code><del>Mutex</del> <ins>Lockable</ins></code>
requirements <ins>(30.2.5.2).</ins><del>, except that a call to
<code>try_lock()</code> may throw an exception.</del> [<i>Note:</i> The
<code>unique_lock</code> class template meets these requirements when
suitably instantiated. — <i>end note</i>]
</p></blockquote>
</blockquote>

<p>
Replace 30.5.2 [thread.condition.condvarany] paragraph 1 with:
</p>

<blockquote><p>
1 A <code>Lock</code> type shall meet the <del>requirements for
a <code>Mutex</code> type, except that
<code>try_lock</code> is not required</del> <ins><code>BasicLockable</code>
requirements (30.2.5.1)</ins>.
[<i>Note:</i> All of the standard mutex types meet this requirement.
<ins>If a <code>Lock</code> type other than one of the standard mutex types
(or a <code>unique_lock</code> wrapper for a standard mutex type)
is used with <code>condition_variable_any</code>
then the user must ensure that
any necessary synchronization is in place
with respect to the predicate associated
with the <code>condition_variable_any</code> instance.</ins>
— <i>end note</i>]
</p></blockquote>


</body></html>
