use std::future::Future;
use tokio::task::{JoinError, JoinSet};
#[derive(Debug)]
pub struct SpawnedTask<R> {
inner: JoinSet<R>,
}
impl<R: 'static> SpawnedTask<R> {
pub fn spawn<T>(task: T) -> Self
where
T: Future<Output = R>,
T: Send + 'static,
R: Send,
{
let mut inner = JoinSet::new();
inner.spawn(task);
Self { inner }
}
pub fn spawn_blocking<T>(task: T) -> Self
where
T: FnOnce() -> R,
T: Send + 'static,
R: Send,
{
let mut inner = JoinSet::new();
inner.spawn_blocking(task);
Self { inner }
}
pub async fn join(mut self) -> Result<R, JoinError> {
self.inner
.join_next()
.await
.expect("`SpawnedTask` instance always contains exactly 1 task")
}
pub async fn join_unwind(self) -> R {
self.join().await.unwrap_or_else(|e| {
if e.is_panic() {
std::panic::resume_unwind(e.into_panic());
} else {
unreachable!("SpawnedTask was cancelled unexpectedly");
}
})
}
}