1 | <?xml version="1.0" encoding="utf-8"?> |
---|
2 | <!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" |
---|
3 | "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [ |
---|
4 | <!ENTITY % thread.entities SYSTEM "entities.xml"> |
---|
5 | %thread.entities; |
---|
6 | ]> |
---|
7 | <!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford |
---|
8 | Subject to the Boost Software License, Version 1.0. |
---|
9 | (See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0) |
---|
10 | --> |
---|
11 | <section id="thread.concepts" last-revision="$Date: 2007/01/02 21:44:39 $"> |
---|
12 | <title>Concepts</title> |
---|
13 | |
---|
14 | <para>&Boost.Thread; currently supports two types of mutex concepts: |
---|
15 | ordinary <link linkend="thread.concepts.mutexes">Mutexes</link>, |
---|
16 | which allow only one thread at a time to access a resource, and |
---|
17 | <link linkend="thread.concepts.read-write-mutexes">Read/Write Mutexes</link>, |
---|
18 | which allow only one thread at a time to access a resource when it is |
---|
19 | being modified (the "Write" part of Read/Write), but allows multiple threads |
---|
20 | to access a resource when it is only being referenced (the "Read" part of |
---|
21 | Read/Write).</para> |
---|
22 | <note> Unfortunately it turned out that the current implementation of Read/Write Mutex has |
---|
23 | some serious problems. So it was decided not to put this implementation into |
---|
24 | release grade code. Also discussions on the mailing list led to the |
---|
25 | conclusion that the current concepts need to be rethought. In particular |
---|
26 | the schedulings <link linkend="thread.concepts.read-write-scheduling-policies.inter-class"> |
---|
27 | Inter-Class Scheduling Policies</link> are deemed unnecessary. |
---|
28 | There seems to be common belief that a fair scheme suffices. |
---|
29 | The following documentation has been retained however, to give |
---|
30 | readers of this document the opportunity to study the original design. |
---|
31 | </note> |
---|
32 | |
---|
33 | <section id="thread.concepts.mutexes"> |
---|
34 | <title>Mutexes</title> |
---|
35 | |
---|
36 | <note>Certain changes to the mutexes and lock concepts are |
---|
37 | currently under discussion. In particular, the combination of |
---|
38 | the multiple lock concepts into a single lock concept |
---|
39 | is likely, and the combination of the multiple mutex |
---|
40 | concepts into a single mutex concept is also possible.</note> |
---|
41 | |
---|
42 | <para>A mutex (short for mutual-exclusion) object is used to serialize |
---|
43 | access to a resource shared between multiple threads. The |
---|
44 | <link linkend="thread.concepts.Mutex">Mutex</link> concept, with |
---|
45 | <link linkend="thread.concepts.TryMutex">TryMutex</link> and |
---|
46 | <link linkend="thread.concepts.TimedMutex">TimedMutex</link> refinements, |
---|
47 | formalize the requirements. A model that implements Mutex and its |
---|
48 | refinements has two states: <emphasis role="bold">locked</emphasis> and |
---|
49 | <emphasis role="bold">unlocked</emphasis>. Before using a shared resource, a |
---|
50 | thread locks a &Boost.Thread; mutex object |
---|
51 | (an object whose type is a model of |
---|
52 | <link linkend="thread.concepts.Mutex">Mutex</link> or one of it's |
---|
53 | refinements), ensuring |
---|
54 | <link linkend="thread.glossary.thread-safe">thread-safe</link> access to |
---|
55 | the shared resource. When use of the shared resource is complete, the thread |
---|
56 | unlocks the mutex object, allowing another thread to acquire the lock and |
---|
57 | use the shared resource.</para> |
---|
58 | <para>Traditional C thread APIs, like POSIX threads or the Windows thread |
---|
59 | APIs, expose functions to lock and unlock a mutex object. This is dangerous |
---|
60 | since it's easy to forget to unlock a locked mutex. When the flow of control |
---|
61 | is complex, with multiple return points, the likelihood of forgetting to |
---|
62 | unlock a mutex object becomes even greater. When exceptions are thrown, |
---|
63 | it becomes nearly impossible to ensure that the mutex object is unlocked |
---|
64 | properly when using these traditional API's. The result is |
---|
65 | <link linkend="thread.glossary.deadlock">deadlock</link>.</para> |
---|
66 | <para>Many C++ threading libraries use a pattern known as <emphasis>Scoped |
---|
67 | Locking</emphasis> &cite.SchmidtStalRohnertBuschmann; to free the programmer from |
---|
68 | the need to explicitly lock and unlock mutex objects. With this pattern, a |
---|
69 | <link linkend="thread.concepts.lock-concepts">Lock</link> concept is employed where |
---|
70 | the lock object's constructor locks the associated mutex object and the |
---|
71 | destructor automatically does the unlocking. The |
---|
72 | &Boost.Thread; library takes this pattern to |
---|
73 | the extreme in that Lock concepts are the only way to lock and unlock a |
---|
74 | mutex object: lock and unlock functions are not exposed by any |
---|
75 | &Boost.Thread; mutex objects. This helps to |
---|
76 | ensure safe usage patterns, especially when code throws exceptions.</para> |
---|
77 | |
---|
78 | <section id="thread.concepts.locking-strategies"> |
---|
79 | <title>Locking Strategies</title> |
---|
80 | |
---|
81 | <para>Every mutex object follows one of several locking strategies. These |
---|
82 | strategies define the semantics for the locking operation when the calling |
---|
83 | thread already owns a lock on the mutex object.</para> |
---|
84 | |
---|
85 | <section id="thread.concepts.recursive-locking-strategy"> |
---|
86 | <title>Recursive Locking Strategy</title> |
---|
87 | |
---|
88 | <para>With a recursive locking strategy, when a thread attempts to acquire |
---|
89 | a lock on the mutex object for which it already owns a lock, the operation |
---|
90 | is successful. Note the distinction between a thread, which may have |
---|
91 | multiple locks outstanding on a recursive mutex object, and a lock object, |
---|
92 | which even for a recursive mutex object cannot have any of its lock |
---|
93 | functions called multiple times without first calling unlock.</para> |
---|
94 | |
---|
95 | <para>Internally a lock count is maintained and the owning thread must |
---|
96 | unlock the mutex object the same number of times that it locked it before |
---|
97 | the mutex object's state returns to unlocked. Since mutex objects in |
---|
98 | &Boost.Thread; expose locking |
---|
99 | functionality only through lock concepts, a thread will always unlock a |
---|
100 | mutex object the same number of times that it locked it. This helps to |
---|
101 | eliminate a whole set of errors typically found in traditional C style |
---|
102 | thread APIs.</para> |
---|
103 | |
---|
104 | <para>Classes <classname>boost::recursive_mutex</classname>, |
---|
105 | <classname>boost::recursive_try_mutex</classname> and |
---|
106 | <classname>boost::recursive_timed_mutex</classname> use this locking |
---|
107 | strategy.</para> |
---|
108 | </section> |
---|
109 | |
---|
110 | <section id="thread.concepts.checked-locking-strategy"> |
---|
111 | <title>Checked Locking Strategy</title> |
---|
112 | |
---|
113 | <para>With a checked locking strategy, when a thread attempts to acquire a |
---|
114 | lock on the mutex object for which the thread already owns a lock, the |
---|
115 | operation will fail with some sort of error indication. Further, attempts |
---|
116 | by a thread to unlock a mutex object that was not locked by the thread |
---|
117 | will also return some sort of error indication. In |
---|
118 | &Boost.Thread;, an exception of type |
---|
119 | <classname>boost::lock_error</classname> |
---|
120 | would be thrown in these cases.</para> |
---|
121 | |
---|
122 | <para>&Boost.Thread; does not currently |
---|
123 | provide any mutex objects that use this strategy.</para> |
---|
124 | </section> |
---|
125 | |
---|
126 | <section id="thread.concepts.unchecked-locking-strategy"> |
---|
127 | <title>Unchecked Locking Strategy</title> |
---|
128 | |
---|
129 | <para>With an unchecked locking strategy, when a thread attempts to acquire |
---|
130 | a lock on a mutex object for which the thread already owns a lock the |
---|
131 | operation will |
---|
132 | <link linkend="thread.glossary.deadlock">deadlock</link>. In general |
---|
133 | this locking strategy is less safe than a checked or recursive strategy, |
---|
134 | but it's also a faster strategy and so is employed by many libraries.</para> |
---|
135 | |
---|
136 | <para>&Boost.Thread; does not currently |
---|
137 | provide any mutex objects that use this strategy.</para> |
---|
138 | </section> |
---|
139 | |
---|
140 | <section id="thread.concepts.unspecified-locking-strategy"> |
---|
141 | <title>Unspecified Locking Strategy</title> |
---|
142 | |
---|
143 | <para>With an unspecified locking strategy, when a thread attempts to |
---|
144 | acquire a lock on a mutex object for which the thread already owns a lock |
---|
145 | the operation results in |
---|
146 | <link linkend="thread.glossary.undefined-behavior">undefined behavior</link>. |
---|
147 | </para> |
---|
148 | |
---|
149 | <para>In general a mutex object with an unspecified locking strategy is |
---|
150 | unsafe, and it requires programmer discipline to use the mutex object |
---|
151 | properly. However, this strategy allows an implementation to be as fast as |
---|
152 | possible with no restrictions on its implementation. This is especially |
---|
153 | true for portable implementations that wrap the native threading support |
---|
154 | of a platform. For this reason, the classes |
---|
155 | <classname>boost::mutex</classname>, |
---|
156 | <classname>boost::try_mutex</classname> and |
---|
157 | <classname>boost::timed_mutex</classname> use this locking strategy |
---|
158 | despite the lack of safety.</para> |
---|
159 | </section> |
---|
160 | </section> |
---|
161 | |
---|
162 | <section id="thread.concepts.sheduling-policies"> |
---|
163 | <title>Scheduling Policies</title> |
---|
164 | |
---|
165 | <para>Every mutex object follows one of several scheduling policies. These |
---|
166 | policies define the semantics when the mutex object is unlocked and there is |
---|
167 | more than one thread waiting to acquire a lock. In other words, the policy |
---|
168 | defines which waiting thread shall acquire the lock.</para> |
---|
169 | |
---|
170 | <section id="thread.concepts.FIFO-scheduling-policy"> |
---|
171 | <title>FIFO Scheduling Policy</title> |
---|
172 | |
---|
173 | <para>With a FIFO ("First In First Out") scheduling policy, threads waiting |
---|
174 | for the lock will acquire it in a first-come-first-served order. |
---|
175 | This can help prevent a high priority thread from starving lower priority |
---|
176 | threads that are also waiting on the mutex object's lock.</para> |
---|
177 | </section> |
---|
178 | |
---|
179 | <section id="thread.concepts.priority-driven-scheduling-policy"> |
---|
180 | <title>Priority Driven Policy</title> |
---|
181 | |
---|
182 | <para>With a Priority Driven scheduling policy, the thread with the |
---|
183 | highest priority acquires the lock. Note that this means that low-priority |
---|
184 | threads may never acquire the lock if the mutex object has high contention |
---|
185 | and there is always at least one high-priority thread waiting. This is |
---|
186 | known as thread starvation. When multiple threads of the same priority are |
---|
187 | waiting on the mutex object's lock one of the other scheduling priorities |
---|
188 | will determine which thread shall acquire the lock.</para> |
---|
189 | </section> |
---|
190 | |
---|
191 | <section id="thread.concepts.unspecified-scheduling-policy"> |
---|
192 | <title>Unspecified Policy</title> |
---|
193 | |
---|
194 | <para>The mutex object does not specify a scheduling policy. In order to |
---|
195 | ensure portability, all &Boost.Thread; |
---|
196 | mutex objects use an unspecified scheduling policy.</para> |
---|
197 | </section> |
---|
198 | </section> |
---|
199 | |
---|
200 | <section id="thread.concepts.mutex-concepts"> |
---|
201 | <title>Mutex Concepts</title> |
---|
202 | |
---|
203 | <section id="thread.concepts.Mutex"> |
---|
204 | <title>Mutex Concept</title> |
---|
205 | |
---|
206 | <para>A Mutex object has two states: locked and unlocked. Mutex object |
---|
207 | state can only be determined by a lock object meeting the |
---|
208 | appropriate lock concept requirements |
---|
209 | and constructed for the Mutex object.</para> |
---|
210 | |
---|
211 | <para>A Mutex is |
---|
212 | <ulink url="../../libs/utility/utility.htm#Class%20noncopyable"> |
---|
213 | NonCopyable</ulink>.</para> |
---|
214 | <para>For a Mutex type <code>M</code> |
---|
215 | and an object <code>m</code> of that type, |
---|
216 | the following expressions must be well-formed |
---|
217 | and have the indicated effects.</para> |
---|
218 | |
---|
219 | <table> |
---|
220 | <title>Mutex Expressions</title> |
---|
221 | |
---|
222 | <tgroup cols="2"> |
---|
223 | <thead> |
---|
224 | <row> |
---|
225 | <entry>Expression</entry> |
---|
226 | <entry>Effects</entry> |
---|
227 | </row> |
---|
228 | </thead> |
---|
229 | |
---|
230 | <tbody> |
---|
231 | <row> |
---|
232 | <entry>M m;</entry> |
---|
233 | <entry><para>Constructs a mutex object m.</para> |
---|
234 | <para>Postcondition: m is unlocked.</para></entry> |
---|
235 | </row> |
---|
236 | <row> |
---|
237 | <entry>(&m)->~M();</entry> |
---|
238 | <entry>Precondition: m is unlocked. Destroys a mutex object |
---|
239 | m.</entry> |
---|
240 | </row> |
---|
241 | <row> |
---|
242 | <entry>M::scoped_lock</entry> |
---|
243 | <entry>A model of |
---|
244 | <link linkend="thread.concepts.ScopedLock">ScopedLock</link> |
---|
245 | </entry> |
---|
246 | </row> |
---|
247 | </tbody> |
---|
248 | </tgroup> |
---|
249 | </table> |
---|
250 | </section> |
---|
251 | |
---|
252 | <section id="thread.concepts.TryMutex"> |
---|
253 | <title>TryMutex Concept</title> |
---|
254 | |
---|
255 | <para>A TryMutex is a refinement of |
---|
256 | <link linkend="thread.concepts.Mutex">Mutex</link>. |
---|
257 | For a TryMutex type <code>M</code> |
---|
258 | and an object <code>m</code> of that type, |
---|
259 | the following expressions must be well-formed |
---|
260 | and have the indicated effects.</para> |
---|
261 | |
---|
262 | <table> |
---|
263 | <title>TryMutex Expressions</title> |
---|
264 | |
---|
265 | <tgroup cols="2"> |
---|
266 | <thead> |
---|
267 | <row> |
---|
268 | <entry>Expression</entry> |
---|
269 | <entry>Effects</entry> |
---|
270 | </row> |
---|
271 | </thead> |
---|
272 | |
---|
273 | <tbody> |
---|
274 | <row> |
---|
275 | <entry>M::scoped_try_lock</entry> |
---|
276 | <entry>A model of |
---|
277 | <link linkend="thread.concepts.ScopedTryLock">ScopedTryLock</link> |
---|
278 | </entry> |
---|
279 | </row> |
---|
280 | </tbody> |
---|
281 | </tgroup> |
---|
282 | </table> |
---|
283 | </section> |
---|
284 | |
---|
285 | <section id="thread.concepts.TimedMutex"> |
---|
286 | <title>TimedMutex Concept</title> |
---|
287 | |
---|
288 | <para>A TimedMutex is a refinement of |
---|
289 | <link linkend="thread.concepts.TryMutex">TryMutex</link>. |
---|
290 | For a TimedMutex type <code>M</code> |
---|
291 | and an object <code>m</code> of that type, |
---|
292 | the following expressions must be well-formed |
---|
293 | and have the indicated effects.</para> |
---|
294 | |
---|
295 | <table> |
---|
296 | <title>TimedMutex Expressions</title> |
---|
297 | |
---|
298 | <tgroup cols="2"> |
---|
299 | <thead> |
---|
300 | <row> |
---|
301 | <entry>Expression</entry> |
---|
302 | <entry>Effects</entry> |
---|
303 | </row> |
---|
304 | </thead> |
---|
305 | |
---|
306 | <tbody> |
---|
307 | <row> |
---|
308 | <entry>M::scoped_timed_lock</entry> |
---|
309 | <entry>A model of |
---|
310 | <link |
---|
311 | linkend="thread.concepts.ScopedTimedLock">ScopedTimedLock</link> |
---|
312 | </entry> |
---|
313 | </row> |
---|
314 | </tbody> |
---|
315 | </tgroup> |
---|
316 | </table> |
---|
317 | </section> |
---|
318 | </section> |
---|
319 | |
---|
320 | <section id="thread.concepts.mutex-models"> |
---|
321 | <title>Mutex Models</title> |
---|
322 | |
---|
323 | <para>&Boost.Thread; currently supplies six models of |
---|
324 | <link linkend="thread.concepts.Mutex">Mutex</link> |
---|
325 | and its refinements.</para> |
---|
326 | |
---|
327 | <table> |
---|
328 | <title>Mutex Models</title> |
---|
329 | |
---|
330 | <tgroup cols="3"> |
---|
331 | <thead> |
---|
332 | <row> |
---|
333 | <entry>Concept</entry> |
---|
334 | <entry>Refines</entry> |
---|
335 | <entry>Models</entry> |
---|
336 | </row> |
---|
337 | </thead> |
---|
338 | |
---|
339 | <tbody> |
---|
340 | <row> |
---|
341 | <entry><link linkend="thread.concepts.Mutex">Mutex</link></entry> |
---|
342 | <entry></entry> |
---|
343 | <entry> |
---|
344 | <para><classname>boost::mutex</classname></para> |
---|
345 | <para><classname>boost::recursive_mutex</classname></para> |
---|
346 | </entry> |
---|
347 | </row> |
---|
348 | <row> |
---|
349 | <entry><link linkend="thread.concepts.TryMutex">TryMutex</link></entry> |
---|
350 | <entry><link linkend="thread.concepts.Mutex">Mutex</link></entry> |
---|
351 | <entry> |
---|
352 | <para><classname>boost::try_mutex</classname></para> |
---|
353 | <para><classname>boost::recursive_try_mutex</classname></para> |
---|
354 | </entry> |
---|
355 | </row> |
---|
356 | <row> |
---|
357 | <entry><link linkend="thread.concepts.TimedMutex">TimedMutex</link></entry> |
---|
358 | <entry><link linkend="thread.concepts.TryMutex">TryMutex</link></entry> |
---|
359 | <entry> |
---|
360 | <para><classname>boost::timed_mutex</classname></para> |
---|
361 | <para><classname>boost::recursive_timed_mutex</classname></para> |
---|
362 | </entry> |
---|
363 | </row> |
---|
364 | </tbody> |
---|
365 | </tgroup> |
---|
366 | </table> |
---|
367 | </section> |
---|
368 | |
---|
369 | <section id="thread.concepts.lock-concepts"> |
---|
370 | <title>Lock Concepts</title> |
---|
371 | |
---|
372 | <para>A lock object provides a safe means for locking and unlocking a mutex |
---|
373 | object (an object whose type is a model of <link |
---|
374 | linkend="thread.concepts.Mutex">Mutex</link> or one of its refinements). In |
---|
375 | other words they are an implementation of the <emphasis>Scoped |
---|
376 | Locking</emphasis> &cite.SchmidtStalRohnertBuschmann; pattern. The <link |
---|
377 | linkend="thread.concepts.ScopedLock">ScopedLock</link>, |
---|
378 | <link linkend="thread.concepts.ScopedTryLock">ScopedTryLock</link>, and |
---|
379 | <link linkend="thread.concepts.ScopedTimedLock">ScopedTimedLock</link> |
---|
380 | concepts formalize the requirements.</para> |
---|
381 | <para>Lock objects are constructed with a reference to a mutex object and |
---|
382 | typically acquire ownership of the mutex object by setting its state to |
---|
383 | locked. They also ensure ownership is relinquished in the destructor. Lock |
---|
384 | objects also expose functions to query the lock status and to manually lock |
---|
385 | and unlock the mutex object.</para> |
---|
386 | <para>Lock objects are meant to be short lived, expected to be used at block |
---|
387 | scope only. The lock objects are not <link |
---|
388 | linkend="thread.glossary.thread-safe">thread-safe</link>. Lock objects must |
---|
389 | maintain state to indicate whether or not they've been locked and this state |
---|
390 | is not protected by any synchronization concepts. For this reason a lock |
---|
391 | object should never be shared between multiple threads.</para> |
---|
392 | |
---|
393 | <section id="thread.concepts.Lock"> |
---|
394 | <title>Lock Concept</title> |
---|
395 | |
---|
396 | <para>For a Lock type <code>L</code> |
---|
397 | and an object <code>lk</code> |
---|
398 | and const object <code>clk</code> of that type, |
---|
399 | the following expressions must be well-formed |
---|
400 | and have the indicated effects.</para> |
---|
401 | |
---|
402 | <table> |
---|
403 | <title>Lock Expressions</title> |
---|
404 | |
---|
405 | <tgroup cols="2"> |
---|
406 | <thead> |
---|
407 | <row> |
---|
408 | <entry>Expression</entry> |
---|
409 | <entry>Effects</entry> |
---|
410 | </row> |
---|
411 | </thead> |
---|
412 | |
---|
413 | <tbody> |
---|
414 | <row> |
---|
415 | <entry><code>(&lk)->~L();</code></entry> |
---|
416 | <entry><code>if (locked()) unlock();</code></entry> |
---|
417 | </row> |
---|
418 | <row> |
---|
419 | <entry><code>(&clk)->operator const void*()</code></entry> |
---|
420 | <entry>Returns type void*, non-zero if the associated mutex |
---|
421 | object has been locked by <code>clk</code>, otherwise 0.</entry> |
---|
422 | </row> |
---|
423 | <row> |
---|
424 | <entry><code>clk.locked()</code></entry> |
---|
425 | <entry>Returns a <code>bool</code>, <code>(&clk)->operator |
---|
426 | const void*() != 0</code></entry> |
---|
427 | </row> |
---|
428 | <row> |
---|
429 | <entry><code>lk.lock()</code></entry> |
---|
430 | <entry> |
---|
431 | <para>Throws <classname>boost::lock_error</classname> |
---|
432 | if <code>locked()</code>.</para> |
---|
433 | |
---|
434 | <para>If the associated mutex object is |
---|
435 | already locked by some other thread, places the current thread in the |
---|
436 | <link linkend="thread.glossary.thread-state">Blocked</link> state until |
---|
437 | the associated mutex is unlocked, after which the current thread |
---|
438 | is placed in the <link |
---|
439 | linkend="thread.glossary.thread-state">Ready</link> state, |
---|
440 | eventually to be returned to the <link |
---|
441 | linkend="thread.glossary.thread-state">Running</link> state. If |
---|
442 | the associated mutex object is already locked by the same thread |
---|
443 | the behavior is dependent on the <link |
---|
444 | linkend="thread.concepts.locking-strategies">locking |
---|
445 | strategy</link> of the associated mutex object.</para> |
---|
446 | |
---|
447 | <para>Postcondition: <code>locked() == true</code></para> |
---|
448 | </entry> |
---|
449 | </row> |
---|
450 | <row> |
---|
451 | <entry><code>lk.unlock()</code></entry> |
---|
452 | <entry> |
---|
453 | <para>Throws <classname>boost::lock_error</classname> |
---|
454 | if <code>!locked()</code>.</para> |
---|
455 | |
---|
456 | <para>Unlocks the associated mutex.</para> |
---|
457 | |
---|
458 | <para>Postcondition: <code>!locked()</code></para></entry> |
---|
459 | </row> |
---|
460 | </tbody> |
---|
461 | </tgroup> |
---|
462 | </table> |
---|
463 | </section> |
---|
464 | |
---|
465 | <section id="thread.concepts.ScopedLock"> |
---|
466 | <title>ScopedLock Concept</title> |
---|
467 | |
---|
468 | <para>A ScopedLock is a refinement of <link |
---|
469 | linkend="thread.concepts.Lock">Lock</link>. |
---|
470 | For a ScopedLock type <code>L</code> |
---|
471 | and an object <code>lk</code> of that type, |
---|
472 | and an object <code>m</code> of a type meeting the |
---|
473 | <link linkend="thread.concepts.Mutex">Mutex</link> requirements, |
---|
474 | and an object <code>b</code> of type <code>bool</code>, |
---|
475 | the following expressions must be well-formed |
---|
476 | and have the indicated effects.</para> |
---|
477 | |
---|
478 | <table> |
---|
479 | <title>ScopedLock Expressions</title> |
---|
480 | |
---|
481 | <tgroup cols="2"> |
---|
482 | <thead> |
---|
483 | <row> |
---|
484 | <entry>Expression</entry> |
---|
485 | <entry>Effects</entry> |
---|
486 | </row> |
---|
487 | </thead> |
---|
488 | |
---|
489 | <tbody> |
---|
490 | <row> |
---|
491 | <entry><code>L lk(m);</code></entry> |
---|
492 | <entry>Constructs an object <code>lk</code>, and associates mutex |
---|
493 | object <code>m</code> with it, then calls |
---|
494 | <code>lock()</code></entry> |
---|
495 | </row> |
---|
496 | <row> |
---|
497 | <entry><code>L lk(m,b);</code></entry> |
---|
498 | <entry>Constructs an object <code>lk</code>, and associates mutex |
---|
499 | object <code>m</code> with it, then if <code>b</code>, calls |
---|
500 | <code>lock()</code></entry> |
---|
501 | </row> |
---|
502 | </tbody> |
---|
503 | </tgroup> |
---|
504 | </table> |
---|
505 | </section> |
---|
506 | |
---|
507 | <section id="thread.concepts.TryLock"> |
---|
508 | <title>TryLock Concept</title> |
---|
509 | |
---|
510 | <para>A TryLock is a refinement of <link |
---|
511 | linkend="thread.concepts.Lock">Lock</link>. |
---|
512 | For a TryLock type <code>L</code> |
---|
513 | and an object <code>lk</code> of that type, |
---|
514 | the following expressions must be well-formed |
---|
515 | and have the indicated effects.</para> |
---|
516 | |
---|
517 | <table> |
---|
518 | <title>TryLock Expressions</title> |
---|
519 | |
---|
520 | <tgroup cols="2"> |
---|
521 | <thead> |
---|
522 | <row> |
---|
523 | <entry>Expression</entry> |
---|
524 | <entry>Effects</entry> |
---|
525 | </row> |
---|
526 | </thead> |
---|
527 | |
---|
528 | <tbody> |
---|
529 | <row> |
---|
530 | <entry><code>lk.try_lock()</code></entry> |
---|
531 | <entry> |
---|
532 | <para>Throws <classname>boost::lock_error</classname> |
---|
533 | if locked().</para> |
---|
534 | |
---|
535 | <para>Makes a |
---|
536 | non-blocking attempt to lock the associated mutex object, |
---|
537 | returning <code>true</code> if the lock attempt is successful, |
---|
538 | otherwise <code>false</code>. If the associated mutex object is |
---|
539 | already locked by the same thread the behavior is dependent on the |
---|
540 | <link linkend="thread.concepts.locking-strategies">locking |
---|
541 | strategy</link> of the associated mutex object.</para> |
---|
542 | </entry> |
---|
543 | </row> |
---|
544 | </tbody> |
---|
545 | </tgroup> |
---|
546 | </table> |
---|
547 | </section> |
---|
548 | |
---|
549 | <section id="thread.concepts.ScopedTryLock"> |
---|
550 | <title>ScopedTryLock Concept</title> |
---|
551 | |
---|
552 | <para>A ScopedTryLock is a refinement of <link |
---|
553 | linkend="thread.concepts.TryLock">TryLock</link>. |
---|
554 | For a ScopedTryLock type <code>L</code> |
---|
555 | and an object <code>lk</code> of that type, |
---|
556 | and an object <code>m</code> of a type meeting the |
---|
557 | <link linkend="thread.concepts.TryMutex">TryMutex</link> requirements, |
---|
558 | and an object <code>b</code> of type <code>bool</code>, |
---|
559 | the following expressions must be well-formed |
---|
560 | and have the indicated effects.</para> |
---|
561 | |
---|
562 | <table> |
---|
563 | <title>ScopedTryLock Expressions</title> |
---|
564 | |
---|
565 | <tgroup cols="2"> |
---|
566 | <thead> |
---|
567 | <row> |
---|
568 | <entry>Expression</entry> |
---|
569 | <entry>Effects</entry> |
---|
570 | </row> |
---|
571 | </thead> |
---|
572 | |
---|
573 | <tbody> |
---|
574 | <row> |
---|
575 | <entry><code>L lk(m);</code></entry> |
---|
576 | <entry>Constructs an object <code>lk</code>, and associates mutex |
---|
577 | object <code>m</code> with it, then calls |
---|
578 | <code>try_lock()</code></entry> |
---|
579 | </row> |
---|
580 | <row> |
---|
581 | <entry><code>L lk(m,b);</code></entry> |
---|
582 | <entry>Constructs an object <code>lk</code>, and associates mutex |
---|
583 | object <code>m</code> with it, then if <code>b</code>, calls |
---|
584 | <code>lock()</code></entry> |
---|
585 | </row> |
---|
586 | </tbody> |
---|
587 | </tgroup> |
---|
588 | </table> |
---|
589 | </section> |
---|
590 | |
---|
591 | <section id="thread.concepts.TimedLock"> |
---|
592 | <title>TimedLock Concept</title> |
---|
593 | |
---|
594 | <para>A TimedLock is a refinement of <link |
---|
595 | linkend="thread.concepts.TryLock">TryLock</link>. |
---|
596 | For a TimedLock type <code>L</code> |
---|
597 | and an object <code>lk</code> of that type, |
---|
598 | and an object <code>t</code> of type <classname>boost::xtime</classname>, |
---|
599 | the following expressions must be well-formed |
---|
600 | and have the indicated effects.</para> |
---|
601 | |
---|
602 | <table> |
---|
603 | <title>TimedLock Expressions</title> |
---|
604 | <tgroup cols="2"> |
---|
605 | <thead> |
---|
606 | <row> |
---|
607 | <entry>Expression</entry> |
---|
608 | <entry>Effects</entry> |
---|
609 | </row> |
---|
610 | </thead> |
---|
611 | |
---|
612 | <tbody> |
---|
613 | <row> |
---|
614 | <entry><code>lk.timed_lock(t)</code></entry> |
---|
615 | <entry> |
---|
616 | <para>Throws <classname>boost::lock_error</classname> |
---|
617 | if locked().</para> |
---|
618 | |
---|
619 | <para>Makes a blocking attempt |
---|
620 | to lock the associated mutex object, and returns <code>true</code> |
---|
621 | if successful within the specified time <code>t</code>, otherwise |
---|
622 | <code>false</code>. If the associated mutex object is already |
---|
623 | locked by the same thread the behavior is dependent on the <link |
---|
624 | linkend="thread.concepts.locking-strategies">locking |
---|
625 | strategy</link> of the associated mutex object.</para> |
---|
626 | </entry> |
---|
627 | </row> |
---|
628 | </tbody> |
---|
629 | </tgroup> |
---|
630 | </table> |
---|
631 | </section> |
---|
632 | |
---|
633 | <section id="thread.concepts.ScopedTimedLock"> |
---|
634 | <title>ScopedTimedLock Concept</title> |
---|
635 | |
---|
636 | <para>A ScopedTimedLock is a refinement of <link |
---|
637 | linkend="thread.concepts.TimedLock">TimedLock</link>. |
---|
638 | For a ScopedTimedLock type <code>L</code> |
---|
639 | and an object <code>lk</code> of that type, |
---|
640 | and an object <code>m</code> of a type meeting the |
---|
641 | <link linkend="thread.concepts.TimedMutex">TimedMutex</link> requirements, |
---|
642 | and an object <code>b</code> of type <code>bool</code>, |
---|
643 | and an object <code>t</code> of type <classname>boost::xtime</classname>, |
---|
644 | the following expressions must be well-formed |
---|
645 | and have the indicated effects.</para> |
---|
646 | |
---|
647 | <table> |
---|
648 | <title>ScopedTimedLock Expressions</title> |
---|
649 | <tgroup cols="2"> |
---|
650 | <thead> |
---|
651 | <row> |
---|
652 | <entry>Expression</entry> |
---|
653 | <entry>Effects</entry> |
---|
654 | </row> |
---|
655 | </thead> |
---|
656 | |
---|
657 | <tbody> |
---|
658 | <row> |
---|
659 | <entry><code>L lk(m,t);</code></entry> |
---|
660 | <entry>Constructs an object <code>lk</code>, and associates mutex |
---|
661 | object <code>m</code> with it, then calls |
---|
662 | <code>timed_lock(t)</code></entry> |
---|
663 | </row> |
---|
664 | <row> |
---|
665 | <entry><code>L lk(m,b);</code></entry> |
---|
666 | <entry>Constructs an object <code>lk</code>, and associates mutex |
---|
667 | object <code>m</code> with it, then if <code>b</code>, calls |
---|
668 | <code>lock()</code></entry> |
---|
669 | </row> |
---|
670 | </tbody> |
---|
671 | </tgroup> |
---|
672 | </table> |
---|
673 | </section> |
---|
674 | </section> |
---|
675 | |
---|
676 | <section id="thread.concepts.lock-models"> |
---|
677 | <title>Lock Models</title> |
---|
678 | |
---|
679 | <para>&Boost.Thread; currently supplies twelve models of |
---|
680 | <link linkend="thread.concepts.Lock">Lock</link> |
---|
681 | and its refinements.</para> |
---|
682 | |
---|
683 | <table> |
---|
684 | <title>Lock Models</title> |
---|
685 | |
---|
686 | <tgroup cols="3"> |
---|
687 | <thead> |
---|
688 | <row> |
---|
689 | <entry>Concept</entry> |
---|
690 | <entry>Refines</entry> |
---|
691 | <entry>Models</entry> |
---|
692 | </row> |
---|
693 | </thead> |
---|
694 | |
---|
695 | <tbody> |
---|
696 | <row> |
---|
697 | <entry><link linkend="thread.concepts.Lock">Lock</link></entry> |
---|
698 | <entry></entry> |
---|
699 | <entry></entry> |
---|
700 | </row> |
---|
701 | <row> |
---|
702 | <entry><link linkend="thread.concepts.ScopedLock">ScopedLock</link></entry> |
---|
703 | <entry><link linkend="thread.concepts.Lock">Lock</link></entry> |
---|
704 | <entry> |
---|
705 | <para><classname>boost::mutex::scoped_lock</classname></para> |
---|
706 | <para><classname>boost::recursive_mutex::scoped_lock</classname></para> |
---|
707 | |
---|
708 | <para><classname>boost::try_mutex::scoped_lock</classname></para> |
---|
709 | <para><classname>boost::recursive_try_mutex::scoped_lock</classname></para> |
---|
710 | |
---|
711 | <para><classname>boost::timed_mutex::scoped_lock</classname></para> |
---|
712 | <para><classname>boost::recursive_timed_mutex::scoped_lock</classname></para> |
---|
713 | </entry> |
---|
714 | </row> |
---|
715 | <row> |
---|
716 | <entry><link linkend="thread.concepts.TryLock">TryLock</link></entry> |
---|
717 | <entry><link linkend="thread.concepts.Lock">Lock</link></entry> |
---|
718 | <entry></entry> |
---|
719 | </row> |
---|
720 | <row> |
---|
721 | <entry><link linkend="thread.concepts.ScopedTryLock">ScopedTryLock</link></entry> |
---|
722 | <entry><link linkend="thread.concepts.TryLock">TryLock</link></entry> |
---|
723 | <entry> |
---|
724 | <para><classname>boost::try_mutex::scoped_try_lock</classname></para> |
---|
725 | <para><classname>boost::recursive_try_mutex::scoped_try_lock</classname></para> |
---|
726 | |
---|
727 | <para><classname>boost::timed_mutex::scoped_try_lock</classname></para> |
---|
728 | <para><classname>boost::recursive_timed_mutex::scoped_try_lock</classname></para> |
---|
729 | </entry> |
---|
730 | </row> |
---|
731 | <row> |
---|
732 | <entry><link linkend="thread.concepts.TimedLock">TimedLock</link></entry> |
---|
733 | <entry><link linkend="thread.concepts.TryLock">TryLock</link></entry> |
---|
734 | <entry></entry> |
---|
735 | </row> |
---|
736 | <row> |
---|
737 | <entry><link linkend="thread.concepts.ScopedTimedLock">ScopedTimedLock</link></entry> |
---|
738 | <entry><link linkend="thread.concepts.TimedLock">TimedLock</link></entry> |
---|
739 | <entry> |
---|
740 | <para><classname>boost::timed_mutex::scoped_timed_lock</classname></para> |
---|
741 | <para><classname>boost::recursive_timed_mutex::scoped_timed_lock</classname></para> |
---|
742 | </entry> |
---|
743 | </row> |
---|
744 | </tbody> |
---|
745 | </tgroup> |
---|
746 | </table> |
---|
747 | </section> |
---|
748 | </section> |
---|
749 | |
---|
750 | <section id="thread.concepts.read-write-mutexes"> |
---|
751 | <title>Read/Write Mutexes</title> |
---|
752 | <note> Unfortunately it turned out that the current implementation has |
---|
753 | some serious problems. So it was decided not to put this implementation into |
---|
754 | release grade code. Also discussions on the mailing list led to the |
---|
755 | conclusion that the current concepts need to be rethought. In particular |
---|
756 | the schedulings <link linkend="thread.concepts.read-write-scheduling-policies.inter-class"> |
---|
757 | Inter-Class Scheduling Policies</link> are deemed unnecessary. |
---|
758 | There seems to be common belief that a fair scheme suffices. |
---|
759 | The following documentation has been retained however, to give |
---|
760 | readers of this document the opportunity to study the original design. |
---|
761 | </note> |
---|
762 | |
---|
763 | <para>A read/write mutex (short for reader/writer mutual-exclusion) object |
---|
764 | is used to serialize access to a resource shared between multiple |
---|
765 | threads, where multiple "readers" can share simultaneous access, but |
---|
766 | "writers" require exclusive access. The |
---|
767 | <link linkend="thread.concepts.ReadWriteMutex">ReadWriteMutex</link> concept, with |
---|
768 | <link linkend="thread.concepts.TryReadWriteMutex">TryReadWriteMutex</link> and |
---|
769 | <link linkend="thread.concepts.TimedReadWriteMutex"> TimedReadWriteMutex</link> |
---|
770 | refinements formalize the requirements. A model that implements |
---|
771 | ReadWriteMutex and its refinements has three states: |
---|
772 | <emphasis role="bold">read-locked</emphasis>, |
---|
773 | <emphasis role="bold">write-locked</emphasis>, and |
---|
774 | <emphasis role="bold">unlocked</emphasis>. |
---|
775 | Before reading from a shared resource, a thread |
---|
776 | <emphasis role="bold">read-locks</emphasis> |
---|
777 | a &Boost.Thread; read/write mutex object |
---|
778 | (an object whose type is a model of |
---|
779 | <link linkend="thread.concepts.ReadWriteMutex">ReadWriteMutex</link> |
---|
780 | or one of it's refinements), ensuring |
---|
781 | <link linkend="thread.glossary.thread-safe">thread-safe</link> |
---|
782 | access for reading from the shared resource. Before writing |
---|
783 | to a shared resource, a thread |
---|
784 | <emphasis role="bold">write-locks</emphasis> a &Boost.Thread; |
---|
785 | read/write mutex object |
---|
786 | (an object whose type is a model of |
---|
787 | <link linkend="thread.concepts.ReadWriteMutex">ReadWriteMutex</link> |
---|
788 | or one of it's refinements), ensuring |
---|
789 | <link linkend="thread.glossary.thread-safe">thread-safe</link> |
---|
790 | access for altering the shared resource. When use of the shared |
---|
791 | resource is complete, the thread unlocks the mutex object, |
---|
792 | allowing another thread to acquire the lock and use the shared |
---|
793 | resource.</para> |
---|
794 | |
---|
795 | <para>Traditional C thread APIs that provide read/write mutex |
---|
796 | primitives (like POSIX threads) expose functions to lock and unlock a |
---|
797 | mutex object. This is dangerous since it's easy to forget to unlock a |
---|
798 | locked mutex. When the flow of control is complex, with multiple |
---|
799 | return points, the likelihood of forgetting to unlock a mutex object |
---|
800 | becomes even greater. When exceptions are thrown, it becomes nearly |
---|
801 | impossible to ensure that the mutex object is unlocked |
---|
802 | properly when using these traditional API's. The result is |
---|
803 | <link linkend="thread.glossary.deadlock">deadlock</link>.</para> |
---|
804 | |
---|
805 | <para>Many C++ threading libraries use a pattern known as <emphasis>Scoped |
---|
806 | Locking</emphasis> &cite.SchmidtStalRohnertBuschmann; to free the |
---|
807 | programmer from the need to explicitly lock and unlock |
---|
808 | read/write mutex objects. With this pattern, a |
---|
809 | <link linkend="thread.concepts.read-write-lock-concepts">Read/Write Lock</link> |
---|
810 | concept is employed where the lock object's constructor locks |
---|
811 | the associated read/write mutex object |
---|
812 | and the destructor automatically does the unlocking. The |
---|
813 | &Boost.Thread; library takes this pattern to |
---|
814 | the extreme in that |
---|
815 | <link linkend="thread.concepts.read-write-lock-concepts">Read/Write Lock</link> |
---|
816 | concepts are the only way to lock and unlock a read/write mutex |
---|
817 | object: lock and unlock functions are not exposed by any |
---|
818 | &Boost.Thread; read/write mutex objects. This helps to |
---|
819 | ensure safe usage patterns, especially when code throws exceptions.</para> |
---|
820 | |
---|
821 | <section id="thread.concepts.read-write-locking-strategies"> |
---|
822 | <title>Locking Strategies</title> |
---|
823 | |
---|
824 | <para>Every read/write mutex object follows one of several locking |
---|
825 | strategies. These strategies define the semantics for the locking |
---|
826 | operation when the calling thread already owns a lock on the |
---|
827 | read/write mutex object.</para> |
---|
828 | |
---|
829 | <section id="thread.concepts.read-write-locking-strategies.recursive"> |
---|
830 | <title>Recursive Locking Strategy</title> |
---|
831 | |
---|
832 | <para>With a recursive locking strategy, when a thread attempts |
---|
833 | to acquire a lock on a read/write mutex object |
---|
834 | for which it already owns a lock, the operation is successful, |
---|
835 | except in the case where a thread holding a read-lock |
---|
836 | attempts to obtain a write lock, in which case a |
---|
837 | <classname>boost::lock_error</classname> exception will |
---|
838 | be thrown. Note the distinction between a thread, which may have |
---|
839 | multiple locks outstanding on a recursive read/write mutex object, |
---|
840 | and a lock object, which even for a recursive read/write mutex |
---|
841 | object cannot have any of its lock functions called multiple |
---|
842 | times without first calling unlock.</para> |
---|
843 | |
---|
844 | <informaltable> |
---|
845 | <tgroup cols="3"> |
---|
846 | <thead> |
---|
847 | <row> |
---|
848 | <entry>Lock Type Held</entry> |
---|
849 | <entry>Lock Type Requested</entry> |
---|
850 | <entry>Action</entry> |
---|
851 | </row> |
---|
852 | </thead> |
---|
853 | |
---|
854 | <tbody> |
---|
855 | <row> |
---|
856 | <entry>read-lock</entry> |
---|
857 | <entry>read-lock</entry> |
---|
858 | <entry>Grant the read-lock immediately</entry> |
---|
859 | </row> |
---|
860 | <row> |
---|
861 | <entry>read-lock</entry> |
---|
862 | <entry>write-lock</entry> |
---|
863 | <entry>If this thread is the only holder of the read-lock, |
---|
864 | grants the write lock immediately. Otherwise throws a |
---|
865 | <classname>boost::lock_error</classname> exception.</entry> |
---|
866 | </row> |
---|
867 | <row> |
---|
868 | <entry>write-locked</entry> |
---|
869 | <entry>read-lock</entry> |
---|
870 | <entry>Grants the (additional) read-lock immediately.</entry> |
---|
871 | </row> |
---|
872 | <row> |
---|
873 | <entry>write-locked</entry> |
---|
874 | <entry>write-lock</entry> |
---|
875 | <entry> Grant the write-lock immediately</entry> |
---|
876 | </row> |
---|
877 | </tbody> |
---|
878 | </tgroup> |
---|
879 | </informaltable> |
---|
880 | |
---|
881 | <para>Internally a lock count is maintained and the owning |
---|
882 | thread must unlock the mutex object the same number of times |
---|
883 | that it locked it before the mutex object's state returns |
---|
884 | to unlocked. Since mutex objects in &Boost.Thread; expose |
---|
885 | locking functionality only through lock concepts, a thread |
---|
886 | will always unlock a mutex object the same number of times |
---|
887 | that it locked it. This helps to eliminate a whole set of |
---|
888 | errors typically found in traditional C style thread APIs. |
---|
889 | </para> |
---|
890 | |
---|
891 | <para>&Boost.Thread; does not currently provide any read/write mutex objects |
---|
892 | that use this strategy. A successful implementation of this locking strategy |
---|
893 | may require |
---|
894 | <link linkend="thread.concepts.read-write-locking-strategies.thread-identification">thread identification</link>. |
---|
895 | </para> |
---|
896 | </section> |
---|
897 | |
---|
898 | <section id="thread.concepts.read-write-locking-strategies.checked"> |
---|
899 | <title>Checked Locking Strategy</title> |
---|
900 | |
---|
901 | <para>With a checked locking strategy, when a thread attempts |
---|
902 | to acquire a lock on the mutex object for which the thread |
---|
903 | already owns a lock, the operation will fail with some sort of |
---|
904 | error indication, except in the case of multiple read-lock |
---|
905 | acquisition which is a normal operation for ANY ReadWriteMutex. |
---|
906 | Further, attempts by a thread to unlock a mutex that was not |
---|
907 | locked by the thread will also return some sort of error |
---|
908 | indication. In &Boost.Thread;, an exception of type |
---|
909 | <classname>boost::lock_error</classname> would be thrown in |
---|
910 | these cases.</para> |
---|
911 | |
---|
912 | <informaltable> |
---|
913 | <tgroup cols="3"> |
---|
914 | <thead> |
---|
915 | <row> |
---|
916 | <entry>Lock Type Held</entry> |
---|
917 | <entry>Lock Type Requested</entry> |
---|
918 | <entry>Action</entry> |
---|
919 | </row> |
---|
920 | </thead> |
---|
921 | |
---|
922 | <tbody> |
---|
923 | <row> |
---|
924 | <entry>read-lock</entry> |
---|
925 | <entry>read-lock</entry> |
---|
926 | <entry>Grant the read-lock immediately</entry> |
---|
927 | </row> |
---|
928 | <row> |
---|
929 | <entry>read-lock</entry> |
---|
930 | <entry>write-lock</entry> |
---|
931 | <entry>Throw <classname>boost::lock_error</classname></entry> |
---|
932 | </row> |
---|
933 | <row> |
---|
934 | <entry>write-locked</entry> |
---|
935 | <entry>read-lock</entry> |
---|
936 | <entry>Throw <classname>boost::lock_error</classname></entry> |
---|
937 | </row> |
---|
938 | <row> |
---|
939 | <entry>write-locked</entry> |
---|
940 | <entry>write-lock</entry> |
---|
941 | <entry> Throw <classname>boost::lock_error</classname></entry> |
---|
942 | </row> |
---|
943 | </tbody> |
---|
944 | </tgroup> |
---|
945 | </informaltable> |
---|
946 | |
---|
947 | <para>&Boost.Thread; does not currently provide any read/write mutex objects |
---|
948 | that use this strategy. A successful implementation of this locking strategy |
---|
949 | may require |
---|
950 | <link linkend="thread.concepts.read-write-locking-strategies.thread-identification">thread identification</link>. |
---|
951 | </para> |
---|
952 | </section> |
---|
953 | |
---|
954 | <section id="thread.concepts.read-write-locking-strategies.unchecked"> |
---|
955 | <title>Unchecked Locking Strategy</title> |
---|
956 | |
---|
957 | <para>With an unchecked locking strategy, when a thread |
---|
958 | attempts to acquire a lock on the read/write mutex object |
---|
959 | for which the thread already owns a lock, the operation |
---|
960 | will <link linkend="thread.glossary.deadlock">deadlock</link>. |
---|
961 | In general this locking strategy is less safe than a checked |
---|
962 | or recursive strategy, but it can be a faster strategy and so |
---|
963 | is employed by many libraries.</para> |
---|
964 | |
---|
965 | <informaltable> |
---|
966 | <tgroup cols="3"> |
---|
967 | <thead> |
---|
968 | <row> |
---|
969 | <entry>Lock Type Held</entry> |
---|
970 | <entry>Lock Type Requested</entry> |
---|
971 | <entry>Action</entry> |
---|
972 | </row> |
---|
973 | </thead> |
---|
974 | |
---|
975 | <tbody> |
---|
976 | <row> |
---|
977 | <entry>read-lock</entry> |
---|
978 | <entry>read-lock</entry> |
---|
979 | <entry>Grant the read-lock immediately</entry> |
---|
980 | </row> |
---|
981 | <row> |
---|
982 | <entry>read-lock</entry> |
---|
983 | <entry>write-lock</entry> |
---|
984 | <entry><link linkend="thread.glossary.deadlock">Deadlock</link></entry> |
---|
985 | </row> |
---|
986 | <row> |
---|
987 | <entry>write-locked</entry> |
---|
988 | <entry>read-lock</entry> |
---|
989 | <entry><link linkend="thread.glossary.deadlock">Deadlock</link></entry> |
---|
990 | </row> |
---|
991 | <row> |
---|
992 | <entry>write-locked</entry> |
---|
993 | <entry>write-lock</entry> |
---|
994 | <entry><link linkend="thread.glossary.deadlock">Deadlock</link></entry> |
---|
995 | </row> |
---|
996 | </tbody> |
---|
997 | </tgroup> |
---|
998 | </informaltable> |
---|
999 | |
---|
1000 | <para>&Boost.Thread; does not currently provide any mutex |
---|
1001 | objects that use this strategy. For ReadWriteMutexes on |
---|
1002 | platforms that contain natively recursive synchronization |
---|
1003 | primitives, implementing a guaranteed-deadlock can actually |
---|
1004 | involve extra work, and would likely require |
---|
1005 | <link linkend="thread.concepts.read-write-locking-strategies.thread-identification">thread identification</link>. |
---|
1006 | </para> |
---|
1007 | </section> |
---|
1008 | |
---|
1009 | <section id="thread.concepts.read-write-locking-strategies.unspecified"> |
---|
1010 | <title>Unspecified Locking Strategy</title> |
---|
1011 | |
---|
1012 | <para>With an unspecified locking strategy, when a thread |
---|
1013 | attempts to acquire a lock on a read/write mutex object for |
---|
1014 | which the thread already owns a lock, the operation results |
---|
1015 | in <link linkend="thread.glossary.undefined-behavior">undefined behavior</link>. |
---|
1016 | When a read/write mutex object has an unspecified locking |
---|
1017 | strategy the programmer must assume that the read/write mutex |
---|
1018 | object instead uses an unchecked strategy as the worse case, |
---|
1019 | although some platforms may exhibit a mix of unchecked and |
---|
1020 | recursive behavior.</para> |
---|
1021 | |
---|
1022 | <informaltable> |
---|
1023 | <tgroup cols="3"> |
---|
1024 | <thead> |
---|
1025 | <row> |
---|
1026 | <entry>Lock Type Held</entry> |
---|
1027 | <entry>Lock Type Requested</entry> |
---|
1028 | <entry>Action</entry> |
---|
1029 | </row> |
---|
1030 | </thead> |
---|
1031 | |
---|
1032 | <tbody> |
---|
1033 | <row> |
---|
1034 | <entry>read-lock</entry> |
---|
1035 | <entry>read-lock</entry> |
---|
1036 | <entry>Grant the read-lock immediately</entry> |
---|
1037 | </row> |
---|
1038 | <row> |
---|
1039 | <entry>read-lock</entry> |
---|
1040 | <entry>write-lock</entry> |
---|
1041 | <entry> |
---|
1042 | <link linkend="thread.glossary.undefined-behavior">Undefined</link>, but generally <link linkend="thread.glossary.deadlock">deadlock</link> |
---|
1043 | </entry> |
---|
1044 | </row> |
---|
1045 | <row> |
---|
1046 | <entry>write-locked</entry> |
---|
1047 | <entry>read-lock</entry> |
---|
1048 | <entry><link linkend="thread.glossary.undefined-behavior">Undefined</link>, but generally <link linkend="thread.glossary.deadlock">deadlock</link></entry> |
---|
1049 | </row> |
---|
1050 | <row> |
---|
1051 | <entry>write-locked</entry> |
---|
1052 | <entry>write-lock</entry> |
---|
1053 | <entry><link linkend="thread.glossary.undefined-behavior">Undefined</link>, but generally <link linkend="thread.glossary.deadlock">deadlock</link></entry> |
---|
1054 | </row> |
---|
1055 | </tbody> |
---|
1056 | </tgroup> |
---|
1057 | </informaltable> |
---|
1058 | |
---|
1059 | <para>In general a read/write mutex object with an unspecified |
---|
1060 | locking strategy is unsafe, and it requires programmer discipline |
---|
1061 | to use the read/write mutex object properly. However, this strategy |
---|
1062 | allows an implementation to be as fast as possible with no restrictions |
---|
1063 | on its implementation. This is especially true for portable implementations |
---|
1064 | that wrap the native threading support of a platform. For this reason, the |
---|
1065 | classes |
---|
1066 | <classname>read_write_mutex</classname>, |
---|
1067 | <classname>try_read_write_mutex</classname>, and |
---|
1068 | <classname>timed_read_write_mutex</classname> |
---|
1069 | use this locking strategy despite the lack of safety.</para> |
---|
1070 | </section> |
---|
1071 | |
---|
1072 | <section id="thread.concepts.read-write-locking-strategies.thread-identification"> |
---|
1073 | <title>Thread Identification</title> |
---|
1074 | |
---|
1075 | <para>ReadWriteMutexes can support specific Locking Strategies |
---|
1076 | (recursive and checked) which help to detect and protect against |
---|
1077 | self-deadlock. Self-deadlock can occur when a holder of a locked |
---|
1078 | ReadWriteMutex attempts to obtain another lock. Given an |
---|
1079 | implemention <emphasis>I</emphasis> which is susceptible to |
---|
1080 | self-deadlock but otherwise correct and efficient, a recursive or |
---|
1081 | checked implementation <emphasis>Ir</emphasis> or |
---|
1082 | <emphasis>Ic</emphasis> can use the same basic implementation, |
---|
1083 | but make special checks against self-deadlock by tracking the |
---|
1084 | identities of thread(s) currently holding locks. This approach |
---|
1085 | makes deadlock detection othrogonal to the basic ReadWriteMutex |
---|
1086 | implementaion.</para> |
---|
1087 | |
---|
1088 | <para>Alternatively, a different basic implementation for |
---|
1089 | ReadWriteMutex concepts, |
---|
1090 | <emphasis>I'</emphasis> (I-Prime) may exist which uses recursive |
---|
1091 | or checked versions of synchronization primitives to produce |
---|
1092 | a recursive or checked ReadWriteMutex while still providing |
---|
1093 | flexibility in terms of Scheduling Policies. </para> |
---|
1094 | |
---|
1095 | <para>Please refer to the &Boost.Thread; |
---|
1096 | <link linkend="thread.concepts.read-write-mutex-concepts">read/write mutex concept</link> |
---|
1097 | documentation for a discussion of locking strategies. |
---|
1098 | The read/write mutex supports only the |
---|
1099 | <link linkend="thread.concepts.read-write-locking-strategies.unspecified">unspecified</link> |
---|
1100 | locking strategy. ReadWriteMutexes are parameterized on a |
---|
1101 | Mutex type which they use to control write-locking |
---|
1102 | and access to internal state.</para> |
---|
1103 | </section> |
---|
1104 | |
---|
1105 | <section id="thread.concepts.read-write-locking-strategies.promotion"> |
---|
1106 | <title>Lock Promotion</title> |
---|
1107 | |
---|
1108 | <para>ReadWriteMutexes can support lock promotion, where a |
---|
1109 | mutex which is in the read-locked state transitions to a |
---|
1110 | write-locked state without releasing the lock. Lock |
---|
1111 | promotion can be tricky to implement; for instance, |
---|
1112 | extra care must be taken to ensure that only one thread holding a |
---|
1113 | read-lock can block awaiting promotion at any given time. If |
---|
1114 | more than one read-lock holder is allowed to enter a blocked |
---|
1115 | state while waiting to be promoted, deadlock will result since |
---|
1116 | both threads will be waiting for the other to release their read-lock. |
---|
1117 | </para> |
---|
1118 | |
---|
1119 | <para>Currently, &Boost.Thread; supports lock promotion |
---|
1120 | through <code>promote()</code>, <code>try_promote()</code>, |
---|
1121 | and <code>timed_promote()</code> operations.</para> |
---|
1122 | </section> |
---|
1123 | |
---|
1124 | <section id="thread.concepts.read-write-locking-strategies.demotion"> |
---|
1125 | <title>Lock Demotion</title> |
---|
1126 | |
---|
1127 | <para>ReadWriteMutexes can support lock demotion, where a |
---|
1128 | mutex which is in the write-locked state transitions to a |
---|
1129 | read-locked state without releasing the lock. |
---|
1130 | Since by definition only one thread at a time may hold |
---|
1131 | a write-lock, the problem with deadlock that can occur |
---|
1132 | during lock promotion is not a problem for lock |
---|
1133 | demotion.</para> |
---|
1134 | |
---|
1135 | <para>Currently, &Boost.Thread; supports lock demotion |
---|
1136 | through <code>demote()</code>, <code>try_demote()</code>, |
---|
1137 | and <code>timed_demote()</code> operations.</para> |
---|
1138 | </section> |
---|
1139 | </section> |
---|
1140 | |
---|
1141 | <section id="thread.concepts.read-write-scheduling-policies"> |
---|
1142 | <title>Scheduling Policies</title> |
---|
1143 | |
---|
1144 | <para>Every read/write mutex object follows one of several scheduling |
---|
1145 | policies. These policies define the semantics when the mutex object |
---|
1146 | is unlocked and there is more than one thread waiting to acquire a |
---|
1147 | lock. In other words, the policy defines which waiting thread shall |
---|
1148 | acquire the lock. For a read/write mutex, it is particularly important |
---|
1149 | to define the behavior when threads are requesting both read and |
---|
1150 | write access simultaneously. This will be referred to as "inter-class |
---|
1151 | scheduling" because it describes the scheduling between two |
---|
1152 | classes of threads (those waiting for a read lock and those |
---|
1153 | waiting for a write lock).</para> |
---|
1154 | |
---|
1155 | <para>For some types of inter-class scheduling, an "intra-class" |
---|
1156 | scheduling policy can also be defined that will describe the order |
---|
1157 | in which waiting threads of the same class (i.e., those |
---|
1158 | waiting for the same type of lock) will acquire the thread. |
---|
1159 | </para> |
---|
1160 | |
---|
1161 | <section id="thread.concepts.read-write-scheduling-policies.inter-class"> |
---|
1162 | <title>Inter-Class Scheduling Policies</title> |
---|
1163 | |
---|
1164 | <section id="thread.concepts.read-write-scheduling-policies.reader-priority"> |
---|
1165 | <title>ReaderPriority</title> |
---|
1166 | |
---|
1167 | <para>With ReaderPriority scheduling, any pending request for |
---|
1168 | a read-lock will have priority over a pending request for a |
---|
1169 | write-lock, irrespective of the current lock state of the |
---|
1170 | read/write mutex, and irrespective of the relative order |
---|
1171 | that the pending requests arrive.</para> |
---|
1172 | |
---|
1173 | <informaltable> |
---|
1174 | <tgroup cols="3"> |
---|
1175 | <thead> |
---|
1176 | <row> |
---|
1177 | <entry>Current mutex state</entry> |
---|
1178 | <entry>Request Type</entry> |
---|
1179 | <entry>Action</entry> |
---|
1180 | </row> |
---|
1181 | </thead> |
---|
1182 | |
---|
1183 | <tbody> |
---|
1184 | <row> |
---|
1185 | <entry>unlocked</entry> |
---|
1186 | <entry>read-lock</entry> |
---|
1187 | <entry>Grant the read-lock immediately</entry> |
---|
1188 | </row> |
---|
1189 | <row> |
---|
1190 | <entry>read-locked</entry> |
---|
1191 | <entry>read-lock</entry> |
---|
1192 | <entry>Grant the additional read-lock immediately.</entry> |
---|
1193 | </row> |
---|
1194 | <row> |
---|
1195 | <entry>write-locked</entry> |
---|
1196 | <entry>read-lock</entry> |
---|
1197 | <entry>Wait to acquire the lock until the thread |
---|
1198 | holding the write-lock releases its lock (or until |
---|
1199 | the specified time, if any). A |
---|
1200 | read-lock will be granted to all pending readers |
---|
1201 | before any other thread can acquire a write-lock. |
---|
1202 | <para>TODO: try-lock, timed-lock.</para> |
---|
1203 | </entry> |
---|
1204 | </row> |
---|
1205 | <row> |
---|
1206 | <entry>unlocked</entry> |
---|
1207 | <entry>write-lock</entry> |
---|
1208 | <entry>Grant the write-lock immediately, if and |
---|
1209 | only if there are no pending read-lock requests. |
---|
1210 | <para>TODO: try-lock, timed-lock.</para> |
---|
1211 | </entry> |
---|
1212 | </row> |
---|
1213 | <row> |
---|
1214 | <entry>read-locked</entry> |
---|
1215 | <entry>write-lock</entry> |
---|
1216 | <entry> Wait to acquire the lock until all |
---|
1217 | threads holding read-locks release their locks |
---|
1218 | <emphasis role="bold">AND</emphasis> no requests |
---|
1219 | for read-locks exist. If other write-lock |
---|
1220 | requests exist, the lock is granted in accordance |
---|
1221 | with the intra-class scheduling policy. |
---|
1222 | <para>TODO: try-lock, timed-lock.</para> |
---|
1223 | </entry> |
---|
1224 | </row> |
---|
1225 | <row> |
---|
1226 | <entry>write-locked</entry> |
---|
1227 | <entry>write-lock</entry> |
---|
1228 | <entry>Wait to acquire the lock until the thread |
---|
1229 | holding the write-lock releases its lock |
---|
1230 | <emphasis role="bold">AND</emphasis> no requests |
---|
1231 | for read-locks exist. If other write-lock |
---|
1232 | requests exist, the lock is granted in accordance |
---|
1233 | with the intra-class scheduling policy. |
---|
1234 | <para>TODO: try-lock, timed-lock.</para> |
---|
1235 | </entry> |
---|
1236 | </row> |
---|
1237 | <row> |
---|
1238 | <entry>read-locked</entry> |
---|
1239 | <entry>promote</entry> |
---|
1240 | <entry><para>TODO</para></entry> |
---|
1241 | </row> |
---|
1242 | <row> |
---|
1243 | <entry>write-locked</entry> |
---|
1244 | <entry>demote</entry> |
---|
1245 | <entry><para>TODO</para></entry> |
---|
1246 | </row> |
---|
1247 | </tbody> |
---|
1248 | </tgroup> |
---|
1249 | </informaltable> |
---|
1250 | </section> |
---|
1251 | |
---|
1252 | <section id="thread.concepts.read-write-scheduling-policies.writer-priority"> |
---|
1253 | <title>WriterPriority</title> |
---|
1254 | |
---|
1255 | <para>With WriterPriority scheduling, any pending request |
---|
1256 | for a write-lock will have priority over a pending request |
---|
1257 | for a read-lock, irrespective of the current lock state |
---|
1258 | of the read/write mutex, and irrespective of the relative |
---|
1259 | order that the pending requests arrive.</para> |
---|
1260 | |
---|
1261 | <informaltable> |
---|
1262 | <tgroup cols="3"> |
---|
1263 | <thead> |
---|
1264 | <row> |
---|
1265 | <entry>Current mutex state</entry> |
---|
1266 | <entry>Request Type</entry> |
---|
1267 | <entry>Action</entry> |
---|
1268 | </row> |
---|
1269 | </thead> |
---|
1270 | |
---|
1271 | <tbody> |
---|
1272 | <row> |
---|
1273 | <entry>unlocked</entry> |
---|
1274 | <entry>read-lock</entry> |
---|
1275 | <entry>Grant the read-lock immediately.</entry> |
---|
1276 | </row> |
---|
1277 | <row> |
---|
1278 | <entry>read-locked</entry> |
---|
1279 | <entry>read-lock</entry> |
---|
1280 | <entry>Grant the additional read-lock immediately, |
---|
1281 | <emphasis role="bold">IF</emphasis> no outstanding |
---|
1282 | requests for a write-lock exist; otherwise TODO. |
---|
1283 | <para>TODO: try-lock, timed-lock.</para> |
---|
1284 | </entry> |
---|
1285 | </row> |
---|
1286 | <row> |
---|
1287 | <entry>write-locked</entry> |
---|
1288 | <entry>read-lock</entry> |
---|
1289 | <entry> Wait to acquire the lock until the |
---|
1290 | thread holding the write-lock |
---|
1291 | releases its lock. The read lock will be granted |
---|
1292 | once no other outstanding write-lock requests |
---|
1293 | exist. |
---|
1294 | <para>TODO: try-lock, timed-lock.</para> |
---|
1295 | </entry> |
---|
1296 | </row> |
---|
1297 | <row> |
---|
1298 | <entry>unlocked</entry> |
---|
1299 | <entry>write-lock</entry> |
---|
1300 | <entry>Grant the write-lock immediately.</entry> |
---|
1301 | </row> |
---|
1302 | <row> |
---|
1303 | <entry>read-locked</entry> |
---|
1304 | <entry>write-lock</entry> |
---|
1305 | <entry>Wait to acquire the lock until all |
---|
1306 | threads holding read-locks release their locks. |
---|
1307 | If other write-lock requests exist, the lock |
---|
1308 | is granted in accordance with the intra-class |
---|
1309 | scheduling policy. This request will be granted |
---|
1310 | before any new read-lock requests are granted. |
---|
1311 | <para>TODO: try-lock, timed-lock.</para> |
---|
1312 | </entry> |
---|
1313 | </row> |
---|
1314 | <row> |
---|
1315 | <entry>write-locked</entry> |
---|
1316 | <entry>write-lock</entry> |
---|
1317 | <entry>Wait to acquire the lock until the thread |
---|
1318 | holding the write-lock releases its lock. If |
---|
1319 | other write-lock requests exist, the lock is |
---|
1320 | granted in accordance with the intra-class |
---|
1321 | scheduling policy. This request will be granted |
---|
1322 | before any new read-lock requests are granted. |
---|
1323 | <para>TODO: try-lock, timed-lock.</para> |
---|
1324 | </entry> |
---|
1325 | </row> |
---|
1326 | <row> |
---|
1327 | <entry>read-locked</entry> |
---|
1328 | <entry>promote</entry> |
---|
1329 | <entry><para>TODO</para></entry> |
---|
1330 | </row> |
---|
1331 | <row> |
---|
1332 | <entry>write-locked</entry> |
---|
1333 | <entry>demote</entry> |
---|
1334 | <entry><para>TODO</para></entry> |
---|
1335 | </row> |
---|
1336 | </tbody> |
---|
1337 | </tgroup> |
---|
1338 | </informaltable> |
---|
1339 | </section> |
---|
1340 | |
---|
1341 | <section id="thread.concepts.read-write-scheduling-policies.alternating-many-reads"> |
---|
1342 | <title>AlternatingPriority/ManyReads</title> |
---|
1343 | |
---|
1344 | <para>With AlternatingPriority/ManyReads scheduling, reader |
---|
1345 | or writer starvation is avoided by alternatively granting read |
---|
1346 | or write access when pending requests exist for both types of |
---|
1347 | locks. Outstanding read-lock requests are treated as a group |
---|
1348 | when it is the "readers' turn"</para> |
---|
1349 | |
---|
1350 | <informaltable> |
---|
1351 | <tgroup cols="3"> |
---|
1352 | <thead> |
---|
1353 | <row> |
---|
1354 | <entry>Current mutex state</entry> |
---|
1355 | <entry>Request Type</entry> |
---|
1356 | <entry>Action</entry> |
---|
1357 | </row> |
---|
1358 | </thead> |
---|
1359 | |
---|
1360 | <tbody> |
---|
1361 | <row> |
---|
1362 | <entry>unlocked</entry> |
---|
1363 | <entry>read-lock</entry> |
---|
1364 | <entry>Grant the read-lock immediately.</entry> |
---|
1365 | </row> |
---|
1366 | <row> |
---|
1367 | <entry>read-locked</entry> |
---|
1368 | <entry>read-lock</entry> |
---|
1369 | <entry>Grant the additional read-lock immediately, |
---|
1370 | <emphasis role="bold">IF</emphasis> no outstanding |
---|
1371 | requests for a write-lock exist. If outstanding |
---|
1372 | write-lock requests exist, this lock will not |
---|
1373 | be granted until at least one of the |
---|
1374 | write-locks is granted and released. If other |
---|
1375 | read-lock requests exist, all read-locks will be |
---|
1376 | granted as a group. |
---|
1377 | <para>TODO: try-lock, timed-lock.</para> |
---|
1378 | </entry> |
---|
1379 | </row> |
---|
1380 | <row> |
---|
1381 | <entry>write-locked</entry> |
---|
1382 | <entry>read-lock</entry> |
---|
1383 | <entry> Wait to acquire the lock until the thread |
---|
1384 | holding the write-lock releases its lock. If other |
---|
1385 | outstanding write-lock requests exist, they will |
---|
1386 | have to wait until all current read-lock requests |
---|
1387 | are serviced. |
---|
1388 | <para>TODO: try-lock, timed-lock.</para> |
---|
1389 | </entry> |
---|
1390 | </row> |
---|
1391 | <row> |
---|
1392 | <entry>unlocked</entry> |
---|
1393 | <entry>write-lock</entry> |
---|
1394 | <entry>Grant the write-lock immediately.</entry> |
---|
1395 | </row> |
---|
1396 | <row> |
---|
1397 | <entry>read-locked</entry> |
---|
1398 | <entry>write-lock</entry> |
---|
1399 | <entry> |
---|
1400 | <para>Wait to acquire the lock until all threads |
---|
1401 | holding read-locks release their locks.</para> |
---|
1402 | |
---|
1403 | <para>If other write-lock requests exist, this |
---|
1404 | lock will be granted to one of them in accordance |
---|
1405 | with the intra-class scheduling policy.</para> |
---|
1406 | |
---|
1407 | <para>TODO: try-lock, timed-lock.</para> |
---|
1408 | </entry> |
---|
1409 | </row> |
---|
1410 | <row> |
---|
1411 | <entry>write-locked</entry> |
---|
1412 | <entry>write-lock</entry> |
---|
1413 | <entry>Wait to acquire the lock until the thread |
---|
1414 | holding the write-lock releases its lock. If |
---|
1415 | other outstanding read-lock requests exist, this |
---|
1416 | lock will not be granted until all of the |
---|
1417 | currently waiting read-locks are granted and |
---|
1418 | released. If other write-lock requests exist, |
---|
1419 | this lock will be granted in accordance with the |
---|
1420 | intra-class scheduling policy. |
---|
1421 | <para>TODO: try-lock, timed-lock.</para> |
---|
1422 | </entry> |
---|
1423 | </row> |
---|
1424 | <row> |
---|
1425 | <entry>read-locked</entry> |
---|
1426 | <entry>promote</entry> |
---|
1427 | <entry><para>TODO</para></entry> |
---|
1428 | </row> |
---|
1429 | <row> |
---|
1430 | <entry>write-locked</entry> |
---|
1431 | <entry>demote</entry> |
---|
1432 | <entry><para>TODO</para></entry> |
---|
1433 | </row> |
---|
1434 | </tbody> |
---|
1435 | </tgroup> |
---|
1436 | </informaltable> |
---|
1437 | </section> |
---|
1438 | |
---|
1439 | <section id="thread.concepts.read-write-scheduling-policies.alternating-single-read"> |
---|
1440 | <title>AlternatingPriority/SingleRead</title> |
---|
1441 | |
---|
1442 | <para>With AlternatingPriority/SingleRead scheduling, reader |
---|
1443 | or writer starvation is avoided by alternatively granting read |
---|
1444 | or write access when pending requests exist for both types of |
---|
1445 | locks. Outstanding read-lock requests are services one at a |
---|
1446 | time when it is the "readers' turn"</para> |
---|
1447 | |
---|
1448 | <informaltable> |
---|
1449 | <tgroup cols="3"> |
---|
1450 | <thead> |
---|
1451 | <row> |
---|
1452 | <entry>Current mutex state</entry> |
---|
1453 | <entry>Request Type</entry> |
---|
1454 | <entry>Action</entry> |
---|
1455 | </row> |
---|
1456 | </thead> |
---|
1457 | |
---|
1458 | <tbody> |
---|
1459 | <row> |
---|
1460 | <entry>unlocked</entry> |
---|
1461 | <entry>read-lock</entry> |
---|
1462 | <entry>Grant the read-lock immediately.</entry> |
---|
1463 | </row> |
---|
1464 | <row> |
---|
1465 | <entry>read-locked</entry> |
---|
1466 | <entry>read-lock</entry> |
---|
1467 | <entry>Grant the additional read-lock immediately, |
---|
1468 | <emphasis role="bold">IF</emphasis> no outstanding |
---|
1469 | requests for a write-lock exist. If outstanding |
---|
1470 | write-lock requests exist, this lock will not |
---|
1471 | be granted until at least one of the write-locks |
---|
1472 | is granted and released. |
---|
1473 | <para>TODO: try-lock, timed-lock.</para> |
---|
1474 | </entry> |
---|
1475 | </row> |
---|
1476 | <row> |
---|
1477 | <entry>write-locked</entry> |
---|
1478 | <entry>read-lock</entry> |
---|
1479 | <entry> |
---|
1480 | <para>Wait to acquire the lock until the thread |
---|
1481 | holding the write-lock releases its lock.</para> |
---|
1482 | <para>If other outstanding write-lock requests |
---|
1483 | exist, exactly one read-lock request will be |
---|
1484 | granted before the next write-lock is granted. |
---|
1485 | </para> |
---|
1486 | <para>TODO: try-lock, timed-lock.</para> |
---|
1487 | </entry> |
---|
1488 | </row> |
---|
1489 | <row> |
---|
1490 | <entry>unlocked</entry> |
---|
1491 | <entry>write-lock</entry> |
---|
1492 | <entry>Grant the write-lock immediately.</entry> |
---|
1493 | </row> |
---|
1494 | <row> |
---|
1495 | <entry>read-locked</entry> |
---|
1496 | <entry>write-lock</entry> |
---|
1497 | <entry> |
---|
1498 | <para>Wait to acquire the lock until all |
---|
1499 | threads holding read-locks release their |
---|
1500 | locks.</para> |
---|
1501 | |
---|
1502 | <para>If other write-lock requests exist, |
---|
1503 | this lock will be granted to one of them |
---|
1504 | in accordance with the intra-class |
---|
1505 | scheduling policy.</para></entry> |
---|
1506 | |
---|
1507 | <para>TODO: try-lock, timed-lock.</para> |
---|
1508 | </row> |
---|
1509 | <row> |
---|
1510 | <entry>write-locked</entry> |
---|
1511 | <entry>write-lock</entry> |
---|
1512 | <entry>Wait to acquire the lock until the |
---|
1513 | thread holding the write-lock releases its |
---|
1514 | lock. If other outstanding read-lock requests |
---|
1515 | exist, this lock can not be granted until |
---|
1516 | exactly one read-lock request is granted and |
---|
1517 | released. If other write-lock requests exist, |
---|
1518 | this lock will be granted in accordance with |
---|
1519 | the intra-class scheduling policy. |
---|
1520 | <para>TODO: try-lock, timed-lock.</para> |
---|
1521 | </entry> |
---|
1522 | </row> |
---|
1523 | <row> |
---|
1524 | <entry>read-locked</entry> |
---|
1525 | <entry>promote</entry> |
---|
1526 | <entry><para>TODO</para></entry> |
---|
1527 | </row> |
---|
1528 | <row> |
---|
1529 | <entry>write-locked</entry> |
---|
1530 | <entry>demote</entry> |
---|
1531 | <entry><para>TODO</para></entry> |
---|
1532 | </row> |
---|
1533 | </tbody> |
---|
1534 | </tgroup> |
---|
1535 | </informaltable> |
---|
1536 | </section> |
---|
1537 | </section> |
---|
1538 | |
---|
1539 | <section id="thread.concepts.read-write-scheduling-policies.intra-class"> |
---|
1540 | <title>Intra-Class Scheduling Policies</title> |
---|
1541 | |
---|
1542 | <para>Please refer to |
---|
1543 | <xref linkend="thread.concepts.sheduling-policies" /> |
---|
1544 | for a discussion of mutex scheduling policies, which are identical to |
---|
1545 | read/write mutex intra-class scheduling policies.</para> |
---|
1546 | |
---|
1547 | <para>For threads waiting to obtain write-locks, the read/write mutex |
---|
1548 | supports only the |
---|
1549 | <link linkend="thread.concepts.unspecified-scheduling-policy">Unspecified</link> |
---|
1550 | intra-class scheduling policy. That is, given a set of threads |
---|
1551 | waiting for write-locks, the order, relative to one another, in |
---|
1552 | which they receive the write-lock is unspecified.</para> |
---|
1553 | |
---|
1554 | <para>For threads waiting to obtain read-locks, the read/write mutex |
---|
1555 | supports only the |
---|
1556 | <link linkend="thread.concepts.unspecified-scheduling-policy">Unspecified</link> |
---|
1557 | intra-class scheduling policy. That is, given a set of threads |
---|
1558 | waiting for read-locks, the order, relative to one another, in |
---|
1559 | which they receive the read-lock is unspecified.</para> |
---|
1560 | </section> |
---|
1561 | </section> |
---|
1562 | |
---|
1563 | <section id="thread.concepts.read-write-mutex-concepts"> |
---|
1564 | <title>Mutex Concepts</title> |
---|
1565 | |
---|
1566 | <section id="thread.concepts.ReadWriteMutex"> |
---|
1567 | <title>ReadWriteMutex Concept</title> |
---|
1568 | |
---|
1569 | <para>A ReadWriteMutex object has three states: read-locked, |
---|
1570 | write-locked, and unlocked. ReadWriteMutex object state can |
---|
1571 | only be determined by a lock object meeting the appropriate lock concept |
---|
1572 | requirements and constructed for the ReadWriteMutex object.</para> |
---|
1573 | |
---|
1574 | <para>A ReadWriteMutex is |
---|
1575 | <ulink url="../../libs/utility/utility.htm#Class%20noncopyable">NonCopyable</ulink>. |
---|
1576 | </para> |
---|
1577 | |
---|
1578 | <para>For a ReadWriteMutex type <code>M</code>, |
---|
1579 | and an object <code>m</code> of that type, |
---|
1580 | the following expressions must be well-formed |
---|
1581 | and have the indicated effects.</para> |
---|
1582 | |
---|
1583 | <table> |
---|
1584 | <title>ReadWriteMutex Expressions</title> |
---|
1585 | |
---|
1586 | <tgroup cols="2"> |
---|
1587 | <thead> |
---|
1588 | <row> |
---|
1589 | <entry>Expression</entry> |
---|
1590 | <entry>Effects</entry> |
---|
1591 | </row> |
---|
1592 | </thead> |
---|
1593 | |
---|
1594 | <tbody> |
---|
1595 | <row> |
---|
1596 | <entry><code>M m;</code></entry> |
---|
1597 | <entry>Constructs a read/write mutex object <code>m</code>. |
---|
1598 | Post-condition: <code>m</code> is unlocked.</entry> |
---|
1599 | </row> |
---|
1600 | <row> |
---|
1601 | <entry><code>(&m)->~M();</code></entry> |
---|
1602 | <entry>Precondition: <code>m</code> is unlocked. |
---|
1603 | Destroys a read/write mutex object <code>m</code>. |
---|
1604 | </entry> |
---|
1605 | </row> |
---|
1606 | <row> |
---|
1607 | <entry><code>M::scoped_read_write_lock</code></entry> |
---|
1608 | <entry>A type meeting the |
---|
1609 | <link linkend="thread.concepts.ScopedReadWriteLock">ScopedReadWriteLock</link> |
---|
1610 | requirements. </entry> |
---|
1611 | </row> |
---|
1612 | <row> |
---|
1613 | <entry><code>M::scoped_read_lock</code></entry> |
---|
1614 | <entry>A type meeting the |
---|
1615 | <link linkend="thread.concepts.ScopedLock">ScopedLock</link> |
---|
1616 | requirements. </entry> |
---|
1617 | </row> |
---|
1618 | <row> |
---|
1619 | <entry><code>M::scoped_write_lock</code></entry> |
---|
1620 | <entry>A type meeting the |
---|
1621 | <link linkend="thread.concepts.ScopedLock">ScopedLock</link> |
---|
1622 | requirements. </entry> |
---|
1623 | </row> |
---|
1624 | </tbody> |
---|
1625 | </tgroup> |
---|
1626 | </table> |
---|
1627 | </section> |
---|
1628 | |
---|
1629 | <section id="thread.concepts.TryReadWriteMutex"> |
---|
1630 | <title>TryReadWriteMutex Concept</title> |
---|
1631 | |
---|
1632 | <para>A TryReadWriteMutex is a refinement of |
---|
1633 | <link linkend="thread.concepts.ReadWriteMutex">ReadWriteMutex</link>. |
---|
1634 | For a TryReadWriteMutex type <code>M</code> |
---|
1635 | and an object <code>m</code> of that type, |
---|
1636 | the following expressions must be well-formed |
---|
1637 | and have the indicated effects.</para> |
---|
1638 | |
---|
1639 | <table> |
---|
1640 | <title>TryReadWriteMutex Expressions</title> |
---|
1641 | |
---|
1642 | <tgroup cols="2"> |
---|
1643 | <thead> |
---|
1644 | <row> |
---|
1645 | <entry>Expression</entry> |
---|
1646 | <entry>Effects</entry> |
---|
1647 | </row> |
---|
1648 | </thead> |
---|
1649 | |
---|
1650 | <tbody> |
---|
1651 | <row> |
---|
1652 | <entry><code>M::scoped_try_read_write_lock</code></entry> |
---|
1653 | <entry>A type meeting the |
---|
1654 | <link linkend="thread.concepts.ScopedTryReadWriteLock">ScopedTryReadWriteLock</link> |
---|
1655 | requirements.</entry> |
---|
1656 | </row> |
---|
1657 | <row> |
---|
1658 | <entry><code>M::scoped_try_read_lock</code></entry> |
---|
1659 | <entry>A type meeting the |
---|
1660 | <link linkend="thread.concepts.ScopedTryLock">ScopedTryLock</link> |
---|
1661 | requirements.</entry> |
---|
1662 | </row> |
---|
1663 | <row> |
---|
1664 | <entry><code>M::scoped_try_write_lock</code></entry> |
---|
1665 | <entry>A type meeting the |
---|
1666 | <link linkend="thread.concepts.ScopedTryLock">ScopedTryLock</link> |
---|
1667 | requirements.</entry> |
---|
1668 | </row> |
---|
1669 | </tbody> |
---|
1670 | </tgroup> |
---|
1671 | </table> |
---|
1672 | </section> |
---|
1673 | |
---|
1674 | <section id="thread.concepts.TimedReadWriteMutex"> |
---|
1675 | <title>TimedReadWriteMutex Concept</title> |
---|
1676 | |
---|
1677 | <para>A TimedReadWriteMutex is a refinement of |
---|
1678 | <link linkend="thread.concepts.TryReadWriteMutex">TryReadWriteMutex</link>. |
---|
1679 | For a TimedReadWriteMutex type <code>M</code> |
---|
1680 | and an object <code>m</code> of that type |
---|
1681 | the following expressions must be well-formed |
---|
1682 | and have the indicated effects.</para> |
---|
1683 | |
---|
1684 | <table> |
---|
1685 | <title>TimedReadWriteMutex Expressions</title> |
---|
1686 | |
---|
1687 | <tgroup cols="2"> |
---|
1688 | <thead> |
---|
1689 | <row> |
---|
1690 | <entry>Expression</entry> |
---|
1691 | <entry>Effects</entry> |
---|
1692 | </row> |
---|
1693 | </thead> |
---|
1694 | |
---|
1695 | <tbody> |
---|
1696 | <row> |
---|
1697 | <entry><code>M::scoped_timed_read_write_lock</code></entry> |
---|
1698 | <entry>A type meeting the |
---|
1699 | <link linkend="thread.concepts.ScopedTimedReadWriteLock">ScopedTimedReadWriteLock</link> |
---|
1700 | requirements.</entry> |
---|
1701 | </row> |
---|
1702 | <row> |
---|
1703 | <entry><code>M::scoped_timed_read_lock</code></entry> |
---|
1704 | <entry>A type meeting the |
---|
1705 | <link linkend="thread.concepts.ScopedTimedLock">ScopedTimedLock</link> |
---|
1706 | requirements.</entry> |
---|
1707 | </row> |
---|
1708 | <row> |
---|
1709 | <entry><code>M::scoped_timed_write_lock</code></entry> |
---|
1710 | <entry>A type meeting the |
---|
1711 | <link linkend="thread.concepts.ScopedTimedLock">ScopedTimedLock</link> |
---|
1712 | requirements.</entry> |
---|
1713 | </row> |
---|
1714 | </tbody> |
---|
1715 | </tgroup> |
---|
1716 | </table> |
---|
1717 | </section> |
---|
1718 | </section> |
---|
1719 | |
---|
1720 | <section id="thread.concepts.read-write-mutex-models"> |
---|
1721 | <title>Mutex Models</title> |
---|
1722 | |
---|
1723 | <para>&Boost.Thread; currently supplies three models of |
---|
1724 | <link linkend="thread.concepts.ReadWriteMutex">ReadWriteMutex</link> |
---|
1725 | and its refinements.</para> |
---|
1726 | |
---|
1727 | <table> |
---|
1728 | <title>Mutex Models</title> |
---|
1729 | |
---|
1730 | <tgroup cols="3"> |
---|
1731 | <thead> |
---|
1732 | <row> |
---|
1733 | <entry>Concept</entry> |
---|
1734 | <entry>Refines</entry> |
---|
1735 | <entry>Models</entry> |
---|
1736 | </row> |
---|
1737 | </thead> |
---|
1738 | |
---|
1739 | <tbody> |
---|
1740 | <row> |
---|
1741 | <entry><link linkend="thread.concepts.ReadWriteMutex">ReadWriteMutex</link></entry> |
---|
1742 | <entry></entry> |
---|
1743 | <entry><classname>boost::read_write_mutex</classname></entry> |
---|
1744 | </row> |
---|
1745 | <row> |
---|
1746 | <entry><link linkend="thread.concepts.TryReadWriteMutex">TryReadWriteMutex</link></entry> |
---|
1747 | <entry><link linkend="thread.concepts.ReadWriteMutex">ReadWriteMutex</link></entry> |
---|
1748 | <entry><classname>boost::try_read_write_mutex</classname></entry> |
---|
1749 | </row> |
---|
1750 | <row> |
---|
1751 | <entry><link linkend="thread.concepts.TimedReadWriteMutex">TimedReadWriteMutex</link></entry> |
---|
1752 | <entry><link linkend="thread.concepts.TryReadWriteMutex">TryReadWriteMutex</link></entry> |
---|
1753 | <entry><classname>boost::timed_read_write_mutex</classname></entry> |
---|
1754 | </row> |
---|
1755 | </tbody> |
---|
1756 | </tgroup> |
---|
1757 | </table> |
---|
1758 | </section> |
---|
1759 | |
---|
1760 | <section id="thread.concepts.read-write-lock-concepts"> |
---|
1761 | <title>Lock Concepts</title> |
---|
1762 | |
---|
1763 | <para>A read/write lock object provides a safe means for locking |
---|
1764 | and unlocking a read/write mutex object (an object whose type is |
---|
1765 | a model of |
---|
1766 | <link linkend="thread.concepts.ReadWriteMutex">ReadWriteMutex</link> |
---|
1767 | or one of its refinements). In other words they are an |
---|
1768 | implementation of the <emphasis>Scoped Locking</emphasis> |
---|
1769 | &cite.SchmidtStalRohnertBuschmann; pattern. The |
---|
1770 | <link linkend="thread.concepts.ScopedReadWriteLock">ScopedReadWriteLock</link>, |
---|
1771 | <link linkend="thread.concepts.ScopedTryReadWriteLock">ScopedTryReadWriteLock</link>, and |
---|
1772 | <link linkend="thread.concepts.ScopedTimedReadWriteLock">ScopedTimedReadWriteLock</link> |
---|
1773 | concepts formalize the requirements.</para> |
---|
1774 | |
---|
1775 | <para>Read/write lock objects are constructed with a reference to a |
---|
1776 | read/write mutex object and typically acquire ownership of the |
---|
1777 | read/write mutex object by setting its state to locked. They also |
---|
1778 | ensure ownership is relinquished in the destructor. Lock objects |
---|
1779 | also expose functions to query the lock status and to manually lock |
---|
1780 | and unlock the read/write mutex object.</para> |
---|
1781 | |
---|
1782 | <para>Read/write lock objects are meant to be short lived, expected |
---|
1783 | to be used at block scope only. The read/write lock objects are not |
---|
1784 | <link linkend="thread.glossary.thread-safe">thread-safe</link>. |
---|
1785 | Read/write lock objects must maintain state to indicate whether or |
---|
1786 | not they've been locked and this state is not protected by any |
---|
1787 | synchronization concepts. For this reason a read/write lock object |
---|
1788 | should never be shared between multiple threads.</para> |
---|
1789 | |
---|
1790 | <section id="thread.concepts.ReadWriteLock"> |
---|
1791 | <title>ReadWriteLock Concept</title> |
---|
1792 | |
---|
1793 | <para>For a read/write lock type <code>L</code> |
---|
1794 | and an object <code>lk</code> |
---|
1795 | and const object <code>clk</code> of that type, |
---|
1796 | the following expressions must be well-formed |
---|
1797 | and have the indicated effects.</para> |
---|
1798 | |
---|
1799 | <table> |
---|
1800 | <title>ReadWriteLock Expressions</title> |
---|
1801 | |
---|
1802 | <tgroup cols="2"> |
---|
1803 | <thead> |
---|
1804 | <row> |
---|
1805 | <entry>Expression</entry> |
---|
1806 | <entry>Effects</entry> |
---|
1807 | </row> |
---|
1808 | </thead> |
---|
1809 | |
---|
1810 | <tbody> |
---|
1811 | <row> |
---|
1812 | <entry><code>(&lk)->~L();</code></entry> |
---|
1813 | <entry><code>if (locked()) unlock();</code></entry> |
---|
1814 | </row> |
---|
1815 | <row> |
---|
1816 | <entry><code>(&clk)->operator const void*()</code></entry> |
---|
1817 | <entry>Returns type void*, non-zero if the associated read/write |
---|
1818 | mutex object has been either read-locked or write-locked by |
---|
1819 | <code>clk</code>, otherwise 0.</entry> |
---|
1820 | </row> |
---|
1821 | <row> |
---|
1822 | <entry><code>clk.locked()</code></entry> |
---|
1823 | <entry>Returns a <code>bool</code>, <code>(&clk)->operator |
---|
1824 | const void*() != 0</code></entry> |
---|
1825 | </row> |
---|
1826 | <row> |
---|
1827 | <entry><code>clk.state()</code></entry> |
---|
1828 | <entry>Returns an enumeration constant of type <code>read_write_lock_state</code>: |
---|
1829 | <code>read_write_lock_state::read_locked</code> if the associated read/write mutex object has been |
---|
1830 | read-locked by <code>clk</code>, <code>read_write_lock_state::write_locked</code> if it |
---|
1831 | has been write-locked by <code>clk</code>, and <code>read_write_lock_state::unlocked</code> |
---|
1832 | if has not been locked by <code>clk</code>.</entry> |
---|
1833 | </row> |
---|
1834 | <row> |
---|
1835 | <entry><code>clk.read_locked()</code></entry> |
---|
1836 | <entry>Returns a <code>bool</code>, <code>(&clk)->state() == read_write_lock_state::read_locked</code>.</entry> |
---|
1837 | </row> |
---|
1838 | <row> |
---|
1839 | <entry><code>clk.write_locked()</code></entry> |
---|
1840 | <entry>Returns a <code>bool</code>, <code>(&clk)->state() == read_write_lock_state::write_locked</code>.</entry> |
---|
1841 | </row> |
---|
1842 | <row> |
---|
1843 | <entry><code>lk.read_lock()</code></entry> |
---|
1844 | <entry> |
---|
1845 | <para>Throws <classname>boost::lock_error</classname> |
---|
1846 | if <code>locked()</code>.</para> |
---|
1847 | |
---|
1848 | <para>If the associated read/write mutex |
---|
1849 | object is already read-locked by some other |
---|
1850 | thread, the effect depends on the |
---|
1851 | <link linkend="thread.concepts.read-write-scheduling-policies.inter-class">inter-class scheduling policy</link> |
---|
1852 | of the associated read/write mutex: |
---|
1853 | either immediately obtains an additional |
---|
1854 | read-lock on the associated read/write |
---|
1855 | mutex, or places the current thread in the |
---|
1856 | <link linkend="thread.glossary.thread-state">Blocked</link> |
---|
1857 | state until the associated read/write mutex |
---|
1858 | is unlocked, after which the current thread |
---|
1859 | is placed in the |
---|
1860 | <link linkend="thread.glossary.thread-state">Ready</link> |
---|
1861 | state, eventually to be returned to the |
---|
1862 | <link linkend="thread.glossary.thread-state">Running</link> |
---|
1863 | state.</para> |
---|
1864 | |
---|
1865 | <para>If the associated read/write mutex |
---|
1866 | object is already write-locked by some other |
---|
1867 | thread, places the current thread in the |
---|
1868 | <link linkend="thread.glossary.thread-state">Blocked</link> |
---|
1869 | state until the associated read/write mutex |
---|
1870 | is unlocked, after which the current thread |
---|
1871 | is placed in the |
---|
1872 | <link linkend="thread.glossary.thread-state">Ready</link> |
---|
1873 | state, eventually to be returned to the |
---|
1874 | <link linkend="thread.glossary.thread-state">Running</link> |
---|
1875 | state.</para> |
---|
1876 | |
---|
1877 | <para>If the associated read/write mutex |
---|
1878 | object is already locked by the same thread |
---|
1879 | the behavior is dependent on the |
---|
1880 | <link linkend="thread.concepts.read-write-locking-strategies">locking strategy</link> |
---|
1881 | of the associated read/write mutex object. |
---|
1882 | </para> |
---|
1883 | |
---|
1884 | <para>Postcondition: <code>state() == read_write_lock_state::read_locked</code></para> |
---|
1885 | </entry> |
---|
1886 | </row> |
---|
1887 | <row> |
---|
1888 | <entry><code>lk.write_lock()</code></entry> |
---|
1889 | |
---|
1890 | <entry> |
---|
1891 | <para>Throws <classname>boost::lock_error</classname> |
---|
1892 | if <code>locked()</code>.</para> |
---|
1893 | |
---|
1894 | <para>If the associated read/write mutex |
---|
1895 | object is already locked by some other |
---|
1896 | thread, places the current thread in the |
---|
1897 | <link linkend="thread.glossary.thread-state">Blocked</link> |
---|
1898 | state until the associated read/write mutex |
---|
1899 | is unlocked, after which the current thread |
---|
1900 | is placed in the |
---|
1901 | <link linkend="thread.glossary.thread-state">Ready</link> |
---|
1902 | state, eventually to be returned to the |
---|
1903 | <link linkend="thread.glossary.thread-state">Running</link> |
---|
1904 | state.</para> |
---|
1905 | |
---|
1906 | <para>If the associated read/write mutex |
---|
1907 | object is already locked by the same thread |
---|
1908 | the behavior is dependent on the |
---|
1909 | <link linkend="thread.concepts.read-write-locking-strategies">locking strategy</link> |
---|
1910 | of the associated read/write mutex object. |
---|
1911 | </para> |
---|
1912 | |
---|
1913 | <para>Postcondition: <code>state() == read_write_lock_state::write_locked</code></para> |
---|
1914 | </entry> |
---|
1915 | </row> |
---|
1916 | <row> |
---|
1917 | <entry><code>lk.demote()</code></entry> |
---|
1918 | <entry> |
---|
1919 | <para>Throws <classname>boost::lock_error</classname> |
---|
1920 | if <code>state() != read_write_lock_state::write_locked</code>.</para> |
---|
1921 | |
---|
1922 | <para>Converts the lock held on the associated read/write mutex |
---|
1923 | object from a write-lock to a read-lock without releasing |
---|
1924 | the lock.</para> |
---|
1925 | |
---|
1926 | <para>Postcondition: <code>state() == read_write_lock_state::read_locked</code></para> |
---|
1927 | </entry> |
---|
1928 | </row> |
---|
1929 | <row> |
---|
1930 | <entry><code>lk.promote()</code></entry> |
---|
1931 | <entry> |
---|
1932 | <para>Throws <classname>boost::lock_error</classname> |
---|
1933 | if <code>state() != read_write_lock_state::read_locked</code> |
---|
1934 | or if the lock cannot be promoted because another lock |
---|
1935 | on the same mutex is already waiting to be promoted.</para> |
---|
1936 | |
---|
1937 | <para>Makes a blocking attempt to convert the lock held on the associated |
---|
1938 | read/write mutex object from a read-lock to a write-lock without releasing |
---|
1939 | the lock.</para> |
---|
1940 | </entry> |
---|
1941 | </row> |
---|
1942 | <row> |
---|
1943 | <entry><code>lk.unlock()</code></entry> |
---|
1944 | <entry> |
---|
1945 | <para>Throws <classname>boost::lock_error</classname> |
---|
1946 | if <code>!locked()</code>.</para> |
---|
1947 | |
---|
1948 | <para>Unlocks the associated read/write mutex.</para> |
---|
1949 | |
---|
1950 | <para>Postcondition: <code>!locked()</code></para> |
---|
1951 | </entry> |
---|
1952 | </row> |
---|
1953 | </tbody> |
---|
1954 | </tgroup> |
---|
1955 | </table> |
---|
1956 | </section> |
---|
1957 | |
---|
1958 | <section id="thread.concepts.ScopedReadWriteLock"> |
---|
1959 | <title>ScopedReadWriteLock Concept</title> |
---|
1960 | |
---|
1961 | <para>A ScopedReadWriteLock is a refinement of |
---|
1962 | <link linkend="thread.concepts.ReadWriteLock">ReadWriteLock</link>. |
---|
1963 | For a ScopedReadWriteLock type <code>L</code> |
---|
1964 | and an object <code>lk</code> of that type, |
---|
1965 | and an object <code>m</code> of a type meeting the |
---|
1966 | <link linkend="thread.concepts.ReadWriteMutex">ReadWriteMutex</link> requirements, |
---|
1967 | and an object <code>s</code> of type <code>read_write_lock_state</code>, |
---|
1968 | the following expressions must be well-formed |
---|
1969 | and have the indicated effects.</para> |
---|
1970 | |
---|
1971 | <table> |
---|
1972 | <title>ScopedReadWriteLock Expressions</title> |
---|
1973 | |
---|
1974 | <tgroup cols="2"> |
---|
1975 | <thead> |
---|
1976 | <row> |
---|
1977 | <entry>Expression</entry> |
---|
1978 | <entry>Effects</entry> |
---|
1979 | </row> |
---|
1980 | </thead> |
---|
1981 | |
---|
1982 | <tbody> |
---|
1983 | <row> |
---|
1984 | <entry><code>L lk(m,s);</code></entry> |
---|
1985 | <entry>Constructs an object <code>lk</code> and associates read/write mutex |
---|
1986 | object <code>m</code> with it, then: if <code>s == read_write_lock_state::read_locked</code>, calls |
---|
1987 | <code>read_lock()</code>; if <code>s==read_write_lock_state::write_locked</code>, |
---|
1988 | calls <code>write_lock()</code>.</entry> |
---|
1989 | </row> |
---|
1990 | </tbody> |
---|
1991 | </tgroup> |
---|
1992 | </table> |
---|
1993 | </section> |
---|
1994 | |
---|
1995 | <section id="thread.concepts.TryReadWriteLock"> |
---|
1996 | <title>TryReadWriteLock Expressions</title> |
---|
1997 | |
---|
1998 | <para>A TryReadWriteLock is a refinement of |
---|
1999 | <link linkend="thread.concepts.ReadWriteLock">ReadWriteLock</link>. |
---|
2000 | For a TryReadWriteLock type <code>L</code> |
---|
2001 | and an object <code>lk</code> of that type, |
---|
2002 | the following expressions must be well-formed |
---|
2003 | and have the indicated effects.</para> |
---|
2004 | |
---|
2005 | <table> |
---|
2006 | <title>TryReadWriteLock Expressions</title> |
---|
2007 | |
---|
2008 | <tgroup cols="2"> |
---|
2009 | <thead> |
---|
2010 | <row> |
---|
2011 | <entry>Expression</entry> |
---|
2012 | <entry>Effects</entry> |
---|
2013 | </row> |
---|
2014 | </thead> |
---|
2015 | |
---|
2016 | <tbody> |
---|
2017 | <row> |
---|
2018 | <entry><code>lk.try_read_lock()</code></entry> |
---|
2019 | <entry> |
---|
2020 | <para>Throws <classname>boost::lock_error</classname> |
---|
2021 | if locked().</para> |
---|
2022 | |
---|
2023 | <para>Makes a non-blocking attempt to read-lock the associated read/write |
---|
2024 | mutex object, returning <code>true</code> if the attempt is successful, |
---|
2025 | otherwise <code>false</code>. If the associated read/write mutex object is |
---|
2026 | already locked by the same thread the behavior is dependent on the |
---|
2027 | <link linkend="thread.concepts.locking-strategies">locking |
---|
2028 | strategy</link> of the associated read/write mutex object.</para> |
---|
2029 | </entry> |
---|
2030 | </row> |
---|
2031 | <row> |
---|
2032 | <entry><code>lk.try_write_lock()</code></entry> |
---|
2033 | <entry> |
---|
2034 | <para>Throws <classname>boost::lock_error</classname> |
---|
2035 | if locked().</para> |
---|
2036 | |
---|
2037 | <para>Makes a non-blocking attempt to write-lock the associated read/write |
---|
2038 | mutex object, returning <code>true</code> if the attempt is successful, |
---|
2039 | otherwise <code>false</code>. If the associated read/write mutex object is |
---|
2040 | already locked by the same thread the behavior is dependent on the |
---|
2041 | <link linkend="thread.concepts.locking-strategies">locking |
---|
2042 | strategy</link> of the associated read/write mutex object.</para> |
---|
2043 | </entry> |
---|
2044 | </row> |
---|
2045 | <row> |
---|
2046 | <entry><code>lk.try_demote()</code></entry> |
---|
2047 | <entry> |
---|
2048 | <para>Throws <classname>boost::lock_error</classname> |
---|
2049 | if <code>state() != read_write_lock_state::write_locked</code>.</para> |
---|
2050 | |
---|
2051 | <para>Makes a non-blocking attempt to convert the lock held on the associated |
---|
2052 | read/write mutex object from a write-lock to a read-lock without releasing |
---|
2053 | the lock, returning <code>true</code> if the attempt is successful, |
---|
2054 | otherwise <code>false</code>.</para> |
---|
2055 | </entry> |
---|
2056 | </row> |
---|
2057 | <row> |
---|
2058 | <entry><code>lk.try_promote()</code></entry> |
---|
2059 | <entry> |
---|
2060 | <para>Throws <classname>boost::lock_error</classname> |
---|
2061 | if <code>state() != read_write_lock_state::read_locked</code>.</para> |
---|
2062 | |
---|
2063 | <para>Makes a non-blocking attempt to convert the lock held on the associated |
---|
2064 | read/write mutex object from a read-lock to a write-lock without releasing |
---|
2065 | the lock, returning <code>true</code> if the attempt is successful, |
---|
2066 | otherwise <code>false</code>.</para> |
---|
2067 | </entry> |
---|
2068 | </row> |
---|
2069 | </tbody> |
---|
2070 | </tgroup> |
---|
2071 | </table> |
---|
2072 | </section> |
---|
2073 | |
---|
2074 | <section id="thread.concepts.ScopedTryReadWriteLock"> |
---|
2075 | <title>ScopedTryReadWriteLock Expressions</title> |
---|
2076 | |
---|
2077 | <para>A ScopedTryReadWriteLock is a refinement of |
---|
2078 | <link linkend="thread.concepts.TryReadWriteLock">TryReadWriteLock</link>. |
---|
2079 | For a ScopedTryReadWriteLock type <code>L</code> |
---|
2080 | and an object <code>lk</code> of that type, |
---|
2081 | and an object <code>m</code> of a type meeting the |
---|
2082 | <link linkend="thread.concepts.TryMutex">TryReadWriteMutex</link> requirements, |
---|
2083 | and an object <code>s</code> of type <code>read_write_lock_state</code>, |
---|
2084 | and an object <code>b</code> of type <code>blocking_mode</code>, |
---|
2085 | the following expressions must be well-formed |
---|
2086 | and have the indicated effects.</para> |
---|
2087 | |
---|
2088 | <table> |
---|
2089 | <title>ScopedTryReadWriteLock Expressions</title> |
---|
2090 | |
---|
2091 | <tgroup cols="2"> |
---|
2092 | <thead> |
---|
2093 | <row> |
---|
2094 | <entry>Expression</entry> |
---|
2095 | <entry>Effects</entry> |
---|
2096 | </row> |
---|
2097 | </thead> |
---|
2098 | |
---|
2099 | <tbody> |
---|
2100 | <row> |
---|
2101 | <entry><code>L lk(m,s,b);</code></entry> |
---|
2102 | <entry>Constructs an object <code>lk</code> and associates read/write mutex |
---|
2103 | object <code>m</code> with it, then: if <code>s == read_write_lock_state::read_locked</code>, calls |
---|
2104 | <code>read_lock()</code> if <code>b</code>, otherwise <code>try_read_lock()</code>; |
---|
2105 | if <code>s==read_write_lock_state::write_locked</code>, calls <code>write_lock()</code> if <code>b</code>, |
---|
2106 | otherwise <code>try_write_lock</code>.</entry> |
---|
2107 | </row> |
---|
2108 | </tbody> |
---|
2109 | </tgroup> |
---|
2110 | </table> |
---|
2111 | </section> |
---|
2112 | |
---|
2113 | <section id="thread.concepts.TimedReadWriteLock"> |
---|
2114 | <title>TimedReadWriteLock Concept</title> |
---|
2115 | |
---|
2116 | <para>A TimedReadWriteLock is a refinement of |
---|
2117 | <link linkend="thread.concepts.TryReadWriteLock">TryReadWriteLock</link>. |
---|
2118 | For a TimedReadWriteLock type <code>L</code> |
---|
2119 | and an object <code>lk</code> of that type, |
---|
2120 | and an object <code>t</code> of type <classname>boost::xtime</classname>, |
---|
2121 | the following expressions must be well-formed |
---|
2122 | and have the indicated effects.</para> |
---|
2123 | |
---|
2124 | <table> |
---|
2125 | <title>TimedReadWriteLock Expressions</title> |
---|
2126 | |
---|
2127 | <tgroup cols="2"> |
---|
2128 | <thead> |
---|
2129 | <row> |
---|
2130 | <entry>Expression</entry> |
---|
2131 | <entry>Effects</entry> |
---|
2132 | </row> |
---|
2133 | </thead> |
---|
2134 | |
---|
2135 | <tbody> |
---|
2136 | <row> |
---|
2137 | <entry><code>lk.timed_read_lock(t)</code></entry> |
---|
2138 | <entry> |
---|
2139 | <para>Throws <classname>boost::lock_error</classname> |
---|
2140 | if locked().</para> |
---|
2141 | |
---|
2142 | <para>Makes a blocking attempt to read-lock the associated read/write mutex object, |
---|
2143 | and returns <code>true</code> if successful within the specified time <code>t</code>, |
---|
2144 | otherwise <code>false</code>. If the associated read/write mutex object is already |
---|
2145 | locked by the same thread the behavior is dependent on the <link |
---|
2146 | linkend="thread.concepts.locking-strategies">locking |
---|
2147 | strategy</link> of the associated read/write mutex object.</para> |
---|
2148 | </entry> |
---|
2149 | </row> |
---|
2150 | <row> |
---|
2151 | <entry><code>lk.timed_write_lock(t)</code></entry> |
---|
2152 | <entry> |
---|
2153 | <para>Throws <classname>boost::lock_error</classname> |
---|
2154 | if locked().</para> |
---|
2155 | |
---|
2156 | <para>Makes a blocking attempt to write-lock the associated read/write mutex object, |
---|
2157 | and returns <code>true</code> if successful within the specified time <code>t</code>, |
---|
2158 | otherwise <code>false</code>. If the associated read/write mutex object is already |
---|
2159 | locked by the same thread the behavior is dependent on the <link |
---|
2160 | linkend="thread.concepts.locking-strategies">locking |
---|
2161 | strategy</link> of the associated read/write mutex object.</para> |
---|
2162 | </entry> |
---|
2163 | </row> |
---|
2164 | <row> |
---|
2165 | <entry><code>lk.timed_demote(t)</code></entry> |
---|
2166 | <entry> |
---|
2167 | <para>Throws <classname>boost::lock_error</classname> |
---|
2168 | if <code>state() != read_write_lock_state::write_locked</code>.</para> |
---|
2169 | |
---|
2170 | <para>Makes a blocking attempt to convert the lock held on the associated |
---|
2171 | read/write mutex object from a write-lock to a read-lock without releasing |
---|
2172 | the lock, returning <code>true</code> if the attempt is successful |
---|
2173 | in the specified time <code>t</code>, otherwise <code>false</code>.</para> |
---|
2174 | </entry> |
---|
2175 | </row> |
---|
2176 | <row> |
---|
2177 | <entry><code>lk.timed_promote(t)</code></entry> |
---|
2178 | <entry> |
---|
2179 | <para>Throws <classname>boost::lock_error</classname> |
---|
2180 | if <code>state() != read_write_lock_state::read_locked</code>.</para> |
---|
2181 | |
---|
2182 | <para>Makes a blocking attempt to convert the lock held on the associated |
---|
2183 | read/write mutex object from a read-lock to a write-lock without releasing |
---|
2184 | the lock, returning <code>true</code> if the attempt is successful |
---|
2185 | in the specified time <code>t</code>, otherwise <code>false</code>.</para> |
---|
2186 | </entry> |
---|
2187 | </row> |
---|
2188 | </tbody> |
---|
2189 | </tgroup> |
---|
2190 | </table> |
---|
2191 | </section> |
---|
2192 | |
---|
2193 | <section id="thread.concepts.ScopedTimedReadWriteLock"> |
---|
2194 | <title>ScopedTimedReadWriteLock Concept</title> |
---|
2195 | |
---|
2196 | <para>A ScopedTimedReadWriteLock is a refinement of |
---|
2197 | <link linkend="thread.concepts.TimedReadWriteLock">TimedReadWriteLock</link>. |
---|
2198 | For a ScopedTimedReadWriteLock type <code>L</code> |
---|
2199 | and an object <code>lk</code> of that type, |
---|
2200 | and an object <code>m</code> of a type meeting the |
---|
2201 | <link linkend="thread.concepts.TimedReadWriteMutex">TimedReadWriteMutex</link> requirements, |
---|
2202 | and an object <code>s</code> of type <code>read_write_lock_state</code>, |
---|
2203 | and an object <code>t</code> of type <classname>boost::xtime</classname>, |
---|
2204 | and an object <code>b</code> of type <code>blocking_mode</code>, |
---|
2205 | the following expressions must be well-formed and have the |
---|
2206 | indicated effects.</para> |
---|
2207 | |
---|
2208 | <table> |
---|
2209 | <title>ScopedTimedReadWriteLock Expressions</title> |
---|
2210 | |
---|
2211 | <tgroup cols="2"> |
---|
2212 | <thead> |
---|
2213 | <row> |
---|
2214 | <entry>Expression</entry> |
---|
2215 | <entry>Effects</entry> |
---|
2216 | </row> |
---|
2217 | </thead> |
---|
2218 | |
---|
2219 | <tbody> |
---|
2220 | <row> |
---|
2221 | <entry><code>L lk(m,s,b);</code></entry> |
---|
2222 | <entry>Constructs an object <code>lk</code> and associates read/write mutex |
---|
2223 | object <code>m</code> with it, then: if <code>s == read_write_lock_state::read_locked</code>, calls |
---|
2224 | <code>read_lock()</code> if <code>b</code>, otherwise <code>try_read_lock()</code>; |
---|
2225 | if <code>s==read_write_lock_state::write_locked</code>, calls <code>write_lock()</code> if <code>b</code>, |
---|
2226 | otherwise <code>try_write_lock</code>.</entry> |
---|
2227 | </row> |
---|
2228 | <row> |
---|
2229 | <entry><code>L lk(m,s,t);</code></entry> |
---|
2230 | <entry>Constructs an object <code>lk</code> and associates read/write mutex |
---|
2231 | object <code>m</code> with it, then: if <code>s == read_write_lock_state::read_locked</code>, calls |
---|
2232 | <code>timed_read_lock(t)</code>; if <code>s==read_write_lock_state::write_locked</code>, |
---|
2233 | calls <code>timed_write_lock(t)</code>.</entry> |
---|
2234 | </row> |
---|
2235 | </tbody> |
---|
2236 | </tgroup> |
---|
2237 | </table> |
---|
2238 | </section> |
---|
2239 | </section> |
---|
2240 | |
---|
2241 | <section id="thread.concepts.read-write-lock-models"> |
---|
2242 | <title>Lock Models</title> |
---|
2243 | |
---|
2244 | <para>&Boost.Thread; currently supplies six models of |
---|
2245 | <link linkend="thread.concepts.ReadWriteLock">ReadWriteLock</link> |
---|
2246 | and its refinements.</para> |
---|
2247 | |
---|
2248 | <table> |
---|
2249 | <title>Lock Models</title> |
---|
2250 | |
---|
2251 | <tgroup cols="3"> |
---|
2252 | <thead> |
---|
2253 | <row> |
---|
2254 | <entry>Concept</entry> |
---|
2255 | <entry>Refines</entry> |
---|
2256 | <entry>Models</entry> |
---|
2257 | </row> |
---|
2258 | </thead> |
---|
2259 | |
---|
2260 | <tbody> |
---|
2261 | <row> |
---|
2262 | <entry><link linkend="thread.concepts.ReadWriteLock">ReadWriteLock</link></entry> |
---|
2263 | <entry></entry> |
---|
2264 | <entry></entry> |
---|
2265 | </row> |
---|
2266 | <row> |
---|
2267 | <entry><link linkend="thread.concepts.ScopedReadWriteLock">ScopedReadWriteLock</link></entry> |
---|
2268 | <entry><link linkend="thread.concepts.ReadWriteLock">ReadWriteLock</link></entry> |
---|
2269 | <entry> |
---|
2270 | <para><classname>boost::read_write_mutex::scoped_read_write_lock</classname></para> |
---|
2271 | <para><classname>boost::try_read_write_mutex::scoped_read_write_lock</classname></para> |
---|
2272 | <para><classname>boost::timed_read_write_mutex::scoped_read_write_lock</classname></para> |
---|
2273 | </entry> |
---|
2274 | </row> |
---|
2275 | <row> |
---|
2276 | <entry><link linkend="thread.concepts.TryReadWriteLock">TryReadWriteLock</link></entry> |
---|
2277 | <entry><link linkend="thread.concepts.ReadWriteLock">ReadWriteLock</link></entry> |
---|
2278 | <entry></entry> |
---|
2279 | </row> |
---|
2280 | <row> |
---|
2281 | <entry><link linkend="thread.concepts.ScopedTryReadWriteLock">ScopedTryReadWriteLock</link></entry> |
---|
2282 | <entry><link linkend="thread.concepts.TryReadWriteLock">TryReadWriteLock</link></entry> |
---|
2283 | <entry> |
---|
2284 | <para><classname>boost::try_read_write_mutex::scoped_try_read_write_lock</classname></para> |
---|
2285 | <para><classname>boost::timed_read_write_mutex::scoped_try_read_write_lock</classname></para> |
---|
2286 | </entry> |
---|
2287 | </row> |
---|
2288 | <row> |
---|
2289 | <entry><link linkend="thread.concepts.TimedReadWriteLock">TimedReadWriteLock</link></entry> |
---|
2290 | <entry><link linkend="thread.concepts.TryReadWriteLock">TryReadWriteLock</link></entry> |
---|
2291 | <entry></entry> |
---|
2292 | </row> |
---|
2293 | <row> |
---|
2294 | <entry><link linkend="thread.concepts.ScopedTimedReadWriteLock">ScopedTimedReadWriteLock</link></entry> |
---|
2295 | <entry><link linkend="thread.concepts.TimedReadWriteLock">TimedReadWriteLock</link></entry> |
---|
2296 | <entry> |
---|
2297 | <para><classname>boost::timed_read_write_mutex::scoped_timed_read_write_lock</classname></para> |
---|
2298 | </entry> |
---|
2299 | </row> |
---|
2300 | </tbody> |
---|
2301 | </tgroup> |
---|
2302 | </table> |
---|
2303 | </section> |
---|
2304 | </section> |
---|
2305 | </section> |
---|