When using pre-coroutine asio interface I could dispatch an async function in the current execution context (main function) and let it finish in the ctx
.
#include <iostream>
#include <asio.hpp>
using namespace std;
using namespace literals;
int main() {
asio::io_context ctx;
asio::steady_timer t(ctx, 2s);
asio::dispatch([&](){
cout << "inside coro before wait" << endl;
t.async_wait([](asio::error_code){
cout << "inside coro after wait" << endl;
});
});
cout << "starting ctx.run()" << endl;
ctx.run();
}
$ ./sol
inside coro before wait
starting ctx.run()
inside coro after wait
I would like to replicate this with asio::awaitable
but dispatch
doesn't support coroutines.
On the other hand co_spawn
only adds the coroutine to the context, and doesn't initiate it immediately.
I could use ctx.poll()
/ctx.run_one()
but the coroutine would have to be the only one ready to execute or at least the first one.
Anwser
If I'm not mistaken the only way to start a coroutine (from outside of coroutine) is using asio::co_spawn(executor, awaitable, token)
. In contrast to dispatch
, co_spawn
takes an executor as an argument, where as @sehe said dispatch
uses associated executor. So to answer my question on how to start a coroutine immediately is to run it in asio::system_executor()
.
#include <bits/stdc++.h>
#include <asio.hpp>
using namespace std;
using namespace literals;
int main() {
asio::io_context ctx;
asio::co_spawn(asio::system_executor(), [&]() -> asio::awaitable<void> {
cout << "inside coro before wait" << endl;
asio::steady_timer t(ctx, 2s);
co_await t.async_wait(asio::use_awaitable);
cout << "inside coro after wait" << endl;
co_return;
}, asio::detached);
cout << "starting ctx.run()" << endl;
ctx.run();
}
$ ./sol
inside coro before wait
starting ctx.run()
inside coro after wait