karyon_core/async_runtime/
executor.rs1use std::{future::Future, panic::catch_unwind, sync::Arc, thread};
2
3use once_cell::sync::OnceCell;
4
5#[cfg(feature = "smol")]
6pub use smol::Executor as SmolEx;
7
8#[cfg(feature = "tokio")]
9pub use tokio::runtime::Runtime;
10
11use super::Task;
12
13#[derive(Clone)]
43pub struct Executor {
44 #[cfg(feature = "smol")]
45 inner: Arc<SmolEx<'static>>,
46 #[cfg(feature = "tokio")]
47 inner: Arc<Runtime>,
48}
49
50impl Executor {
51 pub fn spawn<T: Send + 'static>(
52 &self,
53 future: impl Future<Output = T> + Send + 'static,
54 ) -> Task<T> {
55 self.inner.spawn(future).into()
56 }
57
58 #[cfg(feature = "tokio")]
59 pub fn handle(&self) -> &tokio::runtime::Handle {
60 self.inner.handle()
61 }
62}
63
64static GLOBAL_EXECUTOR: OnceCell<Executor> = OnceCell::new();
65
66pub fn global_executor() -> Executor {
69 #[cfg(feature = "smol")]
70 fn init_executor() -> Executor {
71 let ex = smol::Executor::new();
72 thread::Builder::new()
73 .name("smol-executor".to_string())
74 .spawn(|| loop {
75 catch_unwind(|| {
76 smol::block_on(global_executor().inner.run(std::future::pending::<()>()))
77 })
78 .ok();
79 })
80 .expect("cannot spawn executor thread");
81 ex.spawn(async_process::driver()).detach();
84 Executor {
85 inner: Arc::new(ex),
86 }
87 }
88
89 #[cfg(feature = "tokio")]
90 fn init_executor() -> Executor {
91 let ex = Arc::new(tokio::runtime::Runtime::new().expect("cannot build tokio runtime"));
92 thread::Builder::new()
93 .name("tokio-executor".to_string())
94 .spawn({
95 let ex = ex.clone();
96 move || {
97 catch_unwind(|| ex.block_on(std::future::pending::<()>())).ok();
98 }
99 })
100 .expect("cannot spawn tokio runtime thread");
101 Executor { inner: ex }
102 }
103
104 GLOBAL_EXECUTOR.get_or_init(init_executor).clone()
105}
106
107#[cfg(feature = "smol")]
108impl From<Arc<smol::Executor<'static>>> for Executor {
109 fn from(ex: Arc<smol::Executor<'static>>) -> Executor {
110 Executor { inner: ex }
111 }
112}
113
114#[cfg(feature = "tokio")]
115impl From<Arc<tokio::runtime::Runtime>> for Executor {
116 fn from(rt: Arc<tokio::runtime::Runtime>) -> Executor {
117 Executor { inner: rt }
118 }
119}
120
121#[cfg(feature = "smol")]
122impl From<smol::Executor<'static>> for Executor {
123 fn from(ex: smol::Executor<'static>) -> Executor {
124 Executor {
125 inner: Arc::new(ex),
126 }
127 }
128}
129
130#[cfg(feature = "tokio")]
131impl From<tokio::runtime::Runtime> for Executor {
132 fn from(rt: tokio::runtime::Runtime) -> Executor {
133 Executor {
134 inner: Arc::new(rt),
135 }
136 }
137}