On Wed, Jul 26, 2023 at 2:32 AM Christian Mazakas via Boost
Not if we want users. Coroutines ate much more relevant at this time.
The problem is, this definitely isn't true.
Users already have Asio's `use_awaitable`. A coroutine library that uses Asio as its event loop is basically a lateral move from, well, just using Asio with `co_spawn` and `use_awaitable`.
Asio's awaitable are not anywhere near a complete coroutine library. They are (by design) meant to work within asio to compose async operations in a specific way. You can't "escape" awaitables, i.e. you can't co_await anything else than an asio::awaitable. This was one of the reasons I wrote experimental::coro (that can co_yield) and now you got two, and since chris addred co_compose three different coroutine types that can't efficiently interact with each other.
This kind of functionality should never touch the standard because it ties a coroutine to an execution context. In fact, I'd argue this library's biggest mistake is doing exactly that.
It's a mistake shared by all asynchronous coroutine libraries. It's unavoidable. It would be possible for async to provide it's own type erased type for the scheduler. But that would effectively be reimplementing asio::any_io_executor in immature form, for the great gain that we don't need to include one header from another boost library. I did really consider that, but since any_io_executor allows me to do that already, I fail to see the point.
What I'm thinking of is something like cppcoro's task type, a task type that can only be co_await'd by a parent coroutine. To this end, `cppcoro::task<T>` can appear in interfaces and then runtime authors are free to invoke this via their own runtime-specific coroutine types. cppcoro's task stores the type-erased coroutine_handle when it's transformed into an awaitable so it works with all parent coroutine types.
That is what async does.
I think we need vocabulary types like that, with schedulers set alongside them. It worries me to see an executor directly tied to a coroutine when it's really not required, let alone purported that this should actually be a standardized practice. There's definitely room for innovation in the coroutine space but it's hard to argue for a "coroutine library" that I can't even use without bringing in Asio.
It is required as soon as you write asynchronous code that does multiple things at once. async brings in the executor part of async, so it doesn't need to create it's own, like cppcoro does for example. In that case I reproduced well-tested & seasoned code from asio with my own greenfield impl to avoid an include of a header that's already present (because boost) for an immature implementation that's almost the same while losing the easy usability with boost.beast, boost.process, boost.mysql & boost.redis. I know you want to use io_uring and you seem to think you can't. What's the issue with creating your own awaitables that use io_uring and co_await them from async's coroutines?