• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
2<html>
3<head>
4<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
5<title>Usage examples</title>
6<link rel="stylesheet" href="../../../doc/src/boostbook.css" type="text/css">
7<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
8<link rel="home" href="../index.html" title="The Boost C++ Libraries BoostBook Documentation Subset">
9<link rel="up" href="../atomic.html" title="Chapter 6. Boost.Atomic">
10<link rel="prev" href="interface.html" title="Programming interfaces">
11<link rel="next" href="limitations.html" title="Limitations">
12</head>
13<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
14<table cellpadding="2" width="100%"><tr>
15<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../boost.png"></td>
16<td align="center"><a href="../../../index.html">Home</a></td>
17<td align="center"><a href="../../../libs/libraries.htm">Libraries</a></td>
18<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
19<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
20<td align="center"><a href="../../../more/index.htm">More</a></td>
21</tr></table>
22<hr>
23<div class="spirit-nav">
24<a accesskey="p" href="interface.html"><img src="../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../atomic.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="limitations.html"><img src="../../../doc/src/images/next.png" alt="Next"></a>
25</div>
26<div class="section">
27<div class="titlepage"><div><div><h2 class="title" style="clear: both">
28<a name="atomic.usage_examples"></a><a class="link" href="usage_examples.html" title="Usage examples">Usage examples</a>
29</h2></div></div></div>
30<div class="toc"><dl class="toc">
31<dt><span class="section"><a href="usage_examples.html#boost_atomic.usage_examples.example_reference_counters">Reference
32      counting</a></span></dt>
33<dt><span class="section"><a href="usage_examples.html#boost_atomic.usage_examples.example_spinlock">Spinlock</a></span></dt>
34<dt><span class="section"><a href="usage_examples.html#boost_atomic.usage_examples.singleton">Singleton with
35      double-checked locking pattern</a></span></dt>
36<dt><span class="section"><a href="usage_examples.html#boost_atomic.usage_examples.example_ringbuffer">Wait-free
37      ring buffer</a></span></dt>
38<dt><span class="section"><a href="usage_examples.html#boost_atomic.usage_examples.mp_queue">Lock-free multi-producer
39      queue</a></span></dt>
40</dl></div>
41<div class="section">
42<div class="titlepage"><div><div><h3 class="title">
43<a name="boost_atomic.usage_examples.example_reference_counters"></a><a class="link" href="usage_examples.html#boost_atomic.usage_examples.example_reference_counters" title="Reference counting">Reference
44      counting</a>
45</h3></div></div></div>
46<div class="toc"><dl class="toc">
47<dt><span class="section"><a href="usage_examples.html#boost_atomic.usage_examples.example_reference_counters.implementation">Implementation</a></span></dt>
48<dt><span class="section"><a href="usage_examples.html#boost_atomic.usage_examples.example_reference_counters.usage">Usage</a></span></dt>
49<dt><span class="section"><a href="usage_examples.html#boost_atomic.usage_examples.example_reference_counters.discussion">Discussion</a></span></dt>
50</dl></div>
51<p>
52        The purpose of a <span class="emphasis"><em>reference counter</em></span> is to count the number
53        of pointers to an object. The object can be destroyed as soon as the reference
54        counter reaches zero.
55      </p>
56<div class="section">
57<div class="titlepage"><div><div><h4 class="title">
58<a name="boost_atomic.usage_examples.example_reference_counters.implementation"></a><a class="link" href="usage_examples.html#boost_atomic.usage_examples.example_reference_counters.implementation" title="Implementation">Implementation</a>
59</h4></div></div></div>
60<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">intrusive_ptr</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
61<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">atomic</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
62
63<span class="keyword">class</span> <span class="identifier">X</span> <span class="special">{</span>
64<span class="keyword">public</span><span class="special">:</span>
65  <span class="keyword">typedef</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">intrusive_ptr</span><span class="special">&lt;</span><span class="identifier">X</span><span class="special">&gt;</span> <span class="identifier">pointer</span><span class="special">;</span>
66  <span class="identifier">X</span><span class="special">()</span> <span class="special">:</span> <span class="identifier">refcount_</span><span class="special">(</span><span class="number">0</span><span class="special">)</span> <span class="special">{}</span>
67
68<span class="keyword">private</span><span class="special">:</span>
69  <span class="keyword">mutable</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">atomic</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;</span> <span class="identifier">refcount_</span><span class="special">;</span>
70  <span class="keyword">friend</span> <span class="keyword">void</span> <span class="identifier">intrusive_ptr_add_ref</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">X</span> <span class="special">*</span> <span class="identifier">x</span><span class="special">)</span>
71  <span class="special">{</span>
72    <span class="identifier">x</span><span class="special">-&gt;</span><span class="identifier">refcount_</span><span class="special">.</span><span class="identifier">fetch_add</span><span class="special">(</span><span class="number">1</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">memory_order_relaxed</span><span class="special">);</span>
73  <span class="special">}</span>
74  <span class="keyword">friend</span> <span class="keyword">void</span> <span class="identifier">intrusive_ptr_release</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">X</span> <span class="special">*</span> <span class="identifier">x</span><span class="special">)</span>
75  <span class="special">{</span>
76    <span class="keyword">if</span> <span class="special">(</span><span class="identifier">x</span><span class="special">-&gt;</span><span class="identifier">refcount_</span><span class="special">.</span><span class="identifier">fetch_sub</span><span class="special">(</span><span class="number">1</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">memory_order_release</span><span class="special">)</span> <span class="special">==</span> <span class="number">1</span><span class="special">)</span> <span class="special">{</span>
77      <span class="identifier">boost</span><span class="special">::</span><span class="identifier">atomic_thread_fence</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">memory_order_acquire</span><span class="special">);</span>
78      <span class="keyword">delete</span> <span class="identifier">x</span><span class="special">;</span>
79    <span class="special">}</span>
80  <span class="special">}</span>
81<span class="special">};</span>
82</pre>
83</div>
84<div class="section">
85<div class="titlepage"><div><div><h4 class="title">
86<a name="boost_atomic.usage_examples.example_reference_counters.usage"></a><a class="link" href="usage_examples.html#boost_atomic.usage_examples.example_reference_counters.usage" title="Usage">Usage</a>
87</h4></div></div></div>
88<pre class="programlisting"><span class="identifier">X</span><span class="special">::</span><span class="identifier">pointer</span> <span class="identifier">x</span> <span class="special">=</span> <span class="keyword">new</span> <span class="identifier">X</span><span class="special">;</span>
89</pre>
90</div>
91<div class="section">
92<div class="titlepage"><div><div><h4 class="title">
93<a name="boost_atomic.usage_examples.example_reference_counters.discussion"></a><a class="link" href="usage_examples.html#boost_atomic.usage_examples.example_reference_counters.discussion" title="Discussion">Discussion</a>
94</h4></div></div></div>
95<p>
96          Increasing the reference counter can always be done with <code class="literal">memory_order_relaxed</code>:
97          New references to an object can only be formed from an existing reference,
98          and passing an existing reference from one thread to another must already
99          provide any required synchronization.
100        </p>
101<p>
102          It is important to enforce any possible access to the object in one thread
103          (through an existing reference) to <span class="emphasis"><em>happen before</em></span> deleting
104          the object in a different thread. This is achieved by a "release"
105          operation after dropping a reference (any access to the object through
106          this reference must obviously happened before), and an "acquire"
107          operation before deleting the object.
108        </p>
109<p>
110          It would be possible to use <code class="literal">memory_order_acq_rel</code> for
111          the <code class="literal">fetch_sub</code> operation, but this results in unneeded
112          "acquire" operations when the reference counter does not yet
113          reach zero and may impose a performance penalty.
114        </p>
115</div>
116</div>
117<div class="section">
118<div class="titlepage"><div><div><h3 class="title">
119<a name="boost_atomic.usage_examples.example_spinlock"></a><a class="link" href="usage_examples.html#boost_atomic.usage_examples.example_spinlock" title="Spinlock">Spinlock</a>
120</h3></div></div></div>
121<div class="toc"><dl class="toc">
122<dt><span class="section"><a href="usage_examples.html#boost_atomic.usage_examples.example_spinlock.implementation">Implementation</a></span></dt>
123<dt><span class="section"><a href="usage_examples.html#boost_atomic.usage_examples.example_spinlock.usage">Usage</a></span></dt>
124<dt><span class="section"><a href="usage_examples.html#boost_atomic.usage_examples.example_spinlock.discussion">Discussion</a></span></dt>
125</dl></div>
126<p>
127        The purpose of a <span class="emphasis"><em>spin lock</em></span> is to prevent multiple threads
128        from concurrently accessing a shared data structure. In contrast to a mutex,
129        threads will busy-wait and waste CPU cycles instead of yielding the CPU to
130        another thread. <span class="emphasis"><em>Do not use spinlocks unless you are certain that
131        you understand the consequences.</em></span>
132      </p>
133<div class="section">
134<div class="titlepage"><div><div><h4 class="title">
135<a name="boost_atomic.usage_examples.example_spinlock.implementation"></a><a class="link" href="usage_examples.html#boost_atomic.usage_examples.example_spinlock.implementation" title="Implementation">Implementation</a>
136</h4></div></div></div>
137<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">atomic</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
138
139<span class="keyword">class</span> <span class="identifier">spinlock</span> <span class="special">{</span>
140<span class="keyword">private</span><span class="special">:</span>
141  <span class="keyword">typedef</span> <span class="keyword">enum</span> <span class="special">{</span><span class="identifier">Locked</span><span class="special">,</span> <span class="identifier">Unlocked</span><span class="special">}</span> <span class="identifier">LockState</span><span class="special">;</span>
142  <span class="identifier">boost</span><span class="special">::</span><span class="identifier">atomic</span><span class="special">&lt;</span><span class="identifier">LockState</span><span class="special">&gt;</span> <span class="identifier">state_</span><span class="special">;</span>
143
144<span class="keyword">public</span><span class="special">:</span>
145  <span class="identifier">spinlock</span><span class="special">()</span> <span class="special">:</span> <span class="identifier">state_</span><span class="special">(</span><span class="identifier">Unlocked</span><span class="special">)</span> <span class="special">{}</span>
146
147  <span class="keyword">void</span> <span class="identifier">lock</span><span class="special">()</span>
148  <span class="special">{</span>
149    <span class="keyword">while</span> <span class="special">(</span><span class="identifier">state_</span><span class="special">.</span><span class="identifier">exchange</span><span class="special">(</span><span class="identifier">Locked</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">memory_order_acquire</span><span class="special">)</span> <span class="special">==</span> <span class="identifier">Locked</span><span class="special">)</span> <span class="special">{</span>
150      <span class="comment">/* busy-wait */</span>
151    <span class="special">}</span>
152  <span class="special">}</span>
153  <span class="keyword">void</span> <span class="identifier">unlock</span><span class="special">()</span>
154  <span class="special">{</span>
155    <span class="identifier">state_</span><span class="special">.</span><span class="identifier">store</span><span class="special">(</span><span class="identifier">Unlocked</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">memory_order_release</span><span class="special">);</span>
156  <span class="special">}</span>
157<span class="special">};</span>
158</pre>
159</div>
160<div class="section">
161<div class="titlepage"><div><div><h4 class="title">
162<a name="boost_atomic.usage_examples.example_spinlock.usage"></a><a class="link" href="usage_examples.html#boost_atomic.usage_examples.example_spinlock.usage" title="Usage">Usage</a>
163</h4></div></div></div>
164<pre class="programlisting"><span class="identifier">spinlock</span> <span class="identifier">s</span><span class="special">;</span>
165
166<span class="identifier">s</span><span class="special">.</span><span class="identifier">lock</span><span class="special">();</span>
167<span class="comment">// access data structure here</span>
168<span class="identifier">s</span><span class="special">.</span><span class="identifier">unlock</span><span class="special">();</span>
169</pre>
170</div>
171<div class="section">
172<div class="titlepage"><div><div><h4 class="title">
173<a name="boost_atomic.usage_examples.example_spinlock.discussion"></a><a class="link" href="usage_examples.html#boost_atomic.usage_examples.example_spinlock.discussion" title="Discussion">Discussion</a>
174</h4></div></div></div>
175<p>
176          The purpose of the spinlock is to make sure that one access to the shared
177          data structure always strictly "happens before" another. The
178          usage of acquire/release in lock/unlock is required and sufficient to guarantee
179          this ordering.
180        </p>
181<p>
182          It would be correct to write the "lock" operation in the following
183          way:
184        </p>
185<pre class="programlisting"><span class="identifier">lock</span><span class="special">()</span>
186<span class="special">{</span>
187  <span class="keyword">while</span> <span class="special">(</span><span class="identifier">state_</span><span class="special">.</span><span class="identifier">exchange</span><span class="special">(</span><span class="identifier">Locked</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">memory_order_relaxed</span><span class="special">)</span> <span class="special">==</span> <span class="identifier">Locked</span><span class="special">)</span> <span class="special">{</span>
188    <span class="comment">/* busy-wait */</span>
189  <span class="special">}</span>
190  <span class="identifier">atomic_thread_fence</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">memory_order_acquire</span><span class="special">);</span>
191<span class="special">}</span>
192</pre>
193<p>
194          This "optimization" is however a) useless and b) may in fact
195          hurt: a) Since the thread will be busily spinning on a blocked spinlock,
196          it does not matter if it will waste the CPU cycles with just "exchange"
197          operations or with both useless "exchange" and "acquire"
198          operations. b) A tight "exchange" loop without any memory-synchronizing
199          instruction introduced through an "acquire" operation will on
200          some systems monopolize the memory subsystem and degrade the performance
201          of other system components.
202        </p>
203</div>
204</div>
205<div class="section">
206<div class="titlepage"><div><div><h3 class="title">
207<a name="boost_atomic.usage_examples.singleton"></a><a class="link" href="usage_examples.html#boost_atomic.usage_examples.singleton" title="Singleton with double-checked locking pattern">Singleton with
208      double-checked locking pattern</a>
209</h3></div></div></div>
210<div class="toc"><dl class="toc">
211<dt><span class="section"><a href="usage_examples.html#boost_atomic.usage_examples.singleton.implementation">Implementation</a></span></dt>
212<dt><span class="section"><a href="usage_examples.html#boost_atomic.usage_examples.singleton.usage">Usage</a></span></dt>
213<dt><span class="section"><a href="usage_examples.html#boost_atomic.usage_examples.singleton.discussion">Discussion</a></span></dt>
214</dl></div>
215<p>
216        The purpose of the <span class="emphasis"><em>Singleton with double-checked locking pattern</em></span>
217        is to ensure that at most one instance of a particular object is created.
218        If one instance has been created already, access to the existing object should
219        be as light-weight as possible.
220      </p>
221<div class="section">
222<div class="titlepage"><div><div><h4 class="title">
223<a name="boost_atomic.usage_examples.singleton.implementation"></a><a class="link" href="usage_examples.html#boost_atomic.usage_examples.singleton.implementation" title="Implementation">Implementation</a>
224</h4></div></div></div>
225<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">atomic</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
226<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">mutex</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
227
228<span class="keyword">class</span> <span class="identifier">X</span> <span class="special">{</span>
229<span class="keyword">public</span><span class="special">:</span>
230  <span class="keyword">static</span> <span class="identifier">X</span> <span class="special">*</span> <span class="identifier">instance</span><span class="special">()</span>
231  <span class="special">{</span>
232    <span class="identifier">X</span> <span class="special">*</span> <span class="identifier">tmp</span> <span class="special">=</span> <span class="identifier">instance_</span><span class="special">.</span><span class="identifier">load</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">memory_order_consume</span><span class="special">);</span>
233    <span class="keyword">if</span> <span class="special">(!</span><span class="identifier">tmp</span><span class="special">)</span> <span class="special">{</span>
234      <span class="identifier">boost</span><span class="special">::</span><span class="identifier">mutex</span><span class="special">::</span><span class="identifier">scoped_lock</span> <span class="identifier">guard</span><span class="special">(</span><span class="identifier">instantiation_mutex</span><span class="special">);</span>
235      <span class="identifier">tmp</span> <span class="special">=</span> <span class="identifier">instance_</span><span class="special">.</span><span class="identifier">load</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">memory_order_consume</span><span class="special">);</span>
236      <span class="keyword">if</span> <span class="special">(!</span><span class="identifier">tmp</span><span class="special">)</span> <span class="special">{</span>
237        <span class="identifier">tmp</span> <span class="special">=</span> <span class="keyword">new</span> <span class="identifier">X</span><span class="special">;</span>
238        <span class="identifier">instance_</span><span class="special">.</span><span class="identifier">store</span><span class="special">(</span><span class="identifier">tmp</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">memory_order_release</span><span class="special">);</span>
239      <span class="special">}</span>
240    <span class="special">}</span>
241    <span class="keyword">return</span> <span class="identifier">tmp</span><span class="special">;</span>
242  <span class="special">}</span>
243<span class="keyword">private</span><span class="special">:</span>
244  <span class="keyword">static</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">atomic</span><span class="special">&lt;</span><span class="identifier">X</span> <span class="special">*&gt;</span> <span class="identifier">instance_</span><span class="special">;</span>
245  <span class="keyword">static</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">mutex</span> <span class="identifier">instantiation_mutex</span><span class="special">;</span>
246<span class="special">};</span>
247
248<span class="identifier">boost</span><span class="special">::</span><span class="identifier">atomic</span><span class="special">&lt;</span><span class="identifier">X</span> <span class="special">*&gt;</span> <span class="identifier">X</span><span class="special">::</span><span class="identifier">instance_</span><span class="special">(</span><span class="number">0</span><span class="special">);</span>
249</pre>
250</div>
251<div class="section">
252<div class="titlepage"><div><div><h4 class="title">
253<a name="boost_atomic.usage_examples.singleton.usage"></a><a class="link" href="usage_examples.html#boost_atomic.usage_examples.singleton.usage" title="Usage">Usage</a>
254</h4></div></div></div>
255<pre class="programlisting"><span class="identifier">X</span> <span class="special">*</span> <span class="identifier">x</span> <span class="special">=</span> <span class="identifier">X</span><span class="special">::</span><span class="identifier">instance</span><span class="special">();</span>
256<span class="comment">// dereference x</span>
257</pre>
258</div>
259<div class="section">
260<div class="titlepage"><div><div><h4 class="title">
261<a name="boost_atomic.usage_examples.singleton.discussion"></a><a class="link" href="usage_examples.html#boost_atomic.usage_examples.singleton.discussion" title="Discussion">Discussion</a>
262</h4></div></div></div>
263<p>
264          The mutex makes sure that only one instance of the object is ever created.
265          The <code class="literal">instance</code> method must make sure that any dereference
266          of the object strictly "happens after" creating the instance
267          in another thread. The use of <code class="literal">memory_order_release</code> after
268          creating and initializing the object and <code class="literal">memory_order_consume</code>
269          before dereferencing the object provides this guarantee.
270        </p>
271<p>
272          It would be permissible to use <code class="literal">memory_order_acquire</code>
273          instead of <code class="literal">memory_order_consume</code>, but this provides a
274          stronger guarantee than is required since only operations depending on
275          the value of the pointer need to be ordered.
276        </p>
277</div>
278</div>
279<div class="section">
280<div class="titlepage"><div><div><h3 class="title">
281<a name="boost_atomic.usage_examples.example_ringbuffer"></a><a class="link" href="usage_examples.html#boost_atomic.usage_examples.example_ringbuffer" title="Wait-free ring buffer">Wait-free
282      ring buffer</a>
283</h3></div></div></div>
284<div class="toc"><dl class="toc">
285<dt><span class="section"><a href="usage_examples.html#boost_atomic.usage_examples.example_ringbuffer.implementation">Implementation</a></span></dt>
286<dt><span class="section"><a href="usage_examples.html#boost_atomic.usage_examples.example_ringbuffer.usage">Usage</a></span></dt>
287<dt><span class="section"><a href="usage_examples.html#boost_atomic.usage_examples.example_ringbuffer.discussion">Discussion</a></span></dt>
288</dl></div>
289<p>
290        A <span class="emphasis"><em>wait-free ring buffer</em></span> provides a mechanism for relaying
291        objects from one single "producer" thread to one single "consumer"
292        thread without any locks. The operations on this data structure are "wait-free"
293        which means that each operation finishes within a constant number of steps.
294        This makes this data structure suitable for use in hard real-time systems
295        or for communication with interrupt/signal handlers.
296      </p>
297<div class="section">
298<div class="titlepage"><div><div><h4 class="title">
299<a name="boost_atomic.usage_examples.example_ringbuffer.implementation"></a><a class="link" href="usage_examples.html#boost_atomic.usage_examples.example_ringbuffer.implementation" title="Implementation">Implementation</a>
300</h4></div></div></div>
301<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">atomic</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
302
303<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="identifier">size_t</span> <span class="identifier">Size</span><span class="special">&gt;</span>
304<span class="keyword">class</span> <span class="identifier">ringbuffer</span> <span class="special">{</span>
305<span class="keyword">public</span><span class="special">:</span>
306  <span class="identifier">ringbuffer</span><span class="special">()</span> <span class="special">:</span> <span class="identifier">head_</span><span class="special">(</span><span class="number">0</span><span class="special">),</span> <span class="identifier">tail_</span><span class="special">(</span><span class="number">0</span><span class="special">)</span> <span class="special">{}</span>
307
308  <span class="keyword">bool</span> <span class="identifier">push</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">T</span> <span class="special">&amp;</span> <span class="identifier">value</span><span class="special">)</span>
309  <span class="special">{</span>
310    <span class="identifier">size_t</span> <span class="identifier">head</span> <span class="special">=</span> <span class="identifier">head_</span><span class="special">.</span><span class="identifier">load</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">memory_order_relaxed</span><span class="special">);</span>
311    <span class="identifier">size_t</span> <span class="identifier">next_head</span> <span class="special">=</span> <span class="identifier">next</span><span class="special">(</span><span class="identifier">head</span><span class="special">);</span>
312    <span class="keyword">if</span> <span class="special">(</span><span class="identifier">next_head</span> <span class="special">==</span> <span class="identifier">tail_</span><span class="special">.</span><span class="identifier">load</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">memory_order_acquire</span><span class="special">))</span>
313      <span class="keyword">return</span> <span class="keyword">false</span><span class="special">;</span>
314    <span class="identifier">ring_</span><span class="special">[</span><span class="identifier">head</span><span class="special">]</span> <span class="special">=</span> <span class="identifier">value</span><span class="special">;</span>
315    <span class="identifier">head_</span><span class="special">.</span><span class="identifier">store</span><span class="special">(</span><span class="identifier">next_head</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">memory_order_release</span><span class="special">);</span>
316    <span class="keyword">return</span> <span class="keyword">true</span><span class="special">;</span>
317  <span class="special">}</span>
318  <span class="keyword">bool</span> <span class="identifier">pop</span><span class="special">(</span><span class="identifier">T</span> <span class="special">&amp;</span> <span class="identifier">value</span><span class="special">)</span>
319  <span class="special">{</span>
320    <span class="identifier">size_t</span> <span class="identifier">tail</span> <span class="special">=</span> <span class="identifier">tail_</span><span class="special">.</span><span class="identifier">load</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">memory_order_relaxed</span><span class="special">);</span>
321    <span class="keyword">if</span> <span class="special">(</span><span class="identifier">tail</span> <span class="special">==</span> <span class="identifier">head_</span><span class="special">.</span><span class="identifier">load</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">memory_order_acquire</span><span class="special">))</span>
322      <span class="keyword">return</span> <span class="keyword">false</span><span class="special">;</span>
323    <span class="identifier">value</span> <span class="special">=</span> <span class="identifier">ring_</span><span class="special">[</span><span class="identifier">tail</span><span class="special">];</span>
324    <span class="identifier">tail_</span><span class="special">.</span><span class="identifier">store</span><span class="special">(</span><span class="identifier">next</span><span class="special">(</span><span class="identifier">tail</span><span class="special">),</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">memory_order_release</span><span class="special">);</span>
325    <span class="keyword">return</span> <span class="keyword">true</span><span class="special">;</span>
326  <span class="special">}</span>
327<span class="keyword">private</span><span class="special">:</span>
328  <span class="identifier">size_t</span> <span class="identifier">next</span><span class="special">(</span><span class="identifier">size_t</span> <span class="identifier">current</span><span class="special">)</span>
329  <span class="special">{</span>
330    <span class="keyword">return</span> <span class="special">(</span><span class="identifier">current</span> <span class="special">+</span> <span class="number">1</span><span class="special">)</span> <span class="special">%</span> <span class="identifier">Size</span><span class="special">;</span>
331  <span class="special">}</span>
332  <span class="identifier">T</span> <span class="identifier">ring_</span><span class="special">[</span><span class="identifier">Size</span><span class="special">];</span>
333  <span class="identifier">boost</span><span class="special">::</span><span class="identifier">atomic</span><span class="special">&lt;</span><span class="identifier">size_t</span><span class="special">&gt;</span> <span class="identifier">head_</span><span class="special">,</span> <span class="identifier">tail_</span><span class="special">;</span>
334<span class="special">};</span>
335</pre>
336</div>
337<div class="section">
338<div class="titlepage"><div><div><h4 class="title">
339<a name="boost_atomic.usage_examples.example_ringbuffer.usage"></a><a class="link" href="usage_examples.html#boost_atomic.usage_examples.example_ringbuffer.usage" title="Usage">Usage</a>
340</h4></div></div></div>
341<pre class="programlisting"><span class="identifier">ringbuffer</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">,</span> <span class="number">32</span><span class="special">&gt;</span> <span class="identifier">r</span><span class="special">;</span>
342
343<span class="comment">// try to insert an element</span>
344<span class="keyword">if</span> <span class="special">(</span><span class="identifier">r</span><span class="special">.</span><span class="identifier">push</span><span class="special">(</span><span class="number">42</span><span class="special">))</span> <span class="special">{</span> <span class="comment">/* succeeded */</span> <span class="special">}</span>
345<span class="keyword">else</span> <span class="special">{</span> <span class="comment">/* buffer full */</span> <span class="special">}</span>
346
347<span class="comment">// try to retrieve an element</span>
348<span class="keyword">int</span> <span class="identifier">value</span><span class="special">;</span>
349<span class="keyword">if</span> <span class="special">(</span><span class="identifier">r</span><span class="special">.</span><span class="identifier">pop</span><span class="special">(</span><span class="identifier">value</span><span class="special">))</span> <span class="special">{</span> <span class="comment">/* succeeded */</span> <span class="special">}</span>
350<span class="keyword">else</span> <span class="special">{</span> <span class="comment">/* buffer empty */</span> <span class="special">}</span>
351</pre>
352</div>
353<div class="section">
354<div class="titlepage"><div><div><h4 class="title">
355<a name="boost_atomic.usage_examples.example_ringbuffer.discussion"></a><a class="link" href="usage_examples.html#boost_atomic.usage_examples.example_ringbuffer.discussion" title="Discussion">Discussion</a>
356</h4></div></div></div>
357<p>
358          The implementation makes sure that the ring indices do not "lap-around"
359          each other to ensure that no elements are either lost or read twice.
360        </p>
361<p>
362          Furthermore it must guarantee that read-access to a particular object in
363          <code class="literal">pop</code> "happens after" it has been written in
364          <code class="literal">push</code>. This is achieved by writing <code class="literal">head_ </code>
365          with "release" and reading it with "acquire". Conversely
366          the implementation also ensures that read access to a particular ring element
367          "happens before" before rewriting this element with a new value
368          by accessing <code class="literal">tail_</code> with appropriate ordering constraints.
369        </p>
370</div>
371</div>
372<div class="section">
373<div class="titlepage"><div><div><h3 class="title">
374<a name="boost_atomic.usage_examples.mp_queue"></a><a class="link" href="usage_examples.html#boost_atomic.usage_examples.mp_queue" title="Lock-free multi-producer queue">Lock-free multi-producer
375      queue</a>
376</h3></div></div></div>
377<div class="toc"><dl class="toc">
378<dt><span class="section"><a href="usage_examples.html#boost_atomic.usage_examples.mp_queue.implementation">Implementation</a></span></dt>
379<dt><span class="section"><a href="usage_examples.html#boost_atomic.usage_examples.mp_queue.usage">Usage</a></span></dt>
380<dt><span class="section"><a href="usage_examples.html#boost_atomic.usage_examples.mp_queue.discussion">Discussion</a></span></dt>
381</dl></div>
382<p>
383        The purpose of the <span class="emphasis"><em>lock-free multi-producer queue</em></span> is
384        to allow an arbitrary number of producers to enqueue objects which are retrieved
385        and processed in FIFO order by a single consumer.
386      </p>
387<div class="section">
388<div class="titlepage"><div><div><h4 class="title">
389<a name="boost_atomic.usage_examples.mp_queue.implementation"></a><a class="link" href="usage_examples.html#boost_atomic.usage_examples.mp_queue.implementation" title="Implementation">Implementation</a>
390</h4></div></div></div>
391<pre class="programlisting"><span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">&gt;</span>
392<span class="keyword">class</span> <span class="identifier">lockfree_queue</span> <span class="special">{</span>
393<span class="keyword">public</span><span class="special">:</span>
394  <span class="keyword">struct</span> <span class="identifier">node</span> <span class="special">{</span>
395    <span class="identifier">T</span> <span class="identifier">data</span><span class="special">;</span>
396    <span class="identifier">node</span> <span class="special">*</span> <span class="identifier">next</span><span class="special">;</span>
397  <span class="special">};</span>
398  <span class="keyword">void</span> <span class="identifier">push</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">T</span> <span class="special">&amp;</span><span class="identifier">data</span><span class="special">)</span>
399  <span class="special">{</span>
400    <span class="identifier">node</span> <span class="special">*</span> <span class="identifier">n</span> <span class="special">=</span> <span class="keyword">new</span> <span class="identifier">node</span><span class="special">;</span>
401    <span class="identifier">n</span><span class="special">-&gt;</span><span class="identifier">data</span> <span class="special">=</span> <span class="identifier">data</span><span class="special">;</span>
402    <span class="identifier">node</span> <span class="special">*</span> <span class="identifier">stale_head</span> <span class="special">=</span> <span class="identifier">head_</span><span class="special">.</span><span class="identifier">load</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">memory_order_relaxed</span><span class="special">);</span>
403    <span class="keyword">do</span> <span class="special">{</span>
404      <span class="identifier">n</span><span class="special">-&gt;</span><span class="identifier">next</span> <span class="special">=</span> <span class="identifier">stale_head</span><span class="special">;</span>
405    <span class="special">}</span> <span class="keyword">while</span> <span class="special">(!</span><span class="identifier">head_</span><span class="special">.</span><span class="identifier">compare_exchange_weak</span><span class="special">(</span><span class="identifier">stale_head</span><span class="special">,</span> <span class="identifier">n</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">memory_order_release</span><span class="special">));</span>
406  <span class="special">}</span>
407
408  <span class="identifier">node</span> <span class="special">*</span> <span class="identifier">pop_all</span><span class="special">(</span><span class="keyword">void</span><span class="special">)</span>
409  <span class="special">{</span>
410    <span class="identifier">T</span> <span class="special">*</span> <span class="identifier">last</span> <span class="special">=</span> <span class="identifier">pop_all_reverse</span><span class="special">(),</span> <span class="special">*</span> <span class="identifier">first</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span>
411    <span class="keyword">while</span><span class="special">(</span><span class="identifier">last</span><span class="special">)</span> <span class="special">{</span>
412      <span class="identifier">T</span> <span class="special">*</span> <span class="identifier">tmp</span> <span class="special">=</span> <span class="identifier">last</span><span class="special">;</span>
413      <span class="identifier">last</span> <span class="special">=</span> <span class="identifier">last</span><span class="special">-&gt;</span><span class="identifier">next</span><span class="special">;</span>
414      <span class="identifier">tmp</span><span class="special">-&gt;</span><span class="identifier">next</span> <span class="special">=</span> <span class="identifier">first</span><span class="special">;</span>
415      <span class="identifier">first</span> <span class="special">=</span> <span class="identifier">tmp</span><span class="special">;</span>
416    <span class="special">}</span>
417    <span class="keyword">return</span> <span class="identifier">first</span><span class="special">;</span>
418  <span class="special">}</span>
419
420  <span class="identifier">lockfree_queue</span><span class="special">()</span> <span class="special">:</span> <span class="identifier">head_</span><span class="special">(</span><span class="number">0</span><span class="special">)</span> <span class="special">{}</span>
421
422  <span class="comment">// alternative interface if ordering is of no importance</span>
423  <span class="identifier">node</span> <span class="special">*</span> <span class="identifier">pop_all_reverse</span><span class="special">(</span><span class="keyword">void</span><span class="special">)</span>
424  <span class="special">{</span>
425    <span class="keyword">return</span> <span class="identifier">head_</span><span class="special">.</span><span class="identifier">exchange</span><span class="special">(</span><span class="number">0</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">memory_order_consume</span><span class="special">);</span>
426  <span class="special">}</span>
427<span class="keyword">private</span><span class="special">:</span>
428  <span class="identifier">boost</span><span class="special">::</span><span class="identifier">atomic</span><span class="special">&lt;</span><span class="identifier">node</span> <span class="special">*&gt;</span> <span class="identifier">head_</span><span class="special">;</span>
429<span class="special">};</span>
430</pre>
431</div>
432<div class="section">
433<div class="titlepage"><div><div><h4 class="title">
434<a name="boost_atomic.usage_examples.mp_queue.usage"></a><a class="link" href="usage_examples.html#boost_atomic.usage_examples.mp_queue.usage" title="Usage">Usage</a>
435</h4></div></div></div>
436<pre class="programlisting"><span class="identifier">lockfree_queue</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;</span> <span class="identifier">q</span><span class="special">;</span>
437
438<span class="comment">// insert elements</span>
439<span class="identifier">q</span><span class="special">.</span><span class="identifier">push</span><span class="special">(</span><span class="number">42</span><span class="special">);</span>
440<span class="identifier">q</span><span class="special">.</span><span class="identifier">push</span><span class="special">(</span><span class="number">2</span><span class="special">);</span>
441
442<span class="comment">// pop elements</span>
443<span class="identifier">lockfree_queue</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;::</span><span class="identifier">node</span> <span class="special">*</span> <span class="identifier">x</span> <span class="special">=</span> <span class="identifier">q</span><span class="special">.</span><span class="identifier">pop_all</span><span class="special">()</span>
444<span class="keyword">while</span><span class="special">(</span><span class="identifier">x</span><span class="special">)</span> <span class="special">{</span>
445  <span class="identifier">X</span> <span class="special">*</span> <span class="identifier">tmp</span> <span class="special">=</span> <span class="identifier">x</span><span class="special">;</span>
446  <span class="identifier">x</span> <span class="special">=</span> <span class="identifier">x</span><span class="special">-&gt;</span><span class="identifier">next</span><span class="special">;</span>
447  <span class="comment">// process tmp-&gt;data, probably delete it afterwards</span>
448  <span class="keyword">delete</span> <span class="identifier">tmp</span><span class="special">;</span>
449<span class="special">}</span>
450</pre>
451</div>
452<div class="section">
453<div class="titlepage"><div><div><h4 class="title">
454<a name="boost_atomic.usage_examples.mp_queue.discussion"></a><a class="link" href="usage_examples.html#boost_atomic.usage_examples.mp_queue.discussion" title="Discussion">Discussion</a>
455</h4></div></div></div>
456<p>
457          The implementation guarantees that all objects enqueued are processed in
458          the order they were enqueued by building a singly-linked list of object
459          in reverse processing order. The queue is atomically emptied by the consumer
460          (in an operation that is not only lock-free but wait-free) and brought
461          into correct order.
462        </p>
463<p>
464          It must be guaranteed that any access to an object to be enqueued by the
465          producer "happens before" any access by the consumer. This is
466          assured by inserting objects into the list with <span class="emphasis"><em>release</em></span>
467          and dequeuing them with <span class="emphasis"><em>consume</em></span> memory order. It is
468          not necessary to use <span class="emphasis"><em>acquire</em></span> memory order in <code class="literal">waitfree_queue::pop_all</code>
469          because all operations involved depend on the value of the atomic pointer
470          through dereference.
471        </p>
472</div>
473</div>
474</div>
475<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
476<td align="left"></td>
477<td align="right"><div class="copyright-footer">Copyright © 2011 Helge Bahmann<br>Copyright © 2012 Tim Blechmann<br>Copyright © 2013, 2017, 2018, 2020 Andrey
478      Semashev<p>
479        Distributed under the Boost Software License, Version 1.0. (See accompanying
480        file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
481      </p>
482</div></td>
483</tr></table>
484<hr>
485<div class="spirit-nav">
486<a accesskey="p" href="interface.html"><img src="../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../atomic.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="limitations.html"><img src="../../../doc/src/images/next.png" alt="Next"></a>
487</div>
488</body>
489</html>
490