Skip to content

Commit

Permalink
Add a helper for always ready futures (#2825)
Browse files Browse the repository at this point in the history
  • Loading branch information
GnomedDev authored and taiki-e committed Oct 5, 2024
1 parent d3a7aca commit e843c70
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 0 deletions.
62 changes: 62 additions & 0 deletions futures-util/src/future/always_ready.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
use super::assert_future;
use core::pin::Pin;
use futures_core::future::{FusedFuture, Future};
use futures_core::task::{Context, Poll};

/// Future for the [`always_ready`](always_ready()) function.
#[must_use = "futures do nothing unless you `.await` or poll them"]
pub struct AlwaysReady<T, F: Fn() -> T>(F);

impl<T, F: Fn() -> T> core::fmt::Debug for AlwaysReady<T, F> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_tuple("AlwaysReady").finish()
}
}

impl<T, F: Fn() -> T + Clone> Clone for AlwaysReady<T, F> {
fn clone(&self) -> Self {
Self(self.0.clone())
}
}

impl<T, F: Fn() -> T + Copy> Copy for AlwaysReady<T, F> {}

impl<T, F: Fn() -> T> Unpin for AlwaysReady<T, F> {}

impl<T, F: Fn() -> T> FusedFuture for AlwaysReady<T, F> {
fn is_terminated(&self) -> bool {
false
}
}

impl<T, F: Fn() -> T> Future for AlwaysReady<T, F> {
type Output = T;

#[inline]
fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<T> {
Poll::Ready(self.0())
}
}

/// Creates a future that is always immediately ready with a value.
///
/// This is particularly useful in avoiding a heap allocation when an API needs [`Box<dyn Future<Output = T>>`],
/// as [`AlwaysReady`] does not have to store a boolean for `is_finished`.
///
/// # Examples
///
/// ```
/// # futures::executor::block_on(async {
/// use std::mem::size_of_val;
///
/// use futures::future;
///
/// let a = future::always_ready(|| 1);
/// assert_eq!(size_of_val(&a), 0);
/// assert_eq!(a.await, 1);
/// assert_eq!(a.await, 1);
/// # });
/// ```
pub fn always_ready<T, F: Fn() -> T>(prod: F) -> AlwaysReady<T, F> {
assert_future::<T, _>(AlwaysReady(prod))
}
3 changes: 3 additions & 0 deletions futures-util/src/future/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@ pub use self::poll_immediate::{poll_immediate, PollImmediate};
mod ready;
pub use self::ready::{err, ok, ready, Ready};

mod always_ready;
pub use self::always_ready::{always_ready, AlwaysReady};

mod join;
pub use self::join::{join, join3, join4, join5, Join, Join3, Join4, Join5};

Expand Down

0 comments on commit e843c70

Please sign in to comment.