UNPKG

boost-react-native-bundle

Version:

Boost library as in https://sourceforge.net/projects/boost/files/boost/1.57.0/

550 lines (541 loc) 1.5 MB
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII"> <title>Synchronization</title> <link rel="stylesheet" href="../../../doc/src/boostbook.css" type="text/css"> <meta name="generator" content="DocBook XSL Stylesheets V1.78.1"> <link rel="home" href="../index.html" title="The Boost C++ Libraries BoostBook Documentation Subset"> <link rel="up" href="../thread.html" title="Chapter&#160;30.&#160;Thread 4.4.0"> <link rel="prev" href="ScopedThreads.html" title="Scoped Threads"> <link rel="next" href="thread_local_storage.html" title="Thread Local Storage"> </head> <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> <table cellpadding="2" width="100%"><tr> <td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../boost.png"></td> <td align="center"><a href="../../../index.html">Home</a></td> <td align="center"><a href="../../../libs/libraries.htm">Libraries</a></td> <td align="center"><a href="http://www.boost.org/users/people.html">People</a></td> <td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td> <td align="center"><a href="../../../more/index.htm">More</a></td> </tr></table> <hr> <div class="spirit-nav"> <a accesskey="p" href="ScopedThreads.html"><img src="../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../thread.html"><img src="../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="thread_local_storage.html"><img src="../../../doc/src/images/next.png" alt="Next"></a> </div> <div class="section"> <div class="titlepage"><div><div><h2 class="title" style="clear: both"> <a name="thread.synchronization"></a><a class="link" href="synchronization.html" title="Synchronization">Synchronization</a> </h2></div></div></div> <div class="toc"><dl class="toc"> <dt><span class="section"><a href="synchronization.html#thread.synchronization.tutorial">Tutorial</a></span></dt> <dt><span class="section"><a href="synchronization.html#thread.synchronization.mutex_concepts">Mutex Concepts</a></span></dt> <dt><span class="section"><a href="synchronization.html#thread.synchronization.lock_option">Lock Options</a></span></dt> <dt><span class="section"><a href="synchronization.html#thread.synchronization.lock_guard">Lock Guard</a></span></dt> <dt><span class="section"><a href="synchronization.html#thread.synchronization.with_lock_guard">With Lock Guard</a></span></dt> <dt><span class="section"><a href="synchronization.html#thread.synchronization.lock_concepts">Lock Concepts</a></span></dt> <dt><span class="section"><a href="synchronization.html#thread.synchronization.locks">Lock Types</a></span></dt> <dt><span class="section"><a href="synchronization.html#thread.synchronization.other_locks">Other Lock Types - EXTENSION</a></span></dt> <dt><span class="section"><a href="synchronization.html#thread.synchronization.lock_functions">Lock functions</a></span></dt> <dt><span class="section"><a href="synchronization.html#thread.synchronization.lock_factories">Lock Factories - EXTENSION</a></span></dt> <dt><span class="section"><a href="synchronization.html#thread.synchronization.mutex_types">Mutex Types</a></span></dt> <dt><span class="section"><a href="synchronization.html#thread.synchronization.condvar_ref">Condition Variables</a></span></dt> <dt><span class="section"><a href="synchronization.html#thread.synchronization.once">One-time Initialization</a></span></dt> <dt><span class="section"><a href="synchronization.html#thread.synchronization.barriers">Barriers -- EXTENSION</a></span></dt> <dt><span class="section"><a href="synchronization.html#thread.synchronization.latches">Latches -- EXPERIMENTAL</a></span></dt> <dt><span class="section"><a href="synchronization.html#thread.synchronization.executors">Executors and Schedulers -- EXPERIMENTAL</a></span></dt> <dt><span class="section"><a href="synchronization.html#thread.synchronization.futures">Futures</a></span></dt> </dl></div> <div class="section"> <div class="titlepage"><div><div><h3 class="title"> <a name="thread.synchronization.tutorial"></a><a class="link" href="synchronization.html#thread.synchronization.tutorial" title="Tutorial">Tutorial</a> </h3></div></div></div> <div class="toc"><dl class="toc"> <dt><span class="section"><a href="synchronization.html#thread.synchronization.tutorial.internal_locking">Internal Locking</a></span></dt> <dt><span class="section"><a href="synchronization.html#thread.synchronization.tutorial.external_locking_____strict_lock__and__externally_locked__classes">External Locking -- <code class="computeroutput"><span class="identifier">strict_lock</span></code> and <code class="computeroutput"><span class="identifier">externally_locked</span></code> classes</a></span></dt> <dt><span class="section"><a href="synchronization.html#thread.synchronization.tutorial.with">Executing Around a Function</a></span></dt> </dl></div> <p> <a href="http://home.roadrunner.com/~hinnant/mutexes/locking.html" target="_top">Handling mutexes in C++</a> is an excellent tutorial. You need just replace std and ting by boost. </p> <p> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2406.html" target="_top">Mutex, Lock, Condition Variable Rationale</a> adds rationale for the design decisions made for mutexes, locks and condition variables. </p> <p> In addition to the C++11 standard locks, Boost.Thread provides other locks and some utilities that help the user to make their code thread-safe. </p> <div class="section"> <div class="titlepage"><div><div><h4 class="title"> <a name="thread.synchronization.tutorial.internal_locking"></a><a class="link" href="synchronization.html#thread.synchronization.tutorial.internal_locking" title="Internal Locking">Internal Locking</a> </h4></div></div></div> <div class="toc"><dl class="toc"> <dt><span class="section"><a href="synchronization.html#thread.synchronization.tutorial.internal_locking.concurrent_threads_of_execution">Concurrent threads of execution</a></span></dt> <dt><span class="section"><a href="synchronization.html#thread.synchronization.tutorial.internal_locking.internal_locking">Internal locking</a></span></dt> <dt><span class="section"><a href="synchronization.html#thread.synchronization.tutorial.internal_locking.internal_and_external_locking">Internal and external locking</a></span></dt> </dl></div> <div class="note"><table border="0" summary="Note"> <tr> <td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../doc/src/images/note.png"></td> <th align="left">Note</th> </tr> <tr><td align="left" valign="top"><p> This tutorial is an adaptation of chapter Concurrency of the Object-Oriented Programming in the BETA Programming Language and of the paper of Andrei Alexandrescu "Multithreading and the C++ Type System" to the Boost library. </p></td></tr> </table></div> <div class="section"> <div class="titlepage"><div><div><h5 class="title"> <a name="thread.synchronization.tutorial.internal_locking.concurrent_threads_of_execution"></a><a class="link" href="synchronization.html#thread.synchronization.tutorial.internal_locking.concurrent_threads_of_execution" title="Concurrent threads of execution">Concurrent threads of execution</a> </h5></div></div></div> <p> Consider, for example, modeling a bank account class that supports simultaneous deposits and withdrawals from multiple locations (arguably the "Hello, World" of multithreaded programming). </p> <p> From here a component is a model of the <code class="computeroutput"><span class="identifier">Callable</span></code> concept. </p> <p> I C++11 (Boost) concurrent execution of a component is obtained by means of the <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">thread</span></code>(<code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">thread</span></code>): </p> <pre class="programlisting"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">thread</span> <span class="identifier">thread1</span><span class="special">(</span><span class="identifier">S</span><span class="special">);</span> </pre> <p> where <code class="computeroutput"><span class="identifier">S</span></code> is a model of <code class="computeroutput"><span class="identifier">Callable</span></code>. The meaning of this expression is that execution of <code class="computeroutput"><span class="identifier">S</span><span class="special">()</span></code> will take place concurrently with the current thread of execution executing the expression. </p> <p> The following example includes a bank account of a person (Joe) and two components, one corresponding to a bank agent depositing money in Joe's account, and one representing Joe. Joe will only be withdrawing money from the account: </p> <pre class="programlisting"><span class="keyword">class</span> <span class="identifier">BankAccount</span><span class="special">;</span> <span class="identifier">BankAccount</span> <span class="identifier">JoesAccount</span><span class="special">;</span> <span class="keyword">void</span> <span class="identifier">bankAgent</span><span class="special">()</span> <span class="special">{</span> <span class="keyword">for</span> <span class="special">(</span><span class="keyword">int</span> <span class="identifier">i</span> <span class="special">=</span><span class="number">10</span><span class="special">;</span> <span class="identifier">i</span><span class="special">&gt;</span><span class="number">0</span><span class="special">;</span> <span class="special">--</span><span class="identifier">i</span><span class="special">)</span> <span class="special">{</span> <span class="comment">//...</span> <span class="identifier">JoesAccount</span><span class="special">.</span><span class="identifier">Deposit</span><span class="special">(</span><span class="number">500</span><span class="special">);</span> <span class="comment">//...</span> <span class="special">}</span> <span class="special">}</span> <span class="keyword">void</span> <span class="identifier">Joe</span><span class="special">()</span> <span class="special">{</span> <span class="keyword">for</span> <span class="special">(</span><span class="keyword">int</span> <span class="identifier">i</span> <span class="special">=</span><span class="number">10</span><span class="special">;</span> <span class="identifier">i</span><span class="special">&gt;</span><span class="number">0</span><span class="special">;</span> <span class="special">--</span><span class="identifier">i</span><span class="special">)</span> <span class="special">{</span> <span class="comment">//...</span> <span class="keyword">int</span> <span class="identifier">myPocket</span> <span class="special">=</span> <span class="identifier">JoesAccount</span><span class="special">.</span><span class="identifier">Withdraw</span><span class="special">(</span><span class="number">100</span><span class="special">);</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="identifier">myPocket</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> <span class="comment">//...</span> <span class="special">}</span> <span class="special">}</span> <span class="keyword">int</span> <span class="identifier">main</span><span class="special">()</span> <span class="special">{</span> <span class="comment">//...</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">thread</span> <span class="identifier">thread1</span><span class="special">(</span><span class="identifier">bankAgent</span><span class="special">);</span> <span class="comment">// start concurrent execution of bankAgent</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">thread</span> <span class="identifier">thread2</span><span class="special">(</span><span class="identifier">Joe</span><span class="special">);</span> <span class="comment">// start concurrent execution of Joe</span> <span class="identifier">thread1</span><span class="special">.</span><span class="identifier">join</span><span class="special">();</span> <span class="identifier">thread2</span><span class="special">.</span><span class="identifier">join</span><span class="special">();</span> <span class="keyword">return</span> <span class="number">0</span><span class="special">;</span> <span class="special">}</span> </pre> <p> From time to time, the <code class="computeroutput"><span class="identifier">bankAgent</span></code> will deposit $500 in <code class="computeroutput"><span class="identifier">JoesAccount</span></code>. <code class="computeroutput"><span class="identifier">Joe</span></code> will similarly withdraw $100 from his account. These sentences describe that the <code class="computeroutput"><span class="identifier">bankAgent</span></code> and <code class="computeroutput"><span class="identifier">Joe</span></code> are executed concurrently. </p> </div> <div class="section"> <div class="titlepage"><div><div><h5 class="title"> <a name="thread.synchronization.tutorial.internal_locking.internal_locking"></a><a class="link" href="synchronization.html#thread.synchronization.tutorial.internal_locking.internal_locking" title="Internal locking">Internal locking</a> </h5></div></div></div> <p> The above example works well as long as the components <code class="computeroutput"><span class="identifier">bankAgent</span></code> and <code class="computeroutput"><span class="identifier">Joe</span></code> doesn't access <code class="computeroutput"><span class="identifier">JoesAccount</span></code> at the same time. There is, however, no guarantee that this will not happen. We may use a mutex to guarantee exclusive access to each bank. </p> <pre class="programlisting"><span class="keyword">class</span> <span class="identifier">BankAccount</span> <span class="special">{</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">mutex</span> <span class="identifier">mtx_</span><span class="special">;</span> <span class="keyword">int</span> <span class="identifier">balance_</span><span class="special">;</span> <span class="keyword">public</span><span class="special">:</span> <span class="keyword">void</span> <span class="identifier">Deposit</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">amount</span><span class="special">)</span> <span class="special">{</span> <span class="identifier">mtx_</span><span class="special">.</span><span class="identifier">lock</span><span class="special">();</span> <span class="identifier">balance_</span> <span class="special">+=</span> <span class="identifier">amount</span><span class="special">;</span> <span class="identifier">mtx_</span><span class="special">.</span><span class="identifier">unlock</span><span class="special">();</span> <span class="special">}</span> <span class="keyword">void</span> <span class="identifier">Withdraw</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">amount</span><span class="special">)</span> <span class="special">{</span> <span class="identifier">mtx_</span><span class="special">.</span><span class="identifier">lock</span><span class="special">();</span> <span class="identifier">balance_</span> <span class="special">-=</span> <span class="identifier">amount</span><span class="special">;</span> <span class="identifier">mtx_</span><span class="special">.</span><span class="identifier">unlock</span><span class="special">();</span> <span class="special">}</span> <span class="keyword">int</span> <span class="identifier">GetBalance</span><span class="special">()</span> <span class="special">{</span> <span class="identifier">mtx_</span><span class="special">.</span><span class="identifier">lock</span><span class="special">();</span> <span class="keyword">int</span> <span class="identifier">b</span> <span class="special">=</span> <span class="identifier">balance_</span><span class="special">;</span> <span class="identifier">mtx_</span><span class="special">.</span><span class="identifier">unlock</span><span class="special">();</span> <span class="keyword">return</span> <span class="identifier">b</span><span class="special">;</span> <span class="special">}</span> <span class="special">};</span> </pre> <p> Execution of the <code class="computeroutput"><span class="identifier">Deposit</span></code> and <code class="computeroutput"><span class="identifier">Withdraw</span></code> operations will no longer be able to make simultaneous access to balance. </p> <p> A mutex is a simple and basic mechanism for obtaining synchronization. In the above example it is relatively easy to be convinced that the synchronization works correctly (in the absence of exception). In a system with several concurrent objects and several shared objects, it may be difficult to describe synchronization by means of mutexes. Programs that make heavy use of mutexes may be difficult to read and write. Instead, we shall introduce a number of generic classes for handling more complicated forms of synchronization and communication. </p> <p> With the RAII idiom we can simplify a lot this using the scoped locks. In the code below, guard's constructor locks the passed-in object <code class="computeroutput"><span class="identifier">mtx_</span></code>, and guard's destructor unlocks <code class="computeroutput"><span class="identifier">mtx_</span></code>. </p> <pre class="programlisting"><span class="keyword">class</span> <span class="identifier">BankAccount</span> <span class="special">{</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">mutex</span> <span class="identifier">mtx_</span><span class="special">;</span> <span class="comment">// explicit mutex declaration </span> <span class="keyword">int</span> <span class="identifier">balance_</span><span class="special">;</span> <span class="keyword">public</span><span class="special">:</span> <span class="keyword">void</span> <span class="identifier">Deposit</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">amount</span><span class="special">)</span> <span class="special">{</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">lock_guard</span><span class="special">&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">mutex</span><span class="special">&gt;</span> <span class="identifier">guard</span><span class="special">(</span><span class="identifier">mtx_</span><span class="special">);</span> <span class="identifier">balance_</span> <span class="special">+=</span> <span class="identifier">amount</span><span class="special">;</span> <span class="special">}</span> <span class="keyword">void</span> <span class="identifier">Withdraw</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">amount</span><span class="special">)</span> <span class="special">{</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">lock_guard</span><span class="special">&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">mutex</span><span class="special">&gt;</span> <span class="identifier">guard</span><span class="special">(</span><span class="identifier">mtx_</span><span class="special">);</span> <span class="identifier">balance_</span> <span class="special">-=</span> <span class="identifier">amount</span><span class="special">;</span> <span class="special">}</span> <span class="keyword">int</span> <span class="identifier">GetBalance</span><span class="special">()</span> <span class="special">{</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">lock_guard</span><span class="special">&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">mutex</span><span class="special">&gt;</span> <span class="identifier">guard</span><span class="special">(</span><span class="identifier">mtx_</span><span class="special">);</span> <span class="keyword">return</span> <span class="identifier">balance_</span><span class="special">;</span> <span class="special">}</span> <span class="special">};</span> </pre> <p> The object-level locking idiom doesn't cover the entire richness of a threading model. For example, the model above is quite deadlock-prone when you try to coordinate multi-object transactions. Nonetheless, object-level locking is useful in many cases, and in combination with other mechanisms can provide a satisfactory solution to many threaded access problems in object-oriented programs. </p> </div> <div class="section"> <div class="titlepage"><div><div><h5 class="title"> <a name="thread.synchronization.tutorial.internal_locking.internal_and_external_locking"></a><a class="link" href="synchronization.html#thread.synchronization.tutorial.internal_locking.internal_and_external_locking" title="Internal and external locking">Internal and external locking</a> </h5></div></div></div> <p> The BankAccount class above uses internal locking. Basically, a class that uses internal locking guarantees that any concurrent calls to its public member functions don't corrupt an instance of that class. This is typically ensured by having each public member function acquire a lock on the object upon entry. This way, for any given object of that class, there can be only one member function call active at any moment, so the operations are nicely serialized. </p> <p> This approach is reasonably easy to implement and has an attractive simplicity. Unfortunately, "simple" might sometimes morph into "simplistic." </p> <p> Internal locking is insufficient for many real-world synchronization tasks. Imagine that you want to implement an ATM withdrawal transaction with the BankAccount class. The requirements are simple. The ATM transaction consists of two withdrawals-one for the actual money and one for the $2 commission. The two withdrawals must appear in strict sequence; that is, no other transaction can exist between them. </p> <p> The obvious implementation is erratic: </p> <pre class="programlisting"><span class="keyword">void</span> <span class="identifier">ATMWithdrawal</span><span class="special">(</span><span class="identifier">BankAccount</span><span class="special">&amp;</span> <span class="identifier">acct</span><span class="special">,</span> <span class="keyword">int</span> <span class="identifier">sum</span><span class="special">)</span> <span class="special">{</span> <span class="identifier">acct</span><span class="special">.</span><span class="identifier">Withdraw</span><span class="special">(</span><span class="identifier">sum</span><span class="special">);</span> <span class="comment">// preemption possible</span> <span class="identifier">acct</span><span class="special">.</span><span class="identifier">Withdraw</span><span class="special">(</span><span class="number">2</span><span class="special">);</span> <span class="special">}</span> </pre> <p> The problem is that between the two calls above, another thread can perform another operation on the account, thus breaking the second design requirement. </p> <p> In an attempt to solve this problem, let's lock the account from the outside during the two operations: </p> <pre class="programlisting"><span class="keyword">void</span> <span class="identifier">ATMWithdrawal</span><span class="special">(</span><span class="identifier">BankAccount</span><span class="special">&amp;</span> <span class="identifier">acct</span><span class="special">,</span> <span class="keyword">int</span> <span class="identifier">sum</span><span class="special">)</span> <span class="special">{</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">lock_guard</span><span class="special">&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">mutex</span><span class="special">&gt;</span> <span class="identifier">guard</span><span class="special">(</span><span class="identifier">acct</span><span class="special">.</span><span class="identifier">mtx_</span><span class="special">);</span> <span class="number">1</span> <span class="identifier">acct</span><span class="special">.</span><span class="identifier">Withdraw</span><span class="special">(</span><span class="identifier">sum</span><span class="special">);</span> <span class="identifier">acct</span><span class="special">.</span><span class="identifier">Withdraw</span><span class="special">(</span><span class="number">2</span><span class="special">);</span> <span class="special">}</span> </pre> <p> Notice that the code above doesn't compile, the <code class="computeroutput"><span class="identifier">mtx_</span></code> field is private. We have two possibilities: </p> <div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "> <li class="listitem"> make <code class="computeroutput"><span class="identifier">mtx_</span></code> public which seems odd </li> <li class="listitem"> make the <code class="computeroutput"><span class="identifier">BankAccount</span></code> lockable by adding the lock/unlock functions </li> </ul></div> <p> We can add these functions explicitly </p> <pre class="programlisting"><span class="keyword">class</span> <span class="identifier">BankAccount</span> <span class="special">{</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">mutex</span> <span class="identifier">mtx_</span><span class="special">;</span> <span class="keyword">int</span> <span class="identifier">balance_</span><span class="special">;</span> <span class="keyword">public</span><span class="special">:</span> <span class="keyword">void</span> <span class="identifier">Deposit</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">amount</span><span class="special">)</span> <span class="special">{</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">lock_guard</span><span class="special">&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">mutex</span><span class="special">&gt;</span> <span class="identifier">guard</span><span class="special">(</span><span class="identifier">mtx_</span><span class="special">);</span> <span class="identifier">balance_</span> <span class="special">+=</span> <span class="identifier">amount</span><span class="special">;</span> <span class="special">}</span> <span class="keyword">void</span> <span class="identifier">Withdraw</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">amount</span><span class="special">)</span> <span class="special">{</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">lock_guard</span><span class="special">&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">mutex</span><span class="special">&gt;</span> <span class="identifier">guard</span><span class="special">(</span><span class="identifier">mtx_</span><span class="special">);</span> <span class="identifier">balance_</span> <span class="special">-=</span> <span class="identifier">amount</span><span class="special">;</span> <span class="special">}</span> <span class="keyword">void</span> <span class="identifier">lock</span><span class="special">()</span> <span class="special">{</span> <span class="identifier">mtx_</span><span class="special">.</span><span class="identifier">lock</span><span class="special">();</span> <span class="special">}</span> <span class="keyword">void</span> <span class="identifier">unlock</span><span class="special">()</span> <span class="special">{</span> <span class="identifier">mtx_</span><span class="special">.</span><span class="identifier">unlock</span><span class="special">();</span> <span class="special">}</span> <span class="special">};</span> </pre> <p> or inheriting from a class which add these lockable functions. </p> <p> The <code class="computeroutput"><span class="identifier">basic_lockable_adapter</span></code> class helps to define the <code class="computeroutput"><span class="identifier">BankAccount</span></code> class as </p> <pre class="programlisting"><span class="keyword">class</span> <span class="identifier">BankAccount</span> <span class="special">:</span> <span class="keyword">public</span> <span class="identifier">basic_lockable_adapter</span><span class="special">&lt;</span><span class="identifier">mutex</span><span class="special">&gt;</span> <span class="special">{</span> <span class="keyword">int</span> <span class="identifier">balance_</span><span class="special">;</span> <span class="keyword">public</span><span class="special">:</span> <span class="keyword">void</span> <span class="identifier">Deposit</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">amount</span><span class="special">)</span> <span class="special">{</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">lock_guard</span><span class="special">&lt;</span><span class="identifier">BankAccount</span><span class="special">&gt;</span> <span class="identifier">guard</span><span class="special">(*</span><span class="keyword">this</span><span class="special">);</span> <span class="identifier">balance_</span> <span class="special">+=</span> <span class="identifier">amount</span><span class="special">;</span> <span class="special">}</span> <span class="keyword">void</span> <span class="identifier">Withdraw</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">amount</span><span class="special">)</span> <span class="special">{</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">lock_guard</span><span class="special">&lt;</span><span class="identifier">BankAccount</span><span class="special">&gt;</span> <span class="identifier">guard</span><span class="special">(*</span><span class="keyword">this</span><span class="special">);</span> <span class="identifier">balance_</span> <span class="special">-=</span> <span class="identifier">amount</span><span class="special">;</span> <span class="special">}</span> <span class="keyword">int</span> <span class="identifier">GetBalance</span><span class="special">()</span> <span class="special">{</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">lock_guard</span><span class="special">&lt;</span><span class="identifier">BankAccount</span><span class="special">&gt;</span> <span class="identifier">guard</span><span class="special">(*</span><span class="keyword">this</span><span class="special">);</span> <span class="keyword">return</span> <span class="identifier">balance_</span><span class="special">;</span> <span class="special">}</span> <span class="special">};</span> </pre> <p> and the code that doesn't compiles becomes </p> <pre class="programlisting"><span class="keyword">void</span> <span class="identifier">ATMWithdrawal</span><span class="special">(</span><span class="identifier">BankAccount</span><span class="special">&amp;</span> <span class="identifier">acct</span><span class="special">,</span> <span class="keyword">int</span> <span class="identifier">sum</span><span class="special">)</span> <span class="special">{</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">lock_guard</span><span class="special">&lt;</span><span class="identifier">BankAccount</span><span class="special">&gt;</span> <span class="identifier">guard</span><span class="special">(</span><span class="identifier">acct</span><span class="special">);</span> <span class="identifier">acct</span><span class="special">.</span><span class="identifier">Withdraw</span><span class="special">(</span><span class="identifier">sum</span><span class="special">);</span> <span class="identifier">acct</span><span class="special">.</span><span class="identifier">Withdraw</span><span class="special">(</span><span class="number">2</span><span class="special">);</span> <span class="special">}</span> </pre> <p> Notice that now acct is being locked by Withdraw after it has already been locked by guard. When running such code, one of two things happens. </p> <div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "> <li class="listitem"> Your mutex implementation might support the so-called recursive mutex semantics. This means that the same thread can lock the same mutex several times successfully. In this case, the implementation works but has a performance overhead due to unnecessary locking. (The locking/unlocking sequence in the two Withdraw calls is not needed but performed anyway-and that costs time.) </li> <li class="listitem"> Your mutex implementation might not support recursive locking, which means that as soon as you try to acquire it the second time, it blocks-so the ATMWithdrawal function enters the dreaded deadlock. </li> </ul></div> <p> As <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">mutex</span></code> is not recursive, we need to use its recursive version <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">recursive_mutex</span></code>. </p> <pre class="programlisting"><span class="keyword">class</span> <span class="identifier">BankAccount</span> <span class="special">:</span> <span class="keyword">public</span> <span class="identifier">basic_lockable_adapter</span><span class="special">&lt;</span><span class="identifier">recursive_mutex</span><span class="special">&gt;</span> <span class="special">{</span> <span class="comment">// ...</span> <span class="special">};</span> </pre> <p> The caller-ensured locking approach is more flexible and the most efficient, but very dangerous. In an implementation using caller-ensured locking, BankAccount still holds a mutex, but its member functions don't manipulate it at all. Deposit and Withdraw are not thread-safe anymore. Instead, the client code is responsible for locking BankAccount properly. </p> <pre class="programlisting"><span class="keyword">class</span> <span class="identifier">BankAccount</span> <span class="special">:</span> <span class="keyword">public</span> <span class="identifier">basic_lockable_adapter</span><span class="special">&lt;</span><span class="identifier">boost</span><span class="special">:</span><span class="identifier">mutex</span><span class="special">&gt;</span> <span class="special">{</span> <span class="keyword">int</span> <span class="identifier">balance_</span><span class="special">;</span> <span class="keyword">public</span><span class="special">:</span> <span class="keyword">void</span> <span class="identifier">Deposit</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">amount</span><span class="special">)</span> <span class="special">{</span> <span class="identifier">balance_</span> <span class="special">+=</span> <span class="identifier">amount</span><span class="special">;</span> <span class="special">}</span> <span class="keyword">void</span> <span class="identifier">Withdraw</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">amount</span><span class="special">)</span> <span class="special">{</span> <span class="identifier">balance_</span> <span class="special">-=</span> <span class="identifier">amount</span><span class="special">;</span> <span class="special">}</span> <span class="special">};</span> </pre> <p> Obviously, the caller-ensured locking approach has a safety problem. BankAccount's implementation code is finite, and easy to reach and maintain, but there's an unbounded amount of client code that manipulates BankAccount objects. In designing applications, it's important to differentiate between requirements imposed on bounded code and unbounded code. If your class makes undue requirements on unbounded code, that's usually a sign that encapsulation is out the window. </p> <p> To conclude, if in designing a multi-threaded class you settle on internal locking, you expose yourself to inefficiency or deadlocks. On the other hand, if you rely on caller-provided locking, you make your class error-prone and difficult to use. Finally, external locking completely avoids the issue by leaving it all to the client code. </p> </div> </div> <div class="section"> <div class="titlepage"><div><div><h4 class="title"> <a name="thread.synchronization.tutorial.external_locking_____strict_lock__and__externally_locked__classes"></a><a class="link" href="synchronization.html#thread.synchronization.tutorial.external_locking_____strict_lock__and__externally_locked__classes" title="External Locking -- strict_lock and externally_locked classes">External Locking -- <code class="computeroutput"><span class="identifier">strict_lock</span></code> and <code class="computeroutput"><span class="identifier">externally_locked</span></code> classes</a> </h4></div></div></div> <div class="toc"><dl class="toc"> <dt><span class="section"><a href="synchronization.html#thread.synchronization.tutorial.external_locking_____strict_lock__and__externally_locked__classes.locks_as_permits">Locks as permits</a></span></dt> <dt><span class="section"><a href="synchronization.html#thread.synchronization.tutorial.external_locking_____strict_lock__and__externally_locked__classes.improving_external_locking">Improving External Locking</a></span></dt> <dt><span class="section"><a href="synchronization.html#thread.synchronization.tutorial.external_locking_____strict_lock__and__externally_locked__classes.allowing_other_strict_locks">Allowing other strict locks</a></span></dt> </dl></div> <div class="note"><table border="0" summary="Note"> <tr> <td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../doc/src/images/note.png"></td> <th align="left">Note</th> </tr> <tr><td align="left" valign="top"><p> This tutorial is an adaptation of the paper by Andrei Alexandrescu "Multithreading and the C++ Type System" to the Boost library. </p></td></tr> </table></div> <div class="section"> <div class="titlepage"><div><div><h5 class="title"> <a name="thread.synchronization.tutorial.external_locking_____strict_lock__and__externally_locked__classes.locks_as_permits"></a><a class="link" href="synchronization.html#thread.synchronization.tutorial.external_locking_____strict_lock__and__externally_locked__classes.locks_as_permits" title="Locks as permits">Locks as permits</a> </h5></div></div></div> <p> So what to do? Ideally, the BankAccount class should do the following: </p> <div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "> <li class="listitem"> Support both locking models (internal and external). </li> <li class="listitem"> Be efficient; that is, use no unnecessary locking. </li> <li class="listitem"> Be safe; that is, BankAccount objects cannot be manipulated without appropriate locking. </li> </ul></div> <p> Let's make a worthwhile observation: Whenever you lock a BankAccount, you do so by using a <code class="computeroutput"><span class="identifier">lock_guard</span><span class="special">&lt;</span><span class="identifier">BankAccount</span><span class="special">&gt;</span></code> object. Turning this statement around, wherever there's a <code class="computeroutput"><span class="identifier">lock_guard</span><span class="special">&lt;</span><span class="identifier">BankAccount</span><span class="special">&gt;</span></code>, there's also a locked <code class="computeroutput"><span class="identifier">BankAccount</span></code> somewhere. Thus, you can think of-and use-a <code class="computeroutput"><span class="identifier">lock_guard</span><span class="special">&lt;</span><span class="identifier">BankAccount</span><span class="special">&gt;</span></code> object as a permit. Owning a <code class="computeroutput"><span class="identifier">lock_guard</span><span class="special">&lt;</span><span class="identifier">BankAccount</span><span class="special">&gt;</span></code> gives you rights to do certain things. The <code class="computeroutput"><span class="identifier">lock_guard</span><span class="special">&lt;</span><span class="identifier">BankAccount</span><span class="special">&gt;</span></code> object should not be copied or aliased (it's not a transmissible permit). </p> <div class="orderedlist"><ol class="orderedlist" type="1"> <li class="listitem"> As long as a permit is still alive, the <code class="computeroutput"><span class="identifier">BankAccount</span></code> object stays locked. </li> <li class="listitem"> When the <code class="computeroutput"><span class="identifier">lock_guard</span><span class="special">&lt;</span><span class="identifier">BankAccount</span><span class="special">&gt;</span></code> is destroyed, the <code class="computeroutput"><span class="identifier">BankAccount</span></code>'s mutex is released. </li> </ol></div> <p> The net effect is that at any point in your code, having access to a <code class="computeroutput"><span class="identifier">lock_guard</span><span class="special">&lt;</span><span class="identifier">BankAccount</span><span class="special">&gt;</span></code> object guarantees that a <code class="computeroutput"><span class="identifier">BankAccount</span></code> is locked. (You don't know exactly which <code class="computeroutput"><span class="identifier">BankAccount</span></code> is locked, however-an issue that we'll address soon.) </p> <p> For now, let's make a couple of enhancements to the <code class="computeroutput"><span class="identifier">lock_guard</span></code> class template defined in Boost.Thread. We'll call the enhanced version <code class="computeroutput"><span class="identifier">strict_lock</span></code>. Essentially, a <code class="computeroutput"><span class="identifier">strict_lock</span></code>'s role is only to live on the stack as an automatic variable. <code class="computeroutput"><span class="identifier">strict_lock</span></code> must adhere to a non-copy and non-alias policy. <code class="computeroutput"><span class="identifier">strict_lock</span></code> disables copying by making the copy constructor and the assignment operator private. </p> <pre class="programlisting"><span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">Lockable</span><span class="special">&gt;</span> <span class="keyword">class</span> <span class="identifier">strict_lock</span> <span class="special">{</span> <span class="keyword">public</span><span class="special">:</span> <span class="keyword">typedef</span> <span class="identifier">Lockable</span> <span class="identifier">lockable_type</span><span class="special">;</span> <span class="keyword">explicit</span> <span class="identifier">strict_lock</span><span class="special">(</span><span class="identifier">lockable_type</span><span class="special">&amp;</span> <span class="identifier">obj</span><span class="special">)</span> <span class="special">:</span> <span class="identifier">obj_</span><span class="special">(</span><span class="identifier">obj</span><span class="special">)</span> <span class="special">{</span> <span class="identifier">obj</span><span class="special">.</span><span class="identifier">lock</span><span class="special">();</span> <span class="comment">// locks on construction</span> <span class="special">}</span> <span class="identifier">strict_lock</span><span class="special">()</span> <span class="special">=</span> <span class="keyword">delete</span><span class="special">;</span> <span class="identifier">strict_lock</span><span class="special">(</span><span class="identifier">strict_lock</span> <span class="keyword">const</span><span class="special">&amp;)</span> <span class="special">=</span> <span class="keyword">delete</span><span class="special">;</span> <span class="identifier">strict_lock</span><span class="special">&amp;</span> <span class="keyword">operator</span><span class="special">=(</span><span class="identifier">strict_lock</span> <span class="keyword">const</span><span class="special">&amp;)</span> <span class="special">=</span> <span class="keyword">delete</span><span class="special">;</span> <span class="special">~</span><span class="identifier">strict_lock</span><span class="special">()</span> <span class="special">{</span> <span class="identifier">obj_</span><span class="special">.</span><span class="identifier">unlock</span><span class="special">();</span> <span class="special">}</span> <span class="comment">// unlocks on destruction </span> <span class="keyword">bool</span> <span class="identifier">owns_lock</span><span class="special">(</span><span class="identifier">mutex_type</span> <span class="keyword">const</span><span class="special">*</span> <span class="identifier">l</span><span class="special">)</span> <span class="keyword">const</span> <span class="keyword">noexcept</span> <span class="comment">// strict lockers specific function </span> <span class="special">{</span> <span class="keyword">return</span> <span class="identifier">l</span> <span class="special">==</span> <span class="special">&amp;</span><span class="identifier">obj_</span><span class="special">;</span> <span class="special">}</span> <span class="keyword">private</span><span class="special">:</span> <span class="identifier">lockable_type</span><span class="special">&amp;</span> <span class="identifier">obj_</span><span class="special">;</span> <span class="special">};</span> </pre> <p> Silence can be sometimes louder than words-what's forbidden to do with a <code class="computeroutput"><span class="identifier">strict_lock</span></code> is as important as what you can do. Let's see what you can and what you cannot do with a <code class="computeroutput"><span class="identifier">strict_lock</span></code> instantiation: </p> <div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc;