439 lines
16 KiB
HTML
439 lines
16 KiB
HTML
<html>
|
|
<head>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
|
<title>coroutine</title>
|
|
<link rel="stylesheet" href="../../../../doc/src/boostbook.css" type="text/css">
|
|
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
|
|
<link rel="home" href="../../boost_asio.html" title="Boost.Asio">
|
|
<link rel="up" href="../reference.html" title="Reference">
|
|
<link rel="prev" href="const_buffers_1/value_type.html" title="const_buffers_1::value_type">
|
|
<link rel="next" href="coroutine/coroutine.html" title="coroutine::coroutine">
|
|
</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="const_buffers_1/value_type.html"><img src="../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../reference.html"><img src="../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../boost_asio.html"><img src="../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="coroutine/coroutine.html"><img src="../../../../doc/src/images/next.png" alt="Next"></a>
|
|
</div>
|
|
<div class="section">
|
|
<div class="titlepage"><div><div><h3 class="title">
|
|
<a name="boost_asio.reference.coroutine"></a><a class="link" href="coroutine.html" title="coroutine">coroutine</a>
|
|
</h3></div></div></div>
|
|
<p>
|
|
<a class="indexterm" name="boost_asio.indexterm.coroutine"></a>
|
|
</p>
|
|
<p>
|
|
Provides support for implementing stackless coroutines.
|
|
</p>
|
|
<pre class="programlisting">class coroutine
|
|
</pre>
|
|
<h5>
|
|
<a name="boost_asio.reference.coroutine.h0"></a>
|
|
<span class="phrase"><a name="boost_asio.reference.coroutine.member_functions"></a></span><a class="link" href="coroutine.html#boost_asio.reference.coroutine.member_functions">Member
|
|
Functions</a>
|
|
</h5>
|
|
<div class="informaltable"><table class="table">
|
|
<colgroup>
|
|
<col>
|
|
<col>
|
|
</colgroup>
|
|
<thead><tr>
|
|
<th>
|
|
<p>
|
|
Name
|
|
</p>
|
|
</th>
|
|
<th>
|
|
<p>
|
|
Description
|
|
</p>
|
|
</th>
|
|
</tr></thead>
|
|
<tbody>
|
|
<tr>
|
|
<td>
|
|
<p>
|
|
<a class="link" href="coroutine/coroutine.html" title="coroutine::coroutine"><span class="bold"><strong>coroutine</strong></span></a> <span class="silver">[constructor]</span>
|
|
</p>
|
|
</td>
|
|
<td>
|
|
<p>
|
|
Constructs a coroutine in its initial state.
|
|
</p>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>
|
|
<p>
|
|
<a class="link" href="coroutine/is_child.html" title="coroutine::is_child"><span class="bold"><strong>is_child</strong></span></a>
|
|
</p>
|
|
</td>
|
|
<td>
|
|
<p>
|
|
Returns true if the coroutine is the child of a fork.
|
|
</p>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>
|
|
<p>
|
|
<a class="link" href="coroutine/is_complete.html" title="coroutine::is_complete"><span class="bold"><strong>is_complete</strong></span></a>
|
|
</p>
|
|
</td>
|
|
<td>
|
|
<p>
|
|
Returns true if the coroutine has reached its terminal state.
|
|
</p>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>
|
|
<p>
|
|
<a class="link" href="coroutine/is_parent.html" title="coroutine::is_parent"><span class="bold"><strong>is_parent</strong></span></a>
|
|
</p>
|
|
</td>
|
|
<td>
|
|
<p>
|
|
Returns true if the coroutine is the parent of a fork.
|
|
</p>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table></div>
|
|
<p>
|
|
The <code class="computeroutput">coroutine</code> class may be used to implement stackless coroutines.
|
|
The class itself is used to store the current state of the coroutine.
|
|
</p>
|
|
<p>
|
|
Coroutines are copy-constructible and assignable, and the space overhead
|
|
is a single int. They can be used as a base class:
|
|
</p>
|
|
<pre class="programlisting">class session : coroutine
|
|
{
|
|
...
|
|
};
|
|
</pre>
|
|
<p>
|
|
or as a data member:
|
|
</p>
|
|
<pre class="programlisting">class session
|
|
{
|
|
...
|
|
coroutine coro_;
|
|
};
|
|
</pre>
|
|
<p>
|
|
or even bound in as a function argument using lambdas or <code class="computeroutput">bind()</code>.
|
|
The important thing is that as the application maintains a copy of the object
|
|
for as long as the coroutine must be kept alive.
|
|
</p>
|
|
<h5>
|
|
<a name="boost_asio.reference.coroutine.h1"></a>
|
|
<span class="phrase"><a name="boost_asio.reference.coroutine.pseudo_keywords"></a></span><a class="link" href="coroutine.html#boost_asio.reference.coroutine.pseudo_keywords">Pseudo-keywords</a>
|
|
</h5>
|
|
<p>
|
|
A coroutine is used in conjunction with certain "pseudo-keywords",
|
|
which are implemented as macros. These macros are defined by a header file:
|
|
</p>
|
|
<pre class="programlisting">#include <boost/asio/yield.hpp>
|
|
</pre>
|
|
<p>
|
|
and may conversely be undefined as follows:
|
|
</p>
|
|
<pre class="programlisting">#include <boost/asio/unyield.hpp>
|
|
</pre>
|
|
<p>
|
|
<span class="bold"><strong>reenter</strong></span>
|
|
</p>
|
|
<p>
|
|
The <code class="computeroutput">reenter</code> macro is used to define the body of a coroutine.
|
|
It takes a single argument: a pointer or reference to a coroutine object.
|
|
For example, if the base class is a coroutine object you may write:
|
|
</p>
|
|
<pre class="programlisting">reenter (this)
|
|
{
|
|
... coroutine body ...
|
|
}
|
|
</pre>
|
|
<p>
|
|
and if a data member or other variable you can write:
|
|
</p>
|
|
<pre class="programlisting">reenter (coro_)
|
|
{
|
|
... coroutine body ...
|
|
}
|
|
</pre>
|
|
<p>
|
|
When <code class="computeroutput">reenter</code> is executed at runtime, control jumps to the location
|
|
of the last <code class="computeroutput">yield</code> or <code class="computeroutput">fork</code>.
|
|
</p>
|
|
<p>
|
|
The coroutine body may also be a single statement, such as:
|
|
</p>
|
|
<pre class="programlisting">reenter (this) for (;;)
|
|
{
|
|
...
|
|
}
|
|
</pre>
|
|
<p>
|
|
<span class="bold"><strong>Limitation:</strong></span> The <code class="computeroutput">reenter</code> macro
|
|
is implemented using a switch. This means that you must take care when using
|
|
local variables within the coroutine body. The local variable is not allowed
|
|
in a position where reentering the coroutine could bypass the variable definition.
|
|
</p>
|
|
<p>
|
|
<span class="bold"><strong>yield <span class="emphasis"><em>statement</em></span></strong></span>
|
|
</p>
|
|
<p>
|
|
This form of the <code class="computeroutput">yield</code> keyword is often used with asynchronous
|
|
operations:
|
|
</p>
|
|
<pre class="programlisting">yield socket_->async_read_some(buffer(*buffer_), *this);
|
|
</pre>
|
|
<p>
|
|
This divides into four logical steps:
|
|
</p>
|
|
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
|
|
<li class="listitem">
|
|
<code class="computeroutput">yield</code> saves the current state of the coroutine.
|
|
</li>
|
|
<li class="listitem">
|
|
The statement initiates the asynchronous operation.
|
|
</li>
|
|
<li class="listitem">
|
|
The resume point is defined immediately following the statement.
|
|
</li>
|
|
<li class="listitem">
|
|
Control is transferred to the end of the coroutine body.
|
|
</li>
|
|
</ul></div>
|
|
<p>
|
|
When the asynchronous operation completes, the function object is invoked
|
|
and <code class="computeroutput">reenter</code> causes control to transfer to the resume point.
|
|
It is important to remember to carry the coroutine state forward with the
|
|
asynchronous operation. In the above snippet, the current class is a function
|
|
object object with a coroutine object as base class or data member.
|
|
</p>
|
|
<p>
|
|
The statement may also be a compound statement, and this permits us to define
|
|
local variables with limited scope:
|
|
</p>
|
|
<pre class="programlisting">yield
|
|
{
|
|
mutable_buffers_1 b = buffer(*buffer_);
|
|
socket_->async_read_some(b, *this);
|
|
}
|
|
</pre>
|
|
<p>
|
|
<span class="bold"><strong>yield return <span class="emphasis"><em>expression</em></span> ;</strong></span>
|
|
</p>
|
|
<p>
|
|
This form of <code class="computeroutput">yield</code> is often used in generators or coroutine-based
|
|
parsers. For example, the function object:
|
|
</p>
|
|
<pre class="programlisting">struct interleave : coroutine
|
|
{
|
|
istream& is1;
|
|
istream& is2;
|
|
char operator()(char c)
|
|
{
|
|
reenter (this) for (;;)
|
|
{
|
|
yield return is1.get();
|
|
yield return is2.get();
|
|
}
|
|
}
|
|
};
|
|
</pre>
|
|
<p>
|
|
defines a trivial coroutine that interleaves the characters from two input
|
|
streams.
|
|
</p>
|
|
<p>
|
|
This type of <code class="computeroutput">yield</code> divides into three logical steps:
|
|
</p>
|
|
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
|
|
<li class="listitem">
|
|
<code class="computeroutput">yield</code> saves the current state of the coroutine.
|
|
</li>
|
|
<li class="listitem">
|
|
The resume point is defined immediately following the semicolon.
|
|
</li>
|
|
<li class="listitem">
|
|
The value of the expression is returned from the function.
|
|
</li>
|
|
</ul></div>
|
|
<p>
|
|
<span class="bold"><strong>yield ;</strong></span>
|
|
</p>
|
|
<p>
|
|
This form of <code class="computeroutput">yield</code> is equivalent to the following steps:
|
|
</p>
|
|
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
|
|
<li class="listitem">
|
|
<code class="computeroutput">yield</code> saves the current state of the coroutine.
|
|
</li>
|
|
<li class="listitem">
|
|
The resume point is defined immediately following the semicolon.
|
|
</li>
|
|
<li class="listitem">
|
|
Control is transferred to the end of the coroutine body.
|
|
</li>
|
|
</ul></div>
|
|
<p>
|
|
This form might be applied when coroutines are used for cooperative threading
|
|
and scheduling is explicitly managed. For example:
|
|
</p>
|
|
<pre class="programlisting">struct task : coroutine
|
|
{
|
|
...
|
|
void operator()()
|
|
{
|
|
reenter (this)
|
|
{
|
|
while (... not finished ...)
|
|
{
|
|
... do something ...
|
|
yield;
|
|
... do some more ...
|
|
yield;
|
|
}
|
|
}
|
|
}
|
|
...
|
|
};
|
|
...
|
|
task t1, t2;
|
|
for (;;)
|
|
{
|
|
t1();
|
|
t2();
|
|
}
|
|
</pre>
|
|
<p>
|
|
<span class="bold"><strong>yield break ;</strong></span>
|
|
</p>
|
|
<p>
|
|
The final form of <code class="computeroutput">yield</code> is used to explicitly terminate the
|
|
coroutine. This form is comprised of two steps:
|
|
</p>
|
|
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
|
|
<li class="listitem">
|
|
<code class="computeroutput">yield</code> sets the coroutine state to indicate termination.
|
|
</li>
|
|
<li class="listitem">
|
|
Control is transferred to the end of the coroutine body.
|
|
</li>
|
|
</ul></div>
|
|
<p>
|
|
Once terminated, calls to <code class="computeroutput">is_complete()</code> return true and the
|
|
coroutine cannot be reentered.
|
|
</p>
|
|
<p>
|
|
Note that a coroutine may also be implicitly terminated if the coroutine
|
|
body is exited without a yield, e.g. by return, throw or by running to the
|
|
end of the body.
|
|
</p>
|
|
<p>
|
|
<span class="bold"><strong>fork <span class="emphasis"><em>statement</em></span></strong></span>
|
|
</p>
|
|
<p>
|
|
The <code class="computeroutput">fork</code> pseudo-keyword is used when "forking" a coroutine,
|
|
i.e. splitting it into two (or more) copies. One use of <code class="computeroutput">fork</code>
|
|
is in a server, where a new coroutine is created to handle each client connection:
|
|
</p>
|
|
<pre class="programlisting">reenter (this)
|
|
{
|
|
do
|
|
{
|
|
socket_.reset(new tcp::socket(my_context_));
|
|
yield acceptor->async_accept(*socket_, *this);
|
|
fork server(*this)();
|
|
} while (is_parent());
|
|
... client-specific handling follows ...
|
|
}
|
|
</pre>
|
|
<p>
|
|
The logical steps involved in a <code class="computeroutput">fork</code> are:
|
|
</p>
|
|
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
|
|
<li class="listitem">
|
|
<code class="computeroutput">fork</code> saves the current state of the coroutine.
|
|
</li>
|
|
<li class="listitem">
|
|
The statement creates a copy of the coroutine and either executes it
|
|
immediately or schedules it for later execution.
|
|
</li>
|
|
<li class="listitem">
|
|
The resume point is defined immediately following the semicolon.
|
|
</li>
|
|
<li class="listitem">
|
|
For the "parent", control immediately continues from the next
|
|
line.
|
|
</li>
|
|
</ul></div>
|
|
<p>
|
|
The functions <code class="computeroutput">is_parent()</code> and <code class="computeroutput">is_child()</code> can be
|
|
used to differentiate between parent and child. You would use these functions
|
|
to alter subsequent control flow.
|
|
</p>
|
|
<p>
|
|
Note that <code class="computeroutput">fork</code> doesn't do the actual forking by itself. It is
|
|
the application's responsibility to create a clone of the coroutine and call
|
|
it. The clone can be called immediately, as above, or scheduled for delayed
|
|
execution using something like <a class="link" href="post.html" title="post"><code class="computeroutput">post</code></a>.
|
|
</p>
|
|
<h5>
|
|
<a name="boost_asio.reference.coroutine.h2"></a>
|
|
<span class="phrase"><a name="boost_asio.reference.coroutine.alternate_macro_names"></a></span><a class="link" href="coroutine.html#boost_asio.reference.coroutine.alternate_macro_names">Alternate
|
|
macro names</a>
|
|
</h5>
|
|
<p>
|
|
If preferred, an application can use macro names that follow a more typical
|
|
naming convention, rather than the pseudo-keywords. These are:
|
|
</p>
|
|
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
|
|
<li class="listitem">
|
|
<code class="computeroutput">BOOST_ASIO_CORO_REENTER</code> instead of <code class="computeroutput">reenter</code>
|
|
</li>
|
|
<li class="listitem">
|
|
<code class="computeroutput">BOOST_ASIO_CORO_YIELD</code> instead of <code class="computeroutput">yield</code>
|
|
</li>
|
|
<li class="listitem">
|
|
<code class="computeroutput">BOOST_ASIO_CORO_FORK</code> instead of <code class="computeroutput">fork</code>
|
|
</li>
|
|
</ul></div>
|
|
<h5>
|
|
<a name="boost_asio.reference.coroutine.h3"></a>
|
|
<span class="phrase"><a name="boost_asio.reference.coroutine.requirements"></a></span><a class="link" href="coroutine.html#boost_asio.reference.coroutine.requirements">Requirements</a>
|
|
</h5>
|
|
<p>
|
|
<span class="emphasis"><em>Header: </em></span><code class="literal">boost/asio/coroutine.hpp</code>
|
|
</p>
|
|
<p>
|
|
<span class="emphasis"><em>Convenience header: </em></span><code class="literal">boost/asio.hpp</code>
|
|
</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 © 2003-2021 Christopher
|
|
M. Kohlhoff<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="const_buffers_1/value_type.html"><img src="../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../reference.html"><img src="../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../boost_asio.html"><img src="../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="coroutine/coroutine.html"><img src="../../../../doc/src/images/next.png" alt="Next"></a>
|
|
</div>
|
|
</body>
|
|
</html>
|