2
0
mirror of https://github.com/boostorg/thread.git synced 2026-01-23 18:12:12 +00:00
Files
thread/doc/concepts.xml
Aleksey Gurtovoy 113b974bb7 merge RC_1_32_0 fixes
[SVN r26333]
2004-11-28 04:44:21 +00:00

2287 lines
87 KiB
XML

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
<!ENTITY % threads.entities SYSTEM "entities.xml">
%threads.entities;
]>
<section id="threads.concepts" last-revision="$Date$">
<title>Concepts</title>
<para>&Boost.Threads; currently supports two types of mutex concepts:
ordinary <link linkend="threads.concepts.mutexes">Mutexes</link>,
which allow only one thread at a time to access a resource, and
<link linkend="threads.concepts.read-write-mutexes">Read/Write Mutexes</link>,
which allow only one thread at a time to access a resource when it is
being modified (the "Write" part of Read/Write), but allows multiple threads
to access a resource when it is only being referenced (the "Read" part of
Read/Write).</para>
<section id="threads.concepts.mutexes">
<title>Mutexes</title>
<note>Certain changes to the mutexes and lock concepts are
currently under discussion. In particular, the combination of
the multiple lock concepts into a single lock concept
is likely, and the combination of the multiple mutex
concepts into a single mutex concept is also possible.</note>
<para>A mutex (short for mutual-exclusion) object is used to serialize
access to a resource shared between multiple threads. The
<link linkend="threads.concepts.Mutex">Mutex</link> concept, with
<link linkend="threads.concepts.TryMutex">TryMutex</link> and
<link linkend="threads.concepts.TimedMutex">TimedMutex</link> refinements,
formalize the requirements. A model that implements Mutex and its
refinements has two states: <emphasis role="bold">locked</emphasis> and
<emphasis role="bold">unlocked</emphasis>. Before using a shared resource, a
thread locks a &Boost.Threads; mutex object
(an object whose type is a model of
<link linkend="threads.concepts.Mutex">Mutex</link> or one of it's
refinements), ensuring
<link linkend="threads.glossary.thread-safe">thread-safe</link> access to
the shared resource. When use of the shared resource is complete, the thread
unlocks the mutex object, allowing another thread to acquire the lock and
use the shared resource.</para>
<para>Traditional C thread APIs, like POSIX threads or the Windows thread
APIs, expose functions to lock and unlock a mutex object. This is dangerous
since it's easy to forget to unlock a locked mutex. When the flow of control
is complex, with multiple return points, the likelihood of forgetting to
unlock a mutex object becomes even greater. When exceptions are thrown,
it becomes nearly impossible to ensure that the mutex object is unlocked
properly when using these traditional API's. The result is
<link linkend="threads.glossary.deadlock">deadlock</link>.</para>
<para>Many C++ threading libraries use a pattern known as <emphasis>Scoped
Locking</emphasis> &cite.SchmidtStalRohnertBuschmann; to free the programmer from
the need to explicitly lock and unlock mutex objects. With this pattern, a
<link linkend="threads.concepts.lock-concepts">Lock</link> concept is employed where
the lock object's constructor locks the associated mutex object and the
destructor automatically does the unlocking. The
&Boost.Threads; library takes this pattern to
the extreme in that Lock concepts are the only way to lock and unlock a
mutex object: lock and unlock functions are not exposed by any
&Boost.Threads; mutex objects. This helps to
ensure safe usage patterns, especially when code throws exceptions.</para>
<section id="threads.concepts.locking-strategies">
<title>Locking Strategies</title>
<para>Every mutex object follows one of several locking strategies. These
strategies define the semantics for the locking operation when the calling
thread already owns a lock on the mutex object.</para>
<section id="threads.concepts.recursive-locking-strategy">
<title>Recursive Locking Strategy</title>
<para>With a recursive locking strategy, when a thread attempts to acquire
a lock on the mutex object for which it already owns a lock, the operation
is successful. Note the distinction between a thread, which may have
multiple locks outstanding on a recursive mutex object, and a lock object,
which even for a recursive mutex object cannot have any of its lock
functions called multiple times without first calling unlock.</para>
<para>Internally a lock count is maintained and the owning thread must
unlock the mutex object the same number of times that it locked it before
the mutex object's state returns to unlocked. Since mutex objects in
&Boost.Threads; expose locking
functionality only through lock concepts, a thread will always unlock a
mutex object the same number of times that it locked it. This helps to
eliminate a whole set of errors typically found in traditional C style
thread APIs.</para>
<para>Classes <classname>boost::recursive_mutex</classname>,
<classname>boost::recursive_try_mutex</classname> and
<classname>boost::recursive_timed_mutex</classname> use this locking
strategy.</para>
</section>
<section id="threads.concepts.checked-locking-strategy">
<title>Checked Locking Strategy</title>
<para>With a checked locking strategy, when a thread attempts to acquire a
lock on the mutex object for which the thread already owns a lock, the
operation will fail with some sort of error indication. Further, attempts
by a thread to unlock a mutex object that was not locked by the thread
will also return some sort of error indication. In
&Boost.Threads;, an exception of type
<classname>boost::lock_error</classname>
would be thrown in these cases.</para>
<para>&Boost.Threads; does not currently
provide any mutex objects that use this strategy.</para>
</section>
<section id="threads.concepts.unchecked-locking-strategy">
<title>Unchecked Locking Strategy</title>
<para>With an unchecked locking strategy, when a thread attempts to acquire
a lock on a mutex object for which the thread already owns a lock the
operation will
<link linkend="threads.glossary.deadlock">deadlock</link>. In general
this locking strategy is less safe than a checked or recursive strategy,
but it's also a faster strategy and so is employed by many libraries.</para>
<para>&Boost.Threads; does not currently
provide any mutex objects that use this strategy.</para>
</section>
<section id="threads.concepts.unspecified-locking-strategy">
<title>Unspecified Locking Strategy</title>
<para>With an unspecified locking strategy, when a thread attempts to
acquire a lock on a mutex object for which the thread already owns a lock
the operation results in
<link linkend="threads.glossary.undefined-behavior">undefined behavior</link>.
</para>
<para>In general a mutex object with an unspecified locking strategy is
unsafe, and it requires programmer discipline to use the mutex object
properly. However, this strategy allows an implementation to be as fast as
possible with no restrictions on its implementation. This is especially
true for portable implementations that wrap the native threading support
of a platform. For this reason, the classes
<classname>boost::mutex</classname>,
<classname>boost::try_mutex</classname> and
<classname>boost::timed_mutex</classname> use this locking strategy
despite the lack of safety.</para>
</section>
</section>
<section id="threads.concepts.sheduling-policies">
<title>Scheduling Policies</title>
<para>Every mutex object follows one of several scheduling policies. These
policies define the semantics when the mutex object is unlocked and there is
more than one thread waiting to acquire a lock. In other words, the policy
defines which waiting thread shall acquire the lock.</para>
<section id="threads.concepts.FIFO-scheduling-policy">
<title>FIFO Scheduling Policy</title>
<para>With a FIFO ("First In First Out") scheduling policy, threads waiting
for the lock will acquire it in a first-come-first-served order.
This can help prevent a high priority thread from starving lower priority
threads that are also waiting on the mutex object's lock.</para>
</section>
<section id="threads.concepts.priority-driven-scheduling-policy">
<title>Priority Driven Policy</title>
<para>With a Priority Driven scheduling policy, the thread with the
highest priority acquires the lock. Note that this means that low-priority
threads may never acquire the lock if the mutex object has high contention
and there is always at least one high-priority thread waiting. This is
known as thread starvation. When multiple threads of the same priority are
waiting on the mutex object's lock one of the other scheduling priorities
will determine which thread shall acquire the lock.</para>
</section>
<section id="threads.concepts.unspecified-scheduling-policy">
<title>Unspecified Policy</title>
<para>The mutex object does not specify a scheduling policy. In order to
ensure portability, all &Boost.Threads;
mutex objects use an unspecified scheduling policy.</para>
</section>
</section>
<section id="threads.concepts.mutex-concepts">
<title>Mutex Concepts</title>
<section id="threads.concepts.Mutex">
<title>Mutex Concept</title>
<para>A Mutex object has two states: locked and unlocked. Mutex object
state can only be determined by a lock object meeting the
appropriate lock concept requirements
and constructed for the Mutex object.</para>
<para>A Mutex is
<ulink url="../../libs/utility/utility.htm#Class%20noncopyable">
NonCopyable</ulink>.</para>
<para>For a Mutex type <code>M</code>
and an object <code>m</code> of that type,
the following expressions must be well-formed
and have the indicated effects.</para>
<table>
<title>Mutex Expressions</title>
<tgroup cols="2">
<thead>
<row>
<entry>Expression</entry>
<entry>Effects</entry>
</row>
</thead>
<tbody>
<row>
<entry>M m;</entry>
<entry><para>Constructs a mutex object m.</para>
<para>Postcondition: m is unlocked.</para></entry>
</row>
<row>
<entry>(&amp;m)-&gt;~M();</entry>
<entry>Precondition: m is unlocked. Destroys a mutex object
m.</entry>
</row>
<row>
<entry>M::scoped_lock</entry>
<entry>A model of
<link linkend="threads.concepts.ScopedLock">ScopedLock</link>
</entry>
</row>
</tbody>
</tgroup>
</table>
</section>
<section id="threads.concepts.TryMutex">
<title>TryMutex Concept</title>
<para>A TryMutex is a refinement of
<link linkend="threads.concepts.Mutex">Mutex</link>.
For a TryMutex type <code>M</code>
and an object <code>m</code> of that type,
the following expressions must be well-formed
and have the indicated effects.</para>
<table>
<title>TryMutex Expressions</title>
<tgroup cols="2">
<thead>
<row>
<entry>Expression</entry>
<entry>Effects</entry>
</row>
</thead>
<tbody>
<row>
<entry>M::scoped_try_lock</entry>
<entry>A model of
<link linkend="threads.concepts.ScopedTryLock">ScopedTryLock</link>
</entry>
</row>
</tbody>
</tgroup>
</table>
</section>
<section id="threads.concepts.TimedMutex">
<title>TimedMutex Concept</title>
<para>A TimedMutex is a refinement of
<link linkend="threads.concepts.TryMutex">TryMutex</link>.
For a TimedMutex type <code>M</code>
and an object <code>m</code> of that type,
the following expressions must be well-formed
and have the indicated effects.</para>
<table>
<title>TimedMutex Expressions</title>
<tgroup cols="2">
<thead>
<row>
<entry>Expression</entry>
<entry>Effects</entry>
</row>
</thead>
<tbody>
<row>
<entry>M::scoped_timed_lock</entry>
<entry>A model of
<link
linkend="threads.concepts.ScopedTimedLock">ScopedTimedLock</link>
</entry>
</row>
</tbody>
</tgroup>
</table>
</section>
</section>
<section id="threads.concepts.mutex-models">
<title>Mutex Models</title>
<para>&Boost.Threads; currently supplies six models of
<link linkend="threads.concepts.Mutex">Mutex</link>
and its refinements.</para>
<table>
<title>Mutex Models</title>
<tgroup cols="3">
<thead>
<row>
<entry>Concept</entry>
<entry>Refines</entry>
<entry>Models</entry>
</row>
</thead>
<tbody>
<row>
<entry><link linkend="threads.concepts.Mutex">Mutex</link></entry>
<entry></entry>
<entry>
<para><classname>boost::mutex</classname></para>
<para><classname>boost::recursive_mutex</classname></para>
</entry>
</row>
<row>
<entry><link linkend="threads.concepts.TryMutex">TryMutex</link></entry>
<entry><link linkend="threads.concepts.Mutex">Mutex</link></entry>
<entry>
<para><classname>boost::try_mutex</classname></para>
<para><classname>boost::recursive_try_mutex</classname></para>
</entry>
</row>
<row>
<entry><link linkend="threads.concepts.TimedMutex">TimedMutex</link></entry>
<entry><link linkend="threads.concepts.TryMutex">TryMutex</link></entry>
<entry>
<para><classname>boost::timed_mutex</classname></para>
<para><classname>boost::recursive_timed_mutex</classname></para>
</entry>
</row>
</tbody>
</tgroup>
</table>
</section>
<section id="threads.concepts.lock-concepts">
<title>Lock Concepts</title>
<para>A lock object provides a safe means for locking and unlocking a mutex
object (an object whose type is a model of <link
linkend="threads.concepts.Mutex">Mutex</link> or one of its refinements). In
other words they are an implementation of the <emphasis>Scoped
Locking</emphasis> &cite.SchmidtStalRohnertBuschmann; pattern. The <link
linkend="threads.concepts.ScopedLock">ScopedLock</link>,
<link linkend="threads.concepts.ScopedTryLock">ScopedTryLock</link>, and
<link linkend="threads.concepts.ScopedTimedLock">ScopedTimedLock</link>
concepts formalize the requirements.</para>
<para>Lock objects are constructed with a reference to a mutex object and
typically acquire ownership of the mutex object by setting its state to
locked. They also ensure ownership is relinquished in the destructor. Lock
objects also expose functions to query the lock status and to manually lock
and unlock the mutex object.</para>
<para>Lock objects are meant to be short lived, expected to be used at block
scope only. The lock objects are not <link
linkend="threads.glossary.thread-safe">thread-safe</link>. Lock objects must
maintain state to indicate whether or not they've been locked and this state
is not protected by any synchronization concepts. For this reason a lock
object should never be shared between multiple threads.</para>
<section id="threads.concepts.Lock">
<title>Lock Concept</title>
<para>For a Lock type <code>L</code>
and an object <code>lk</code>
and const object <code>clk</code> of that type,
the following expressions must be well-formed
and have the indicated effects.</para>
<table>
<title>Lock Expressions</title>
<tgroup cols="2">
<thead>
<row>
<entry>Expression</entry>
<entry>Effects</entry>
</row>
</thead>
<tbody>
<row>
<entry><code>(&amp;lk)-&gt;~L();</code></entry>
<entry><code>if (locked()) unlock();</code></entry>
</row>
<row>
<entry><code>(&amp;clk)-&gt;operator const void*()</code></entry>
<entry>Returns type void*, non-zero if the associated mutex
object has been locked by <code>clk</code>, otherwise 0.</entry>
</row>
<row>
<entry><code>clk.locked()</code></entry>
<entry>Returns a <code>bool</code>, <code>(&amp;clk)-&gt;operator
const void*() != 0</code></entry>
</row>
<row>
<entry><code>lk.lock()</code></entry>
<entry>
<para>Throws <classname>boost::lock_error</classname>
if <code>locked()</code>.</para>
<para>If the associated mutex object is
already locked by some other thread, places the current thread in the
<link linkend="threads.glossary.thread-state">Blocked</link> state until
the associated mutex is unlocked, after which the current thread
is placed in the <link
linkend="threads.glossary.thread-state">Ready</link> state,
eventually to be returned to the <link
linkend="threads.glossary.thread-state">Running</link> state. If
the associated mutex object is already locked by the same thread
the behavior is dependent on the <link
linkend="threads.concepts.locking-strategies">locking
strategy</link> of the associated mutex object.</para>
<para>Postcondition: <code>locked() == true</code></para>
</entry>
</row>
<row>
<entry><code>lk.unlock()</code></entry>
<entry>
<para>Throws <classname>boost::lock_error</classname>
if <code>!locked()</code>.</para>
<para>Unlocks the associated mutex.</para>
<para>Postcondition: <code>!locked()</code></para></entry>
</row>
</tbody>
</tgroup>
</table>
</section>
<section id="threads.concepts.ScopedLock">
<title>ScopedLock Concept</title>
<para>A ScopedLock is a refinement of <link
linkend="threads.concepts.Lock">Lock</link>.
For a ScopedLock type <code>L</code>
and an object <code>lk</code> of that type,
and an object <code>m</code> of a type meeting the
<link linkend="threads.concepts.Mutex">Mutex</link> requirements,
and an object <code>b</code> of type <code>bool</code>,
the following expressions must be well-formed
and have the indicated effects.</para>
<table>
<title>ScopedLock Expressions</title>
<tgroup cols="2">
<thead>
<row>
<entry>Expression</entry>
<entry>Effects</entry>
</row>
</thead>
<tbody>
<row>
<entry><code>L lk(m);</code></entry>
<entry>Constructs an object <code>lk</code>, and associates mutex
object <code>m</code> with it, then calls
<code>lock()</code></entry>
</row>
<row>
<entry><code>L lk(m,b);</code></entry>
<entry>Constructs an object <code>lk</code>, and associates mutex
object <code>m</code> with it, then if <code>b</code>, calls
<code>lock()</code></entry>
</row>
</tbody>
</tgroup>
</table>
</section>
<section id="threads.concepts.TryLock">
<title>TryLock Concept</title>
<para>A TryLock is a refinement of <link
linkend="threads.concepts.Lock">Lock</link>.
For a TryLock type <code>L</code>
and an object <code>lk</code> of that type,
the following expressions must be well-formed
and have the indicated effects.</para>
<table>
<title>TryLock Expressions</title>
<tgroup cols="2">
<thead>
<row>
<entry>Expression</entry>
<entry>Effects</entry>
</row>
</thead>
<tbody>
<row>
<entry><code>lk.try_lock()</code></entry>
<entry>
<para>Throws <classname>boost::lock_error</classname>
if locked().</para>
<para>Makes a
non-blocking attempt to lock the associated mutex object,
returning <code>true</code> if the lock attempt is successful,
otherwise <code>false</code>. If the associated mutex object is
already locked by the same thread the behavior is dependent on the
<link linkend="threads.concepts.locking-strategies">locking
strategy</link> of the associated mutex object.</para>
</entry>
</row>
</tbody>
</tgroup>
</table>
</section>
<section id="threads.concepts.ScopedTryLock">
<title>ScopedTryLock Concept</title>
<para>A ScopedTryLock is a refinement of <link
linkend="threads.concepts.TryLock">TryLock</link>.
For a ScopedTryLock type <code>L</code>
and an object <code>lk</code> of that type,
and an object <code>m</code> of a type meeting the
<link linkend="threads.concepts.TryMutex">TryMutex</link> requirements,
and an object <code>b</code> of type <code>bool</code>,
the following expressions must be well-formed
and have the indicated effects.</para>
<table>
<title>ScopedTryLock Expressions</title>
<tgroup cols="2">
<thead>
<row>
<entry>Expression</entry>
<entry>Effects</entry>
</row>
</thead>
<tbody>
<row>
<entry><code>L lk(m);</code></entry>
<entry>Constructs an object <code>lk</code>, and associates mutex
object <code>m</code> with it, then calls
<code>try_lock()</code></entry>
</row>
<row>
<entry><code>L lk(m,b);</code></entry>
<entry>Constructs an object <code>lk</code>, and associates mutex
object <code>m</code> with it, then if <code>b</code>, calls
<code>lock()</code></entry>
</row>
</tbody>
</tgroup>
</table>
</section>
<section id="threads.concepts.TimedLock">
<title>TimedLock Concept</title>
<para>A TimedLock is a refinement of <link
linkend="threads.concepts.TryLock">TryLock</link>.
For a TimedLock type <code>L</code>
and an object <code>lk</code> of that type,
and an object <code>t</code> of type <classname>boost::xtime</classname>,
the following expressions must be well-formed
and have the indicated effects.</para>
<table>
<title>TimedLock Expressions</title>
<tgroup cols="2">
<thead>
<row>
<entry>Expression</entry>
<entry>Effects</entry>
</row>
</thead>
<tbody>
<row>
<entry><code>lk.timed_lock(t)</code></entry>
<entry>
<para>Throws <classname>boost::lock_error</classname>
if locked().</para>
<para>Makes a blocking attempt
to lock the associated mutex object, and returns <code>true</code>
if successful within the specified time <code>t</code>, otherwise
<code>false</code>. If the associated mutex object is already
locked by the same thread the behavior is dependent on the <link
linkend="threads.concepts.locking-strategies">locking
strategy</link> of the associated mutex object.</para>
</entry>
</row>
</tbody>
</tgroup>
</table>
</section>
<section id="threads.concepts.ScopedTimedLock">
<title>ScopedTimedLock Concept</title>
<para>A ScopedTimedLock is a refinement of <link
linkend="threads.concepts.TimedLock">TimedLock</link>.
For a ScopedTimedLock type <code>L</code>
and an object <code>lk</code> of that type,
and an object <code>m</code> of a type meeting the
<link linkend="threads.concepts.TimedMutex">TimedMutex</link> requirements,
and an object <code>b</code> of type <code>bool</code>,
and an object <code>t</code> of type <classname>boost::xtime</classname>,
the following expressions must be well-formed
and have the indicated effects.</para>
<table>
<title>ScopedTimedLock Expressions</title>
<tgroup cols="2">
<thead>
<row>
<entry>Expression</entry>
<entry>Effects</entry>
</row>
</thead>
<tbody>
<row>
<entry><code>L lk(m,t);</code></entry>
<entry>Constructs an object <code>lk</code>, and associates mutex
object <code>m</code> with it, then calls
<code>timed_lock(t)</code></entry>
</row>
<row>
<entry><code>L lk(m,b);</code></entry>
<entry>Constructs an object <code>lk</code>, and associates mutex
object <code>m</code> with it, then if <code>b</code>, calls
<code>lock()</code></entry>
</row>
</tbody>
</tgroup>
</table>
</section>
</section>
<section id="threads.concepts.lock-models">
<title>Lock Models</title>
<para>&Boost.Threads; currently supplies twelve models of
<link linkend="threads.concepts.Lock">Lock</link>
and its refinements.</para>
<table>
<title>Lock Models</title>
<tgroup cols="3">
<thead>
<row>
<entry>Concept</entry>
<entry>Refines</entry>
<entry>Models</entry>
</row>
</thead>
<tbody>
<row>
<entry><link linkend="threads.concepts.Lock">Lock</link></entry>
<entry></entry>
<entry></entry>
</row>
<row>
<entry><link linkend="threads.concepts.ScopedLock">ScopedLock</link></entry>
<entry><link linkend="threads.concepts.Lock">Lock</link></entry>
<entry>
<para><classname>boost::mutex::scoped_lock</classname></para>
<para><classname>boost::recursive_mutex::scoped_lock</classname></para>
<para><classname>boost::try_mutex::scoped_lock</classname></para>
<para><classname>boost::recursive_try_mutex::scoped_lock</classname></para>
<para><classname>boost::timed_mutex::scoped_lock</classname></para>
<para><classname>boost::recursive_timed_mutex::scoped_lock</classname></para>
</entry>
</row>
<row>
<entry><link linkend="threads.concepts.TryLock">TryLock</link></entry>
<entry><link linkend="threads.concepts.Lock">Lock</link></entry>
<entry></entry>
</row>
<row>
<entry><link linkend="threads.concepts.ScopedTryLock">ScopedTryLock</link></entry>
<entry><link linkend="threads.concepts.TryLock">TryLock</link></entry>
<entry>
<para><classname>boost::try_mutex::scoped_try_lock</classname></para>
<para><classname>boost::recursive_try_mutex::scoped_try_lock</classname></para>
<para><classname>boost::timed_mutex::scoped_try_lock</classname></para>
<para><classname>boost::recursive_timed_mutex::scoped_try_lock</classname></para>
</entry>
</row>
<row>
<entry><link linkend="threads.concepts.TimedLock">TimedLock</link></entry>
<entry><link linkend="threads.concepts.TryLock">TryLock</link></entry>
<entry></entry>
</row>
<row>
<entry><link linkend="threads.concepts.ScopedTimedLock">ScopedTimedLock</link></entry>
<entry><link linkend="threads.concepts.TimedLock">TimedLock</link></entry>
<entry>
<para><classname>boost::timed_mutex::scoped_timed_lock</classname></para>
<para><classname>boost::recursive_timed_mutex::scoped_timed_lock</classname></para>
</entry>
</row>
</tbody>
</tgroup>
</table>
</section>
</section>
<section id="threads.concepts.read-write-mutexes">
<title>Read/Write Mutexes</title>
<note>Since the read/write mutex and related classes are new,
both interface and implementation are liable to change
in future releases of &Boost.Threads;.
The lock concepts and lock promotion and demotion in particular
are still under discussion and very likely to change.</note>
<para>A read/write mutex (short for reader/writer mutual-exclusion) object
is used to serialize access to a resource shared between multiple
threads, where multiple "readers" can share simultaneous access, but
"writers" require exclusive access. The
<link linkend="threads.concepts.ReadWriteMutex">ReadWriteMutex</link> concept, with
<link linkend="threads.concepts.TryReadWriteMutex">TryReadWriteMutex</link> and
<link linkend="threads.concepts.TimedReadWriteMutex"> TimedReadWriteMutex</link>
refinements formalize the requirements. A model that implements
ReadWriteMutex and its refinements has three states:
<emphasis role="bold">read-locked</emphasis>,
<emphasis role="bold">write-locked</emphasis>, and
<emphasis role="bold">unlocked</emphasis>.
Before reading from a shared resource, a thread
<emphasis role="bold">read-locks</emphasis>
a &Boost.Threads; read/write mutex object
(an object whose type is a model of
<link linkend="threads.concepts.ReadWriteMutex">ReadWriteMutex</link>
or one of it's refinements), ensuring
<link linkend="threads.glossary.thread-safe">thread-safe</link>
access for reading from the shared resource. Before writing
to a shared resource, a thread
<emphasis role="bold">write-locks</emphasis> a &Boost.Threads;
read/write mutex object
(an object whose type is a model of
<link linkend="threads.concepts.ReadWriteMutex">ReadWriteMutex</link>
or one of it's refinements), ensuring
<link linkend="threads.glossary.thread-safe">thread-safe</link>
access for altering the shared resource. When use of the shared
resource is complete, the thread unlocks the mutex object,
allowing another thread to acquire the lock and use the shared
resource.</para>
<para>Traditional C thread APIs that provide read/write mutex
primitives (like POSIX threads) expose functions to lock and unlock a
mutex object. This is dangerous since it's easy to forget to unlock a
locked mutex. When the flow of control is complex, with multiple
return points, the likelihood of forgetting to unlock a mutex object
becomes even greater. When exceptions are thrown, it becomes nearly
impossible to ensure that the mutex object is unlocked
properly when using these traditional API's. The result is
<link linkend="threads.glossary.deadlock">deadlock</link>.</para>
<para>Many C++ threading libraries use a pattern known as <emphasis>Scoped
Locking</emphasis> &cite.SchmidtStalRohnertBuschmann; to free the
programmer from the need to explicitly lock and unlock
read/write mutex objects. With this pattern, a
<link linkend="threads.concepts.read-write-lock-concepts">Read/Write Lock</link>
concept is employed where the lock object's constructor locks
the associated read/write mutex object
and the destructor automatically does the unlocking. The
&Boost.Threads; library takes this pattern to
the extreme in that
<link linkend="threads.concepts.read-write-lock-concepts">Read/Write Lock</link>
concepts are the only way to lock and unlock a read/write mutex
object: lock and unlock functions are not exposed by any
&Boost.Threads; read/write mutex objects. This helps to
ensure safe usage patterns, especially when code throws exceptions.</para>
<section id="threads.concepts.read-write-locking-strategies">
<title>Locking Strategies</title>
<para>Every read/write mutex object follows one of several locking
strategies. These strategies define the semantics for the locking
operation when the calling thread already owns a lock on the
read/write mutex object.</para>
<section id="threads.concepts.read-write-locking-strategies.recursive">
<title>Recursive Locking Strategy</title>
<para>With a recursive locking strategy, when a thread attempts
to acquire a lock on a read/write mutex object
for which it already owns a lock, the operation is successful,
except in the case where a thread holding a read-lock
attempts to obtain a write lock, in which case a
<classname>boost::lock_error</classname> exception will
be thrown. Note the distinction between a thread, which may have
multiple locks outstanding on a recursive read/write mutex object,
and a lock object, which even for a recursive read/write mutex
object cannot have any of its lock functions called multiple
times without first calling unlock.</para>
<informaltable>
<tgroup cols="3">
<thead>
<row>
<entry>Lock Type Held</entry>
<entry>Lock Type Requested</entry>
<entry>Action</entry>
</row>
</thead>
<tbody>
<row>
<entry>read-lock</entry>
<entry>read-lock</entry>
<entry>Grant the read-lock immediately</entry>
</row>
<row>
<entry>read-lock</entry>
<entry>write-lock</entry>
<entry>If this thread is the only holder of the read-lock,
grants the write lock immediately. Otherwise throws a
<classname>boost::lock_error</classname> exception.</entry>
</row>
<row>
<entry>write-locked</entry>
<entry>read-lock</entry>
<entry>Grants the (additional) read-lock immediately.</entry>
</row>
<row>
<entry>write-locked</entry>
<entry>write-lock</entry>
<entry> Grant the write-lock immediately</entry>
</row>
</tbody>
</tgroup>
</informaltable>
<para>Internally a lock count is maintained and the owning
thread must unlock the mutex object the same number of times
that it locked it before the mutex object's state returns
to unlocked. Since mutex objects in &Boost.Threads; expose
locking functionality only through lock concepts, a thread
will always unlock a mutex object the same number of times
that it locked it. This helps to eliminate a whole set of
errors typically found in traditional C style thread APIs.
</para>
<para>&Boost.Threads; does not currently provide any read/write mutex objects
that use this strategy. A successful implementation of this locking strategy
may require
<link linkend="threads.concepts.read-write-locking-strategies.thread-identification">thread identification</link>.
</para>
</section>
<section id="threads.concepts.read-write-locking-strategies.checked">
<title>Checked Locking Strategy</title>
<para>With a checked locking strategy, when a thread attempts
to acquire a lock on the mutex object for which the thread
already owns a lock, the operation will fail with some sort of
error indication, except in the case of multiple read-lock
acquisition which is a normal operation for ANY ReadWriteMutex.
Further, attempts by a thread to unlock a mutex that was not
locked by the thread will also return some sort of error
indication. In &Boost.Threads;, an exception of type
<classname>boost::lock_error</classname> would be thrown in
these cases.</para>
<informaltable>
<tgroup cols="3">
<thead>
<row>
<entry>Lock Type Held</entry>
<entry>Lock Type Requested</entry>
<entry>Action</entry>
</row>
</thead>
<tbody>
<row>
<entry>read-lock</entry>
<entry>read-lock</entry>
<entry>Grant the read-lock immediately</entry>
</row>
<row>
<entry>read-lock</entry>
<entry>write-lock</entry>
<entry>Throw <classname>boost::lock_error</classname></entry>
</row>
<row>
<entry>write-locked</entry>
<entry>read-lock</entry>
<entry>Throw <classname>boost::lock_error</classname></entry>
</row>
<row>
<entry>write-locked</entry>
<entry>write-lock</entry>
<entry> Throw <classname>boost::lock_error</classname></entry>
</row>
</tbody>
</tgroup>
</informaltable>
<para>&Boost.Threads; does not currently provide any read/write mutex objects
that use this strategy. A successful implementation of this locking strategy
may require
<link linkend="threads.concepts.read-write-locking-strategies.thread-identification">thread identification</link>.
</para>
</section>
<section id="threads.concepts.read-write-locking-strategies.unchecked">
<title>Unchecked Locking Strategy</title>
<para>With an unchecked locking strategy, when a thread
attempts to acquire a lock on the read/write mutex object
for which the thread already owns a lock, the operation
will <link linkend="threads.glossary.deadlock">deadlock</link>.
In general this locking strategy is less safe than a checked
or recursive strategy, but it can be a faster strategy and so
is employed by many libraries.</para>
<informaltable>
<tgroup cols="3">
<thead>
<row>
<entry>Lock Type Held</entry>
<entry>Lock Type Requested</entry>
<entry>Action</entry>
</row>
</thead>
<tbody>
<row>
<entry>read-lock</entry>
<entry>read-lock</entry>
<entry>Grant the read-lock immediately</entry>
</row>
<row>
<entry>read-lock</entry>
<entry>write-lock</entry>
<entry><link linkend="threads.glossary.deadlock">Deadlock</link></entry>
</row>
<row>
<entry>write-locked</entry>
<entry>read-lock</entry>
<entry><link linkend="threads.glossary.deadlock">Deadlock</link></entry>
</row>
<row>
<entry>write-locked</entry>
<entry>write-lock</entry>
<entry><link linkend="threads.glossary.deadlock">Deadlock</link></entry>
</row>
</tbody>
</tgroup>
</informaltable>
<para>&Boost.Threads; does not currently provide any mutex
objects that use this strategy. For ReadWriteMutexes on
platforms that contain natively recursive synchronization
primitives, implementing a guaranteed-deadlock can actually
involve extra work, and would likely require
<link linkend="threads.concepts.read-write-locking-strategies.thread-identification">thread identification</link>.
</para>
</section>
<section id="threads.concepts.read-write-locking-strategies.unspecified">
<title>Unspecified Locking Strategy</title>
<para>With an unspecified locking strategy, when a thread
attempts to acquire a lock on a read/write mutex object for
which the thread already owns a lock, the operation results
in <link linkend="threads.glossary.undefined-behavior">undefined behavior</link>.
When a read/write mutex object has an unspecified locking
strategy the programmer must assume that the read/write mutex
object instead uses an unchecked strategy as the worse case,
although some platforms may exhibit a mix of unchecked and
recursive behavior.</para>
<informaltable>
<tgroup cols="3">
<thead>
<row>
<entry>Lock Type Held</entry>
<entry>Lock Type Requested</entry>
<entry>Action</entry>
</row>
</thead>
<tbody>
<row>
<entry>read-lock</entry>
<entry>read-lock</entry>
<entry>Grant the read-lock immediately</entry>
</row>
<row>
<entry>read-lock</entry>
<entry>write-lock</entry>
<entry>
<link linkend="threads.glossary.undefined-behavior">Undefined</link>, but generally <link linkend="threads.glossary.deadlock">deadlock</link>
</entry>
</row>
<row>
<entry>write-locked</entry>
<entry>read-lock</entry>
<entry><link linkend="threads.glossary.undefined-behavior">Undefined</link>, but generally <link linkend="threads.glossary.deadlock">deadlock</link></entry>
</row>
<row>
<entry>write-locked</entry>
<entry>write-lock</entry>
<entry><link linkend="threads.glossary.undefined-behavior">Undefined</link>, but generally <link linkend="threads.glossary.deadlock">deadlock</link></entry>
</row>
</tbody>
</tgroup>
</informaltable>
<para>In general a read/write mutex object with an unspecified
locking strategy is unsafe, and it requires programmer discipline
to use the read/write mutex object properly. However, this strategy
allows an implementation to be as fast as possible with no restrictions
on its implementation. This is especially true for portable implementations
that wrap the native threading support of a platform. For this reason, the
classes
<classname>read_write_mutex</classname>,
<classname>try_read_write_mutex</classname>, and
<classname>timed_read_write_mutex</classname>
use this locking strategy despite the lack of safety.</para>
</section>
<section id="threads.concepts.read-write-locking-strategies.thread-identification">
<title>Thread Identification</title>
<para>ReadWriteMutexes can support specific Locking Strategies
(recursive and checked) which help to detect and protect against
self-deadlock. Self-deadlock can occur when a holder of a locked
ReadWriteMutex attempts to obtain another lock. Given an
implemention <emphasis>I</emphasis> which is susceptible to
self-deadlock but otherwise correct and efficient, a recursive or
checked implementation <emphasis>Ir</emphasis> or
<emphasis>Ic</emphasis> can use the same basic implementation,
but make special checks against self-deadlock by tracking the
identities of thread(s) currently holding locks. This approach
makes deadlock detection othrogonal to the basic ReadWriteMutex
implementaion.</para>
<para>Alternatively, a different basic implementation for
ReadWriteMutex concepts,
<emphasis>I'</emphasis> (I-Prime) may exist which uses recursive
or checked versions of synchronization primitives to produce
a recursive or checked ReadWriteMutex while still providing
flexibility in terms of Scheduling Policies. </para>
<para>Please refer to the &Boost.Threads;
<link linkend="threads.concepts.read-write-mutex-concepts">read/write mutex concept</link>
documentation for a discussion of locking strategies.
The read/write mutex supports only the
<link linkend="threads.concepts.read-write-locking-strategies.unspecified">unspecified</link>
locking strategy. ReadWriteMutexes are parameterized on a
Mutex type which they use to control write-locking
and access to internal state.</para>
</section>
<section id="threads.concepts.read-write-locking-strategies.promotion">
<title>Lock Promotion</title>
<para>ReadWriteMutexes can support lock promotion, where a
mutex which is in the read-locked state transitions to a
write-locked state without releasing the lock. Lock
promotion can be tricky to implement; for instance,
extra care must be taken to ensure that only one thread holding a
read-lock can block awaiting promotion at any given time. If
more than one read-lock holder is allowed to enter a blocked
state while waiting to be promoted, deadlock will result since
both threads will be waiting for the other to release their read-lock.
</para>
<para>Currently, &Boost.Threads; supports lock promotion
through <code>promote()</code>, <code>try_promote()</code>,
and <code>timed_promote()</code> operations.</para>
</section>
<section id="threads.concepts.read-write-locking-strategies.demotion">
<title>Lock Demotion</title>
<para>ReadWriteMutexes can support lock demotion, where a
mutex which is in the write-locked state transitions to a
read-locked state without releasing the lock.
Since by definition only one thread at a time may hold
a write-lock, the problem with deadlock that can occur
during lock promotion is not a problem for lock
demotion.</para>
<para>Currently, &Boost.Threads; supports lock demotion
through <code>demote()</code>, <code>try_demote()</code>,
and <code>timed_demote()</code> operations.</para>
</section>
</section>
<section id="threads.concepts.read-write-scheduling-policies">
<title>Scheduling Policies</title>
<para>Every read/write mutex object follows one of several scheduling
policies. These policies define the semantics when the mutex object
is unlocked and there is more than one thread waiting to acquire a
lock. In other words, the policy defines which waiting thread shall
acquire the lock. For a read/write mutex, it is particularly important
to define the behavior when threads are requesting both read and
write access simultaneously. This will be referred to as "inter-class
scheduling" because it describes the scheduling between two
classes of threads (those waiting for a read lock and those
waiting for a write lock).</para>
<para>For some types of inter-class scheduling, an "intra-class"
scheduling policy can also be defined that will describe the order
in which waiting threads of the same class (i.e., those
waiting for the same type of lock) will acquire the thread.
</para>
<section id="threads.concepts.read-write-scheduling-policies.inter-class">
<title>Inter-Class Scheduling Policies</title>
<section id="threads.concepts.read-write-scheduling-policies.reader-priority">
<title>ReaderPriority</title>
<para>With ReaderPriority scheduling, any pending request for
a read-lock will have priority over a pending request for a
write-lock, irrespective of the current lock state of the
read/write mutex, and irrespective of the relative order
that the pending requests arrive.</para>
<informaltable>
<tgroup cols="3">
<thead>
<row>
<entry>Current mutex state</entry>
<entry>Request Type</entry>
<entry>Action</entry>
</row>
</thead>
<tbody>
<row>
<entry>unlocked</entry>
<entry>read-lock</entry>
<entry>Grant the read-lock immediately</entry>
</row>
<row>
<entry>read-locked</entry>
<entry>read-lock</entry>
<entry>Grant the additional read-lock immediately.</entry>
</row>
<row>
<entry>write-locked</entry>
<entry>read-lock</entry>
<entry>Wait to acquire the lock until the thread
holding the write-lock releases its lock (or until
the specified time, if any). A
read-lock will be granted to all pending readers
before any other thread can acquire a write-lock.
<para>TODO: try-lock, timed-lock.</para>
</entry>
</row>
<row>
<entry>unlocked</entry>
<entry>write-lock</entry>
<entry>Grant the write-lock immediately, if and
only if there are no pending read-lock requests.
<para>TODO: try-lock, timed-lock.</para>
</entry>
</row>
<row>
<entry>read-locked</entry>
<entry>write-lock</entry>
<entry> Wait to acquire the lock until all
threads holding read-locks release their locks
<emphasis role="bold">AND</emphasis> no requests
for read-locks exist. If other write-lock
requests exist, the lock is granted in accordance
with the intra-class scheduling policy.
<para>TODO: try-lock, timed-lock.</para>
</entry>
</row>
<row>
<entry>write-locked</entry>
<entry>write-lock</entry>
<entry>Wait to acquire the lock until the thread
holding the write-lock releases its lock
<emphasis role="bold">AND</emphasis> no requests
for read-locks exist. If other write-lock
requests exist, the lock is granted in accordance
with the intra-class scheduling policy.
<para>TODO: try-lock, timed-lock.</para>
</entry>
</row>
<row>
<entry>read-locked</entry>
<entry>promote</entry>
<entry><para>TODO</para></entry>
</row>
<row>
<entry>write-locked</entry>
<entry>demote</entry>
<entry><para>TODO</para></entry>
</row>
</tbody>
</tgroup>
</informaltable>
</section>
<section id="threads.concepts.read-write-scheduling-policies.writer-priority">
<title>WriterPriority</title>
<para>With WriterPriority scheduling, any pending request
for a write-lock will have priority over a pending request
for a read-lock, irrespective of the current lock state
of the read/write mutex, and irrespective of the relative
order that the pending requests arrive.</para>
<informaltable>
<tgroup cols="3">
<thead>
<row>
<entry>Current mutex state</entry>
<entry>Request Type</entry>
<entry>Action</entry>
</row>
</thead>
<tbody>
<row>
<entry>unlocked</entry>
<entry>read-lock</entry>
<entry>Grant the read-lock immediately.</entry>
</row>
<row>
<entry>read-locked</entry>
<entry>read-lock</entry>
<entry>Grant the additional read-lock immediately,
<emphasis role="bold">IF</emphasis> no outstanding
requests for a write-lock exist; otherwise TODO.
<para>TODO: try-lock, timed-lock.</para>
</entry>
</row>
<row>
<entry>write-locked</entry>
<entry>read-lock</entry>
<entry> Wait to acquire the lock until the
thread holding the write-lock
releases its lock. The read lock will be granted
once no other outstanding write-lock requests
exist.
<para>TODO: try-lock, timed-lock.</para>
</entry>
</row>
<row>
<entry>unlocked</entry>
<entry>write-lock</entry>
<entry>Grant the write-lock immediately.</entry>
</row>
<row>
<entry>read-locked</entry>
<entry>write-lock</entry>
<entry>Wait to acquire the lock until all
threads holding read-locks release their locks.
If other write-lock requests exist, the lock
is granted in accordance with the intra-class
scheduling policy. This request will be granted
before any new read-lock requests are granted.
<para>TODO: try-lock, timed-lock.</para>
</entry>
</row>
<row>
<entry>write-locked</entry>
<entry>write-lock</entry>
<entry>Wait to acquire the lock until the thread
holding the write-lock releases its lock. If
other write-lock requests exist, the lock is
granted in accordance with the intra-class
scheduling policy. This request will be granted
before any new read-lock requests are granted.
<para>TODO: try-lock, timed-lock.</para>
</entry>
</row>
<row>
<entry>read-locked</entry>
<entry>promote</entry>
<entry><para>TODO</para></entry>
</row>
<row>
<entry>write-locked</entry>
<entry>demote</entry>
<entry><para>TODO</para></entry>
</row>
</tbody>
</tgroup>
</informaltable>
</section>
<section id="threads.concepts.read-write-scheduling-policies.alternating-many-reads">
<title>AlternatingPriority/ManyReads</title>
<para>With AlternatingPriority/ManyReads scheduling, reader
or writer starvation is avoided by alternatively granting read
or write access when pending requests exist for both types of
locks. Outstanding read-lock requests are treated as a group
when it is the "readers' turn"</para>
<informaltable>
<tgroup cols="3">
<thead>
<row>
<entry>Current mutex state</entry>
<entry>Request Type</entry>
<entry>Action</entry>
</row>
</thead>
<tbody>
<row>
<entry>unlocked</entry>
<entry>read-lock</entry>
<entry>Grant the read-lock immediately.</entry>
</row>
<row>
<entry>read-locked</entry>
<entry>read-lock</entry>
<entry>Grant the additional read-lock immediately,
<emphasis role="bold">IF</emphasis> no outstanding
requests for a write-lock exist. If outstanding
write-lock requests exist, this lock will not
be granted until at least one of the
write-locks is granted and released. If other
read-lock requests exist, all read-locks will be
granted as a group.
<para>TODO: try-lock, timed-lock.</para>
</entry>
</row>
<row>
<entry>write-locked</entry>
<entry>read-lock</entry>
<entry> Wait to acquire the lock until the thread
holding the write-lock releases its lock. If other
outstanding write-lock requests exist, they will
have to wait until all current read-lock requests
are serviced.
<para>TODO: try-lock, timed-lock.</para>
</entry>
</row>
<row>
<entry>unlocked</entry>
<entry>write-lock</entry>
<entry>Grant the write-lock immediately.</entry>
</row>
<row>
<entry>read-locked</entry>
<entry>write-lock</entry>
<entry>
<para>Wait to acquire the lock until all threads
holding read-locks release their locks.</para>
<para>If other write-lock requests exist, this
lock will be granted to one of them in accordance
with the intra-class scheduling policy.</para>
<para>TODO: try-lock, timed-lock.</para>
</entry>
</row>
<row>
<entry>write-locked</entry>
<entry>write-lock</entry>
<entry>Wait to acquire the lock until the thread
holding the write-lock releases its lock. If
other outstanding read-lock requests exist, this
lock will not be granted until all of the
currently waiting read-locks are granted and
released. If other write-lock requests exist,
this lock will be granted in accordance with the
intra-class scheduling policy.
<para>TODO: try-lock, timed-lock.</para>
</entry>
</row>
<row>
<entry>read-locked</entry>
<entry>promote</entry>
<entry><para>TODO</para></entry>
</row>
<row>
<entry>write-locked</entry>
<entry>demote</entry>
<entry><para>TODO</para></entry>
</row>
</tbody>
</tgroup>
</informaltable>
</section>
<section id="threads.concepts.read-write-scheduling-policies.alternating-single-read">
<title>AlternatingPriority/SingleRead</title>
<para>With AlternatingPriority/SingleRead scheduling, reader
or writer starvation is avoided by alternatively granting read
or write access when pending requests exist for both types of
locks. Outstanding read-lock requests are services one at a
time when it is the "readers' turn"</para>
<informaltable>
<tgroup cols="3">
<thead>
<row>
<entry>Current mutex state</entry>
<entry>Request Type</entry>
<entry>Action</entry>
</row>
</thead>
<tbody>
<row>
<entry>unlocked</entry>
<entry>read-lock</entry>
<entry>Grant the read-lock immediately.</entry>
</row>
<row>
<entry>read-locked</entry>
<entry>read-lock</entry>
<entry>Grant the additional read-lock immediately,
<emphasis role="bold">IF</emphasis> no outstanding
requests for a write-lock exist. If outstanding
write-lock requests exist, this lock will not
be granted until at least one of the write-locks
is granted and released.
<para>TODO: try-lock, timed-lock.</para>
</entry>
</row>
<row>
<entry>write-locked</entry>
<entry>read-lock</entry>
<entry>
<para>Wait to acquire the lock until the thread
holding the write-lock releases its lock.</para>
<para>If other outstanding write-lock requests
exist, exactly one read-lock request will be
granted before the next write-lock is granted.
</para>
<para>TODO: try-lock, timed-lock.</para>
</entry>
</row>
<row>
<entry>unlocked</entry>
<entry>write-lock</entry>
<entry>Grant the write-lock immediately.</entry>
</row>
<row>
<entry>read-locked</entry>
<entry>write-lock</entry>
<entry>
<para>Wait to acquire the lock until all
threads holding read-locks release their
locks.</para>
<para>If other write-lock requests exist,
this lock will be granted to one of them
in accordance with the intra-class
scheduling policy.</para></entry>
<para>TODO: try-lock, timed-lock.</para>
</row>
<row>
<entry>write-locked</entry>
<entry>write-lock</entry>
<entry>Wait to acquire the lock until the
thread holding the write-lock releases its
lock. If other outstanding read-lock requests
exist, this lock can not be granted until
exactly one read-lock request is granted and
released. If other write-lock requests exist,
this lock will be granted in accordance with
the intra-class scheduling policy.
<para>TODO: try-lock, timed-lock.</para>
</entry>
</row>
<row>
<entry>read-locked</entry>
<entry>promote</entry>
<entry><para>TODO</para></entry>
</row>
<row>
<entry>write-locked</entry>
<entry>demote</entry>
<entry><para>TODO</para></entry>
</row>
</tbody>
</tgroup>
</informaltable>
</section>
</section>
<section id="threads.concepts.read-write-scheduling-policies.intra-class">
<title>Intra-Class Scheduling Policies</title>
<para>Please refer to
<xref linkend="threads.concepts.sheduling-policies" />
for a discussion of mutex scheduling policies, which are identical to
read/write mutex intra-class scheduling policies.</para>
<para>For threads waiting to obtain write-locks, the read/write mutex
supports only the
<link linkend="threads.concepts.unspecified-scheduling-policy">Unspecified</link>
intra-class scheduling policy. That is, given a set of threads
waiting for write-locks, the order, relative to one another, in
which they receive the write-lock is unspecified.</para>
<para>For threads waiting to obtain read-locks, the read/write mutex
supports only the
<link linkend="threads.concepts.unspecified-scheduling-policy">Unspecified</link>
intra-class scheduling policy. That is, given a set of threads
waiting for read-locks, the order, relative to one another, in
which they receive the read-lock is unspecified.</para>
</section>
</section>
<section id="threads.concepts.read-write-mutex-concepts">
<title>Mutex Concepts</title>
<section id="threads.concepts.ReadWriteMutex">
<title>ReadWriteMutex Concept</title>
<para>A ReadWriteMutex object has three states: read-locked,
write-locked, and unlocked. ReadWriteMutex object state can
only be determined by a lock object meeting the appropriate lock concept
requirements and constructed for the ReadWriteMutex object.</para>
<para>A ReadWriteMutex is
<ulink url="../../libs/utility/utility.htm#Class%20noncopyable">NonCopyable</ulink>.
</para>
<para>For a ReadWriteMutex type <code>M</code>,
and an object <code>m</code> of that type,
the following expressions must be well-formed
and have the indicated effects.</para>
<table>
<title>ReadWriteMutex Expressions</title>
<tgroup cols="2">
<thead>
<row>
<entry>Expression</entry>
<entry>Effects</entry>
</row>
</thead>
<tbody>
<row>
<entry><code>M m;</code></entry>
<entry>Constructs a read/write mutex object <code>m</code>.
Post-condition: <code>m</code> is unlocked.</entry>
</row>
<row>
<entry><code>(&amp;m)-&gt;~M();</code></entry>
<entry>Precondition: <code>m</code> is unlocked.
Destroys a read/write mutex object <code>m</code>.
</entry>
</row>
<row>
<entry><code>M::scoped_read_write_lock</code></entry>
<entry>A type meeting the
<link linkend="threads.concepts.ScopedReadWriteLock">ScopedReadWriteLock</link>
requirements. </entry>
</row>
<row>
<entry><code>M::scoped_read_lock</code></entry>
<entry>A type meeting the
<link linkend="threads.concepts.ScopedLock">ScopedLock</link>
requirements. </entry>
</row>
<row>
<entry><code>M::scoped_write_lock</code></entry>
<entry>A type meeting the
<link linkend="threads.concepts.ScopedLock">ScopedLock</link>
requirements. </entry>
</row>
</tbody>
</tgroup>
</table>
</section>
<section id="threads.concepts.TryReadWriteMutex">
<title>TryReadWriteMutex Concept</title>
<para>A TryReadWriteMutex is a refinement of
<link linkend="threads.concepts.ReadWriteMutex">ReadWriteMutex</link>.
For a TryReadWriteMutex type <code>M</code>
and an object <code>m</code> of that type,
the following expressions must be well-formed
and have the indicated effects.</para>
<table>
<title>TryReadWriteMutex Expressions</title>
<tgroup cols="2">
<thead>
<row>
<entry>Expression</entry>
<entry>Effects</entry>
</row>
</thead>
<tbody>
<row>
<entry><code>M::scoped_try_read_write_lock</code></entry>
<entry>A type meeting the
<link linkend="threads.concepts.ScopedTryReadWriteLock">ScopedTryReadWriteLock</link>
requirements.</entry>
</row>
<row>
<entry><code>M::scoped_try_read_lock</code></entry>
<entry>A type meeting the
<link linkend="threads.concepts.ScopedTryLock">ScopedTryLock</link>
requirements.</entry>
</row>
<row>
<entry><code>M::scoped_try_write_lock</code></entry>
<entry>A type meeting the
<link linkend="threads.concepts.ScopedTryLock">ScopedTryLock</link>
requirements.</entry>
</row>
</tbody>
</tgroup>
</table>
</section>
<section id="threads.concepts.TimedReadWriteMutex">
<title>TimedReadWriteMutex Concept</title>
<para>A TimedReadWriteMutex is a refinement of
<link linkend="threads.concepts.TryReadWriteMutex">TryReadWriteMutex</link>.
For a TimedReadWriteMutex type <code>M</code>
and an object <code>m</code> of that type
the following expressions must be well-formed
and have the indicated effects.</para>
<table>
<title>TimedReadWriteMutex Expressions</title>
<tgroup cols="2">
<thead>
<row>
<entry>Expression</entry>
<entry>Effects</entry>
</row>
</thead>
<tbody>
<row>
<entry><code>M::scoped_timed_read_write_lock</code></entry>
<entry>A type meeting the
<link linkend="threads.concepts.ScopedTimedReadWriteLock">ScopedTimedReadWriteLock</link>
requirements.</entry>
</row>
<row>
<entry><code>M::scoped_timed_read_lock</code></entry>
<entry>A type meeting the
<link linkend="threads.concepts.ScopedTimedLock">ScopedTimedLock</link>
requirements.</entry>
</row>
<row>
<entry><code>M::scoped_timed_write_lock</code></entry>
<entry>A type meeting the
<link linkend="threads.concepts.ScopedTimedLock">ScopedTimedLock</link>
requirements.</entry>
</row>
</tbody>
</tgroup>
</table>
</section>
</section>
<section id="threads.concepts.read-write-mutex-models">
<title>Mutex Models</title>
<para>&Boost.Threads; currently supplies three models of
<link linkend="threads.concepts.ReadWriteMutex">ReadWriteMutex</link>
and its refinements.</para>
<table>
<title>Mutex Models</title>
<tgroup cols="3">
<thead>
<row>
<entry>Concept</entry>
<entry>Refines</entry>
<entry>Models</entry>
</row>
</thead>
<tbody>
<row>
<entry><link linkend="threads.concepts.ReadWriteMutex">ReadWriteMutex</link></entry>
<entry></entry>
<entry><classname>boost::read_write_mutex</classname></entry>
</row>
<row>
<entry><link linkend="threads.concepts.TryReadWriteMutex">TryReadWriteMutex</link></entry>
<entry><link linkend="threads.concepts.ReadWriteMutex">ReadWriteMutex</link></entry>
<entry><classname>boost::try_read_write_mutex</classname></entry>
</row>
<row>
<entry><link linkend="threads.concepts.TimedReadWriteMutex">TimedReadWriteMutex</link></entry>
<entry><link linkend="threads.concepts.TryReadWriteMutex">TryReadWriteMutex</link></entry>
<entry><classname>boost::timed_read_write_mutex</classname></entry>
</row>
</tbody>
</tgroup>
</table>
</section>
<section id="threads.concepts.read-write-lock-concepts">
<title>Lock Concepts</title>
<para>A read/write lock object provides a safe means for locking
and unlocking a read/write mutex object (an object whose type is
a model of
<link linkend="threads.concepts.ReadWriteMutex">ReadWriteMutex</link>
or one of its refinements). In other words they are an
implementation of the <emphasis>Scoped Locking</emphasis>
&cite.SchmidtStalRohnertBuschmann; pattern. The
<link linkend="threads.concepts.ScopedReadWriteLock">ScopedReadWriteLock</link>,
<link linkend="threads.concepts.ScopedTryReadWriteLock">ScopedTryReadWriteLock</link>, and
<link linkend="threads.concepts.ScopedTimedReadWriteLock">ScopedTimedReadWriteLock</link>
concepts formalize the requirements.</para>
<para>Read/write lock objects are constructed with a reference to a
read/write mutex object and typically acquire ownership of the
read/write mutex object by setting its state to locked. They also
ensure ownership is relinquished in the destructor. Lock objects
also expose functions to query the lock status and to manually lock
and unlock the read/write mutex object.</para>
<para>Read/write lock objects are meant to be short lived, expected
to be used at block scope only. The read/write lock objects are not
<link linkend="threads.glossary.thread-safe">thread-safe</link>.
Read/write lock objects must maintain state to indicate whether or
not they've been locked and this state is not protected by any
synchronization concepts. For this reason a read/write lock object
should never be shared between multiple threads.</para>
<section id="threads.concepts.ReadWriteLock">
<title>ReadWriteLock Concept</title>
<para>For a read/write lock type <code>L</code>
and an object <code>lk</code>
and const object <code>clk</code> of that type,
the following expressions must be well-formed
and have the indicated effects.</para>
<table>
<title>ReadWriteLock Expressions</title>
<tgroup cols="2">
<thead>
<row>
<entry>Expression</entry>
<entry>Effects</entry>
</row>
</thead>
<tbody>
<row>
<entry><code>(&amp;lk)-&gt;~L();</code></entry>
<entry><code>if (locked()) unlock();</code></entry>
</row>
<row>
<entry><code>(&amp;clk)-&gt;operator const void*()</code></entry>
<entry>Returns type void*, non-zero if the associated read/write
mutex object has been either read-locked or write-locked by
<code>clk</code>, otherwise 0.</entry>
</row>
<row>
<entry><code>clk.locked()</code></entry>
<entry>Returns a <code>bool</code>, <code>(&amp;clk)-&gt;operator
const void*() != 0</code></entry>
</row>
<row>
<entry><code>clk.state()</code></entry>
<entry>Returns an enumeration constant of type <code>read_write_lock_state</code>:
<code>read_write_lock_state::read_locked</code> if the associated read/write mutex object has been
read-locked by <code>clk</code>, <code>read_write_lock_state::write_locked</code> if it
has been write-locked by <code>clk</code>, and <code>read_write_lock_state::unlocked</code>
if has not been locked by <code>clk</code>.</entry>
</row>
<row>
<entry><code>clk.read_locked()</code></entry>
<entry>Returns a <code>bool</code>, <code>(&amp;clk)-&gt;state() == read_write_lock_state::read_locked</code>.</entry>
</row>
<row>
<entry><code>clk.write_locked()</code></entry>
<entry>Returns a <code>bool</code>, <code>(&amp;clk)-&gt;state() == read_write_lock_state::write_locked</code>.</entry>
</row>
<row>
<entry><code>lk.read_lock()</code></entry>
<entry>
<para>Throws <classname>boost::lock_error</classname>
if <code>locked()</code>.</para>
<para>If the associated read/write mutex
object is already read-locked by some other
thread, the effect depends on the
<link linkend="threads.concepts.read-write-scheduling-policies.inter-class">inter-class scheduling policy</link>
of the associated read/write mutex:
either immediately obtains an additional
read-lock on the associated read/write
mutex, or places the current thread in the
<link linkend="threads.glossary.thread-state">Blocked</link>
state until the associated read/write mutex
is unlocked, after which the current thread
is placed in the
<link linkend="threads.glossary.thread-state">Ready</link>
state, eventually to be returned to the
<link linkend="threads.glossary.thread-state">Running</link>
state.</para>
<para>If the associated read/write mutex
object is already write-locked by some other
thread, places the current thread in the
<link linkend="threads.glossary.thread-state">Blocked</link>
state until the associated read/write mutex
is unlocked, after which the current thread
is placed in the
<link linkend="threads.glossary.thread-state">Ready</link>
state, eventually to be returned to the
<link linkend="threads.glossary.thread-state">Running</link>
state.</para>
<para>If the associated read/write mutex
object is already locked by the same thread
the behavior is dependent on the
<link linkend="threads.concepts.read-write-locking-strategies">locking strategy</link>
of the associated read/write mutex object.
</para>
<para>Postcondition: <code>state() == read_write_lock_state::read_locked</code></para>
</entry>
</row>
<row>
<entry><code>lk.write_lock()</code></entry>
<entry>
<para>Throws <classname>boost::lock_error</classname>
if <code>locked()</code>.</para>
<para>If the associated read/write mutex
object is already locked by some other
thread, places the current thread in the
<link linkend="threads.glossary.thread-state">Blocked</link>
state until the associated read/write mutex
is unlocked, after which the current thread
is placed in the
<link linkend="threads.glossary.thread-state">Ready</link>
state, eventually to be returned to the
<link linkend="threads.glossary.thread-state">Running</link>
state.</para>
<para>If the associated read/write mutex
object is already locked by the same thread
the behavior is dependent on the
<link linkend="threads.concepts.read-write-locking-strategies">locking strategy</link>
of the associated read/write mutex object.
</para>
<para>Postcondition: <code>state() == read_write_lock_state::write_locked</code></para>
</entry>
</row>
<row>
<entry><code>lk.demote()</code></entry>
<entry>
<para>Throws <classname>boost::lock_error</classname>
if <code>state() != read_write_lock_state::write_locked</code>.</para>
<para>Converts the lock held on the associated read/write mutex
object from a write-lock to a read-lock without releasing
the lock.</para>
<para>Postcondition: <code>state() == read_write_lock_state::read_locked</code></para>
</entry>
</row>
<row>
<entry><code>lk.promote()</code></entry>
<entry>
<para>Throws <classname>boost::lock_error</classname>
if <code>state() != read_write_lock_state::read_locked</code>
or if the lock cannot be promoted because another lock
on the same mutex is already waiting to be promoted.</para>
<para>Makes a blocking attempt to convert the lock held on the associated
read/write mutex object from a read-lock to a write-lock without releasing
the lock.</para>
</entry>
</row>
<row>
<entry><code>lk.unlock()</code></entry>
<entry>
<para>Throws <classname>boost::lock_error</classname>
if <code>!locked()</code>.</para>
<para>Unlocks the associated read/write mutex.</para>
<para>Postcondition: <code>!locked()</code></para>
</entry>
</row>
</tbody>
</tgroup>
</table>
</section>
<section id="threads.concepts.ScopedReadWriteLock">
<title>ScopedReadWriteLock Concept</title>
<para>A ScopedReadWriteLock is a refinement of
<link linkend="threads.concepts.ReadWriteLock">ReadWriteLock</link>.
For a ScopedReadWriteLock type <code>L</code>
and an object <code>lk</code> of that type,
and an object <code>m</code> of a type meeting the
<link linkend="threads.concepts.ReadWriteMutex">ReadWriteMutex</link> requirements,
and an object <code>s</code> of type <code>read_write_lock_state</code>,
the following expressions must be well-formed
and have the indicated effects.</para>
<table>
<title>ScopedReadWriteLock Expressions</title>
<tgroup cols="2">
<thead>
<row>
<entry>Expression</entry>
<entry>Effects</entry>
</row>
</thead>
<tbody>
<row>
<entry><code>L lk(m,s);</code></entry>
<entry>Constructs an object <code>lk</code> and associates read/write mutex
object <code>m</code> with it, then: if <code>s == read_write_lock_state::read_locked</code>, calls
<code>read_lock()</code>; if <code>s==read_write_lock_state::write_locked</code>,
calls <code>write_lock()</code>.</entry>
</row>
</tbody>
</tgroup>
</table>
</section>
<section id="threads.concepts.TryReadWriteLock">
<title>TryReadWriteLock Expressions</title>
<para>A TryReadWriteLock is a refinement of
<link linkend="threads.concepts.ReadWriteLock">ReadWriteLock</link>.
For a TryReadWriteLock type <code>L</code>
and an object <code>lk</code> of that type,
the following expressions must be well-formed
and have the indicated effects.</para>
<table>
<title>TryReadWriteLock Expressions</title>
<tgroup cols="2">
<thead>
<row>
<entry>Expression</entry>
<entry>Effects</entry>
</row>
</thead>
<tbody>
<row>
<entry><code>lk.try_read_lock()</code></entry>
<entry>
<para>Throws <classname>boost::lock_error</classname>
if locked().</para>
<para>Makes a non-blocking attempt to read-lock the associated read/write
mutex object, returning <code>true</code> if the attempt is successful,
otherwise <code>false</code>. If the associated read/write mutex object is
already locked by the same thread the behavior is dependent on the
<link linkend="threads.concepts.locking-strategies">locking
strategy</link> of the associated read/write mutex object.</para>
</entry>
</row>
<row>
<entry><code>lk.try_write_lock()</code></entry>
<entry>
<para>Throws <classname>boost::lock_error</classname>
if locked().</para>
<para>Makes a non-blocking attempt to write-lock the associated read/write
mutex object, returning <code>true</code> if the attempt is successful,
otherwise <code>false</code>. If the associated read/write mutex object is
already locked by the same thread the behavior is dependent on the
<link linkend="threads.concepts.locking-strategies">locking
strategy</link> of the associated read/write mutex object.</para>
</entry>
</row>
<row>
<entry><code>lk.try_demote()</code></entry>
<entry>
<para>Throws <classname>boost::lock_error</classname>
if <code>state() != read_write_lock_state::write_locked</code>.</para>
<para>Makes a non-blocking attempt to convert the lock held on the associated
read/write mutex object from a write-lock to a read-lock without releasing
the lock, returning <code>true</code> if the attempt is successful,
otherwise <code>false</code>.</para>
</entry>
</row>
<row>
<entry><code>lk.try_promote()</code></entry>
<entry>
<para>Throws <classname>boost::lock_error</classname>
if <code>state() != read_write_lock_state::read_locked</code>.</para>
<para>Makes a non-blocking attempt to convert the lock held on the associated
read/write mutex object from a read-lock to a write-lock without releasing
the lock, returning <code>true</code> if the attempt is successful,
otherwise <code>false</code>.</para>
</entry>
</row>
</tbody>
</tgroup>
</table>
</section>
<section id="threads.concepts.ScopedTryReadWriteLock">
<title>ScopedTryReadWriteLock Expressions</title>
<para>A ScopedTryReadWriteLock is a refinement of
<link linkend="threads.concepts.TryReadWriteLock">TryReadWriteLock</link>.
For a ScopedTryReadWriteLock type <code>L</code>
and an object <code>lk</code> of that type,
and an object <code>m</code> of a type meeting the
<link linkend="threads.concepts.TryMutex">TryReadWriteMutex</link> requirements,
and an object <code>s</code> of type <code>read_write_lock_state</code>,
and an object <code>b</code> of type <code>blocking_mode</code>,
the following expressions must be well-formed
and have the indicated effects.</para>
<table>
<title>ScopedTryReadWriteLock Expressions</title>
<tgroup cols="2">
<thead>
<row>
<entry>Expression</entry>
<entry>Effects</entry>
</row>
</thead>
<tbody>
<row>
<entry><code>L lk(m,s,b);</code></entry>
<entry>Constructs an object <code>lk</code> and associates read/write mutex
object <code>m</code> with it, then: if <code>s == read_write_lock_state::read_locked</code>, calls
<code>read_lock()</code> if <code>b</code>, otherwise <code>try_read_lock()</code>;
if <code>s==read_write_lock_state::write_locked</code>, calls <code>write_lock()</code> if <code>b</code>,
otherwise <code>try_write_lock</code>.</entry>
</row>
</tbody>
</tgroup>
</table>
</section>
<section id="threads.concepts.TimedReadWriteLock">
<title>TimedReadWriteLock Concept</title>
<para>A TimedReadWriteLock is a refinement of
<link linkend="threads.concepts.TryReadWriteLock">TryReadWriteLock</link>.
For a TimedReadWriteLock type <code>L</code>
and an object <code>lk</code> of that type,
and an object <code>t</code> of type <classname>boost::xtime</classname>,
the following expressions must be well-formed
and have the indicated effects.</para>
<table>
<title>TimedReadWriteLock Expressions</title>
<tgroup cols="2">
<thead>
<row>
<entry>Expression</entry>
<entry>Effects</entry>
</row>
</thead>
<tbody>
<row>
<entry><code>lk.timed_read_lock(t)</code></entry>
<entry>
<para>Throws <classname>boost::lock_error</classname>
if locked().</para>
<para>Makes a blocking attempt to read-lock the associated read/write mutex object,
and returns <code>true</code> if successful within the specified time <code>t</code>,
otherwise <code>false</code>. If the associated read/write mutex object is already
locked by the same thread the behavior is dependent on the <link
linkend="threads.concepts.locking-strategies">locking
strategy</link> of the associated read/write mutex object.</para>
</entry>
</row>
<row>
<entry><code>lk.timed_write_lock(t)</code></entry>
<entry>
<para>Throws <classname>boost::lock_error</classname>
if locked().</para>
<para>Makes a blocking attempt to write-lock the associated read/write mutex object,
and returns <code>true</code> if successful within the specified time <code>t</code>,
otherwise <code>false</code>. If the associated read/write mutex object is already
locked by the same thread the behavior is dependent on the <link
linkend="threads.concepts.locking-strategies">locking
strategy</link> of the associated read/write mutex object.</para>
</entry>
</row>
<row>
<entry><code>lk.timed_demote(t)</code></entry>
<entry>
<para>Throws <classname>boost::lock_error</classname>
if <code>state() != read_write_lock_state::write_locked</code>.</para>
<para>Makes a blocking attempt to convert the lock held on the associated
read/write mutex object from a write-lock to a read-lock without releasing
the lock, returning <code>true</code> if the attempt is successful
in the specified time <code>t</code>, otherwise <code>false</code>.</para>
</entry>
</row>
<row>
<entry><code>lk.timed_promote(t)</code></entry>
<entry>
<para>Throws <classname>boost::lock_error</classname>
if <code>state() != read_write_lock_state::read_locked</code>.</para>
<para>Makes a blocking attempt to convert the lock held on the associated
read/write mutex object from a read-lock to a write-lock without releasing
the lock, returning <code>true</code> if the attempt is successful
in the specified time <code>t</code>, otherwise <code>false</code>.</para>
</entry>
</row>
</tbody>
</tgroup>
</table>
</section>
<section id="threads.concepts.ScopedTimedReadWriteLock">
<title>ScopedTimedReadWriteLock Concept</title>
<para>A ScopedTimedReadWriteLock is a refinement of
<link linkend="threads.concepts.TimedReadWriteLock">TimedReadWriteLock</link>.
For a ScopedTimedReadWriteLock type <code>L</code>
and an object <code>lk</code> of that type,
and an object <code>m</code> of a type meeting the
<link linkend="threads.concepts.TimedReadWriteMutex">TimedReadWriteMutex</link> requirements,
and an object <code>s</code> of type <code>read_write_lock_state</code>,
and an object <code>t</code> of type <classname>boost::xtime</classname>,
and an object <code>b</code> of type <code>blocking_mode</code>,
the following expressions must be well-formed and have the
indicated effects.</para>
<table>
<title>ScopedTimedReadWriteLock Expressions</title>
<tgroup cols="2">
<thead>
<row>
<entry>Expression</entry>
<entry>Effects</entry>
</row>
</thead>
<tbody>
<row>
<entry><code>L lk(m,s,b);</code></entry>
<entry>Constructs an object <code>lk</code> and associates read/write mutex
object <code>m</code> with it, then: if <code>s == read_write_lock_state::read_locked</code>, calls
<code>read_lock()</code> if <code>b</code>, otherwise <code>try_read_lock()</code>;
if <code>s==read_write_lock_state::write_locked</code>, calls <code>write_lock()</code> if <code>b</code>,
otherwise <code>try_write_lock</code>.</entry>
</row>
<row>
<entry><code>L lk(m,s,t);</code></entry>
<entry>Constructs an object <code>lk</code> and associates read/write mutex
object <code>m</code> with it, then: if <code>s == read_write_lock_state::read_locked</code>, calls
<code>timed_read_lock(t)</code>; if <code>s==read_write_lock_state::write_locked</code>,
calls <code>timed_write_lock(t)</code>.</entry>
</row>
</tbody>
</tgroup>
</table>
</section>
</section>
<section id="threads.concepts.read-write-lock-models">
<title>Lock Models</title>
<para>&Boost.Threads; currently supplies six models of
<link linkend="threads.concepts.ReadWriteLock">ReadWriteLock</link>
and its refinements.</para>
<table>
<title>Lock Models</title>
<tgroup cols="3">
<thead>
<row>
<entry>Concept</entry>
<entry>Refines</entry>
<entry>Models</entry>
</row>
</thead>
<tbody>
<row>
<entry><link linkend="threads.concepts.ReadWriteLock">ReadWriteLock</link></entry>
<entry></entry>
<entry></entry>
</row>
<row>
<entry><link linkend="threads.concepts.ScopedReadWriteLock">ScopedReadWriteLock</link></entry>
<entry><link linkend="threads.concepts.ReadWriteLock">ReadWriteLock</link></entry>
<entry>
<para><classname>boost::read_write_mutex::scoped_read_write_lock</classname></para>
<para><classname>boost::try_read_write_mutex::scoped_read_write_lock</classname></para>
<para><classname>boost::timed_read_write_mutex::scoped_read_write_lock</classname></para>
</entry>
</row>
<row>
<entry><link linkend="threads.concepts.TryReadWriteLock">TryReadWriteLock</link></entry>
<entry><link linkend="threads.concepts.ReadWriteLock">ReadWriteLock</link></entry>
<entry></entry>
</row>
<row>
<entry><link linkend="threads.concepts.ScopedTryReadWriteLock">ScopedTryReadWriteLock</link></entry>
<entry><link linkend="threads.concepts.TryReadWriteLock">TryReadWriteLock</link></entry>
<entry>
<para><classname>boost::try_read_write_mutex::scoped_try_read_write_lock</classname></para>
<para><classname>boost::timed_read_write_mutex::scoped_try_read_write_lock</classname></para>
</entry>
</row>
<row>
<entry><link linkend="threads.concepts.TimedReadWriteLock">TimedReadWriteLock</link></entry>
<entry><link linkend="threads.concepts.TryReadWriteLock">TryReadWriteLock</link></entry>
<entry></entry>
</row>
<row>
<entry><link linkend="threads.concepts.ScopedTimedReadWriteLock">ScopedTimedReadWriteLock</link></entry>
<entry><link linkend="threads.concepts.TimedReadWriteLock">TimedReadWriteLock</link></entry>
<entry>
<para><classname>boost::timed_read_write_mutex::scoped_timed_read_write_lock</classname></para>
</entry>
</row>
</tbody>
</tgroup>
</table>
</section>
</section>
</section>