Skip to content

Commit b4d62a4

Browse files
rvolosatovsdicej
andauthored
feat(rust): do not yield to the host while guest tasks are ready (#1197)
* feat(rust): do not yield to the host while guest tasks are ready Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net> * Update crates/guest-rust/rt/src/async_support.rs --------- Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net> Co-authored-by: Joel Dice <joel.dice@fermyon.com>
1 parent 1d0f202 commit b4d62a4

File tree

1 file changed

+24
-14
lines changed

1 file changed

+24
-14
lines changed

crates/guest-rust/rt/src/async_support.rs

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#![allow(static_mut_refs)]
33

44
extern crate std;
5+
use core::sync::atomic::{AtomicBool, Ordering};
56
use std::alloc::{self, Layout};
67
use std::any::Any;
78
use std::boxed::Box;
@@ -78,26 +79,29 @@ pub fn with_entry<T>(handle: u32, fun: impl FnOnce(hash_map::Entry<'_, u32, Hand
7879
fun(unsafe { HANDLES.entry(handle) })
7980
}
8081

81-
fn dummy_waker() -> Waker {
82-
struct DummyWaker;
83-
84-
impl Wake for DummyWaker {
85-
fn wake(self: Arc<Self>) {}
86-
}
87-
88-
static WAKER: Lazy<Arc<DummyWaker>> = Lazy::new(|| Arc::new(DummyWaker));
89-
90-
WAKER.clone().into()
91-
}
92-
9382
/// Poll the specified task until it either completes or can't make immediate
9483
/// progress.
9584
unsafe fn poll(state: *mut FutureState) -> Poll<()> {
85+
#[derive(Default)]
86+
struct FutureWaker(AtomicBool);
87+
88+
impl Wake for FutureWaker {
89+
fn wake(self: Arc<Self>) {
90+
Self::wake_by_ref(&self)
91+
}
92+
93+
fn wake_by_ref(self: &Arc<Self>) {
94+
self.0.store(true, Ordering::Relaxed)
95+
}
96+
}
97+
9698
loop {
9799
if let Some(futures) = (*state).tasks.as_mut() {
98100
let old = CURRENT;
99101
CURRENT = state;
100-
let poll = futures.poll_next_unpin(&mut Context::from_waker(&dummy_waker()));
102+
let waker: Arc<FutureWaker> = Arc::default();
103+
let poll =
104+
futures.poll_next_unpin(&mut Context::from_waker(&Arc::clone(&waker).into()));
101105
CURRENT = old;
102106

103107
if SPAWNED.is_empty() {
@@ -107,7 +111,13 @@ unsafe fn poll(state: *mut FutureState) -> Poll<()> {
107111
(*state).tasks = None;
108112
break Poll::Ready(());
109113
}
110-
Poll::Pending => break Poll::Pending,
114+
Poll::Pending => {
115+
// TODO: Return `CallbackCode.YIELD` (see https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md#canon-lift)
116+
// to the host before polling again once a host implementation exists to support it.
117+
if !waker.0.load(Ordering::Relaxed) {
118+
break Poll::Pending;
119+
}
120+
}
111121
}
112122
} else {
113123
futures.extend(SPAWNED.drain(..));

0 commit comments

Comments
 (0)