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>> {
30 let mut rx = self.rx.clone();
31 loop {
32 let res = rx.borrow_and_update().clone();
33 if let Some(res) = res {
34 return res;
35 }
36 if rx.changed().await.is_err() {
37 #[allow(clippy::expect_used)]
38 return rx
39 .borrow()
40 .clone()
41 .expect("SharedHandle background task panicked or was cancelled unexpectedly");
42 }
43 }
44 }
45}