UNPKG

boost-react-native-bundle

Version:

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

351 lines (336 loc) 235 kB
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII"> <title>Synchronized Data Structures</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="thread_local_storage.html" title="Thread Local Storage"> <link rel="next" href="time.html" title="Time Requirements"> </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="thread_local_storage.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="time.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.sds"></a><a class="link" href="sds.html" title="Synchronized Data Structures">Synchronized Data Structures</a> </h2></div></div></div> <div class="toc"><dl class="toc"> <dt><span class="section"><a href="sds.html#thread.sds.synchronized_valuesxxx">Synchronized Values - EXPERIMENTAL</a></span></dt> <dt><span class="section"><a href="sds.html#thread.sds.synchronized_queues">Synchronized Queues -- EXPERIMENTAL</a></span></dt> </dl></div> <div class="section"> <div class="titlepage"><div><div><h3 class="title"> <a name="thread.sds.synchronized_valuesxxx"></a><a class="link" href="sds.html#thread.sds.synchronized_valuesxxx" title="Synchronized Values - EXPERIMENTAL">Synchronized Values - EXPERIMENTAL</a> </h3></div></div></div> <div class="toc"><dl class="toc"> <dt><span class="section"><a href="sds.html#thread.sds.synchronized_valuesxxx.tutorial">Tutorial</a></span></dt> <dt><span class="section"><a href="sds.html#thread.sds.synchronized_valuesxxx.synchronized_value_ref">Reference </a></span></dt> </dl></div> <div class="warning"><table border="0" summary="Warning"> <tr> <td rowspan="2" align="center" valign="top" width="25"><img alt="[Warning]" src="../../../doc/src/images/warning.png"></td> <th align="left">Warning</th> </tr> <tr><td align="left" valign="top"><p> These features are experimental and subject to change in future versions. There are not too much tests yet, so it is possible that you can find out some trivial bugs :( </p></td></tr> </table></div> <div class="section"> <div class="titlepage"><div><div><h4 class="title"> <a name="thread.sds.synchronized_valuesxxx.tutorial"></a><a class="link" href="sds.html#thread.sds.synchronized_valuesxxx.tutorial" title="Tutorial">Tutorial</a> </h4></div></div></div> <div class="toc"><dl class="toc"> <dt><span class="section"><a href="sds.html#thread.sds.synchronized_valuesxxx.tutorial.the_problem_with_mutexes">The Problem with Mutexes</a></span></dt> <dt><span class="section"><a href="sds.html#thread.sds.synchronized_valuesxxx.tutorial.beyond_simple_accesses">Beyond Simple Accesses</a></span></dt> <dt><span class="section"><a href="sds.html#thread.sds.synchronized_valuesxxx.tutorial.operations_across_multiple_objects">Operations Across Multiple Objects</a></span></dt> <dt><span class="section"><a href="sds.html#thread.sds.synchronized_valuesxxx.tutorial.value_semantics">Value semantics</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 of Anthony Williams "Enforcing Correct Mutex Usage with Synchronized Values" to the Boost library. </p></td></tr> </table></div> <div class="section"> <div class="titlepage"><div><div><h5 class="title"> <a name="thread.sds.synchronized_valuesxxx.tutorial.the_problem_with_mutexes"></a><a class="link" href="sds.html#thread.sds.synchronized_valuesxxx.tutorial.the_problem_with_mutexes" title="The Problem with Mutexes">The Problem with Mutexes</a> </h5></div></div></div> <p> The key problem with protecting shared data with a mutex is that there is no easy way to associate the mutex with the data. It is thus relatively easy to accidentally write code that fails to lock the right mutex - or even locks the wrong mutex - and the compiler will not help you. </p> <pre class="programlisting"><span class="identifier">std</span><span class="special">::</span><span class="identifier">mutex</span> <span class="identifier">m1</span><span class="special">;</span> <span class="keyword">int</span> <span class="identifier">value1</span><span class="special">;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">mutex</span> <span class="identifier">m2</span><span class="special">;</span> <span class="keyword">int</span> <span class="identifier">value2</span><span class="special">;</span> <span class="keyword">int</span> <span class="identifier">readValue1</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">lk</span><span class="special">(</span><span class="identifier">m1</span><span class="special">);</span> <span class="keyword">return</span> <span class="identifier">value1</span><span class="special">;</span> <span class="special">}</span> <span class="keyword">int</span> <span class="identifier">readValue2</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">lk</span><span class="special">(</span><span class="identifier">m1</span><span class="special">);</span> <span class="comment">// oops: wrong mutex</span> <span class="keyword">return</span> <span class="identifier">value2</span><span class="special">;</span> <span class="special">}</span> </pre> <p> Moreover, managing the mutex lock also clutters the source code, making it harder to see what is really going on. </p> <p> The use of synchronized_value solves both these problems - the mutex is intimately tied to the value, so you cannot access it without a lock, and yet access semantics are still straightforward. For simple accesses, synchronized_value behaves like a pointer-to-T; for example: </p> <pre class="programlisting"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">synchronized_value</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">&gt;</span> <span class="identifier">value3</span><span class="special">;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">readValue3</span><span class="special">()</span> <span class="special">{</span> <span class="keyword">return</span> <span class="special">*</span><span class="identifier">value3</span><span class="special">;</span> <span class="special">}</span> <span class="keyword">void</span> <span class="identifier">setValue3</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">newVal</span><span class="special">)</span> <span class="special">{</span> <span class="special">*</span><span class="identifier">value3</span><span class="special">=</span><span class="identifier">newVal</span><span class="special">;</span> <span class="special">}</span> <span class="keyword">void</span> <span class="identifier">appendToValue3</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">extra</span><span class="special">)</span> <span class="special">{</span> <span class="identifier">value3</span><span class="special">-&gt;</span><span class="identifier">append</span><span class="special">(</span><span class="identifier">extra</span><span class="special">);</span> <span class="special">}</span> </pre> <p> Both forms of pointer dereference return a proxy object rather than a real reference, to ensure that the lock on the mutex is held across the assignment or method call, but this is transparent to the user. </p> </div> <div class="section"> <div class="titlepage"><div><div><h5 class="title"> <a name="thread.sds.synchronized_valuesxxx.tutorial.beyond_simple_accesses"></a><a class="link" href="sds.html#thread.sds.synchronized_valuesxxx.tutorial.beyond_simple_accesses" title="Beyond Simple Accesses">Beyond Simple Accesses</a> </h5></div></div></div> <p> The pointer-like semantics work very well for simple accesses such as assignment and calls to member functions. However, sometimes you need to perform an operation that requires multiple accesses under protection of the same lock, and that's what the synchronize() method provides. </p> <p> By calling synchronize() you obtain an strict_lock_ptr object that holds a lock on the mutex protecting the data, and which can be used to access the protected data. The lock is held until the strict_lock_ptr object is destroyed, so you can safely perform multi-part operations. The strict_lock_ptr object also acts as a pointer-to-T, just like synchronized_value does, but this time the lock is already held. For example, the following function adds a trailing slash to a path held in a synchronized_value. The use of the strict_lock_ptr object ensures that the string hasn't changed in between the query and the update. </p> <pre class="programlisting"><span class="keyword">void</span> <span class="identifier">addTrailingSlashIfMissing</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">synchronized_value</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">&gt;</span> <span class="special">&amp;</span> <span class="identifier">path</span><span class="special">)</span> <span class="special">{</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">strict_lock_ptr</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">&gt;</span> <span class="identifier">u</span><span class="special">=</span><span class="identifier">path</span><span class="special">.</span><span class="identifier">synchronize</span><span class="special">();</span> <span class="keyword">if</span><span class="special">(</span><span class="identifier">u</span><span class="special">-&gt;</span><span class="identifier">empty</span><span class="special">()</span> <span class="special">||</span> <span class="special">(*</span><span class="identifier">u</span><span class="special">-&gt;</span><span class="identifier">rbegin</span><span class="special">()!=</span><span class="char">'/'</span><span class="special">))</span> <span class="special">{</span> <span class="special">*</span><span class="identifier">u</span><span class="special">+=</span><span class="char">'/'</span><span class="special">;</span> <span class="special">}</span> <span class="special">}</span> </pre> </div> <div class="section"> <div class="titlepage"><div><div><h5 class="title"> <a name="thread.sds.synchronized_valuesxxx.tutorial.operations_across_multiple_objects"></a><a class="link" href="sds.html#thread.sds.synchronized_valuesxxx.tutorial.operations_across_multiple_objects" title="Operations Across Multiple Objects">Operations Across Multiple Objects</a> </h5></div></div></div> <p> Though synchronized_value works very well for protecting a single object of type T, nothing that we've seen so far solves the problem of operations that require atomic access to multiple objects unless those objects can be combined within a single structure protected by a single mutex. </p> <p> One way to protect access to two synchronized_value objects is to construct a strict_lock_ptr for each object and use those to access the respective protected values; for instance: </p> <pre class="programlisting"><span class="identifier">synchronized_value</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">queue</span><span class="special">&lt;</span><span class="identifier">MessageType</span><span class="special">&gt;</span> <span class="special">&gt;</span> <span class="identifier">q1</span><span class="special">,</span><span class="identifier">q2</span><span class="special">;</span> <span class="keyword">void</span> <span class="identifier">transferMessage</span><span class="special">()</span> <span class="special">{</span> <span class="identifier">strict_lock_ptr</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">queue</span><span class="special">&lt;</span><span class="identifier">MessageType</span><span class="special">&gt;</span> <span class="special">&gt;</span> <span class="identifier">u1</span> <span class="special">=</span> <span class="identifier">q1</span><span class="special">.</span><span class="identifier">synchronize</span><span class="special">();</span> <span class="identifier">strict_lock_ptr</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">queue</span><span class="special">&lt;</span><span class="identifier">MessageType</span><span class="special">&gt;</span> <span class="special">&gt;</span> <span class="identifier">u2</span> <span class="special">=</span> <span class="identifier">q2</span><span class="special">.</span><span class="identifier">synchronize</span><span class="special">();</span> <span class="keyword">if</span><span class="special">(!</span><span class="identifier">u1</span><span class="special">-&gt;</span><span class="identifier">empty</span><span class="special">())</span> <span class="special">{</span> <span class="identifier">u2</span><span class="special">-&gt;</span><span class="identifier">push_back</span><span class="special">(</span><span class="identifier">u1</span><span class="special">-&gt;</span><span class="identifier">front</span><span class="special">());</span> <span class="identifier">u1</span><span class="special">-&gt;</span><span class="identifier">pop_front</span><span class="special">();</span> <span class="special">}</span> <span class="special">}</span> </pre> <p> This works well in some scenarios, but not all -- if the same two objects are updated together in different sections of code then you need to take care to ensure that the strict_lock_ptr objects are constructed in the same sequence in all cases, otherwise you have the potential for deadlock. This is just the same as when acquiring any two mutexes. </p> <p> In order to be able to use the dead-lock free lock algorithms we need to use instead unique_lock_ptr, which is Lockable. </p> <pre class="programlisting"><span class="identifier">synchronized_value</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">queue</span><span class="special">&lt;</span><span class="identifier">MessageType</span><span class="special">&gt;</span> <span class="special">&gt;</span> <span class="identifier">q1</span><span class="special">,</span><span class="identifier">q2</span><span class="special">;</span> <span class="keyword">void</span> <span class="identifier">transferMessage</span><span class="special">()</span> <span class="special">{</span> <span class="identifier">unique_lock_ptr</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">queue</span><span class="special">&lt;</span><span class="identifier">MessageType</span><span class="special">&gt;</span> <span class="special">&gt;</span> <span class="identifier">u1</span> <span class="special">=</span> <span class="identifier">q1</span><span class="special">.</span><span class="identifier">unique_synchronize</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">defer_lock</span><span class="special">);</span> <span class="identifier">unique_lock_ptr</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">queue</span><span class="special">&lt;</span><span class="identifier">MessageType</span><span class="special">&gt;</span> <span class="special">&gt;</span> <span class="identifier">u2</span> <span class="special">=</span> <span class="identifier">q2</span><span class="special">.</span><span class="identifier">unique_synchronize</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">defer_lock</span><span class="special">);</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">lock</span><span class="special">(</span><span class="identifier">u1</span><span class="special">,</span><span class="identifier">u2</span><span class="special">);</span> <span class="comment">// dead-lock free algorithm</span> <span class="keyword">if</span><span class="special">(!</span><span class="identifier">u1</span><span class="special">-&gt;</span><span class="identifier">empty</span><span class="special">())</span> <span class="special">{</span> <span class="identifier">u2</span><span class="special">-&gt;</span><span class="identifier">push_back</span><span class="special">(</span><span class="identifier">u1</span><span class="special">-&gt;</span><span class="identifier">front</span><span class="special">());</span> <span class="identifier">u1</span><span class="special">-&gt;</span><span class="identifier">pop_front</span><span class="special">();</span> <span class="special">}</span> <span class="special">}</span> </pre> <p> While the preceding takes care of dead-lock, the access to the synchronized_value via unique_lock_ptr requires a lock that is not forced by the interface. An alternative on compilers providing a standard library that supports movable std::tuple is to use the free synchronize function, which will lock all the mutexes associated to the synchronized values and return a tuple os strict_lock_ptr. </p> <pre class="programlisting"><span class="identifier">synchronized_value</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">queue</span><span class="special">&lt;</span><span class="identifier">MessageType</span><span class="special">&gt;</span> <span class="special">&gt;</span> <span class="identifier">q1</span><span class="special">,</span><span class="identifier">q2</span><span class="special">;</span> <span class="keyword">void</span> <span class="identifier">transferMessage</span><span class="special">()</span> <span class="special">{</span> <span class="keyword">auto</span> <span class="identifier">lks</span> <span class="special">=</span> <span class="identifier">synchronize</span><span class="special">(</span><span class="identifier">u1</span><span class="special">,</span><span class="identifier">u2</span><span class="special">);</span> <span class="comment">// dead-lock free algorithm</span> <span class="keyword">if</span><span class="special">(!</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">get</span><span class="special">&lt;</span><span class="number">1</span><span class="special">&gt;(</span><span class="identifier">lks</span><span class="special">)-&gt;</span><span class="identifier">empty</span><span class="special">())</span> <span class="special">{</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">get</span><span class="special">&lt;</span><span class="number">2</span><span class="special">&gt;(</span><span class="identifier">lks</span><span class="special">)-&gt;</span><span class="identifier">push_back</span><span class="special">(</span><span class="identifier">u1</span><span class="special">-&gt;</span><span class="identifier">front</span><span class="special">());</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">get</span><span class="special">&lt;</span><span class="number">1</span><span class="special">&gt;(</span><span class="identifier">lks</span><span class="special">)-&gt;</span><span class="identifier">pop_front</span><span class="special">();</span> <span class="special">}</span> <span class="special">}</span> </pre> </div> <div class="section"> <div class="titlepage"><div><div><h5 class="title"> <a name="thread.sds.synchronized_valuesxxx.tutorial.value_semantics"></a><a class="link" href="sds.html#thread.sds.synchronized_valuesxxx.tutorial.value_semantics" title="Value semantics">Value semantics</a> </h5></div></div></div> <p> synchronized_value has value semantics even if the syntax lets is close to a pointer (this is just because we are unable to define smart references). </p> </div> </div> <div class="section"> <div class="titlepage"><div><div><h4 class="title"> <a name="thread.sds.synchronized_valuesxxx.synchronized_value_ref"></a><a class="link" href="sds.html#thread.sds.synchronized_valuesxxx.synchronized_value_ref" title="Reference">Reference </a> </h4></div></div></div> <div class="toc"><dl class="toc"> <dt><span class="section"><a href="sds.html#thread.sds.synchronized_valuesxxx.synchronized_value_ref.synchronized_value">Class <code class="computeroutput"><span class="identifier">synchronized_value</span></code></a></span></dt> <dt><span class="section"><a href="sds.html#thread.sds.synchronized_valuesxxx.synchronized_value_ref.synchronize">Non-Member Function <code class="computeroutput"><span class="identifier">synchronize</span></code></a></span></dt> </dl></div> <pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">thread</span><span class="special">/</span><span class="identifier">synchronized_value</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span> <span class="keyword">namespace</span> <span class="identifier">boost</span> <span class="special">{</span> <span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Lockable</span> <span class="special">=</span> <span class="identifier">mutex</span><span class="special">&gt;</span> <span class="keyword">class</span> <span class="identifier">synchronized_value</span><span class="special">;</span> <span class="comment">// Specialized swap algorithm</span> <span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">L</span><span class="special">&gt;</span> <span class="keyword">void</span> <span class="identifier">swap</span><span class="special">(</span><span class="identifier">synchronized_value</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">,</span><span class="identifier">L</span><span class="special">&gt;</span> <span class="special">&amp;</span> <span class="identifier">lhs</span><span class="special">,</span> <span class="identifier">synchronized_value</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">,</span><span class="identifier">L</span><span class="special">&gt;</span> <span class="special">&amp;</span> <span class="identifier">rhs</span><span class="special">);</span> <span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">L</span><span class="special">&gt;</span> <span class="keyword">void</span> <span class="identifier">swap</span><span class="special">(</span><span class="identifier">synchronized_value</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">,</span><span class="identifier">L</span><span class="special">&gt;</span> <span class="special">&amp;</span> <span class="identifier">lhs</span><span class="special">,</span> <span class="identifier">T</span> <span class="special">&amp;</span> <span class="identifier">rhs</span><span class="special">);</span> <span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">L</span><span class="special">&gt;</span> <span class="keyword">void</span> <span class="identifier">swap</span><span class="special">(</span><span class="identifier">T</span> <span class="special">&amp;</span> <span class="identifier">lhs</span><span class="special">,</span> <span class="identifier">synchronized_value</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">,</span><span class="identifier">L</span><span class="special">&gt;</span> <span class="special">&amp;</span> <span class="identifier">rhs</span><span class="special">);</span> <span class="comment">// Hash support</span> <span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">L</span><span class="special">&gt;</span> <span class="keyword">struct</span> <span class="identifier">hash</span><span class="special">&lt;</span><span class="identifier">synchronized_value</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">,</span><span class="identifier">L</span><span class="special">&gt;</span> <span class="special">&gt;;</span> <span class="comment">// Comparison</span> <span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">L</span><span class="special">&gt;</span> <span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">==(</span><span class="identifier">synchronized_value</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">,</span><span class="identifier">L</span><span class="special">&gt;</span> <span class="keyword">const</span><span class="special">&amp;</span><span class="identifier">lhs</span><span class="special">,</span> <span class="identifier">synchronized_value</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">,</span><span class="identifier">L</span><span class="special">&gt;</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">rhs</span><span class="special">)</span> <span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">L</span><span class="special">&gt;</span> <span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">!=(</span><span class="identifier">synchronized_value</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">,</span><span class="identifier">L</span><span class="special">&gt;</span> <span class="keyword">const</span><span class="special">&amp;</span><span class="identifier">lhs</span><span class="special">,</span> <span class="identifier">synchronized_value</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">,</span><span class="identifier">L</span><span class="special">&gt;</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">rhs</span><span class="special">)</span> <span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">L</span><span class="special">&gt;</span> <span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">&lt;(</span><span class="identifier">synchronized_value</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">,</span><span class="identifier">L</span><span class="special">&gt;</span> <span class="keyword">const</span><span class="special">&amp;</span><span class="identifier">lhs</span><span class="special">,</span> <span class="identifier">synchronized_value</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">,</span><span class="identifier">L</span><span class="special">&gt;</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">rhs</span><span class="special">)</span> <span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">L</span><span class="special">&gt;</span> <span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">&lt;=(</span><span class="identifier">synchronized_value</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">,</span><span class="identifier">L</span><span class="special">&gt;</span> <span class="keyword">const</span><span class="special">&amp;</span><span class="identifier">lhs</span><span class="special">,</span> <span class="identifier">synchronized_value</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">,</span><span class="identifier">L</span><span class="special">&gt;</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">rhs</span><span class="special">)</span> <span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">L</span><span class="special">&gt;</span> <span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">&gt;(</span><span class="identifier">synchronized_value</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">,</span><span class="identifier">L</span><span class="special">&gt;</span> <span class="keyword">const</span><span class="special">&amp;</span><span class="identifier">lhs</span><span class="special">,</span> <span class="identifier">synchronized_value</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">,</span><span class="identifier">L</span><span class="special">&gt;</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">rhs</span><span class="special">)</span> <span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">L</span><span class="special">&gt;</span> <span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">&gt;=(</span><span class="identifier">synchronized_value</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">,</span><span class="identifier">L</span><span class="special">&gt;</span> <span class="keyword">const</span><span class="special">&amp;</span><span class="identifier">lhs</span><span class="special">,</span> <span class="identifier">synchronized_value</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">,</span><span class="identifier">L</span><span class="special">&gt;</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">rhs</span><span class="special">)</span> <span class="comment">// Comparison with T</span> <span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">L</span><span class="special">&gt;</span> <span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">==(</span><span class="identifier">T</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">lhs</span><span class="special">,</span> <span class="identifier">synchronized_value</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">,</span><span class="identifier">L</span><span class="special">&gt;</span> <span class="keyword">const</span><span class="special">&amp;</span><span class="identifier">rhs</span><span class="special">);</span> <span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">L</span><span class="special">&gt;</span> <span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">!=(</span><span class="identifier">T</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">lhs</span><span class="special">,</span> <span class="identifier">synchronized_value</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">,</span><span class="identifier">L</span><span class="special">&gt;</span> <span class="keyword">const</span><span class="special">&amp;</span><span class="identifier">rhs</span><span class="special">);</span> <span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">L</span><span class="special">&gt;</span> <span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">&lt;(</span><span class="identifier">T</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">lhs</span><span class="special">,</span> <span class="identifier">synchronized_value</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">,</span><span class="identifier">L</span><span class="special">&gt;</span> <span class="keyword">const</span><span class="special">&amp;</span><span class="identifier">rhs</span><span class="special">);</span> <span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">L</span><span class="special">&gt;</span> <span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">&lt;=(</span><span class="identifier">T</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">lhs</span><span class="special">,</span> <span class="identifier">synchronized_value</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">,</span><span class="identifier">L</span><span class="special">&gt;</span> <span class="keyword">const</span><span class="special">&amp;</span><span class="identifier">rhs</span><span class="special">);</span> <span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">L</span><span class="special">&gt;</span> <span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">&gt;(</span><span class="identifier">T</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">lhs</span><span class="special">,</span> <span class="identifier">synchronized_value</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">,</span><span class="identifier">L</span><span class="special">&gt;</span> <span class="keyword">const</span><span class="special">&amp;</span><span class="identifier">rhs</span><span class="special">);</span> <span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">L</span><span class="special">&gt;</span> <span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">&gt;=(</span><span class="identifier">T</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">lhs</span><span class="special">,</span> <span class="identifier">synchronized_value</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">,</span><span class="identifier">L</span><span class="special">&gt;</span> <span class="keyword">const</span><span class="special">&amp;</span><span class="identifier">rhs</span><span class="special">);</span> <span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">L</span><span class="special">&gt;</span> <span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">==(</span><span class="identifier">synchronized_value</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">,</span><span class="identifier">L</span><span class="special">&gt;</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">lhs</span><span class="special">,</span> <span class="identifier">T</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">rhs</span><span class="special">);</span> <span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">L</span><span class="special">&gt;</span> <span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">!=(</span><span class="identifier">synchronized_value</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">,</span><span class="identifier">L</span><span class="special">&gt;</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">lhs</span><span class="special">,</span> <span class="identifier">T</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">rhs</span><span class="special">);</span> <span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">L</span><span class="special">&gt;</span> <span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">&lt;(</span><span class="identifier">synchronized_value</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">,</span><span class="identifier">L</span><span class="special">&gt;</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">lhs</span><span class="special">,</span> <span class="identifier">T</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">rhs</span><span class="special">);</span> <span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">L</span><span class="special">&gt;</span> <span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">&lt;=(</span><span class="identifier">synchronized_value</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">,</span><span class="identifier">L</span><span class="special">&gt;</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">lhs</span><span class="special">,</span> <span class="identifier">T</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">rhs</span><span class="special">);</span> <span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">L</span><span class="special">&gt;</span> <span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">&gt;(</span><span class="identifier">synchronized_value</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">,</span><span class="identifier">L</span><span class="special">&gt;</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">lhs</span><span class="special">,</span> <span class="identifier">T</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">rhs</span><span class="special">);</span> <span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">L</span><span class="special">&gt;</span> <span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">&gt;=(</span><span class="identifier">synchronized_value</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">,</span><span class="identifier">L</span><span class="special">&gt;</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">lhs</span><span class="special">,</span> <span class="identifier">T</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">rhs</span><span class="special">);</span> <span class="preprocessor">#if</span> <span class="special">!</span> <span class="identifier">defined</span><span class="special">(</span><span class="identifier">BOOST_THREAD_NO_SYNCHRONIZE</span><span class="special">)</span> <span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="special">...</span><span class="identifier">SV</span><span class="special">&gt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">tuple</span><span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">synchronized_value_strict_lock_ptr</span><span class="special">&lt;</span><span class="identifier">SV</span><span class="special">&gt;::</span><span class="identifier">type</span> <span class="special">...&gt;</span> <span class="identifier">synchronize</span><span class="special">(</span><span class="identifier">SV</span><span class="special">&amp;</span> <span class="special">...</span><span class="identifier">sv</span><span class="special">);</span> <span class="preprocessor">#endif</span> <span class="special">}</span> </pre> <div class="section"> <div class="titlepage"><div><div><h5 class="title"> <a name="thread.sds.synchronized_valuesxxx.synchronized_value_ref.synchronized_value"></a><a class="link" href="sds.html#thread.sds.synchronized_valuesxxx.synchronized_value_ref.synchronized_value" title="Class synchronized_value">Class <code class="computeroutput"><span class="identifier">synchronized_value</span></code></a> </h5></div></div></div> <pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">thread</span><span class="special">/</span><span class="identifier">synchronized_value</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span> <span class="keyword">namespace</span> <span class="identifier">boost</span> <span class="special">{</span> <span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Lockable</span> <span class="special">=</span> <span class="identifier">mutex</span><span class="special">&gt;</span> <span class="keyword">class</span> <span class="identifier">synchronized_value</span> <span class="special">{</span> <span class="keyword">public</span><span class="special">:</span> <span class="keyword">typedef</span> <span class="identifier">T</span> <span class="identifier">value_type</span><span class="special">;</span> <span class="keyword">typedef</span> <span class="identifier">Lockable</span> <span class="identifier">mutex_type</span><span class="special">;</span> <span class="identifier">synchronized_value</span><span class="special">()</span> <span class="identifier">noexept</span><span class="special">(</span><span class="identifier">is_nothrow_default_constructible</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">);</span> <span class="identifier">synchronized_value</span><span class="special">(</span><span class="identifier">T</span> <span class="keyword">const</span><span class="special">&amp;</span> <spa