I am unable to form a mental picture of how the control flow happens with spawn.
When I call
spawn(io_service, my_coroutine)
, does it add a new handler to theio_service
queue that wraps a call to themy_coroutine
?When inside the coroutine I call an async function passing it my
yield_context
, does it suspend the coroutine until the async operation completes?void my_coroutine(yield_context yield) { ... async_foo(params ..., yield); ... // control comes here only once the async_foo operation completes }
What I don't understand is how we avoid waits. Say if my_coroutine
serves a TCP connection, how are other instances of my_coroutine
invoked while on particular instance is suspended, waiting for async_foo
to complete?
In short:
spawn()
is invoked, Boost.Asio performs some setup work and then will use astrand
todispatch()
an internal handler that creates a coroutine using the user provided function as an entry point. Under certain conditions, the internal handler can be will be invoked within the call tospawn()
, and other times it will be posted to theio_service
for deferred invocation.io_service
is destroyed, or Boost.Asio detects that the coroutine has been suspended with no way to resume it, at which point Boost.Asio will destroy the coroutine.As mentioned above, when
spawn()
is invoked, Boost.Asio performs some setup work and then will use astrand
todispatch()
an internal handler that creates a coroutine using the user provided function as an entry point. When theyield_context
object is passed as a handler to asynchronous operations, Boost.Asio will yield immediately after initiating the asynchronous operation with a completion handler that will copy results and resume the coroutine. The previously mentioned strand is owned by the coroutine is used to guarantee the yield occurs before resume. Lets consider a simple example demonstratingspawn()
:The above example outputs:
Here is an attempt to illustrate the execution of the example. Paths in
|
indicate the active stack,:
indicates the suspended stack, and arrows are used to indicate transfer of control: