hreads 0.14.0

Multithreading primitives.
Documentation
#[cfg(not_wasm)]
use log::error;

#[cfg(wasm)]
pub fn spawn<F>(future: F)
where F: Future<Output = ()> + 'static {
    wasm_bindgen_futures::spawn_local(future);
}

#[cfg(not_wasm)]
pub fn spawn<F, O>(future: F)
where
    F: Future<Output = O> + Send + 'static,
    O: Send + 'static, {
    tokio::spawn(future);
}

#[cfg(not_wasm)]
pub fn log_spawn<O>(future: impl Future<Output = anyhow::Result<O>> + Send + 'static)
where O: Send + 'static {
    tokio::spawn(async {
        match tokio::spawn(future).await {
            Ok(exec_result) => {
                if let Err(exec_result) = exec_result {
                    error!("Future execution error: {exec_result}");
                }
            }
            Err(join_err) => {
                error!("Join error: {join_err}");
            }
        }
    });
}

pub fn block_on<F>(future: F)
where F: Future<Output = ()> + 'static {
    #[cfg(wasm)]
    wasm_bindgen_futures::spawn_local(future);
    #[cfg(not_wasm)]
    async_std::task::block_on(future);
}

#[cfg(not_wasm)]
pub fn unasync<F, Out>(future: F) -> Out
where F: Future<Output = Out> {
    async_std::task::block_on(future)
}

pub async fn sleep(duration: f32) {
    #[cfg(not_wasm)]
    async_std::task::sleep(std::time::Duration::from_secs_f32(duration)).await;
    #[cfg(wasm)]
    gloo_timers::future::TimeoutFuture::new((duration * 1000.0) as _).await;
}

pub fn now() -> f64 {
    #[cfg(target_arch = "wasm32")]
    {
        web_sys::window()
            .expect("should have a window")
            .performance()
            .expect("should have performance")
            .now()
            / 1000.0
    }

    #[cfg(not(target_arch = "wasm32"))]
    {
        use std::time::{SystemTime, UNIX_EPOCH};

        SystemTime::now()
            .duration_since(UNIX_EPOCH)
            .expect("time went backwards")
            .as_secs_f64()
    }
}

pub fn busy_sleep(seconds: f32) {
    let start = now();
    let target = start + f64::from(seconds);

    while now() < target {
        std::hint::spin_loop();
    }
}

#[cfg(test)]
mod test {

    use wasm_bindgen_test::wasm_bindgen_test;

    use crate::{busy_sleep, now};

    #[wasm_bindgen_test(unsupported = test)]
    fn test_busy_sleep() {
        let start = now();
        busy_sleep(0.2);
        let elapsed = now() - start;

        assert!(elapsed >= 0.2);
        assert!(elapsed < 0.25);
    }
}