use std::future::Future;
use std::panic::catch_unwind;
use std::thread;
use async_executor::{Executor, Task};
use async_io::block_on;
use async_lock::OnceCell;
use futures_lite::future;
pub fn spawn<T: Send + 'static>(future: impl Future<Output = T> + Send + 'static) -> Task<T> {
static GLOBAL: OnceCell<Executor<'_>> = OnceCell::new();
fn global() -> &'static Executor<'static> {
GLOBAL.get_or_init_blocking(|| {
let num_threads = {
std::env::var("SMOL_THREADS")
.ok()
.and_then(|s| s.parse().ok())
.unwrap_or(1)
};
for n in 1..=num_threads {
thread::Builder::new()
.name(format!("smol-{}", n))
.spawn(|| loop {
catch_unwind(|| block_on(global().run(future::pending::<()>()))).ok();
})
.expect("cannot spawn executor thread");
}
let ex = Executor::new();
#[cfg(not(target_os = "espidf"))]
ex.spawn(async_process::driver()).detach();
ex
})
}
global().spawn(future)
}