-
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
Override Waker::clone_from
to avoid cloning Waker
s unnecessarily
#96979
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -231,6 +231,10 @@ impl fmt::Debug for Context<'_> { | |
/// this might be done to wake a future when a blocking function call completes on another | ||
/// thread. | ||
/// | ||
/// Note that it is preferable to use `waker.clone_from(&new_waker)` instead | ||
/// of `*waker = new_waker.clone()`, as the former will avoid cloning the waker | ||
/// unnecessarily if the two wakers [wake the same task](Self::will_wake). | ||
/// | ||
/// [`Future::poll()`]: core::future::Future::poll | ||
/// [`Poll::Pending`]: core::task::Poll::Pending | ||
#[cfg_attr(not(doc), repr(transparent))] // work around https://github.com/rust-lang/rust/issues/66401 | ||
|
@@ -302,7 +306,9 @@ impl Waker { | |
/// when the `Waker`s would awaken the same task. However, if this function | ||
/// returns `true`, it is guaranteed that the `Waker`s will awaken the same task. | ||
/// | ||
/// This function is primarily used for optimization purposes. | ||
/// This function is primarily used for optimization purposes — for example, | ||
/// this type's [`clone_from`](Self::clone_from) implementation uses it to | ||
/// avoid cloning the waker when they would wake the same task anyway. | ||
#[inline] | ||
#[must_use] | ||
#[stable(feature = "futures_api", since = "1.36.0")] | ||
|
@@ -382,6 +388,13 @@ impl Clone for Waker { | |
waker: unsafe { (self.waker.vtable.clone)(self.waker.data) }, | ||
} | ||
} | ||
|
||
#[inline] | ||
fn clone_from(&mut self, source: &Self) { | ||
if !self.will_wake(source) { | ||
*self = source.clone(); | ||
} | ||
} | ||
Comment on lines
+392
to
+397
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Normally, Waker runs clone side effects. This, in some cases, avoids doing so. This seems like observable behavior. Are we okay with changing it? Are there implementations "in the wild" that will be affected negatively by this? Normally, There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This changes how the code is executed, but not its semantics. Like Moreover, I can't imagine any sane code where this breaks something. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It can potentially have an arbitrary side-effect, like printing an integer, but of course I think ruling that as a fundamentally unserious use-case (or at least, easily circumvented by not calling |
||
} | ||
|
||
#[stable(feature = "futures_api", since = "1.36.0")] | ||
|
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.
Unsure if it'd make sense to do this here or another PR, but it might be good to add docs here to aid discoverability (I believe rustdoc pops open trait impls by default when an associated item has docs? or at least it'll catch the eye when scanning the page), and also especially since the will_wake docs link here. I can't remember it off the top of my head, but I'm almost certain there's prior art in the standard library of adding docs to associated items of an impl.
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 think we can handle that in a followup. It might be a good idea to doc ~all the overridden
clone_from
s in std as a single PR.