• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1<html>
2<head>
3<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
4<title>when_any, simple completion</title>
5<link rel="stylesheet" href="../../../../../../../doc/src/boostbook.css" type="text/css">
6<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
7<link rel="home" href="../../../index.html" title="Chapter 1. Fiber">
8<link rel="up" href="../when_any.html" title="when_any">
9<link rel="prev" href="../when_any.html" title="when_any">
10<link rel="next" href="when_any__return_value.html" title="when_any, return value">
11</head>
12<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
13<table cellpadding="2" width="100%"><tr>
14<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../../boost.png"></td>
15<td align="center"><a href="../../../../../../../index.html">Home</a></td>
16<td align="center"><a href="../../../../../../../libs/libraries.htm">Libraries</a></td>
17<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
18<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
19<td align="center"><a href="../../../../../../../more/index.htm">More</a></td>
20</tr></table>
21<hr>
22<div class="spirit-nav">
23<a accesskey="p" href="../when_any.html"><img src="../../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../when_any.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="when_any__return_value.html"><img src="../../../../../../../doc/src/images/next.png" alt="Next"></a>
24</div>
25<div class="section">
26<div class="titlepage"><div><div><h4 class="title">
27<a name="fiber.when_any.when_any.when_any__simple_completion"></a><a name="wait_first_simple_section"></a><a class="link" href="when_any__simple_completion.html" title="when_any, simple completion">when_any,
28        simple completion</a>
29</h4></div></div></div>
30<p>
31          The simplest case is when you only need to know that the first of a set
32          of asynchronous tasks has completed — but you don't need to obtain a return
33          value, and you're confident that they will not throw exceptions.
34        </p>
35<p>
36          <a name="wait_done"></a>For this we introduce a <code class="computeroutput"><span class="identifier">Done</span></code>
37          class to wrap a <code class="computeroutput"><span class="keyword">bool</span></code> variable
38          with a <a class="link" href="../../synchronization/conditions.html#class_condition_variable"><code class="computeroutput">condition_variable</code></a> and a <a class="link" href="../../synchronization/mutex_types.html#class_mutex"><code class="computeroutput">mutex</code></a>:
39        </p>
40<p>
41</p>
42<pre class="programlisting"><span class="comment">// Wrap canonical pattern for condition_variable + bool flag</span>
43<span class="keyword">struct</span> <span class="identifier">Done</span> <span class="special">{</span>
44<span class="keyword">private</span><span class="special">:</span>
45    <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">condition_variable</span>   <span class="identifier">cond</span><span class="special">;</span>
46    <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">mutex</span>                <span class="identifier">mutex</span><span class="special">;</span>
47    <span class="keyword">bool</span>                                <span class="identifier">ready</span> <span class="special">=</span> <span class="keyword">false</span><span class="special">;</span>
48
49<span class="keyword">public</span><span class="special">:</span>
50    <span class="keyword">typedef</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">shared_ptr</span><span class="special">&lt;</span> <span class="identifier">Done</span> <span class="special">&gt;</span>     <span class="identifier">ptr</span><span class="special">;</span>
51
52    <span class="keyword">void</span> <span class="identifier">wait</span><span class="special">()</span> <span class="special">{</span>
53        <span class="identifier">std</span><span class="special">::</span><span class="identifier">unique_lock</span><span class="special">&lt;</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">mutex</span> <span class="special">&gt;</span> <span class="identifier">lock</span><span class="special">(</span> <span class="identifier">mutex</span><span class="special">);</span>
54        <span class="identifier">cond</span><span class="special">.</span><span class="identifier">wait</span><span class="special">(</span> <span class="identifier">lock</span><span class="special">,</span> <span class="special">[</span><span class="keyword">this</span><span class="special">](){</span> <span class="keyword">return</span> <span class="identifier">ready</span><span class="special">;</span> <span class="special">});</span>
55    <span class="special">}</span>
56
57    <span class="keyword">void</span> <span class="identifier">notify</span><span class="special">()</span> <span class="special">{</span>
58        <span class="special">{</span>
59            <span class="identifier">std</span><span class="special">::</span><span class="identifier">unique_lock</span><span class="special">&lt;</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">mutex</span> <span class="special">&gt;</span> <span class="identifier">lock</span><span class="special">(</span> <span class="identifier">mutex</span><span class="special">);</span>
60            <span class="identifier">ready</span> <span class="special">=</span> <span class="keyword">true</span><span class="special">;</span>
61        <span class="special">}</span> <span class="comment">// release mutex</span>
62        <span class="identifier">cond</span><span class="special">.</span><span class="identifier">notify_one</span><span class="special">();</span>
63    <span class="special">}</span>
64<span class="special">};</span>
65</pre>
66<p>
67        </p>
68<p>
69          The pattern we follow throughout this section is to pass a <a href="http://www.cplusplus.com/reference/memory/shared_ptr/" target="_top"><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">shared_ptr</span><span class="special">&lt;&gt;</span></code></a>
70          to the relevant synchronization object to the various tasks' fiber functions.
71          This eliminates nagging questions about the lifespan of the synchronization
72          object relative to the last of the fibers.
73        </p>
74<p>
75          <a name="wait_first_simple"></a><code class="computeroutput"><span class="identifier">wait_first_simple</span><span class="special">()</span></code> uses that tactic for <a class="link" href="when_any__simple_completion.html#wait_done"><code class="computeroutput"><span class="identifier">Done</span></code></a>:
76        </p>
77<p>
78</p>
79<pre class="programlisting"><span class="keyword">template</span><span class="special">&lt;</span> <span class="keyword">typename</span> <span class="special">...</span> <span class="identifier">Fns</span> <span class="special">&gt;</span>
80<span class="keyword">void</span> <span class="identifier">wait_first_simple</span><span class="special">(</span> <span class="identifier">Fns</span> <span class="special">&amp;&amp;</span> <span class="special">...</span> <span class="identifier">functions</span><span class="special">)</span> <span class="special">{</span>
81    <span class="comment">// Use shared_ptr because each function's fiber will bind it separately,</span>
82    <span class="comment">// and we're going to return before the last of them completes.</span>
83    <span class="keyword">auto</span> <span class="identifier">done</span><span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">make_shared</span><span class="special">&lt;</span> <span class="identifier">Done</span> <span class="special">&gt;()</span> <span class="special">);</span>
84    <span class="identifier">wait_first_simple_impl</span><span class="special">(</span> <span class="identifier">done</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">forward</span><span class="special">&lt;</span> <span class="identifier">Fns</span> <span class="special">&gt;(</span> <span class="identifier">functions</span><span class="special">)</span> <span class="special">...</span> <span class="special">);</span>
85    <span class="identifier">done</span><span class="special">-&gt;</span><span class="identifier">wait</span><span class="special">();</span>
86<span class="special">}</span>
87</pre>
88<p>
89        </p>
90<p>
91          <a name="wait_first_simple_impl"></a><code class="computeroutput"><span class="identifier">wait_first_simple_impl</span><span class="special">()</span></code> is an ordinary recursion over the argument
92          pack, capturing <code class="computeroutput"><span class="identifier">Done</span><span class="special">::</span><span class="identifier">ptr</span></code> for each new fiber:
93        </p>
94<p>
95</p>
96<pre class="programlisting"><span class="comment">// Degenerate case: when there are no functions to wait for, return</span>
97<span class="comment">// immediately.</span>
98<span class="keyword">void</span> <span class="identifier">wait_first_simple_impl</span><span class="special">(</span> <span class="identifier">Done</span><span class="special">::</span><span class="identifier">ptr</span><span class="special">)</span> <span class="special">{</span>
99<span class="special">}</span>
100
101<span class="comment">// When there's at least one function to wait for, launch it and recur to</span>
102<span class="comment">// process the rest.</span>
103<span class="keyword">template</span><span class="special">&lt;</span> <span class="keyword">typename</span> <span class="identifier">Fn</span><span class="special">,</span> <span class="keyword">typename</span> <span class="special">...</span> <span class="identifier">Fns</span> <span class="special">&gt;</span>
104<span class="keyword">void</span> <span class="identifier">wait_first_simple_impl</span><span class="special">(</span> <span class="identifier">Done</span><span class="special">::</span><span class="identifier">ptr</span> <span class="identifier">done</span><span class="special">,</span> <span class="identifier">Fn</span> <span class="special">&amp;&amp;</span> <span class="identifier">function</span><span class="special">,</span> <span class="identifier">Fns</span> <span class="special">&amp;&amp;</span> <span class="special">...</span> <span class="identifier">functions</span><span class="special">)</span> <span class="special">{</span>
105    <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">fiber</span><span class="special">(</span> <span class="special">[</span><span class="identifier">done</span><span class="special">,</span> <span class="identifier">function</span><span class="special">](){</span>
106                              <span class="identifier">function</span><span class="special">();</span>
107                              <span class="identifier">done</span><span class="special">-&gt;</span><span class="identifier">notify</span><span class="special">();</span>
108                          <span class="special">}).</span><span class="identifier">detach</span><span class="special">();</span>
109    <span class="identifier">wait_first_simple_impl</span><span class="special">(</span> <span class="identifier">done</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">forward</span><span class="special">&lt;</span> <span class="identifier">Fns</span> <span class="special">&gt;(</span> <span class="identifier">functions</span><span class="special">)</span> <span class="special">...</span> <span class="special">);</span>
110<span class="special">}</span>
111</pre>
112<p>
113        </p>
114<p>
115          The body of the fiber's lambda is extremely simple, as promised: call the
116          function, notify <a class="link" href="when_any__simple_completion.html#wait_done"><code class="computeroutput"><span class="identifier">Done</span></code></a>
117          when it returns. The first fiber to do so allows <code class="computeroutput"><span class="identifier">wait_first_simple</span><span class="special">()</span></code> to return — which is why it's useful to
118          have <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">shared_ptr</span><span class="special">&lt;</span><span class="identifier">Done</span><span class="special">&gt;</span></code>
119          manage the lifespan of our <code class="computeroutput"><span class="identifier">Done</span></code>
120          object rather than declaring it as a stack variable in <code class="computeroutput"><span class="identifier">wait_first_simple</span><span class="special">()</span></code>.
121        </p>
122<p>
123          This is how you might call it:
124        </p>
125<p>
126</p>
127<pre class="programlisting"><span class="identifier">wait_first_simple</span><span class="special">(</span>
128        <span class="special">[](){</span> <span class="identifier">sleeper</span><span class="special">(</span><span class="string">"wfs_long"</span><span class="special">,</span>   <span class="number">150</span><span class="special">);</span> <span class="special">},</span>
129        <span class="special">[](){</span> <span class="identifier">sleeper</span><span class="special">(</span><span class="string">"wfs_medium"</span><span class="special">,</span> <span class="number">100</span><span class="special">);</span> <span class="special">},</span>
130        <span class="special">[](){</span> <span class="identifier">sleeper</span><span class="special">(</span><span class="string">"wfs_short"</span><span class="special">,</span>   <span class="number">50</span><span class="special">);</span> <span class="special">});</span>
131</pre>
132<p>
133        </p>
134<p>
135          In this example, control resumes after <code class="computeroutput"><span class="identifier">wait_first_simple</span><span class="special">()</span></code> when <a class="link" href="../../when_any.html#wait_sleeper"><code class="computeroutput"><span class="identifier">sleeper</span><span class="special">(</span><span class="string">"wfs_short"</span><span class="special">,</span>
136          <span class="number">50</span><span class="special">)</span></code></a>
137          completes — even though the other two <code class="computeroutput"><span class="identifier">sleeper</span><span class="special">()</span></code> fibers are still running.
138        </p>
139</div>
140<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
141<td align="left"></td>
142<td align="right"><div class="copyright-footer">Copyright © 2013 Oliver Kowalke<p>
143        Distributed under the Boost Software License, Version 1.0. (See accompanying
144        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>)
145      </p>
146</div></td>
147</tr></table>
148<hr>
149<div class="spirit-nav">
150<a accesskey="p" href="../when_any.html"><img src="../../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../when_any.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="when_any__return_value.html"><img src="../../../../../../../doc/src/images/next.png" alt="Next"></a>
151</div>
152</body>
153</html>
154