Skip to main content

fast_pull/core/
handle.rs

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}