//! Allows a future to execute for a maximum amount of time. //! //! See [`Timeout`] documentation for more details. //! //! [`Timeout`]: struct@Timeout
use pin_project_lite::pin_project; use std::future::{Future, IntoFuture}; use std::pin::Pin; use std::task::{self, Poll};
/// Requires a `Future` to complete before the specified duration has elapsed. /// /// If the future completes before the duration has elapsed, then the completed /// value is returned. Otherwise, an error is returned and the future is /// canceled. /// /// Note that the timeout is checked before polling the future, so if the future /// does not yield during execution then it is possible for the future to complete /// and exceed the timeout _without_ returning an error. /// /// This function returns a future whose return type is [`Result`]`<T,`[`Elapsed`]`>`, where `T` is the /// return type of the provided future. /// /// If the provided future completes immediately, then the future returned from /// this function is guaranteed to complete immediately with an [`Ok`] variant /// no matter the provided duration. /// /// [`Ok`]: std::result::Result::Ok /// [`Result`]: std::result::Result /// [`Elapsed`]: crate::time::error::Elapsed /// /// # Cancellation /// /// Cancelling a timeout is done by dropping the future. No additional cleanup /// or other work is required. /// /// The original future may be obtained by calling [`Timeout::into_inner`]. This /// consumes the `Timeout`. /// /// # Examples /// /// Create a new `Timeout` set to expire in 10 milliseconds. /// /// ```rust /// use tokio::time::timeout; /// use tokio::sync::oneshot; /// /// use std::time::Duration; /// /// # async fn dox() { /// let (tx, rx) = oneshot::channel(); /// # tx.send(()).unwrap(); /// /// // Wrap the future with a `Timeout` set to expire in 10 milliseconds. /// if let Err(_) = timeout(Duration::from_millis(10), rx).await { /// println!("did not receive value within 10 ms"); /// } /// # } /// ``` /// /// # Panics /// /// This function panics if there is no current timer set. /// /// It can be triggered when [`Builder::enable_time`] or /// [`Builder::enable_all`] are not included in the builder. /// /// It can also panic whenever a timer is created outside of a /// Tokio runtime. That is why `rt.block_on(sleep(...))` will panic, /// since the function is executed outside of the runtime. /// Whereas `rt.block_on(async {sleep(...).await})` doesn't panic. /// And this is because wrapping the function on an async makes it lazy, /// and so gets executed inside the runtime successfully without /// panicking. /// /// [`Builder::enable_time`]: crate::runtime::Builder::enable_time /// [`Builder::enable_all`]: crate::runtime::Builder::enable_all #[track_caller] pubfn timeout<F>(duration: Duration, future: F) -> Timeout<F::IntoFuture> where
F: IntoFuture,
{ let location = trace::caller_location();
let deadline = Instant::now().checked_add(duration); let delay = match deadline {
Some(deadline) => Sleep::new_timeout(deadline, location),
None => Sleep::far_future(location),
};
Timeout::new_with_delay(future.into_future(), delay)
}
/// Requires a `Future` to complete before the specified instant in time. /// /// If the future completes before the instant is reached, then the completed /// value is returned. Otherwise, an error is returned. /// /// This function returns a future whose return type is [`Result`]`<T,`[`Elapsed`]`>`, where `T` is the /// return type of the provided future. /// /// If the provided future completes immediately, then the future returned from /// this function is guaranteed to complete immediately with an [`Ok`] variant /// no matter the provided deadline. /// /// [`Ok`]: std::result::Result::Ok /// [`Result`]: std::result::Result /// [`Elapsed`]: crate::time::error::Elapsed /// /// # Cancellation /// /// Cancelling a timeout is done by dropping the future. No additional cleanup /// or other work is required. /// /// The original future may be obtained by calling [`Timeout::into_inner`]. This /// consumes the `Timeout`. /// /// # Examples /// /// Create a new `Timeout` set to expire in 10 milliseconds. /// /// ```rust /// use tokio::time::{Instant, timeout_at}; /// use tokio::sync::oneshot; /// /// use std::time::Duration; /// /// # async fn dox() { /// let (tx, rx) = oneshot::channel(); /// # tx.send(()).unwrap(); /// /// // Wrap the future with a `Timeout` set to expire 10 milliseconds into the /// // future. /// if let Err(_) = timeout_at(Instant::now() + Duration::from_millis(10), rx).await { /// println!("did not receive value within 10 ms"); /// } /// # } /// ``` pubfn timeout_at<F>(deadline: Instant, future: F) -> Timeout<F::IntoFuture> where
F: IntoFuture,
{ let delay = sleep_until(deadline);
Timeout {
value: future.into_future(),
delay,
}
}
pin_project! { /// Future returned by [`timeout`](timeout) and [`timeout_at`](timeout_at). #[must_use = "futures do nothing unless you `.await` or poll them"] #[derive(Debug)] pubstruct Timeout<T> { #[pin]
value: T, #[pin]
delay: Sleep,
}
}
let has_budget_now = coop::has_budget_remaining();
let delay = me.delay;
let poll_delay = || -> Poll<Self::Output> { match delay.poll(cx) {
Poll::Ready(()) => Poll::Ready(Err(Elapsed::new())),
Poll::Pending => Poll::Pending,
}
};
iflet (true, false) = (had_budget_before, has_budget_now) { // if it is the underlying future that exhausted the budget, we poll // the `delay` with an unconstrained one. This prevents pathological // cases where the underlying future always exhausts the budget and // we never get a chance to evaluate whether the timeout was hit or // not.
coop::with_unconstrained(poll_delay)
} else {
poll_delay()
}
}
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.19 Sekunden
(vorverarbeitet am 2026-06-19)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.