#![forbid(unsafe_code)]
#![warn(missing_docs, missing_debug_implementations, rust_2018_idioms)]
#[cfg(doctest)]
doc_comment::doctest!("../README.md");
use async_executor::{Executor, LocalExecutor, Task};
use once_cell::sync::Lazy;
use futures_lite::future;
use std::{cell::RefCell, future::Future, thread};
static GLOBAL_EXECUTOR: Lazy<Executor> = Lazy::new(|| {
let num_cpus = std::env::var("ASYNC_GLOBAL_EXECUTOR_THREADS")
.ok()
.and_then(|threads| threads.parse().ok())
.unwrap_or_else(num_cpus::get)
.max(1);
for n in 1..=num_cpus {
thread::Builder::new()
.name(format!("async-global-executor-{}", n))
.spawn(|| run(future::pending::<()>()))
.expect("cannot spawn executor thread");
}
Executor::new()
});
thread_local! {
static LOCAL_EXECUTOR: RefCell<LocalExecutor> = RefCell::new(LocalExecutor::new());
}
pub fn run<F: Future<Output = T> + Send + 'static, T: Send + 'static>(future: F) -> T {
LOCAL_EXECUTOR.with(|executor| {
let executor = executor.borrow();
let global = GLOBAL_EXECUTOR.run(future);
async_io::block_on(executor.run(global))
})
}
pub fn spawn<F: Future<Output = T> + Send + 'static, T: Send + 'static>(future: F) -> Task<T> {
GLOBAL_EXECUTOR.spawn(future)
}
pub fn spawn_local<F: Future<Output = T> + 'static, T: 'static>(future: F) -> Task<T> {
Lazy::force(&GLOBAL_EXECUTOR);
LOCAL_EXECUTOR.with(|executor| executor.borrow().spawn(future))
}