Skip to content

Re-implement reactor#35

Merged
pchickey merged 12 commits intomainfrom
pch/new_reactor
Dec 18, 2024
Merged

Re-implement reactor#35
pchickey merged 12 commits intomainfrom
pch/new_reactor

Conversation

@pchickey
Copy link
Contributor

@pchickey pchickey commented Dec 6, 2024

In short: the runtime's reactor has been redesigned so that a Wasi Pollable can be reused to await for more than one readiness event.

Prior to this PR, the only way to wait for a pollable is with Reactor's async fn wait_for(&self, pollable: Pollable). (This method still exists for compatibility, but will dissapear in future PRs after the rest of the repo is ported.) Because this method takes ownership of the Pollable, it can only be used to await for readiness once per Pollable. In Wasi, a Pollable can signal readiness for the entire lifetime of the parent resource. Wstd's failure to reuse results in lots of unnecessary churn calling subscribe and [drop]pollable import calls for each await.

The new Reactor method fn schedule(&self, pollable: Pollable) -> AsyncPollable gives a new AsyncPollable type, which implements Clone and has a (notional) async fn wait_for(&self) method. This means that each Pollable can now, upon being transferred to the Reactor via schedule, be reused in many futures given by AsyncPollable::wait_for. The legacy Reactor::wait_for is now implemented with a Reactor::schedule and immediate AsyncPollable::wait_for.

One knock-on effect is that a Pollable remains owned by the Reactor for as long as there is a live AsyncPollable pointing to it. However, its liveness doesn't necessarily respond to the user's program awaiting on its readiness. So, rather than calling wasi::io::poll::poll on the entire set of owned Polllables, we now have to track which Pollable has Future being polled, and only poll on that subset. This leads to a second layer of registration, private to the internals of this crate, called Waitee, wherein any of the WaitFor futures given by the AsyncPollable::wait_for method registers a Waiter with the Reactor during the first Future::poll call (if it does not immediately result in Ready). To handle cancellation properly, the Waitee is deregistered when the Future is dropped.

A further knock-on effect of this change is that it is no longer appropriate for a Future::poll call to call Reactor::schedule, including via the legacy Reactor::wait_for, because that will produce a registration of the Pollable which will only live as long as the poll call. This meant that the Timer had to be restructured to hold a long-lived AsyncPollable, and have a notional async fn wait(&self) that returns a Future, rather than having its own impl Future.

@pchickey pchickey changed the title Pch/new reactor Re-implement reactor Dec 18, 2024
@pchickey pchickey marked this pull request as ready for review December 18, 2024 23:13
@pchickey
Copy link
Contributor Author

@yoshuawuyts and I went through the majority of these changes together and gave it a verbal review to merge.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant