Skip to content

Commit a57c18b

Browse files
committed
add Poll::ready
1 parent 0157cc9 commit a57c18b

File tree

3 files changed

+92
-0
lines changed

3 files changed

+92
-0
lines changed

library/core/src/task/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,5 @@ pub use self::wake::{Context, RawWaker, RawWakerVTable, Waker};
1313
mod ready;
1414
#[stable(feature = "ready_macro", since = "1.56.0")]
1515
pub use ready::ready;
16+
#[unstable(feature = "poll_ready", issue = "none")]
17+
pub use ready::Ready;

library/core/src/task/poll.rs

+33
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
use crate::convert;
44
use crate::ops::{self, ControlFlow};
55
use crate::result::Result;
6+
use crate::task::Ready;
67

78
/// Indicates whether a value is available or if the current task has been
89
/// scheduled to receive a wakeup instead.
@@ -92,6 +93,38 @@ impl<T> Poll<T> {
9293
pub const fn is_pending(&self) -> bool {
9394
!self.is_ready()
9495
}
96+
97+
/// Extracts the successful type of a [`Poll<T>`].
98+
///
99+
/// When combined with the `?` operator, this function will
100+
/// propogate any [`Poll::Pending`] values to the caller, and
101+
/// extract the `T` from [`Poll::Ready`].
102+
///
103+
/// # Examples
104+
///
105+
/// ```rust
106+
/// #![feature(poll_ready)]
107+
///
108+
/// use std::task::{Context, Poll};
109+
/// use std::future::{self, Future};
110+
/// use std::pin::Pin;
111+
///
112+
/// pub fn do_poll(cx: &mut Context<'_>) -> Poll<()> {
113+
/// let mut fut = future::ready(42);
114+
/// let fut = Pin::new(&mut fut);
115+
///
116+
/// let num = fut.poll(cx).ready()?;
117+
/// # drop(num);
118+
/// // ... use num
119+
///
120+
/// Poll::Ready(())
121+
/// }
122+
/// ```
123+
#[inline]
124+
#[unstable(feature = "poll_ready", issue = "none")]
125+
pub fn ready(self) -> Ready<T> {
126+
Ready(self)
127+
}
95128
}
96129

97130
impl<T, E> Poll<Result<T, E>> {

library/core/src/task/ready.rs

+57
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
use core::convert;
2+
use core::fmt;
3+
use core::ops::{ControlFlow, FromResidual, Try};
4+
use core::task::Poll;
5+
16
/// Extracts the successful type of a [`Poll<T>`].
27
///
38
/// This macro bakes in propagation of [`Pending`] signals by returning early.
@@ -55,3 +60,55 @@ pub macro ready($e:expr) {
5560
}
5661
}
5762
}
63+
64+
/// Extracts the successful type of a [`Poll<T>`].
65+
///
66+
/// See [`Poll::ready`] for details.
67+
#[unstable(feature = "poll_ready", issue = "none")]
68+
pub struct Ready<T>(pub(crate) Poll<T>);
69+
70+
#[unstable(feature = "poll_ready", issue = "none")]
71+
impl<T> Try for Ready<T> {
72+
type Output = T;
73+
type Residual = Ready<convert::Infallible>;
74+
75+
#[inline]
76+
fn from_output(output: Self::Output) -> Self {
77+
Ready(Poll::Ready(output))
78+
}
79+
80+
#[inline]
81+
fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
82+
match self.0 {
83+
Poll::Ready(v) => ControlFlow::Continue(v),
84+
Poll::Pending => ControlFlow::Break(Ready(Poll::Pending)),
85+
}
86+
}
87+
}
88+
89+
#[unstable(feature = "poll_ready", issue = "none")]
90+
impl<T> FromResidual for Ready<T> {
91+
#[inline]
92+
fn from_residual(residual: Ready<convert::Infallible>) -> Self {
93+
match residual.0 {
94+
Poll::Pending => Ready(Poll::Pending),
95+
}
96+
}
97+
}
98+
99+
#[unstable(feature = "poll_ready", issue = "none")]
100+
impl<T> FromResidual<Ready<convert::Infallible>> for Poll<T> {
101+
#[inline]
102+
fn from_residual(residual: Ready<convert::Infallible>) -> Self {
103+
match residual.0 {
104+
Poll::Pending => Poll::Pending,
105+
}
106+
}
107+
}
108+
109+
#[unstable(feature = "poll_ready", issue = "none")]
110+
impl<T> fmt::Debug for Ready<T> {
111+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
112+
f.debug_tuple("Ready").finish()
113+
}
114+
}

0 commit comments

Comments
 (0)