nrc / portable-interoperable

Async fundamentals initiative: portable and interoperable
Apache License 2.0
75 stars 0 forks source link

Tracking issue: an API for executors #2

Open nrc opened 2 years ago

nrc commented 2 years ago

A key goal is to be able to easily switch between executors. Currently, there is no standardised interface for executors, so how a program interacts with an executor is unique to each executor. On the bright side, most executors offer similar APIs (e.g., a spawn function). However, there are differences in the details and some constraints which are not reflected simply by function signatures (e.g., Tokio's requirement that all async code is within the context of an executor).

One approach would be to define a Spawn or Executor trait in std. In addition, there must be a way to 'plug in' the executor, since executors tend to be somewhat global, rather than passed around. We can follow follow the global allocator pattern, but this is not a complete solution since some programs require multiple executors.

Open issues

ibraheemdev commented 2 years ago

Just leaving a list of previously discussed ideas:

yoshuawuyts commented 2 years ago

The most promising direction at the moment would be: "with clauses". This project is still getting started, but if successful would enable authoring a general mechanism by which a runtime can be constructed, passed, and overwritten. An introduction blog post for this is currently in the works, and it's expected this will become a sub-group under the async foundations WG.

Though that doesn't mean that we can't do any work while with clauses are being researched: it'd be great to have a survey which covers all known spawn methods and scheduling techniques across runtimes. To my knowledge this does not exist yet, and is a requisite for any interface design.

ibraheemdev commented 2 years ago

with clauses themselves don't solve the interop problem, we still need an API for executors.

yoshuawuyts commented 2 years ago

with clauses themselves don't solve the interop problem, we still need an API for executors.

That is true, but their design greatly will inform what an executor API would look like. It doesn't seem fruitful to start designing a generalized async runtime APIs before we have clarity if and how with clauses will integrate into the language.

That's why I'm recommending we start by doing a survey to gather requirements. So once we have more clarity on with clauses, we're actually able to start designing and experimenting.

nrc commented 2 years ago

I feel like with is important for some issues, but orthogonal to others. Obviously with clauses would affect how executors are passed around and interacted with, but they seem mostly orthogonal to the question of how an interface should be specified. In other words, I think the tasks of designing with clauses and designing an API for executors are mostly parallelisable.

ericniebler commented 2 years ago

I encourage anyone thinking about designing an async abstraction to read this blog post about structured concurrency and the problems with spawn-like interfaces:

https://vorpus.org/blog/notes-on-structured-concurrency-or-go-statement-considered-harmful/

And then check out the direction standard C++ is heading:

https://wg21.link/P2300

Disclaimer: I am one of the authors of P2300, but not the blog post.

NobodyXu commented 2 years ago

I have written up a draft for the APIs of executors in #13 , feel free to have a look at it.

I also agree that "with clauses" is the best way to plug in an executor, it would enable to user to add trait bound to specify the capabilities they need.