mssf_core/runtime/
executor.rs1use std::future::Future;
7
8use tokio::runtime::Handle;
9
10use crate::error::ErrorCode;
11
12pub trait Executor: Clone + Sync + Send + 'static {
15 fn spawn<F>(&self, future: F) -> impl JoinHandle<F::Output>
24 where
25 F: Future + Send + 'static,
26 F::Output: Send;
27
28 fn block_on<F: Future>(&self, future: F) -> F::Output;
30}
31
32#[trait_variant::make(JoinHandle: Send)]
36pub trait LocalJoinHandle<T> {
37 async fn join(self) -> crate::Result<T>;
38}
39
40#[derive(Clone)]
41pub struct DefaultExecutor {
42 rt: Handle,
43}
44
45pub struct DefaultJoinHandle<T> {
47 inner: tokio::task::JoinHandle<T>,
48}
49
50impl DefaultExecutor {
51 pub fn new(rt: Handle) -> DefaultExecutor {
52 DefaultExecutor { rt }
53 }
54}
55
56impl Executor for DefaultExecutor {
57 fn spawn<F>(&self, future: F) -> impl JoinHandle<F::Output>
58 where
59 F: Future + Send + 'static,
60 F::Output: Send,
61 {
62 let h = self.rt.spawn(future);
63 DefaultJoinHandle::<F::Output> { inner: h }
64 }
65
66 fn block_on<F: Future>(&self, future: F) -> F::Output {
67 self.rt.block_on(future)
68 }
69}
70
71impl<T: Send> JoinHandle<T> for DefaultJoinHandle<T> {
72 async fn join(self) -> crate::Result<T> {
73 match self.inner.await {
74 Ok(x) => Ok(x),
75 Err(e) => {
76 let e = if e.is_cancelled() {
77 ErrorCode::E_ABORT
79 } else if e.is_panic() {
80 ErrorCode::E_UNEXPECTED
81 } else {
82 ErrorCode::E_FAIL
83 };
84 tracing::error!("DefaultJoinHandle: background task failed: {e}");
85 Err(e.into())
86 }
87 }
88 }
89}
90
91#[cfg(test)]
92mod test {
93 use super::DefaultExecutor;
94
95 #[test]
96 fn test_executor() {
97 let rt = tokio::runtime::Runtime::new().unwrap();
98
99 let _ex = DefaultExecutor::new(rt.handle().clone());
100 }
102}