#[cfg(all(target_arch = "wasm32", not(doc), not(target_feature = "atomics")))]
compile_error!("web-spawn requires the `atomics` and `bulk-memory` features to be enabled");
mod spawner;
mod thread;
pub(crate) mod utils;
mod worker;
pub use spawner::Spawner;
pub use thread::Builder;
use std::{any::Any, sync::OnceLock};
use crossbeam_channel::Receiver;
use futures::channel::mpsc::UnboundedSender;
use js_sys::Promise;
use wasm_bindgen::prelude::*;
pub(crate) type Closure = dyn FnOnce() + Send;
pub(crate) static SENDER: OnceLock<UnboundedSender<(Builder, Box<Closure>)>> = OnceLock::new();
#[cfg_attr(not(feature = "no-bundler"), wasm_bindgen(module = "/js/spawn.js"))]
#[cfg_attr(
feature = "no-bundler",
wasm_bindgen(module = "/js/spawn.no-bundler.js")
)]
extern "C" {
#[wasm_bindgen(js_name = startSpawnerWorker)]
fn start_spawner_worker(module: JsValue, memory: JsValue, spawner: Spawner) -> Promise;
}
#[wasm_bindgen(js_name = startSpawner)]
pub fn start_spawner() -> Promise {
start_spawner_worker(
wasm_bindgen::module(),
wasm_bindgen::memory(),
Spawner::new(),
)
}
pub fn spawn<F, T>(f: F) -> JoinHandle<T>
where
F: FnOnce() -> T + Send + 'static,
T: Send + 'static,
{
Builder::new()
.spawn(f)
.expect("spawner should be initialized")
}
#[derive(Debug)]
pub struct JoinHandle<T>(Receiver<std::thread::Result<T>>);
impl<T> JoinHandle<T> {
pub fn is_finished(&self) -> bool {
self.0.is_empty()
}
pub fn join(self) -> std::thread::Result<T> {
self.0
.recv()
.map_err(|_| Box::new("worker thread dropped return channel") as Box<dyn Any + Send>)?
}
}