cppcoro
cppcoro copied to clipboard
Add concurrency abstraction for server connection-handling workloads
The when_all
concurrency primitive currently requires that all of the tasks are created up front whereas with server workloads we'll typically be dynamically starting new tasks to handle the connections as clients connect.
Consider adding some kind of task_pool
or possibly when_all_ready
overload that takes async_generator<task<>>
and returns a task<>
that can start new tasks as they are created but still ensure there is no potential for dangling tasks.
Example usage of a hypothetical when_all_ready
implementation for this:
async_generator<socket> accept_connections(socket listeningSocket);
task<> handle_connection(socket s);
task<> when_all_ready(async_generator<task<>> tasks);
task<> run(socket listeningSocket)
{
return when_all_ready(
accept_connections(std::move(listeningSocket))
| fmap(handle_connection));
}
Interesting idea. Our use case for something along these lines would be the need to spawn different types of processing pipelines at will. These might entail HTTP tunnelling (With or without SSL inspection), web serving, web proxy and many other network protocols.
On a related note, is there any intention of making cppcoro compatible with ASIO?
On a related note, is there any intention of making cppcoro compatible with ASIO?
I don't have any current plans to add support for ASIO as far as adding ability to await ASIO async ops. Cppcoro will provide an alternative to ASIO. Having said that if someone adds support for awaiting ASIO ops to ASIO then there shouldn't be any reason why they couldn't be used in conjunction with other parts of cppcoro.
I've been through and made the relevant files from co_await branch of ASIO buildable with the networking TS ASIO (Master branch) and it works "well". However since experimenting a bit more I think I could forgo all the ASIO coroutine stuff completely by simply having my own awaitable(s) that do callback-style ASIO ops and effectively just resume on completion of the op. In fact I wonder if I can just return your task<> objects for this and leverage the rest of the library. Doing my own awaitables for this does mean I would likely sacrifice the hooks for allocation etc but that might not be too much problem for what I need. I can still use them in the lower layers (stranded handler etc).
Has there been any more thought put into implementing this, or maybe a place where I can read more about how the concept of doing structured concurrency without detached tasks is supposed to work ;P? I'm having a hard time conceptualizing how to use this library to do complex work (stuff that interacts with other libraries and handles multiple concurrent workloads) without a feature similar to this (which I'm used to having from all of the other pseudo-threading environments I've worked with).
Like here: I get a callback from some random library I'm using saying "start doing something" and I'm expected to call some other function when I'm done... this seems like a really basic asynchronous use case (maybe even the most simple one I can contemplate); yet, even after spending months working with this library and after having scanned the documentation a million times over, and even after managing to pull off some interesting workarounds for some of my more annoying integration tasks (such as writing an adapter to let me co_await Boost asio operations from within a cppcoro::task so that I can use Boost Beast, as I seriously doubt cppcoro is going to get an asynchronous coroutine HTTP/SSL/WebSockets implementation any time soon ;P), I still have no clue how to do this really basic operation of "start working on something due to a callback and then call another function when I'm done" without spawning a real OS thread, which kind of defeats the entire purpose of coroutines :(.