use std::time::Duration;
use futures::future::Future;
use kludgine_core::flume;
use lazy_static::lazy_static;
use parking_lot::RwLock;
use smol_timeout::TimeoutExt;
lazy_static! {
pub static ref GLOBAL_THREAD_POOL: RwLock<Option<smol::Executor<'static>>> = RwLock::new(None);
}
pub fn initialize() {
{
let mut pool_guard = GLOBAL_THREAD_POOL.write();
if pool_guard.is_some() {
return;
}
let executor = smol::Executor::new();
*pool_guard = Some(executor);
}
std::thread::spawn(|| {
let (signal, shutdown) = flume::unbounded::<()>();
easy_parallel::Parallel::new()
.each(0..4, |_| {
#[allow(clippy::await_holding_lock)] futures::executor::block_on(async {
let guard = GLOBAL_THREAD_POOL.read();
let executor = guard.as_ref().unwrap();
executor.run(shutdown.recv_async()).await
})
})
.finish(|| {});
drop(signal);
});
}
impl super::Runtime {
pub fn spawn<Fut: Future<Output = T> + Send + 'static, T: Send + 'static>(future: Fut) {
let guard = GLOBAL_THREAD_POOL.read();
let executor = guard.as_ref().unwrap();
executor.spawn(future).detach();
}
pub fn block_on<'a, Fut: Future<Output = R> + Send + 'a, R: Send + Sync + 'a>(
future: Fut,
) -> R {
futures::executor::block_on(future)
}
pub async fn timeout<F: Future<Output = T> + Send, T: Send>(
future: F,
duration: Duration,
) -> Option<T> {
future.timeout(duration).await
}
}