2
0
mirror of https://github.com/boostorg/fiber.git synced 2026-02-17 13:42:21 +00:00
Files
fiber/doc/html/fiber/when_any.html
2015-09-01 17:17:38 +02:00

195 lines
14 KiB
HTML

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>when_any / when_all functionality</title>
<link rel="stylesheet" href="../../../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.75.2">
<link rel="home" href="../index.html" title="Chapter&#160;1.&#160;Fiber">
<link rel="up" href="../index.html" title="Chapter&#160;1.&#160;Fiber">
<link rel="prev" href="nonblocking.html" title="Integrating Fibers with Nonblocking I/O">
<link rel="next" href="when_any/when_any.html" title="when_any">
</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="nonblocking.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.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/when_any.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="fiber.when_any"></a><a name="when_any"></a><a class="link" href="when_any.html" title="when_any / when_all functionality">when_any / when_all
functionality</a>
</h2></div></div></div>
<div class="toc"><dl>
<dt><span class="section"><a href="when_any/when_any.html">when_any</a></span></dt>
<dd><dl>
<dt><span class="section"><a href="when_any/when_any/when_any__simple_completion.html">when_any,
simple completion</a></span></dt>
<dt><span class="section"><a href="when_any/when_any/when_any__return_value.html">when_any,
return value</a></span></dt>
<dt><span class="section"><a href="when_any/when_any/when_any__produce_first_outcome__whether_result_or_exception.html">when_any,
produce first outcome, whether result or exception</a></span></dt>
<dt><span class="section"><a href="when_any/when_any/when_any__produce_first_success.html">when_any,
produce first success</a></span></dt>
<dt><span class="section"><a href="when_any/when_any/when_any__heterogeneous_types.html">when_any,
heterogeneous types</a></span></dt>
</dl></dd>
<dt><span class="section"><a href="when_any/when_all_functionality.html">when_all functionality</a></span></dt>
<dd><dl>
<dt><span class="section"><a href="when_any/when_all_functionality/when_all__simple_completion.html">when_all,
simple completion</a></span></dt>
<dt><span class="section"><a href="when_any/when_all_functionality/when_all__return_values.html">when_all,
return values</a></span></dt>
<dt><span class="section"><a href="when_any/when_all_functionality/when_all_until_first_exception.html">when_all
until first exception</a></span></dt>
<dt><span class="section"><a href="when_any/when_all_functionality/wait_all__collecting_all_exceptions.html">wait_all,
collecting all exceptions</a></span></dt>
<dt><span class="section"><a href="when_any/when_all_functionality/when_all__heterogeneous_types.html">when_all,
heterogeneous types</a></span></dt>
</dl></dd>
</dl></div>
<h4>
<a name="fiber.when_any.h0"></a>
<span><a name="fiber.when_any.overview"></a></span><a class="link" href="when_any.html#fiber.when_any.overview">Overview</a>
</h4>
<p>
A bit of wisdom from the early days of computing still holds true today: prefer
to model program state using the instruction pointer rather than with Boolean
flags. In other words, if the program must "do something" and then
do something almost the same, but with minor changes... perhaps parts of that
something should be broken out as smaller separate functions, rather than introducing
flags to alter the internal behavior of a monolithic function.
</p>
<p>
To that we would add: prefer to describe control flow using C++ native constructs
such as function calls, <code class="computeroutput"><span class="keyword">if</span></code>, <code class="computeroutput"><span class="keyword">while</span></code>, <code class="computeroutput"><span class="keyword">for</span></code>,
<code class="computeroutput"><span class="keyword">do</span></code> et al. rather than as chains
of callbacks.
</p>
<p>
One of the great strengths of <span class="bold"><strong>Boost.Fiber</strong></span>
is the flexibility it confers on the coder to restructure an application from
chains of callbacks to straightforward C++ statement sequence, even when code
in that fiber is in fact interleaved with code running in other fibers.
</p>
<p>
There has been much recent discussion about the benefits of when_any and when_all
functionality. When dealing with asynchronous and possibly unreliable services,
these are valuable idioms. But of course when_any and when_all are closely
tied to the use of chains of callbacks.
</p>
<p>
This section presents recipes for achieving the same ends, in the context of
a fiber that wants to "do something" when one or more other independent
activities have completed. Accordingly, these are <code class="computeroutput"><span class="identifier">wait_something</span><span class="special">()</span></code> functions rather than <code class="computeroutput"><span class="identifier">when_something</span><span class="special">()</span></code> functions. The expectation is that the calling
fiber asks to launch those independent activities, then waits for them, then
sequentially proceeds with whatever processing depends on those results.
</p>
<p>
The function names shown (e.g. <a class="link" href="when_any/when_any/when_any__simple_completion.html#wait_first_simple"><code class="computeroutput"><span class="identifier">wait_first_simple</span><span class="special">()</span></code></a>)
are for illustrative purposes only, because all these functions have been bundled
into a single source file. Presumably, if (say) <a class="link" href="when_any/when_any/when_any__produce_first_success.html#wait_first_success"><code class="computeroutput"><span class="identifier">wait_first_success</span><span class="special">()</span></code></a>
best suits your application needs, you could introduce that variant with the
name <code class="computeroutput"><span class="identifier">wait_any</span><span class="special">()</span></code>.
</p>
<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>
The functions presented in this section accept variadic argument lists of
task functions. Corresponding <code class="computeroutput"><span class="identifier">wait_something</span><span class="special">()</span></code> functions accepting a container of task
functions are left as an exercise for the interested reader. Those should
actually be simpler. Most of the complexity would arise from overloading
the same name for both purposes.
</p></td></tr>
</table></div>
<p>
All the source code for this section is found in <a href="../../../examples/wait_stuff.cpp" target="_top">wait_stuff.cpp</a>.
</p>
<h4>
<a name="fiber.when_any.h1"></a>
<span><a name="fiber.when_any.example_task_function"></a></span><a class="link" href="when_any.html#fiber.when_any.example_task_function">Example
Task Function</a>
</h4>
<p>
<a name="wait_sleeper"></a>We found it convenient to model an asynchronous
task using this function:
</p>
<p>
</p>
<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>
<span class="identifier">T</span> <span class="identifier">sleeper_impl</span><span class="special">(</span> <span class="identifier">T</span> <span class="identifier">item</span><span class="special">,</span> <span class="keyword">int</span> <span class="identifier">ms</span><span class="special">,</span> <span class="keyword">bool</span> <span class="identifier">thrw</span> <span class="special">=</span> <span class="keyword">false</span><span class="special">)</span> <span class="special">{</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">ostringstream</span> <span class="identifier">descb</span><span class="special">,</span> <span class="identifier">funcb</span><span class="special">;</span>
<span class="identifier">descb</span> <span class="special">&lt;&lt;</span> <span class="identifier">item</span><span class="special">;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">desc</span><span class="special">(</span> <span class="identifier">descb</span><span class="special">.</span><span class="identifier">str</span><span class="special">()</span> <span class="special">);</span>
<span class="identifier">funcb</span> <span class="special">&lt;&lt;</span> <span class="string">" sleeper("</span> <span class="special">&lt;&lt;</span> <span class="identifier">item</span> <span class="special">&lt;&lt;</span> <span class="string">")"</span><span class="special">;</span>
<span class="identifier">Verbose</span> <span class="identifier">v</span><span class="special">(</span> <span class="identifier">funcb</span><span class="special">.</span><span class="identifier">str</span><span class="special">()</span> <span class="special">);</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">this_fiber</span><span class="special">::</span><span class="identifier">sleep_for</span><span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">milliseconds</span><span class="special">(</span> <span class="identifier">ms</span><span class="special">)</span> <span class="special">);</span>
<span class="keyword">if</span> <span class="special">(</span> <span class="identifier">thrw</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">throw</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">runtime_error</span><span class="special">(</span> <span class="identifier">desc</span><span class="special">);</span>
<span class="special">}</span>
<span class="keyword">return</span> <span class="identifier">item</span><span class="special">;</span>
<span class="special">}</span>
</pre>
<p>
</p>
<p>
with type-specific <code class="computeroutput"><span class="identifier">sleeper</span><span class="special">()</span></code> "front ends" for <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code>,
<code class="computeroutput"><span class="keyword">double</span></code> and <code class="computeroutput"><span class="keyword">int</span></code>.
</p>
<p>
<code class="computeroutput"><span class="identifier">Verbose</span></code> simply prints a message
to <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span></code> on construction and destruction.
</p>
<p>
Basically:
</p>
<div class="orderedlist"><ol class="orderedlist" type="1">
<li class="listitem">
<code class="computeroutput"><span class="identifier">sleeper</span><span class="special">()</span></code>
prints a start message;
</li>
<li class="listitem">
sleeps for the specified number of milliseconds;
</li>
<li class="listitem">
if <code class="computeroutput"><span class="identifier">thrw</span></code> is passed as <code class="computeroutput"><span class="keyword">true</span></code>, throws a string description of the
passed <code class="computeroutput"><span class="identifier">item</span></code>;
</li>
<li class="listitem">
else returns the passed <code class="computeroutput"><span class="identifier">item</span></code>.
</li>
<li class="listitem">
On the way out, <code class="computeroutput"><span class="identifier">sleeper</span><span class="special">()</span></code> produces a stop message.
</li>
</ol></div>
<p>
This function will feature in the example calls to the various functions presented
below.
</p>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2013 Oliver Kowalke<p>
Distributed under the Boost Software License, Version 1.0. (See accompanying
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>)
</p>
</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="nonblocking.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.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/when_any.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>