cppcoro icon indicating copy to clipboard operation
cppcoro copied to clipboard

Add concurrency abstraction for server connection-handling workloads

Open lewissbaker opened this issue 7 years ago • 5 comments

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.

lewissbaker avatar Aug 25 '17 21:08 lewissbaker

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));
}

lewissbaker avatar Aug 26 '17 11:08 lewissbaker

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?

akoolenbourke avatar Sep 26 '17 01:09 akoolenbourke

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.

lewissbaker avatar Sep 26 '17 13:09 lewissbaker

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).

akoolenbourke avatar Sep 27 '17 00:09 akoolenbourke

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 :(.

saurik avatar Apr 08 '19 04:04 saurik