-
-
Notifications
You must be signed in to change notification settings - Fork 2.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
task: make inner of Unconstrained
accessible
#6886
Conversation
Could you please share the specific use cases you have in mind for this ? |
Preempting and some sort of realtime task. I'm aware that tokio is not suitable for realtime tasks. But For example, I want a timer to preempt current task, which requires this timer to be
It's the only public API to tweak coop scheduling. There is no alternative. And giving it already exists as a public API, I don't think prevent users from using it is a good idea. |
The only potential use case would be to conditionally disable cooperative scheduling. For example: use std::future::poll_fn;
use std::pin::Pin;
async fn main() {
let fut = std::pin::pin!(async {});
let mut fut = unconstrained(fut);
let mut i = 0;
poll_fn(|cx| {
i += 1;
if (i % 2) == 0 {
Pin::new(fut.get_mut()).poll(cx) // poll inner future.
} else {
Pin::new(&mut fut).poll(cx) // Turn off cooperative scheduling
}
})
.await;
} Could you explain why conditionally turning off cooperative scheduling might be useful in specific scenarios ?
By calling |
|
Because, the Future trait does not provide any methods that accept |
Yes but e.g. struct MyFuture {
some_state: State
}
impl Future for MyFuture {
type Output = SomeOutput;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
// do something
}
}
pin_project! {
struct MyWrapper {
#[pin]
inner: Unconstrained<MyFuture>
}
}
impl Future for MyWrapper {
type Output = SomeOutput;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
self.inner.get_ref().some_state.do_something();
self.project().inner.poll(cx)
}
} The |
|
||
/// Gets a pinned mutable reference to the wrapped future. | ||
pub fn get_pin_mut(self: Pin<&mut Self>) -> Pin<&mut F> { | ||
self.project().inner | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// Gets a pinned mutable reference to the wrapped future. | |
pub fn get_pin_mut(self: Pin<&mut Self>) -> Pin<&mut F> { | |
self.project().inner | |
} |
You can always create a Pin
later when needed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No. Pin::new()
requires T
impl Unpin
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That shouldn't be an issue.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider this:
struct State(PhantomPinned);
struct MyFuture {
some_state: State
}
impl MyFuture {
fn ready_to_poll(&self) -> bool {
// check the condition
}
fn setup_work(self: Pin<&mut Self>, cx: &mut Context<'_>) {
// do some setup
}
}
impl Future for MyFuture {
type Output = SomeOutput;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
// poll
}
}
pin_project! {
struct MyWrapper {
#[pin]
inner: Unconstrained<MyFuture>
}
}
impl Future for MyWrapper {
type Output = SomeOutput;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
if self.inner.get_ref().ready_to_poll() {
self.project().inner.poll(cx)
} else {
self.project().inner.get_pin_mut().setup_work(cx);
Poll::Pending
}
}
}
Existing APIs like tokio::io::BufReader
also have get_pin_mut()
You can use |
Right. |
Motivation
The wrapped future in
Unconstrained
was not accessible.Solution
Added four methods:
Unconstrained<F>::get_ref()
Unconstrained<F>::get_mut()
Unconstrained<F>::get_pin_mut()
Unconstrained<F>::into_inner()