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