1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337
|
<html>
<head>
<meta http-equiv="Content-Type" content=
"text/html; charset=iso-8859-1">
<meta name="keywords" content="threads, BTL, thread library, C++">
<title>Boost.Threads, Mutex Concept</title>
</head>
<body bgcolor="#ffffff" link="#0000ff" vlink="#800080">
<table summary="header" border="0" cellpadding="7" cellspacing="0"
width="100%">
<tr>
<td valign="top" width="300">
<h3><img height="86" alt="C++ Boost" src=
"../../../c++boost.gif" width="277"></h3>
</td>
<td valign="top">
<h1 align="center">Boost.Threads</h1>
<h2 align="center">Mutex Concepts</h2>
</td>
</tr>
</table>
<hr>
<p><a href="#Introduction">Introduction</a><br>
<a href="#LockingStrategies">Locking Strategies</a><br>
<a href="#Recursive">Recursive</a><br>
<a href="#CheckedStrategy">Checked</a><br>
<a href="#UncheckedStrategy">Unchecked</a><br>
<a href="#UnspecifiedStrategy">
Unspecified</a><br>
<a href="#SchedulingPolicies">Scheduling Policies</a><br>
<a href="#FIFO">FIFO</a><br>
<a href="#Priority Driven">Priority
Driven</a><br>
<a href="#UndefinedScheduling">
Undefined</a><br>
<a href="#UnspecifiedScheduling">
Unspecified</a><br>
<a href="#Requirements">Concept Requirements</a><br>
<a href="#Mutex">Mutex Concept</a><br>
<a href="#TryMutex">TryMutex Concept</a><br>
<a href="#TimedMutex">TimedMutex
Concept</a><br>
<a href="#Models">Models</a></p>
<h2><a name="Introduction">Introduction</a></h2>
<p>A mutex (short for mutual-exclusion) concept serializes access to a
resource shared between multiple threads. The <a href="#Mutex">
Mutex</a> concept, with <a href="#TryMutex">TryMutex</a> and <a href=
"#TimedMutex">TimedMutex</a> refinements, formalize the requirements. A
model that implements Mutex and its refinements has two states: <b>
locked</b> and <b>unlocked</b>. Before using a shared resource, a
thread locks a Boost.Threads mutex model object, insuring <a href=
"definitions.html#Thread-safe">thread-safe</a> access to the shared
resource. When use of the shared resource is complete, the thread
unlocks the mutex model object, allowing another thread to acquire the
lock and use the shared resource.</p>
<p>Traditional C thread APIs, like Pthreads or the Windows thread APIs,
expose functions to lock and unlock a mutex model. 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 model would become even greater. When
exceptions are thrown, it becomes nearly impossible to ensure that the
mutex is unlocked properly when using these traditional API's. The
result is <a href="definitions.html#Deadlock">deadlock</a>.</p>
<p>Many C++ threading libraries use a pattern known as <i>Scoped
Locking</i> <a href="bibliography.html#Schmidt 00">[Schmidt 00]</a> to
free the programmer from the need to explicitly lock and unlock
mutexes. With this pattern, a <a href="lock_concept.html">lock
concept</a> is employed where the lock model's constructor locks
the associated mutex model and the destructor automatically does the
unlocking. The <b>Boost.Threads</b> library takes this pattern to the
extreme in that lock concepts are the only way to lock and unlock a
mutex model: lock and unlock functions are not exposed by any <b>
Boost.Threads</b> mutex models. This helps to ensure safe usage
patterns, especially when code throws exceptions.</p>
<h2><a name="LockingStrategies">Locking Strategies</a></h2>
<p>Every mutex model 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 model.</p>
<h3><a name="Recursive">Recursive</a></h3>
<p>With a recursive locking strategy when a thread attempts to acquire
a lock on the mutex model 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, and a lock
object, which even for a recursive mutex cannot have its lock()
function called multiple times without first calling unlock().</p>
<p>Internally a lock count is maintained and the owning thread must
unlock the mutex model the same number of times that it's locked it
before the mutex model's state returns to unlocked. Since mutex
models in <b>Boost.Threads</b> expose locking functionality only
through lock concepts, a thread will always unlock a mutex model 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.</p>
<p>Classes <a href="recursive_mutex.html">recursive_mutex</a>, <a href=
"recursive_mutex.html">recursive_try_mutex</a> and <a href=
"recursive_mutex.html">recursive_timed_mutex</a> use this locking
strategy.</p>
<h3><a name="CheckedStrategy">Checked</a></h3>
<p>With a checked locking strategy when a thread attempts to acquire a
lock on the mutex model 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 that was not locked by the
thread will also return some sort of error indication. In <b>
Boost.Threads</b>, an exception of type <a href="lock_error.html">
lock_error</a> would be thrown in these cases.</p>
<p><b>Boost.Threads</b> does not currently provide any mutex models
that use this strategy.</p>
<h3><a name="UncheckedStrategy">Unchecked</a></h3>
<p>With an unchecked locking strategy when a thread attempts to acquire
a lock on the mutex model for which the thread already owns a lock the
operation will <a href="definitions.html#Deadlock">deadlock</a>. 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.</p>
<p><b>Boost.Threads</b> does not currently provide any mutex models
that use this strategy.</p>
<h3><a name="UnspecifiedStrategy">Unspecified</a></h3>
<p>With an unspecified locking strategy, when a thread attempts to
acquire a lock on a mutex model for which the thread already owns a
lock the operation results in <b>undefined behavior</b>. When a mutex
model has an unspecified locking strategy the programmer must assume
that the mutex model instead uses an unchecked strategy.</p>
<p>In general a mutex model with an unspecified locking strategy is
unsafe, and it requires programmer discipline to use the mutex model
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 <a href=
"mutex.html">mutex</a>, <a href="mutex.html">try_mutex</a> and <a href=
"mutex.html">timed_mutex</a> use this locking strategy despite the lack
of safety.</p>
<h2><a name="SchedulingPolicies">Scheduling Policies</a></h2>
<p>Every mutex model follows one of several scheduling policies. These
policies define the semantics when the mutex model 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.</p>
<h3><a name="FIFO">FIFO</a></h3>
<p>With a FIFO scheduling policy, threads waiting for the lock will
acquire it in a first come first serve order (or First In First Out).
This can help prevent a high priority thread from starving lower
priority threads that are also waiting on the mutex lock.</p>
<h3><a name="Priority Driven">Priority Driven</a></h3>
<p>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 model 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 lock one of the other
scheduling priorities will determine which thread shall acquire the
lock.</p>
<h3><a name="UndefinedScheduling">Undefined</a></h3>
<p>Threads acquire the lock in no particular order. Users should assume
that low-priority threads may wait indefinitely, and that threads of
the same priority acquire the lock in essentially random order.</p>
<h3><a name="UnspecifiedScheduling">Unspecified</a></h3>
<p>The mutex model does not specify which scheduling policy is used.
The programmer must assume that an undefined scheduling policy is used.
In order to ensure portability, all <b>Boost.Threads</b> mutex models
use an unspecified scheduling policy.</p>
<h2>Concept <a name="Requirements">Requirements</a></h2>
<h3><a name="Mutex">Mutex</a> Concept</h3>
<p>A Mutex object has two states: locked and unlocked. Mutex object
state can only be determined by an object meeting the <a href=
"lock_concept.html#ScopedLock">ScopedLock</a> requirements and
constructed for the Mutex object.</p>
<p>A Mutex is <a href="../../utility/utility.htm#Class noncopyable">
noncopyable</a>.</p>
<p>For a Mutex type M and an object m of that type, the following
expressions must be well-formed and have the indicated effects.</p>
<table summary="Mutex expressions" border="1" cellpadding="5">
<tr>
<td><b>Expression</b></td>
<td><b>Effects</b></td>
</tr>
<tr>
<td><code>M m;</code></td>
<td>Constructs a mutex object m. Post-condition: m is
unlocked.</td>
</tr>
<tr>
<td><code>(&m)->~M();</code></td>
<td>Precondition: m is unlocked. Destroys a mutex object
m.</td>
</tr>
<tr>
<td><code>M::scoped_lock</code></td>
<td>A type meeting the <a href="lock_concept.html#ScopedLock">
ScopedLock</a> requirements.</td>
</tr>
</table>
<h3><a name="TryMutex">TryMutex</a> Concept</h3>
<p>A TryMutex must meet the <a href="#Mutex">Mutex</a> requirements. In
addition, for a TryMutex type M and an object m of that type, the
following expressions must be well-formed and have the indicated
effects.</p>
<table summary="TryMutex expressions" border="1" cellpadding="5">
<tr>
<td><b>Expression</b></td>
<td><b>Effects</b></td>
</tr>
<tr>
<td><code>M::scoped_try_lock</code></td>
<td>A type meeting the <a href=
"lock_concept.html#ScopedTryLock">ScopedTryLock</a>
requirements.</td>
</tr>
</table>
<h3><a name="TimedMutex">TimedMutex</a> Concept</h3>
<p>A TimedMutex must meet the <a href="#TryMutex">TryMutex</a>
requirements. In addition, for a TimedMutex type M and an object m of
that type, the following expressions must be well-formed and have the
indicated effects.</p>
<table summary="TimedMutex expressions" border="1" cellpadding="5">
<tr>
<td><b>Expression</b></td>
<td><b>Effects</b></td>
</tr>
<tr>
<td><code>M::scoped_timed_lock</code></td>
<td>A type meeting the <a href=
"lock_concept.html#ScopedTimedLock">ScopedTimedLock</a>
requirements.</td>
</tr>
</table>
<h2><a name="Models">Models</a></h2>
<p><b>Boost.Threads</b> currently supplies six classes which model
mutex concepts.</p>
<table summary="Mutex concept classes" border="1" cellpadding="5">
<tr>
<td><b>Concept</b></td>
<td><b>Refines</b></td>
<td><b>Classes Modeling the Concept</b></td>
</tr>
<tr>
<td valign="top"><a href="#Mutex">Mutex</a></td>
<td valign="top"> </td>
<td><a href="mutex.html">mutex</a><br>
<a href="recursive_mutex.html">recursive_mutex</a></td>
</tr>
<tr>
<td valign="top"><a href="#TryMutex">TryMutex</a></td>
<td valign="top"><a href="#Mutex">Mutex</a></td>
<td><a href="mutex.html">try_mutex<br>
</a> <a href="recursive_mutex.html">recursive_try_mutex</a>
</td>
</tr>
<tr>
<td valign="top"><a href="#TimedMutex">TimedMutex</a></td>
<td valign="top"><a href="#TryMutex">TryMutex</a></td>
<td><a href="mutex.html">timed_mutex<br>
</a> <a href="recursive_mutex.html">
recursive_timed_mutex</a></td>
</tr>
</table>
<hr>
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->05 November, 2001<!--webbot bot="Timestamp" endspan i-checksum="39359" --></p>
<p><i>© Copyright <a href="mailto:williamkempf@hotmail.com">
William E. Kempf</a> 2001 all rights reserved.</i></p>
</body>
</html>
|