Skip to main content

freya_core/io/
timer.rs

1use std::time::Duration;
2
3/// Waits for the given duration.
4#[cfg(not(target_os = "emscripten"))]
5pub async fn timer(duration: Duration) {
6    async_io::Timer::after(duration).await;
7}
8
9/// Waits for the given duration, on a browser timer.
10#[cfg(target_os = "emscripten")]
11pub async fn timer(duration: Duration) {
12    use std::ffi::c_void;
13
14    use futures_channel::oneshot::{
15        Sender,
16        channel,
17    };
18
19    unsafe extern "C" {
20        fn emscripten_async_call(
21            callback: extern "C" fn(*mut c_void),
22            argument: *mut c_void,
23            millis: i32,
24        );
25    }
26
27    extern "C" fn wake(argument: *mut c_void) {
28        let sender = unsafe { Box::from_raw(argument.cast::<Sender<()>>()) };
29        sender.send(()).ok();
30    }
31
32    let (sender, receiver) = channel::<()>();
33    let argument = Box::into_raw(Box::new(sender)).cast();
34    let millis = duration.as_millis().min(i32::MAX as u128) as i32;
35
36    unsafe { emscripten_async_call(wake, argument, millis) };
37
38    receiver.await.ok();
39}