Skip to main content

libsurfer/
async_util.rs

1/// Code related to asynchronous features.
2///
3/// As wasm32 and most other platforms behave differently, there are these wrappers.
4use futures_core::Future;
5use serde::Deserialize;
6use tracing::info;
7
8use crate::spawn;
9
10#[derive(Debug, Deserialize, PartialEq, Eq)]
11pub enum AsyncJob {
12    SaveState,
13}
14
15// Platform-dependent trait alias for futures that can be spawned
16#[cfg(target_arch = "wasm32")]
17pub trait SpawnableFuture: Future<Output = ()> + 'static {}
18#[cfg(target_arch = "wasm32")]
19impl<F> SpawnableFuture for F where F: Future<Output = ()> + 'static {}
20
21#[cfg(not(target_arch = "wasm32"))]
22pub trait SpawnableFuture: Future<Output = ()> + Send + 'static {}
23#[cfg(not(target_arch = "wasm32"))]
24impl<F> SpawnableFuture for F where F: Future<Output = ()> + Send + 'static {}
25
26// Wasm doesn't seem to support std::thread, so this spawns a thread where we can
27// but runs the work sequentially where we can not.
28pub fn perform_work<F>(f: F)
29where
30    F: FnOnce() + Send + 'static,
31{
32    spawn! {async {
33        info!("Starting async task");
34        f();
35    }}
36    info!("Returning from perform work");
37}
38
39// Spawn an async task on the appropriate runtime.
40// NOTE: wasm32 does not require a Send bound, but not-wasm32 does.
41pub fn perform_async_work<F>(f: F)
42where
43    F: SpawnableFuture,
44{
45    spawn!(f);
46}
47
48#[cfg(target_arch = "wasm32")]
49pub async fn sleep_ms(delay: u64) {
50    use wasm_bindgen_futures::js_sys;
51
52    let mut cb = |resolve: js_sys::Function, _reject: js_sys::Function| {
53        web_sys::window()
54            .unwrap()
55            .set_timeout_with_callback_and_timeout_and_arguments_0(&resolve, delay as i32)
56            .unwrap();
57    };
58
59    let p = js_sys::Promise::new(&mut cb);
60
61    wasm_bindgen_futures::JsFuture::from(p).await.unwrap();
62}
63
64#[cfg(not(target_arch = "wasm32"))]
65pub async fn sleep_ms(delay_ms: u64) {
66    tokio::time::sleep(tokio::time::Duration::from_millis(delay_ms)).await;
67}
68
69#[macro_export]
70macro_rules! spawn {
71    ($task:expr) => {
72        #[cfg(not(target_arch = "wasm32"))]
73        tokio::spawn($task);
74        #[cfg(target_arch = "wasm32")]
75        wasm_bindgen_futures::spawn_local($task);
76    };
77}