#[allow(unused_imports)]
use cfg_if::cfg_if;
use futures::Future;
cfg_if! {
if #[cfg(not(any(target_arch = "wasm32", target_os = "solana")))] {
pub mod native {
pub use super::*;
pub use tokio::task::yield_now;
pub use tokio::task::yield_now as yield_executor;
pub use tokio::time::sleep;
pub fn spawn<F, T>(future: F)
where
F: Future<Output = T> + Send + 'static,
T: Send + 'static,
{
tokio::task::spawn(async {
future.await
});
}
}
pub use native::*;
}
}
pub mod wasm {
pub use super::*;
pub fn spawn<F, T>(_future: F)
where
F: Future<Output = T> + 'static,
T: 'static,
{
cfg_if::cfg_if! {
if #[cfg(target_arch = "wasm32")] {
async_std::task::block_on(async move { _future.await });
} else {
panic!("workflow_core::task::wasm::spawn() is not allowed on non-wasm target");
}
}
}
cfg_if! {
if #[cfg(target_arch = "wasm32")] {
use std::sync::{Arc, Mutex};
use wasm_bindgen::prelude::*;
use instant::Duration;
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen (catch, js_name = setTimeout)]
pub fn set_timeout(closure: &Closure<dyn FnMut()>, timeout: u32) -> std::result::Result<u32, JsValue>;
#[wasm_bindgen (catch, js_name = clearTimeout)]
pub fn clear_timeout(interval: u32) -> std::result::Result<(), JsValue>;
#[wasm_bindgen(js_name = requestAnimationFrame)]
fn request_animation_frame(callback:js_sys::Function);
}
type SleepClosure = Closure<dyn FnMut()>;
pub async fn sleep(duration : Duration) {
let (sender, receiver) = crate::channel::oneshot::<()>();
let interval = {
let mutex_init : Arc<Mutex<Option<SleepClosure>>> = Arc::new(Mutex::new(None));
let mutex_clear = mutex_init.clone();
let closure = Closure::new(move ||{
sender.try_send(()).unwrap();
*mutex_clear.clone().lock().unwrap() = None;
});
let interval = set_timeout(&closure, duration.as_millis() as u32).unwrap();
*mutex_init.lock().unwrap() = Some(closure);
interval
};
receiver.recv().await.unwrap();
clear_timeout(interval).unwrap();
}
pub use async_std::task::yield_now;
pub async fn yield_executor() {
if !unsafe { REQUEST_ANIMATION_FRAME_INITIALIZED } {
init_yield();
unsafe { REQUEST_ANIMATION_FRAME_INITIALIZED = true };
} else {
let promise = js_sys::Promise::new(&mut |res, _|{
request_animation_frame(res);
});
let _ = wasm_bindgen_futures::JsFuture::from(promise).await;
}
}
static mut REQUEST_ANIMATION_FRAME_INITIALIZED: bool = false;
fn init_yield(){
let _ = js_sys::Function::new_no_args("
if (!this.requestAnimationFrame){
if (this.setImmediate)
this.requestAnimationFrame = (callback)=>setImmediate(callback)
else
this.requestAnimationFrame = (callback)=>setTimeout(callback, 0)
}
")
.call0(&JsValue::undefined());
}
} else {
pub use async_std::task::sleep;
pub use async_std::task::yield_now;
}
}
}
#[cfg(target_arch = "wasm32")]
pub use wasm::*;