1extern crate alloc;
2use alloc::sync::Arc;
3use tokio::{
4 sync::watch,
5 task::{JoinError, JoinHandle},
6};
7
8#[derive(Debug)]
9pub struct SharedHandle<T> {
10 rx: watch::Receiver<Option<Result<T, Arc<JoinError>>>>,
11}
12
13impl<T> SharedHandle<T>
14where
15 T: Clone + Send + Sync + 'static,
16{
17 pub fn new(handle: JoinHandle<T>) -> Self {
18 let (tx, rx) = watch::channel(None);
19 tokio::spawn(async move {
20 let _ = tx.send(Some(handle.await.map_err(Arc::from)));
21 });
22 Self { rx }
23 }
24
25 pub async fn join(&self) -> Result<T, Arc<JoinError>> {
26 let mut rx = self.rx.clone();
27 loop {
28 if let Some(res) = rx.borrow_and_update().clone() {
29 return res;
30 }
31 if rx.changed().await.is_err() {
32 return match rx.borrow().clone() {
33 Some(res) => res,
34 None => panic!(
35 "SharedHandle background task panicked or was cancelled unexpectedly"
36 ),
37 };
38 }
39 }
40 }
41}