![]() |
The spawn() function is a high-level wrapper
for running stackful coroutines. The spawn() function enables programs to implement
asynchronous logic in a synchronous manner, as shown in the following example:
asio::spawn(my_strand, do_echo, asio::detached); // ... void do_echo(asio::yield_context yield) { try { char data[128]; for (;;) { std::size_t length = my_socket.async_read_some( asio::buffer(data), yield); asio::async_write(my_socket, asio::buffer(data, length), yield); } } catch (std::exception& e) { // ... } }
The context switching used by these coroutines is implemented in assembly, using clang or gcc on an LP64 data model, for:
Linux - x86-64, AArch64 macOS - x86-64, AArch64
Other targets require the Boost.Context library.
The first argument to spawn() may be an executor or execution context.
This argument determines the context in which the coroutine is permitted
to execute. For example, a server's per-client object may consist of multiple
coroutines; they should all run on the same strand
so that no explicit synchronisation is required.
The second argument is a function object with signature:
void coroutine(asio::yield_context yield);
that specifies the code to be run as part of the coroutine. The parameter
yield may be passed to
an asynchronous operation in place of the completion handler, as in:
std::size_t length = my_socket.async_read_some( asio::buffer(data), yield);
This starts the asynchronous operation and suspends the coroutine. The coroutine will be resumed automatically when the asynchronous operation completes.
Where an asynchronous operation's handler signature has the form:
void handler(asio::error_code ec, result_type result);
the initiating function returns the result_type. In the async_read_some
example above, this is size_t.
If the asynchronous operation fails, the error_code
is converted into a system_error
exception and thrown.
Where a handler signature has the form:
void handler(asio::error_code ec);
the initiating function returns void.
As above, an error is passed back to the coroutine as a system_error
exception.
To collect the error_code
from an operation, rather than have it throw an exception, associate the
output variable with the yield_context
as follows:
asio::error_code ec; std::size_t length = my_socket.async_read_some( asio::buffer(data), yield[ec]);
Note: if spawn() is used with a specified executor of
type Executor, the function
object signature is actually:
void coroutine(asio::basic_yield_context<Executor> yield);
spawn, yield_context, basic_yield_context, Spawn example (C++11), Stackless Coroutines.