1 use core::pin::Pin; 2 use futures_core::future::{FusedFuture, Future}; 3 use futures_core::task::{Context, Poll}; 4 use pin_project_lite::pin_project; 5 6 pin_project! { 7 /// Future for the [`fuse`](super::FutureExt::fuse) method. 8 #[derive(Debug)] 9 #[must_use = "futures do nothing unless you `.await` or poll them"] 10 pub struct Fuse<Fut> { 11 #[pin] 12 inner: Option<Fut>, 13 } 14 } 15 16 impl<Fut> Fuse<Fut> { new(f: Fut) -> Self17 pub(super) fn new(f: Fut) -> Self { 18 Self { inner: Some(f) } 19 } 20 } 21 22 impl<Fut: Future> Fuse<Fut> { 23 /// Creates a new `Fuse`-wrapped future which is already terminated. 24 /// 25 /// This can be useful in combination with looping and the `select!` 26 /// macro, which bypasses terminated futures. 27 /// 28 /// # Examples 29 /// 30 /// ``` 31 /// # futures::executor::block_on(async { 32 /// use futures::channel::mpsc; 33 /// use futures::future::{Fuse, FusedFuture, FutureExt}; 34 /// use futures::select; 35 /// use futures::stream::StreamExt; 36 /// use futures::pin_mut; 37 /// 38 /// let (sender, mut stream) = mpsc::unbounded(); 39 /// 40 /// // Send a few messages into the stream 41 /// sender.unbounded_send(()).unwrap(); 42 /// sender.unbounded_send(()).unwrap(); 43 /// drop(sender); 44 /// 45 /// // Use `Fuse::terminated()` to create an already-terminated future 46 /// // which may be instantiated later. 47 /// let foo_printer = Fuse::terminated(); 48 /// pin_mut!(foo_printer); 49 /// 50 /// loop { 51 /// select! { 52 /// _ = foo_printer => {}, 53 /// () = stream.select_next_some() => { 54 /// if !foo_printer.is_terminated() { 55 /// println!("Foo is already being printed!"); 56 /// } else { 57 /// foo_printer.set(async { 58 /// // do some other async operations 59 /// println!("Printing foo from `foo_printer` future"); 60 /// }.fuse()); 61 /// } 62 /// }, 63 /// complete => break, // `foo_printer` is terminated and the stream is done 64 /// } 65 /// } 66 /// # }); 67 /// ``` terminated() -> Self68 pub fn terminated() -> Self { 69 Self { inner: None } 70 } 71 } 72 73 impl<Fut: Future> FusedFuture for Fuse<Fut> { is_terminated(&self) -> bool74 fn is_terminated(&self) -> bool { 75 self.inner.is_none() 76 } 77 } 78 79 impl<Fut: Future> Future for Fuse<Fut> { 80 type Output = Fut::Output; 81 poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Fut::Output>82 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Fut::Output> { 83 match self.as_mut().project().inner.as_pin_mut() { 84 Some(fut) => fut.poll(cx).map(|output| { 85 self.project().inner.set(None); 86 output 87 }), 88 None => Poll::Pending, 89 } 90 } 91 } 92