In short:
- When
spawn() is called, Boost.Asio does some configuration work, and then uses strand to dispatch() internal handler that creates a coroutine using a function provided by the user as an entry point. Under certain conditions, the internal handler may be called in the spawn() call, and in other cases it will be sent to io_service for a deferred call. - The corporation pauses until the operation completes and the completion handler is called,
io_service is destroyed, or Boost.Asio detects that the coroutine has been suspended without the possibility of resuming it, after which Boost.Asio will destroy the coroutine.
As mentioned above, when calling spawn() Boost.Asio does some configuration work, and then uses strand to dispatch() internal handler that creates a coroutine using a function provided by the user as an entry point. When the yield_context is passed as an asynchronous operation handler, Boost.Asio will immediately after initializing the asynchronous operation with the completion handler, which will copy the results and resume the coroutine. The previously mentioned thread belongs to the coroutine, which is used to guarantee the return of income before renewal. Consider a simple example demonstrating spawn() :
#include <iostream>
The above example outputs:
Start wait Other work Woke up
Here is an attempt to illustrate the execution of an example. Ways in | indicate an active stack,: indicates a paused stack, and arrows are used to indicate a transfer of control:
boost::asio::io_service io_service; boost::asio::spawn(io_service, &my_work); `-- dispatch a coroutine creator into the io_service. io_service.run(); |-- invoke the coroutine creator | handler. | |-- create and jump into | | into coroutine ----> my_work() : : |-- post &other_work onto : : | the io_service : : |-- create timer : : |-- set timer expiration : : |-- cout << "Start wait" << endl; : : |-- timer.async_wait(yield) : : | |-- create error_code on stack : : | |-- initiate async_wait operation, : : | | passing in completion handler that : : | | will resume the coroutine | `-- return <---- | |-- yield |-- io_service has work (the : : | &other_work and async_wait) : : |-- invoke other_work() : : | `-- cout << "Other work" : : | << endl; : : |-- io_service still has work : : | (the async_wait operation) : : | ...async wait completes... : : |-- invoke completion handler : : | |-- copies error_code : : | | provided by service : : | | into the one on the : : | | coroutine stack : : | |-- resume ----> | `-- return error code : : |-- cout << "Woke up." << endl; : : |-- exiting my_work block, timer is : : | destroyed. | `-- return <---- `-- coroutine done, yielding `-- no outstanding work in io_service, return.
source share