Hello
I have a very basic macro I made
#[proc_macro_attribute]
pub fn main(_attr: TokenStream, item: TokenStream) -> TokenStream {
let ident = item.clone().into_iter().nth(2).unwrap();
quote! {
static mut MAIN: Option<::core::pin::Pin<::alloc::boxed::Box<dyn Future<Output = ()>>>> = None;
static mut ENDED: bool = false;
#[unsafe(no_mangle)]
extern "C" fn resume() {
unsafe {
if ENDED { return }
if MAIN.is_none() {
MAIN = Some(::alloc::boxed::Box::pin($ident()));
}
let wk = ::core::task::Waker::noop();
let mut cx = ::core::task::Context::from_waker(wk);
match MAIN.as_mut().unwrap_unchecked().as_mut().poll(&mut cx) {
::core::task::Poll::Ready(_) => ENDED = true,
::core::task::Poll::Pending => {},
}
}
}
$item
}
}
Which is used like this
#[rt::main]
async fn main() {
loop {
rt::sleep().await
}
}
Resume is called by requestAnimationFrame in the browser, so I want to avoid freezing the entire browser tab, but still have a normal looking main function as Rust is of course really unhappy with managing this global coroutine-like behavior manually
sleep
just returns an empty future.
I think I got something very wrong though since the browser tab very much freezes