selium_kernel/
guest_async.rs1use std::sync::Arc;
2
3use tokio::{select, sync::Notify};
4use wasmtime::{Caller, Linker};
5
6use crate::{KernelError, mailbox::GuestMailbox, registry::InstanceRegistry};
7
8pub struct GuestAsync {
10 shutdown: Arc<Notify>,
11}
12
13impl GuestAsync {
14 pub fn new(notify: Arc<Notify>) -> Self {
16 Self { shutdown: notify }
17 }
18
19 pub fn link(&self, linker: &mut Linker<InstanceRegistry>) -> Result<(), KernelError> {
21 let shutdown = Arc::clone(&self.shutdown);
22 linker.func_wrap_async(
23 "selium::async",
24 "yield_now",
25 move |caller: Caller<'_, InstanceRegistry>, ()| {
26 let mailbox_ref: &'static GuestMailbox =
27 caller.data().mailbox().expect("guest mailbox missing");
28 let shutdown = Arc::clone(&shutdown);
29 Box::new(async move {
30 loop {
31 if mailbox_ref.is_closed() || mailbox_ref.is_signalled() {
32 break;
33 }
34 select! {
35 _ = shutdown.notified() => {
36 break;
37 }
38 _ = mailbox_ref.wait_for_signal() => {}
39 }
40 }
41 })
42 },
43 )?;
44 Ok(())
45 }
46
47 pub fn shutdown(&self) {
49 self.shutdown.notify_waiters();
50 }
51}