Skip to content
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

compare_and_swap "migration" documentation should explain how to get return value #80486

Open
RalfJung opened this issue Dec 29, 2020 · 8 comments
Labels
A-docs Area: documentation for any part of the project, including the compiler, standard library, and tools C-enhancement Category: An issue proposing an enhancement or a PR with one. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.

Comments

@RalfJung
Copy link
Member

RalfJung commented Dec 29, 2020

The compare_and_swap docs explain how to switch the order to compare_exchange, but that is not the only difference: the return type also changed. The docs don't say anything about how to best get the old behavior back with the new method. Many concurrent algorithms are written based on getting the old value back, so there should be a convenient way to get that behavior.

Cc @faern

@RalfJung
Copy link
Member Author

FWIW, the underlying primitive in LLVM that backs compare_exchange returns (T, bool) -- which IMO makes much more sense than Result<T, T>. But that ship has long sailed...

@RalfJung
Copy link
Member Author

Looks like unwrap_or_else(|x| x) is one option. It's not pretty but it works.

@m-ou-se
Copy link
Member

m-ou-se commented Dec 29, 2020

related: #79315

@camelid camelid added C-enhancement Category: An issue proposing an enhancement or a PR with one. A-docs Area: documentation for any part of the project, including the compiler, standard library, and tools T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. labels Dec 30, 2020
@lolgesten
Copy link

I'm probably dense, but I don't understand how I am supposed to change my code.

This is what I had, but reading the compare_exchange documentation, I don't understand what I'm supposed to do now.

    if !DRAIN_MODE.compare_and_swap(false, true, Ordering::Relaxed) {

I understand the motivation for the deprecation, but I feel sad it's done at the cost of a more complex API. For my use case, I simply want atomic access to a bool, and now I'm forced to get my head around the double Ordering parameters to get slightly better performance on ARM (a platform I don't use) + a double boolean Result return type.

Wouldn't it be possible to not deprecate compare_and_swap for people like me, who just want the simple use case?

@RalfJung
Copy link
Member Author

RalfJung commented Feb 23, 2021

@lolgesten without commenting on the rest of what you said, this is how you could change your code:

    if !DRAIN_MODE.compare_exchange(false, true, Ordering::Relaxed, Ordering::Relaxed).unwrap_or_else(|x| x) {

This translation can be applied systematically.

However, I assume what you really want to express here is "if the CAS happened successfully", which would be more clearly expressed as

    if let Ok(_) = DRAIN_MODE.compare_exchange(false, true, Ordering::Relaxed, Ordering::Relaxed) {

or

    if DRAIN_MODE.compare_exchange(false, true, Ordering::Relaxed, Ordering::Relaxed).is_ok() {

Arguably, this code is more clear than your original code, since it is easier to see that it checks for "successful CAS".

@lolgesten
Copy link

@RalfJung thanks! This is what I was suspecting I should do.

In terms of improving the documentation. The table added in the doc for compare_and_swap has the column names "Original", "Success", "Failure". Maybe that could be improved to more clearly indicate the columns are for compare_and_swap and compare_exchange arg1 and compare_exchange arg2.

And also

The return value is a result indicating whether the new value was written and containing the previous value. On success this value is guaranteed to be equal to current.

It's not clear to me whether the doc about failure here is equivalent to Result::Err(boolean). The docs could maybe be clearer about what Result::Ok vs Result:Err means.

@faern
Copy link
Contributor

faern commented Feb 23, 2021

I agree that the "Original" column could be better named. But the column names "Success" and "Failure" are named after the arguments to compare_exchange. I think that makes sense. arg1 and arg2 would be strange since the first two arguments to compare_exchange is current and new. But yes, the text could elaborate a bit more and show one example of a migration maybe.

@RalfJung
Copy link
Member Author

Can they be simply done by opening a PR

Yes. :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-docs Area: documentation for any part of the project, including the compiler, standard library, and tools C-enhancement Category: An issue proposing an enhancement or a PR with one. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

5 participants