use std::sync::OnceLock;
use futures::{future::BoxFuture, Future, SinkExt, StreamExt};
pub trait Executor: Send + Sync {
fn spawn_boxed(&self, fut: BoxFuture<'static, ()>);
}
pub fn syscall_spawn<Fut>(syscall: &dyn Executor, fut: Fut)
where
Fut: Future<Output = ()> + Send + 'static,
{
syscall.spawn_boxed(Box::pin(fut))
}
pub fn syscall_block_on<Fut, R>(syscall: &dyn Executor, fut: Fut) -> R
where
Fut: Future<Output = R> + Send + 'static,
R: Send + 'static,
{
let (mut sender, mut receiver) = futures::channel::mpsc::channel::<R>(0);
syscall_spawn(syscall, async move {
let r = fut.await;
_ = sender.send(r).await;
});
futures::executor::block_on(async move { receiver.next().await.unwrap() })
}
static GLOBAL_EXECUTOR: OnceLock<Box<dyn Executor>> = OnceLock::new();
pub fn register_global_executor<E: Executor + 'static>(executor: E) {
if GLOBAL_EXECUTOR.set(Box::new(executor)).is_err() {
panic!("Multiple calls to register_global_executor are not permitted!!!");
}
}
pub fn global_executor() -> &'static dyn Executor {
GLOBAL_EXECUTOR
.get()
.expect("Call register_global_executor first")
.as_ref()
}