-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
Tracking Issue for task::Waker::noop
#98286
Comments
+1 on this feature, I find myself re-implementing a noop As for the third question, I'd personally prefer either an associated constant or changing the return signature to |
Add `task::Waker::noop` I have found myself reimplementing this function many times when I need a `Context` but don't have a runtime or `futures` to hand. Prior art: [`futures::task::noop_waker`](https://docs.rs/futures/0.3/futures/task/fn.noop_waker.html) and [`futures::task::noop_waker_ref`](https://docs.rs/futures/0.3/futures/task/fn.noop_waker_ref.html) Tracking issue: rust-lang#98286 Unresolved questions: 1. Should we also add `RawWaker::noop()`? (I don't think so, I can't think of a use case for it) 2. Should we also add `Context::noop()`? Depending on the future direction `Context` goes a "noop context" might not even make sense in future. 3. Should it be an associated constant instead? That would allow for `let cx = &mut Context::from_waker(&Waker::NOOP);` to work on one line which is pretty nice. I don't really know what the guideline is here. r? rust-lang/libs-api `@rustbot` label +T-libs-api -T-libs
Add `task::Waker::noop` I have found myself reimplementing this function many times when I need a `Context` but don't have a runtime or `futures` to hand. Prior art: [`futures::task::noop_waker`](https://docs.rs/futures/0.3/futures/task/fn.noop_waker.html) and [`futures::task::noop_waker_ref`](https://docs.rs/futures/0.3/futures/task/fn.noop_waker_ref.html) Tracking issue: rust-lang/rust#98286 Unresolved questions: 1. Should we also add `RawWaker::noop()`? (I don't think so, I can't think of a use case for it) 2. Should we also add `Context::noop()`? Depending on the future direction `Context` goes a "noop context" might not even make sense in future. 3. Should it be an associated constant instead? That would allow for `let cx = &mut Context::from_waker(&Waker::NOOP);` to work on one line which is pretty nice. I don't really know what the guideline is here. r? rust-lang/libs-api `@rustbot` label +T-libs-api -T-libs
Speaking just for myself here: to me this seems generally useful as a utility, somewhat akin to This would basically be a shorthand for creating a waker from |
We discussed this in the WG-async triage call today. While everyone did see use cases for this, some also had concerns about this potentially being misused. E.g. someone might use this when the person should instead call We were curious to hear more about the use cases. If people here could help to fill in the details of the various use cases for this, that would help with discussion, and it may help enable a WG-async consensus to form. |
A use case today, from quinn: I want to send a UDP datagram if doing so would succeed immediately, or otherwise drop the datagram entirely, because it's a response to a cheap request I know the peer will retry. It'd be convenient to be able to express this through a normal async UDP socket interface. |
Two use cases that I've come across:
But I've reached for Separately: I notice that one of the unresolved questions is:
I think that either this, or providing the equivalent of And in 100% of the cases I've ever used a noop waker, I used |
+1 for something that can provide a reference. For me, a noop waker is mainly interesting for tests or experimentation/playground, and enabling another line of code to be saved seems within the spirit of that. I don't know if I've ever needed an owned noop waker, and as kpreid suggests can just No opinion on constant vs function. |
The advantage of this is that `&Waker::NOOP` can live for '`static`, so it does not need to be assigned to a variable to be used in a `Context` creation, which is, as shown in the changes to the tests in this commit, is the most common thing to want to do with a noop waker. An alternative would be to make it be of type `&'static Waker`, which would make that common case even shorter, but that would mean that if an owned `Waker` is desired it must be `.clone()`d from the constant. Or, both versions could be provided, like `futures::task::noop_waker()` and `futures::task::noop_waker_ref()`. But either option seems less elegant to me. Previous discussion on the tracking issue starting here: rust-lang#98286 (comment)
I prepared a change which replaced let mut cx = &mut Context::from_waker(&Waker::NOOP);
cx.waker().wake_by_ref();
If I understand correctly now, this is not possible because the |
The advantage of this is that it does not need to be assigned to a variable to be used in a `Context` creation, which is the most common thing to want to do with a noop waker. If an owned noop waker is desired, it can be created by cloning, but the reverse is harder. Alternatively, both versions could be provided, like `futures::task::noop_waker()` and `futures::task::noop_waker_ref()`, but that seems to me to be API clutter for a very small benefit, whereas having the `&'static` reference available is a large benefit. Previous discussion on the tracking issue starting here: rust-lang#98286 (comment)
In the WG-async call today, we discussed this, resulting in the following consensus: Consensus: WG-async is in favor of returning |
@traviscross Does WG-async have any opinion about the question of making it be |
Change return type of unstable `Waker::noop()` from `Waker` to `&Waker`. The advantage of this is that it does not need to be assigned to a variable to be used in a `Context` creation, which is the most common thing to want to do with a noop waker. It also avoids unnecessarily executing the dynamically dispatched drop function when the noop waker is dropped. If an owned noop waker is desired, it can be created by cloning, but the reverse is harder to do since it requires declaring a constant. Alternatively, both versions could be provided, like `futures::task::noop_waker()` and `futures::task::noop_waker_ref()`, but that seems to me to be API clutter for a very small benefit, whereas having the `&'static` reference available is a large reduction in boilerplate. [Previous discussion on the tracking issue starting here](rust-lang#98286 (comment))
Change return type of unstable `Waker::noop()` from `Waker` to `&Waker`. The advantage of this is that it does not need to be assigned to a variable to be used in a `Context` creation, which is the most common thing to want to do with a noop waker. It also avoids unnecessarily executing the dynamically dispatched drop function when the noop waker is dropped. If an owned noop waker is desired, it can be created by cloning, but the reverse is harder to do since it requires declaring a constant. Alternatively, both versions could be provided, like `futures::task::noop_waker()` and `futures::task::noop_waker_ref()`, but that seems to me to be API clutter for a very small benefit, whereas having the `&'static` reference available is a large reduction in boilerplate. [Previous discussion on the tracking issue starting here](rust-lang#98286 (comment))
Change return type of unstable `Waker::noop()` from `Waker` to `&Waker`. The advantage of this is that it does not need to be assigned to a variable to be used in a `Context` creation, which is the most common thing to want to do with a noop waker. It also avoids unnecessarily executing the dynamically dispatched drop function when the noop waker is dropped. If an owned noop waker is desired, it can be created by cloning, but the reverse is harder to do since it requires declaring a constant. Alternatively, both versions could be provided, like `futures::task::noop_waker()` and `futures::task::noop_waker_ref()`, but that seems to me to be API clutter for a very small benefit, whereas having the `&'static` reference available is a large reduction in boilerplate. [Previous discussion on the tracking issue starting here](rust-lang#98286 (comment))
Change return type of unstable `Waker::noop()` from `Waker` to `&Waker`. The advantage of this is that it does not need to be assigned to a variable to be used in a `Context` creation, which is the most common thing to want to do with a noop waker. It also avoids unnecessarily executing the dynamically dispatched drop function when the noop waker is dropped. If an owned noop waker is desired, it can be created by cloning, but the reverse is harder to do since it requires declaring a constant. Alternatively, both versions could be provided, like `futures::task::noop_waker()` and `futures::task::noop_waker_ref()`, but that seems to me to be API clutter for a very small benefit, whereas having the `&'static` reference available is a large reduction in boilerplate. [Previous discussion on the tracking issue starting here](rust-lang#98286 (comment))
Change return type of unstable `Waker::noop()` from `Waker` to `&Waker`. The advantage of this is that it does not need to be assigned to a variable to be used in a `Context` creation, which is the most common thing to want to do with a noop waker. It also avoids unnecessarily executing the dynamically dispatched drop function when the noop waker is dropped. If an owned noop waker is desired, it can be created by cloning, but the reverse is harder to do since it requires declaring a constant. Alternatively, both versions could be provided, like `futures::task::noop_waker()` and `futures::task::noop_waker_ref()`, but that seems to me to be API clutter for a very small benefit, whereas having the `&'static` reference available is a large reduction in boilerplate. [Previous discussion on the tracking issue starting here](rust-lang#98286 (comment))
The advantage of this is that it does not need to be assigned to a variable to be used in a `Context` creation, which is the most common thing to want to do with a noop waker. If an owned noop waker is desired, it can be created by cloning, but the reverse is harder. Alternatively, both versions could be provided, like `futures::task::noop_waker()` and `futures::task::noop_waker_ref()`, but that seems to me to be API clutter for a very small benefit, whereas having the `&'static` reference available is a large benefit. Previous discussion on the tracking issue starting here: rust-lang#98286 (comment)
Change return type of unstable `Waker::noop()` from `Waker` to `&Waker`. The advantage of this is that it does not need to be assigned to a variable to be used in a `Context` creation, which is the most common thing to want to do with a noop waker. It also avoids unnecessarily executing the dynamically dispatched drop function when the noop waker is dropped. If an owned noop waker is desired, it can be created by cloning, but the reverse is harder to do since it requires declaring a constant. Alternatively, both versions could be provided, like `futures::task::noop_waker()` and `futures::task::noop_waker_ref()`, but that seems to me to be API clutter for a very small benefit, whereas having the `&'static` reference available is a large reduction in boilerplate. [Previous discussion on the tracking issue starting here](rust-lang#98286 (comment))
@kpreid: You raise a good question about whether this should instead be a |
We discussed this in the WG-async call today. Our consensus was: WG-async is in favor of this being an associated constant of type Thanks for @kpreid for raising this point. As far as why it should be of type pub const NOP_CONTEXT: Context<'static> =
Context::from_waker(&Waker::NOOP);
//~^ ERROR destructor of `Waker` cannot be evaluated at compile-time
//~| NOTE the destructor for this type cannot be evaluated in constants
//~^ ERROR temporary value dropped while borrowed
//~| creates a temporary value which is freed while still in use If the constant has type |
As discussed in <https://rust-lang.zulipchat.com/#narrow/stream/219381-t-libs/topic/Associated.20constants.20vs.2E.20functions.20in.20std.20API>, across `std, outside of argumentless `new()` constructor functions, stable constant values are generally provided using `const` items rather than `const fn`s. Therefore, this change is more consistent API design. WG-async approves of this change, per <rust-lang#98286 (comment)>.
As discussed in <https://rust-lang.zulipchat.com/#narrow/stream/219381-t-libs/topic/Associated.20constants.20vs.2E.20functions.20in.20std.20API>, across `std`, outside of argumentless `new()` constructor functions, stable constant values are generally provided using `const` items rather than `const fn`s. Therefore, this change is more consistent API design. WG-async approves of making this change, per <rust-lang#98286 (comment)>.
As discussed in <https://rust-lang.zulipchat.com/#narrow/stream/219381-t-libs/topic/Associated.20constants.20vs.2E.20functions.20in.20std.20API>, across `std`, outside of argumentless `new()` constructor functions, stable constant values are generally provided using `const` items rather than `const fn`s. Therefore, this change is more consistent API design. WG-async approves of making this change, per <rust-lang#98286 (comment)>.
For cross-reference, and @traviscross FYI, I opened #122924 to implement the change to a constant, and I got an objection from @joboet on the grounds that
|
Replied to that here with further discussion continuing there. |
T-libs-api and myself discussed the question of |
Apologies for further bikeshedding on this smallest of features, but was this form ever considered? I kind of like Either way, what's left? FCP? |
Looking forward to this feature. I just noticed that the documentation for I think that the current behavior of |
The thing is that the entire concept of “task” is not formally defined (given various possible executors and combinators; e.g. “Task” is basically “ownership of a
In this frame, |
I don't necessarily disagree, but the whole point of will_wake is to let you reason about task identity. I don't think this is a major problem, but for correctness sake it would make sense to weaken that guarantee, since it doesn't really guarantee anything. will_wake is already described as a "best effort", so it would be good to document that there are degenerate cases where the concept of task identity falls apart |
As I see it, the whole point of |
I'm not arguing, just sharing concerns :) |
I wanted a no-op waker for an exciting future I'm writing. I ended up implementing my own, of course. I also noticed the possibility for misuse, and there was some confusion amongst some of my colleagues. I thought it best to document when not to use this, and made #128064 for that. It would be nice to see this stabilised in some form, even if only to give those docs more exposure. |
#128064 was merged so can we proceed with the stabilization of |
Stabilize noop_waker Tracking Issue: rust-lang#98286 This is a handy feature that's been used widely in tests and example async code and it'd be nice to make it available to users. cc `@rust-lang/wg-async`
Stabilize noop_waker Tracking Issue: rust-lang#98286 This is a handy feature that's been used widely in tests and example async code and it'd be nice to make it available to users. cc ``@rust-lang/wg-async``
Stabilize noop_waker Tracking Issue: rust-lang#98286 This is a handy feature that's been used widely in tests and example async code and it'd be nice to make it available to users. cc `@rust-lang/wg-async`
Stabilize noop_waker Tracking Issue: rust-lang#98286 This is a handy feature that's been used widely in tests and example async code and it'd be nice to make it available to users. cc `@rust-lang/wg-async`
Stabilize noop_waker Tracking Issue: rust-lang#98286 This is a handy feature that's been used widely in tests and example async code and it'd be nice to make it available to users. cc `@rust-lang/wg-async`
Stabilize noop_waker Tracking Issue: rust-lang#98286 This is a handy feature that's been used widely in tests and example async code and it'd be nice to make it available to users. cc `@rust-lang/wg-async`
Feature gate:
#![feature(noop_waker)]
This is a tracking issue for
task::Waker::noop
, a way to easily cratetask::Waker
s that do nothing.Public API
Steps / History
task::Waker::noop
#96875Unresolved Questions
RawWaker::noop()
? (I don't think so, I can't think of a use case for it)Context::noop()
? Depending on the directionContext
goes a “noop context” might not even make sense in future.Should it be an associated constant instead? That would allow forlet cx = &mut Context::from_waker(&Waker::NOOP);
to work on one line (without additional local variables) which is convenient.Waker::noop()
has now been changed to&Waker
.The text was updated successfully, but these errors were encountered: