-
Notifications
You must be signed in to change notification settings - Fork 669
Deprecate Future::wait. #634
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
Conversation
This commit deprecates `Future::wait`. Instead of having a trait function, a wrapper is provided at `future::Blocking`. `Blocking` wraps a `Future` value and provides thread-blocking operation on it. Related: tokio-rs/tokio-rfcs#3
|
Also worth noting, calling |
src/future/blocking.rs
Outdated
| /// the inner future is not in a ready state. | ||
| /// | ||
| /// This function will return immediately if the inner future is not ready. | ||
| pub fn poll(&mut self) -> Option<Result<T::Item, T::Error>> { |
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.
The name poll returning something that isn't Poll seems confusing, when every other future or stream poll will. Maybe something like peek or tap?
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.
I'm open to change the name if a good alternative is proposed.
peekimplies the value remains in the future (and there is a peek combinator that does this on Future).tapI don't understand how tap applies to the behavior (I am not familiar w/ tap as a name here).
Re confusion, the return type is different, so at least it won't compile if you are expecting Poll.
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.
I want to second @seanmonstar's point about poll; we've used that pretty universally to designate that interest will be registered.
It could match cases with blocking data structures in std and be called try_wait, but that's not awesome.
Also, it's a tad confusing for this to be part of the Blocking wrapper, since the point here is precisely that it doesn't block :-)
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.
It could be named something besides Blocking. The real goal of the type is "Use this future from the edge outside of the future task system", but I went with Blocking to make that behavior very explicit.
I considered try_wait, but that doesn't really make sense as it isn't trying to wait...
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.
The only other name that I thought of would be try_take.
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.
Oh I'm not complaining about the name Blocking (which I like), I'm saying that Blocking::poll is a bit confusing because it's not in fact blocking. If you're wanting to poll the future outside of an executor, why would you think to reach for Blocking to do so?
But anyway, I'm more concerned that we find a name other than poll.
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.
re: try_take, I was thinking along similar lines. Seems good?
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.
Does anyone hate try_take instead of poll?
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.
I'm confused as to how this avoids registering interest. My understanding of futures is that they register with the current task before returning NotReady. With poll_future_notify below, isn't the interest is still registered?
src/future/blocking.rs
Outdated
|
|
||
| /// Provides thread-blocking operations on a future. | ||
| /// | ||
| /// See [`blocking`] documentation for more details. |
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.
This links to nothing, missing "(fn.blocking.html)"?
|
I would also want to add some tests for There are also more tests to update to move away from the deprecated wait. |
|
@carllerche It'd be helpful to see the rationale for this API surface as an addition beyond what's in the RFC (maybe I missed the motivation somewhere?) How should one think about having both this and the current-thread executor?
I'm also curious to understand how this fits into the RFC design, which was also attempting to solve this problem. |
|
@aturon A few things:
@alexcrichton's PR deals with It doesn't make sense to include
The goal of the RFC was to prevent being able to spawn current-thread tasks and having them be implicitly dropped. This PR maintains this goal.
|
|
@carllerche Got it, thanks! And yeah, an earlier version of the RFC had something like this (though it was less elaborate; it wasn't a wrapper), which was lost in the shuffle. I'm good with this approach! |
|
Is there a reason for Additionally, I feel as if I'd prefer something closer to In terms of the type |
|
I don't understand why you believe this to be true. A future is very stateful, there is plenty of reason to want to access the inner T before or after blocking. Also, at some point there will be a Re naming, the only thing that I care about is that it is succinct, and clearly communicates that the type can block the thread. |
I meant that only if re: Re naming, if anybody else has input, that would be great as well. |
aturon
left a comment
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.
Just some nits, otherwise LGTM.
| /// transitions to a ready state. Once the future is complete, the result of | ||
| /// this future is returned. | ||
| /// | ||
| /// > **Note:** This method is not appropriate to call on event loops or |
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.
We should make the function panic in those cases, similarly to what was proposed in the RFC. Basically, just need to assert that there is not currently an executor. But maybe you're planning on doing that once we get the Enter stuff in?
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.
Yes, this step will happen in future PRs.
| /// **These operations will block the current thread**. This means that they | ||
| /// should not be called while in the context of a task executor as this will | ||
| /// block the task executor's progress. Also, note that **this value will block | ||
| /// the current thread on drop**. Droping `Blocking` will ensure that the 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.
Might be worth mentioning that this is analogous to dropping a BufWriter in std.
| #[derive(Debug)] | ||
| #[must_use = "sinks do nothing unless used"] | ||
| pub struct Blocking<T: Sink> { | ||
| inner: Option<executor::Spawn<T>>, |
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.
I can't figure out why this is an Option; AFAICT it's always Some (and everything except the dtor asserts that).
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.
It is an Option to support into_inner (which has to be able to extract the inner type without triggering the dtor).
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.
Ah yep, missed that. 👍
aturon
left a comment
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.
Alright, good to go!
|
@alexcrichton could you enable "squash & merge" and "rebase and merge" for this repo? |
|
I'm curious why Also there are a lot of doc tests (and some normal unit tests) using the old |
This commit deprecates
Future::wait. Instead of having a trait function, a wrapper is provided atfuture::Blocking.Blockingwraps aFuturevalue and provides thread-blocking operation on it.The deprecation strategy differs from that proposed in tokio-rs/tokio-rfcs#3. The intent is that there still will be current-thread executor functions described in the PR but those will come after.
This PR proposes adding
future::Blockingwhich wraps aT: Futureand provides thread-blocking operations. Currently, onlywaitandpollare provided, butwait_timeoutcould be added easily later.I opted for this strategy because in @alex's branch, he provided both
BlockingStreamandBlockingSink, yetBlockingFuturewas omitted. IfBlockingSinkandBlockingStreamare worth having (and I think they are), thenBlockingFutureshould also be provided. This proves to be a natural place to add any functions for using a future outside the scope of an executor.I believe that this solves the problems being encountered with
waitby not being a trait function (you won't find this function by looking at what theFuturetrait provides). Also, in the future, thread-blocking operations will panic when invoked from the context of an executor.This PR opts to name the type
future::Blocking.If this PR is accepted, I will apply a similar treatment to
SinkandStream.This PR is based against the
tokio-reformbranch, and not master.Remaining
WaittypesSpawn.