tycho_util/futures/
join_task.rs1use std::pin::Pin;
2use std::task::{Context, Poll};
3
4use futures_util::{Future, FutureExt};
5use tokio::task::JoinHandle;
6
7#[must_use = "futures do nothing unless you `.await` or poll them"]
8pub struct JoinTask<T> {
9 handle: JoinHandle<T>,
10 completed: bool,
11}
12
13impl<T> JoinTask<T> {
14 #[inline]
15 pub fn new<F>(f: F) -> Self
16 where
17 F: Future<Output = T> + Send + 'static,
18 T: Send + 'static,
19 {
20 Self {
21 handle: tokio::spawn(f),
22 completed: false,
23 }
24 }
25
26 pub fn is_finished(&self) -> bool {
27 self.handle.is_finished()
28 }
29}
30
31impl<T> Drop for JoinTask<T> {
32 fn drop(&mut self) {
33 if !self.completed {
34 self.handle.abort();
35 }
36 }
37}
38
39impl<T> Future for JoinTask<T> {
40 type Output = T;
41
42 #[inline]
43 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
44 let res = futures_util::ready!(self.handle.poll_unpin(cx));
45 match res {
46 Ok(value) => {
47 self.completed = true;
48 Poll::Ready(value)
49 }
50 Err(e) => {
51 if e.is_panic() {
52 std::panic::resume_unwind(e.into_panic());
53 }
54
55 Poll::Pending
57 }
58 }
59 }
60}