-
Notifications
You must be signed in to change notification settings - Fork 13.4k
Rewrite docs for fetch_update for clarity #136036
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
base: master
Are you sure you want to change the base?
Conversation
This comment has been minimized.
This comment has been minimized.
Once the proposed text replacement is approved, I will copy it to the other two places that define fetch_update. |
☔ The latest upstream changes (presumably #136185) made this pull request unmergeable. Please resolve the merge conflicts. |
In particular also uses the same names for the orderings as compare_exchange does to reduce confusion as per rust-lang#89116.
mut f: F) -> Result<$int_type, $int_type> | ||
where F: FnMut($int_type) -> Option<$int_type> { | ||
let mut prev = self.load(fetch_order); | ||
let mut prev = self.load(failure); |
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.
perhaps a comment explaining why we are loading with the 'failure' order could be added here?
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 not sold on this particular naming, but this change tries to bring this into line with compare_exchange's use of the terms. It explains the terms like this: "success describes the required ordering for the read-modify-write operation that takes place if the comparison with current succeeds. failure describes the required ordering for the load operation that takes place when the comparison fails.". Perhaps update_order
and load_order
are better terms?
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 existing set_order
and fetch_order
are probably fine. It would indeed seem weird to immediately load a value using failure
.
/// Note: susceptible to the [ABA Problem](https://en.wikipedia.org/wiki/ABA_problem). | ||
/// | ||
/// **Note**: This method is only available on platforms that support atomic operations on | ||
#[doc = concat!("[`", $s_int_type, "`].")] | ||
/// | ||
/// # Considerations | ||
/// | ||
/// This method is not magic; it is not provided by the hardware. | ||
/// It is implemented in terms of | ||
#[doc = concat!("[`", stringify!($atomic_type), "::compare_exchange_weak`],")] | ||
/// and suffers from the same drawbacks. | ||
/// In particular, this method will not circumvent the [ABA Problem]. | ||
/// | ||
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem | ||
/// |
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.
Why was this changed? IMO the longer version is better.
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 implementation using compare_exchange_weak is now explicitly described. This makes it unnecessary to say it is not magic, because that is now obvious. Also, users are more likely to look at the docs for compare_exchange_weak. That leaves the "in particular ... ABA problem", which I've shortened to its core, which is that this method is "susceptible to the ABA Problem".
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 explicit description of how the implementation uses compare_exchange_weak is also why I removed the copy of the description of the constraints on the memory orderings which comes directly from using compare_exchange_weak. Thanks for reviewing!
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.
Agreed with @Sky9x, this section should remain. It's one thing to explain that this uses compare_exchange_weak
, another thing to confirm that it doesn't somehow do some tricks to avoid compare_exchange_weak
's limitations.
Plus I have definitely seen this specific section get linked around.
☔ The latest upstream changes (presumably #142432) made this pull request unmergeable. Please resolve the merge conflicts. |
/// Loads the current value, applies a closure to it, and optionally tries to store a new value. | ||
/// If the closure ever returns None, this method will immediately return `Err(current value)`. |
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 needs an empty line between the two sentences here; otherwise rustdoc will treat the entire section here as the summary line.
/// If the closure returns Some(new value), then this method calls | ||
#[doc = concat!("[`", stringify!($atomic_type), "::compare_exchange_weak`]")] | ||
/// to try to store the new value. | ||
/// If storing a new value fails, because another thread changed the current value, |
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.
/// If storing a new value fails, because another thread changed the current value, | |
/// If storing a new value fails (due to another thread changing the current value) |
Suggested reword to avoid using comma+"because" for an interjection
/// then the given closure will be called again on the new current value | ||
/// (that was just returned by compare_exchange_weak), | ||
/// until either the closure returns None, | ||
/// or compare_exchange_weak succeeds in storing a new value. | ||
/// Returns `Ok(previous value)` if it ever succeeds in storing a new value. | ||
/// Takes a success and a failure [`Ordering`] to pass on to compare_exchange_weak, | ||
/// and also uses the failure ordering for the initial load. |
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.
/// then the given closure will be called again on the new current value | |
/// (that was just returned by compare_exchange_weak), | |
/// until either the closure returns None, | |
/// or compare_exchange_weak succeeds in storing a new value. | |
/// Returns `Ok(previous value)` if it ever succeeds in storing a new value. | |
/// Takes a success and a failure [`Ordering`] to pass on to compare_exchange_weak, | |
/// and also uses the failure ordering for the initial load. | |
/// then the given closure will be called again on the new current value, | |
/// which was just returned by `compare_exchange_weak`. | |
/// This will repeat until either the closure returns None, | |
/// or `compare_exchange_weak` succeeds in storing a new value. The return value is | |
/// `Ok(previous value)` if a new value was ever successfully stored, otherwise | |
/// `Err(current_value)` | |
/// | |
/// Takes a success and a failure [`Ordering`] to pass on to `compare_exchange_weak`, | |
/// and also uses the failure ordering for the initial load. |
Few suggestions:
- Split the long sentence and make the CEW call part of the main flow.
- Mention the
Err
condition right next toOk
. - Split the ordering discussion to a new paragraph.
compare_exchange_weak
needs backticks
Also please make sure to rewrap doc comments to 100 chars before merge, or as far as is possible with the scattered #[doc]
attributes.
/// Note: susceptible to the [ABA Problem](https://en.wikipedia.org/wiki/ABA_problem). | ||
/// | ||
/// **Note**: This method is only available on platforms that support atomic operations on | ||
#[doc = concat!("[`", $s_int_type, "`].")] | ||
/// | ||
/// # Considerations | ||
/// | ||
/// This method is not magic; it is not provided by the hardware. | ||
/// It is implemented in terms of | ||
#[doc = concat!("[`", stringify!($atomic_type), "::compare_exchange_weak`],")] | ||
/// and suffers from the same drawbacks. | ||
/// In particular, this method will not circumvent the [ABA Problem]. | ||
/// | ||
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem | ||
/// |
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.
Agreed with @Sky9x, this section should remain. It's one thing to explain that this uses compare_exchange_weak
, another thing to confirm that it doesn't somehow do some tricks to avoid compare_exchange_weak
's limitations.
Plus I have definitely seen this specific section get linked around.
while let Some(next) = f(prev) { | ||
match self.compare_exchange_weak(prev, next, set_order, fetch_order) { | ||
match self.compare_exchange_weak(prev, next, success, failure) { | ||
x @ Ok(_) => return x, | ||
Err(next_prev) => prev = next_prev | ||
} |
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.
Please make sure to update update
and try_update
as well once this is closer to ready #135894
mut f: F) -> Result<$int_type, $int_type> | ||
where F: FnMut($int_type) -> Option<$int_type> { | ||
let mut prev = self.load(fetch_order); | ||
let mut prev = self.load(failure); |
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 existing set_order
and fetch_order
are probably fine. It would indeed seem weird to immediately load a value using failure
.
@tgross35, thanks for reviewing! I'll look at each of your points soon. |
In particular also uses the same names for the orderings as compare_exchange does to reduce confusion as per #89116.