Skip to content

Commit

Permalink
resolve comments
Browse files Browse the repository at this point in the history
  • Loading branch information
maminrayej committed Jan 31, 2025
1 parent 38218f3 commit 2a977c3
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 86 deletions.
86 changes: 7 additions & 79 deletions tokio/src/task/coop/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,88 +169,16 @@ fn with_budget<R>(budget: Budget, f: impl FnOnce() -> R) -> R {

/// Returns `true` if there is still budget left on the task.
///
/// Futures created by the tokio library functions are budget-aware and yield when there is no more
/// budget left, but not all futures will be budget-aware. Consider future `A` that polls two inner
/// futures `B` and `C`, and returns `Poll::Ready` when one of them is ready. If both inner futures
/// were budget-aware, at some point the budget would be depleted which would cause both futures to
/// return `Poll::Pending` resulting in `A` returning `Poll::Pending` as well. Yielding all the way
/// back to the runtime, the budget would be reset, and `B` and `C` could make progress again.
/// Now let's consider `B` is budget-aware, but `C` is not and is always ready. The budget will be
/// depleted as before, but now since `C` always returns `Poll::Ready`, `A` will always return
/// `Poll::Ready` as well. This way, `A` will not yield back to the runtime which will keep the budget
/// depleted and `B` not making progress.
/// This function is similar to [`consume_budget`], but doesn't decrement the
/// budget when non-zero.
///
/// In these scenarios you could use [`has_budget_remaining`] to check whether the budget has been depleted
/// or not and act accordingly:
/// ```
/// # use std::future::{poll_fn, Future};
/// # use std::task::{Context, Poll};
/// # use std::pin::{pin, Pin};
/// # use std::sync::atomic::{AtomicBool, Ordering};
/// # use tokio::task::coop::{consume_budget, has_budget_remaining};
/// #
/// # #[tokio::main]
/// # async fn main() {
/// struct Greedy;
/// struct Aware;
/// struct Combined {
/// greedy: Greedy,
/// aware: Aware,
/// }
///
/// impl Future for Greedy {
/// type Output = ();
/// # Examples
///
/// fn poll(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Self::Output> {
/// Poll::Ready(())
/// }
/// ```ignore
/// if !has_budget_remaining() {
/// tokio::task::yield_now().await;
/// }
///
/// impl Future for Aware {
/// type Output = ();
///
/// fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
/// pin!(consume_budget()).poll(cx)
/// }
/// }
///
/// impl Future for Combined {
/// type Output = ();
///
/// fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
/// let this = Pin::into_inner(self);
///
/// if !has_budget_remaining() {
/// return Poll::Pending;
/// }
///
/// if Pin::new(&mut this.aware).poll(cx).is_ready() {
/// return Poll::Ready(());
/// } else {
/// return Pin::new(&mut this.greedy).poll(cx);
/// }
/// }
/// }
///
/// let did_yield = AtomicBool::new(false);
///
/// while !did_yield.load(Ordering::Relaxed) {
/// poll_fn(|cx| {
/// let combined = pin!(Combined {
/// greedy: Greedy,
/// aware: Aware,
/// });
///
/// if combined.poll(cx).is_pending() {
/// did_yield.store(true, Ordering::Relaxed);
/// }
///
/// Poll::Ready(())
/// })
/// .await;
/// }
/// # }
///```
/// ```
#[inline(always)]
#[cfg_attr(docsrs, doc(cfg(feature = "rt")))]
pub fn has_budget_remaining() -> bool {
Expand Down
13 changes: 6 additions & 7 deletions tokio/src/task/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -286,20 +286,19 @@ cfg_rt! {
#[doc(hidden)]
#[deprecated = "Moved to tokio::task::coop::consume_budget"]
pub use coop::consume_budget;

mod local;
pub use local::{spawn_local, LocalSet, LocalEnterGuard};

mod task_local;
pub use task_local::LocalKey;

#[doc(hidden)]
#[deprecated = "Moved to tokio::task::coop::unconstrained"]
pub use coop::unconstrained;
#[doc(hidden)]
#[deprecated = "Moved to tokio::task::coop::Unconstrained"]
pub use coop::Unconstrained;

mod local;
pub use local::{spawn_local, LocalSet, LocalEnterGuard};

mod task_local;
pub use task_local::LocalKey;

#[doc(inline)]
pub use join_set::JoinSet;
pub use crate::runtime::task::AbortHandle;
Expand Down

0 comments on commit 2a977c3

Please sign in to comment.