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
<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 30. 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"><</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">mutex</span><span class="special">></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"><</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">mutex</span><span class="special">></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"><</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">></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">&</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">&</span> <span class="identifier">extra</span><span class="special">)</span>
<span class="special">{</span>
<span class="identifier">value3</span><span class="special">-></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"><</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">></span> <span class="special">&</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"><</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">></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">-></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">-></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"><</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">queue</span><span class="special"><</span><span class="identifier">MessageType</span><span class="special">></span> <span class="special">></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"><</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">queue</span><span class="special"><</span><span class="identifier">MessageType</span><span class="special">></span> <span class="special">></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"><</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">queue</span><span class="special"><</span><span class="identifier">MessageType</span><span class="special">></span> <span class="special">></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">-></span><span class="identifier">empty</span><span class="special">())</span>
<span class="special">{</span>
<span class="identifier">u2</span><span class="special">-></span><span class="identifier">push_back</span><span class="special">(</span><span class="identifier">u1</span><span class="special">-></span><span class="identifier">front</span><span class="special">());</span>
<span class="identifier">u1</span><span class="special">-></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"><</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">queue</span><span class="special"><</span><span class="identifier">MessageType</span><span class="special">></span> <span class="special">></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"><</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">queue</span><span class="special"><</span><span class="identifier">MessageType</span><span class="special">></span> <span class="special">></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"><</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">queue</span><span class="special"><</span><span class="identifier">MessageType</span><span class="special">></span> <span class="special">></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">-></span><span class="identifier">empty</span><span class="special">())</span>
<span class="special">{</span>
<span class="identifier">u2</span><span class="special">-></span><span class="identifier">push_back</span><span class="special">(</span><span class="identifier">u1</span><span class="special">-></span><span class="identifier">front</span><span class="special">());</span>
<span class="identifier">u1</span><span class="special">-></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"><</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">queue</span><span class="special"><</span><span class="identifier">MessageType</span><span class="special">></span> <span class="special">></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"><</span><span class="number">1</span><span class="special">>(</span><span class="identifier">lks</span><span class="special">)-></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"><</span><span class="number">2</span><span class="special">>(</span><span class="identifier">lks</span><span class="special">)-></span><span class="identifier">push_back</span><span class="special">(</span><span class="identifier">u1</span><span class="special">-></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"><</span><span class="number">1</span><span class="special">>(</span><span class="identifier">lks</span><span class="special">)-></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"><</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">></span>
<span class="keyword">namespace</span> <span class="identifier">boost</span>
<span class="special">{</span>
<span class="keyword">template</span><span class="special"><</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">></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"><</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">></span>
<span class="keyword">void</span> <span class="identifier">swap</span><span class="special">(</span><span class="identifier">synchronized_value</span><span class="special"><</span><span class="identifier">T</span><span class="special">,</span><span class="identifier">L</span><span class="special">></span> <span class="special">&</span> <span class="identifier">lhs</span><span class="special">,</span> <span class="identifier">synchronized_value</span><span class="special"><</span><span class="identifier">T</span><span class="special">,</span><span class="identifier">L</span><span class="special">></span> <span class="special">&</span> <span class="identifier">rhs</span><span class="special">);</span>
<span class="keyword">template</span> <span class="special"><</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">></span>
<span class="keyword">void</span> <span class="identifier">swap</span><span class="special">(</span><span class="identifier">synchronized_value</span><span class="special"><</span><span class="identifier">T</span><span class="special">,</span><span class="identifier">L</span><span class="special">></span> <span class="special">&</span> <span class="identifier">lhs</span><span class="special">,</span> <span class="identifier">T</span> <span class="special">&</span> <span class="identifier">rhs</span><span class="special">);</span>
<span class="keyword">template</span> <span class="special"><</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">></span>
<span class="keyword">void</span> <span class="identifier">swap</span><span class="special">(</span><span class="identifier">T</span> <span class="special">&</span> <span class="identifier">lhs</span><span class="special">,</span> <span class="identifier">synchronized_value</span><span class="special"><</span><span class="identifier">T</span><span class="special">,</span><span class="identifier">L</span><span class="special">></span> <span class="special">&</span> <span class="identifier">rhs</span><span class="special">);</span>
<span class="comment">// Hash support</span>
<span class="keyword">template</span><span class="special"><</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">></span>
<span class="keyword">struct</span> <span class="identifier">hash</span><span class="special"><</span><span class="identifier">synchronized_value</span><span class="special"><</span><span class="identifier">T</span><span class="special">,</span><span class="identifier">L</span><span class="special">></span> <span class="special">>;</span>
<span class="comment">// Comparison</span>
<span class="keyword">template</span> <span class="special"><</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">></span>
<span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">==(</span><span class="identifier">synchronized_value</span><span class="special"><</span><span class="identifier">T</span><span class="special">,</span><span class="identifier">L</span><span class="special">></span> <span class="keyword">const</span><span class="special">&</span><span class="identifier">lhs</span><span class="special">,</span> <span class="identifier">synchronized_value</span><span class="special"><</span><span class="identifier">T</span><span class="special">,</span><span class="identifier">L</span><span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">rhs</span><span class="special">)</span>
<span class="keyword">template</span> <span class="special"><</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">></span>
<span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">!=(</span><span class="identifier">synchronized_value</span><span class="special"><</span><span class="identifier">T</span><span class="special">,</span><span class="identifier">L</span><span class="special">></span> <span class="keyword">const</span><span class="special">&</span><span class="identifier">lhs</span><span class="special">,</span> <span class="identifier">synchronized_value</span><span class="special"><</span><span class="identifier">T</span><span class="special">,</span><span class="identifier">L</span><span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">rhs</span><span class="special">)</span>
<span class="keyword">template</span> <span class="special"><</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">></span>
<span class="keyword">bool</span> <span class="keyword">operator</span><span class="special"><(</span><span class="identifier">synchronized_value</span><span class="special"><</span><span class="identifier">T</span><span class="special">,</span><span class="identifier">L</span><span class="special">></span> <span class="keyword">const</span><span class="special">&</span><span class="identifier">lhs</span><span class="special">,</span> <span class="identifier">synchronized_value</span><span class="special"><</span><span class="identifier">T</span><span class="special">,</span><span class="identifier">L</span><span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">rhs</span><span class="special">)</span>
<span class="keyword">template</span> <span class="special"><</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">></span>
<span class="keyword">bool</span> <span class="keyword">operator</span><span class="special"><=(</span><span class="identifier">synchronized_value</span><span class="special"><</span><span class="identifier">T</span><span class="special">,</span><span class="identifier">L</span><span class="special">></span> <span class="keyword">const</span><span class="special">&</span><span class="identifier">lhs</span><span class="special">,</span> <span class="identifier">synchronized_value</span><span class="special"><</span><span class="identifier">T</span><span class="special">,</span><span class="identifier">L</span><span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">rhs</span><span class="special">)</span>
<span class="keyword">template</span> <span class="special"><</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">></span>
<span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">>(</span><span class="identifier">synchronized_value</span><span class="special"><</span><span class="identifier">T</span><span class="special">,</span><span class="identifier">L</span><span class="special">></span> <span class="keyword">const</span><span class="special">&</span><span class="identifier">lhs</span><span class="special">,</span> <span class="identifier">synchronized_value</span><span class="special"><</span><span class="identifier">T</span><span class="special">,</span><span class="identifier">L</span><span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">rhs</span><span class="special">)</span>
<span class="keyword">template</span> <span class="special"><</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">></span>
<span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">>=(</span><span class="identifier">synchronized_value</span><span class="special"><</span><span class="identifier">T</span><span class="special">,</span><span class="identifier">L</span><span class="special">></span> <span class="keyword">const</span><span class="special">&</span><span class="identifier">lhs</span><span class="special">,</span> <span class="identifier">synchronized_value</span><span class="special"><</span><span class="identifier">T</span><span class="special">,</span><span class="identifier">L</span><span class="special">></span> <span class="keyword">const</span><span class="special">&</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"><</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">></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">&</span> <span class="identifier">lhs</span><span class="special">,</span> <span class="identifier">synchronized_value</span><span class="special"><</span><span class="identifier">T</span><span class="special">,</span><span class="identifier">L</span><span class="special">></span> <span class="keyword">const</span><span class="special">&</span><span class="identifier">rhs</span><span class="special">);</span>
<span class="keyword">template</span> <span class="special"><</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">></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">&</span> <span class="identifier">lhs</span><span class="special">,</span> <span class="identifier">synchronized_value</span><span class="special"><</span><span class="identifier">T</span><span class="special">,</span><span class="identifier">L</span><span class="special">></span> <span class="keyword">const</span><span class="special">&</span><span class="identifier">rhs</span><span class="special">);</span>
<span class="keyword">template</span> <span class="special"><</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">></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">&</span> <span class="identifier">lhs</span><span class="special">,</span> <span class="identifier">synchronized_value</span><span class="special"><</span><span class="identifier">T</span><span class="special">,</span><span class="identifier">L</span><span class="special">></span> <span class="keyword">const</span><span class="special">&</span><span class="identifier">rhs</span><span class="special">);</span>
<span class="keyword">template</span> <span class="special"><</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">></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">&</span> <span class="identifier">lhs</span><span class="special">,</span> <span class="identifier">synchronized_value</span><span class="special"><</span><span class="identifier">T</span><span class="special">,</span><span class="identifier">L</span><span class="special">></span> <span class="keyword">const</span><span class="special">&</span><span class="identifier">rhs</span><span class="special">);</span>
<span class="keyword">template</span> <span class="special"><</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">></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">&</span> <span class="identifier">lhs</span><span class="special">,</span> <span class="identifier">synchronized_value</span><span class="special"><</span><span class="identifier">T</span><span class="special">,</span><span class="identifier">L</span><span class="special">></span> <span class="keyword">const</span><span class="special">&</span><span class="identifier">rhs</span><span class="special">);</span>
<span class="keyword">template</span> <span class="special"><</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">></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">&</span> <span class="identifier">lhs</span><span class="special">,</span> <span class="identifier">synchronized_value</span><span class="special"><</span><span class="identifier">T</span><span class="special">,</span><span class="identifier">L</span><span class="special">></span> <span class="keyword">const</span><span class="special">&</span><span class="identifier">rhs</span><span class="special">);</span>
<span class="keyword">template</span> <span class="special"><</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">></span>
<span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">==(</span><span class="identifier">synchronized_value</span><span class="special"><</span><span class="identifier">T</span><span class="special">,</span><span class="identifier">L</span><span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">lhs</span><span class="special">,</span> <span class="identifier">T</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">rhs</span><span class="special">);</span>
<span class="keyword">template</span> <span class="special"><</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">></span>
<span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">!=(</span><span class="identifier">synchronized_value</span><span class="special"><</span><span class="identifier">T</span><span class="special">,</span><span class="identifier">L</span><span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">lhs</span><span class="special">,</span> <span class="identifier">T</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">rhs</span><span class="special">);</span>
<span class="keyword">template</span> <span class="special"><</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">></span>
<span class="keyword">bool</span> <span class="keyword">operator</span><span class="special"><(</span><span class="identifier">synchronized_value</span><span class="special"><</span><span class="identifier">T</span><span class="special">,</span><span class="identifier">L</span><span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">lhs</span><span class="special">,</span> <span class="identifier">T</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">rhs</span><span class="special">);</span>
<span class="keyword">template</span> <span class="special"><</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">></span>
<span class="keyword">bool</span> <span class="keyword">operator</span><span class="special"><=(</span><span class="identifier">synchronized_value</span><span class="special"><</span><span class="identifier">T</span><span class="special">,</span><span class="identifier">L</span><span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">lhs</span><span class="special">,</span> <span class="identifier">T</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">rhs</span><span class="special">);</span>
<span class="keyword">template</span> <span class="special"><</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">></span>
<span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">>(</span><span class="identifier">synchronized_value</span><span class="special"><</span><span class="identifier">T</span><span class="special">,</span><span class="identifier">L</span><span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">lhs</span><span class="special">,</span> <span class="identifier">T</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">rhs</span><span class="special">);</span>
<span class="keyword">template</span> <span class="special"><</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">></span>
<span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">>=(</span><span class="identifier">synchronized_value</span><span class="special"><</span><span class="identifier">T</span><span class="special">,</span><span class="identifier">L</span><span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">lhs</span><span class="special">,</span> <span class="identifier">T</span> <span class="keyword">const</span><span class="special">&</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"><</span><span class="keyword">typename</span> <span class="special">...</span><span class="identifier">SV</span><span class="special">></span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">tuple</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">synchronized_value_strict_lock_ptr</span><span class="special"><</span><span class="identifier">SV</span><span class="special">>::</span><span class="identifier">type</span> <span class="special">...></span> <span class="identifier">synchronize</span><span class="special">(</span><span class="identifier">SV</span><span class="special">&</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"><</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">></span>
<span class="keyword">namespace</span> <span class="identifier">boost</span>
<span class="special">{</span>
<span class="keyword">template</span><span class="special"><</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">></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"><</span><span class="identifier">T</span><span class="special">>::</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">&</span> <spa