1use std::sync::OnceLock;
4
5use futures::{future::BoxFuture, Future, SinkExt, StreamExt};
6
7pub trait Executor: Send + Sync {
9 fn spawn_boxed(&self, fut: BoxFuture<'static, ()>);
11}
12
13pub fn syscall_spawn<Fut>(syscall: &dyn Executor, fut: Fut)
15where
16 Fut: Future<Output = ()> + Send + 'static,
17{
18 syscall.spawn_boxed(Box::pin(fut))
19}
20
21pub fn syscall_block_on<Fut, R>(syscall: &dyn Executor, fut: Fut) -> R
25where
26 Fut: Future<Output = R> + Send + 'static,
27 R: Send + 'static,
28{
29 let (mut sender, mut receiver) = futures::channel::mpsc::channel::<R>(0);
30
31 syscall_spawn(syscall, async move {
32 let r = fut.await;
33 _ = sender.send(r).await;
34 });
35
36 futures::executor::block_on(async move { receiver.next().await.unwrap() })
37}
38
39static GLOBAL_EXECUTOR: OnceLock<Box<dyn Executor>> = OnceLock::new();
40
41pub fn register_global_executor<E: Executor + 'static>(executor: E) {
47 if GLOBAL_EXECUTOR.set(Box::new(executor)).is_err() {
48 panic!("Multiple calls to register_global_executor are not permitted!!!");
49 }
50}
51
52pub fn global_executor() -> &'static dyn Executor {
59 GLOBAL_EXECUTOR
60 .get()
61 .expect("Call register_global_executor first")
62 .as_ref()
63}