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

Tracking issue for compare_exchange #31767

Closed
alexcrichton opened this issue Feb 18, 2016 · 16 comments
Closed

Tracking issue for compare_exchange #31767

alexcrichton opened this issue Feb 18, 2016 · 16 comments
Labels
B-unstable Blocker: Implemented in the nightly compiler and unstable. final-comment-period In the final comment period and will be merged soon unless new substantive objections are raised. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.

Comments

@alexcrichton
Copy link
Member

Tracking issue for rust-lang/rfcs#1443

@alexcrichton alexcrichton added B-RFC-approved Blocker: Approved by a merged RFC but not yet implemented. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. labels Feb 18, 2016
@alexcrichton
Copy link
Member Author

cc @Amanieu and #30969 (the implementation)

@alexcrichton alexcrichton added B-unstable Blocker: Implemented in the nightly compiler and unstable. and removed B-RFC-approved Blocker: Approved by a merged RFC but not yet implemented. labels Feb 22, 2016
@alexcrichton
Copy link
Member Author

Note that the FCP for this should also take into account that the stable compare_and_swap should be deprecated

@Amanieu
Copy link
Member

Amanieu commented Feb 22, 2016

I'm having second thoughts about the return type of compare_exchange_weak. (bool, T) doesn't seem very user-friendly, maybe we could replace it with an enum?

@huonw
Copy link
Member

huonw commented Feb 22, 2016

As @Amanieu says, is there a reason that compare_exchange_weak doesn't/can't return Result? i.e. the method on the various Atomic* types is

fn compare_exchange_weak(&self, current: T, new: T, success: Ordering, failure: Ordering) -> Result<T, T>; 

It seems we forgot about this option on the RFC. Thoughts, @rust-lang/libs?

@Amanieu
Copy link
Member

Amanieu commented Feb 22, 2016

I don't think a Result is appropriate in this case since T is not an error type.

@alexcrichton
Copy link
Member Author

Hm, arguably both methods could return Result<T, T> perhaps? Ok(T) means that it was swapped out and T was previously there, whereas Err(T) would mean that it wasn't swapped out and T was the value previously there.

That'd at least unify the APIs, but @Amanieu is right in that .unwrap() may not work or try! in general because T isn't a first-class error. We could add a wrapper, but that may just be overkill?

@Amanieu
Copy link
Member

Amanieu commented Feb 22, 2016

I agree with @alexcrichton that both methods should return the same enum type for consistency. Note that this would require a breaking change the atomic_cxchg intrinsics, which will affect anyone using them directly. However, I still think we should use a custom enum rather than Result.

For reference, here is what I expect a typical compare_exchange_weak loop to look like (with the current (bool, T) return type):

// Load the initial value
let mut val = ATOMIC.load(Ordering::Relaxed);
loop {
    // Do something with it and determine the new value
    let new = do_something(val);

    // Now attempt to atomically change the value to the new one
    match ATOMIC.compare_exchange_weak(val, new, Ordering::Acquire, Ordering::Relaxed) {
        // Success
        (true, _) => break,

        // Failure, we get the current value back. Use that to try again.
        (false, old) => val = old,
    }
}

@huonw
Copy link
Member

huonw commented Feb 22, 2016

The intrinsics do not need to change, the exposed functions can wrap the raw return values up into something more Rusty, like we do for checked arithmetic. This approach is in fact significantly easier than getting the compiler to construct the right enum internally. (Additionally, changing them is entirely unproblematic, they're unstable for a reason)


I don't think anyone would use unwrap: the only reason to use a CAS (rather than just a plain old swap) is if you expect failure. And, try! is mostly similar (although I could imagine propagating a CAS-failure up out of a helper function that is called by some main loop). The fact that these core Result-manipulators don't seem to apply possibly argues for a new enum, but this is a succeeded (Ok)/failed (Err) situation, meaning Result doesn't seem entirely inappropriate to me.

(The first sentence makes me realise: it's somewhat unfortunate that we have mem::swap and Atomic...::swap, but this is ..._exchange, but there's probably not much we can do about that. Having another method with both compare and swap in its name seems like it would just be maliciously designed for maximum confusion with the deprecated compare_and_swap.)

Diving into the details, maybe the return value should be Result<(), T> (or, with a custom enum, enum CasResult<T> { Succeeded, Failed(T) }), since one already knows the old value in the successful case, and, it's often no longer needed anyway (as seen in @Amanieu's snippet).

@alexcrichton
Copy link
Member Author

I personally recommended Result for a few reasons:

  • We've backed away from custom enums in the past before (towards Result)
  • While this isn't necessarily a case for Result-style manipulation, the suite of methods on Result are quite nice
  • Result is ubiquitously known, ergonomic to use, and doesn't add any extra overhead in terms of what you cognitively need to understand.

I suspect many compare_exchange calls would just be followed by .is_ok() in the long run. I'd also lean more towards not hiding information where although Result<(), T> is more semantically correct (you've relinquished ownership kinda) I'd still vote for Result<T, T> as we've got the info and someone will want to use it.

@aturon
Copy link
Member

aturon commented Mar 10, 2016

cc me

@Amanieu
Copy link
Member

Amanieu commented Mar 12, 2016

Should the swap function be deprecated and replaced with exchange? It is the only function whose name doesn't match the C++11 ones. Additionally it isn't consistent with the new compare_exchange names.

@alexcrichton
Copy link
Member Author

I personally would prefer the name swap to exchange and wouldn't want to cause too much unnecessary churn from this, but good to consider!

bors added a commit that referenced this issue Mar 19, 2016
Change compare_exchange to return a Result<T, T>

As per the discussion in #31767

I also changed the feature name from `extended_compare_and_swap` to `compare_exchange`.

r? @alexcrichton
@alexcrichton
Copy link
Member Author

🔔 This issue is now entering its cycle-long final comment period for stabilization 🔔

@alexcrichton alexcrichton added final-comment-period In the final comment period and will be merged soon unless new substantive objections are raised. and removed I-nominated labels Apr 29, 2016
@alexcrichton
Copy link
Member Author

alexcrichton commented Apr 29, 2016

Ah and as a plan of action the libs team proposes:

  • Stabilizing these APIs in 1.10
  • Deprecating compare_and_swap in 1.12

That way there is always a stable non-deprecated way to do compare and swap!

@alexcrichton
Copy link
Member Author

The libs team discussed this during triage yesterday and the decision was to stabilize

alexcrichton added a commit to alexcrichton/rust that referenced this issue May 24, 2016
This commit applies the FCP decisions made by the libs team for the 1.10 cycle,
including both new stabilizations and deprecations. Specifically, the list of
APIs is:

Stabilized:

* `os::windows::fs::OpenOptionsExt::access_mode`
* `os::windows::fs::OpenOptionsExt::share_mode`
* `os::windows::fs::OpenOptionsExt::custom_flags`
* `os::windows::fs::OpenOptionsExt::attributes`
* `os::windows::fs::OpenOptionsExt::security_qos_flags`
* `os::unix::fs::OpenOptionsExt::custom_flags`
* `sync::Weak::new`
* `Default for sync::Weak`
* `panic::set_hook`
* `panic::take_hook`
* `panic::PanicInfo`
* `panic::PanicInfo::payload`
* `panic::PanicInfo::location`
* `panic::Location`
* `panic::Location::file`
* `panic::Location::line`
* `ffi::CStr::from_bytes_with_nul`
* `ffi::CStr::from_bytes_with_nul_unchecked`
* `ffi::FromBytesWithNulError`
* `fs::Metadata::modified`
* `fs::Metadata::accessed`
* `fs::Metadata::created`
* `sync::atomic::Atomic{Usize,Isize,Bool,Ptr}::compare_exchange`
* `sync::atomic::Atomic{Usize,Isize,Bool,Ptr}::compare_exchange_weak`
* `collections::{btree,hash}_map::{Occupied,Vacant,}Entry::key`
* `os::unix::net::{UnixStream, UnixListener, UnixDatagram, SocketAddr}`
* `SocketAddr::is_unnamed`
* `SocketAddr::as_pathname`
* `UnixStream::connect`
* `UnixStream::pair`
* `UnixStream::try_clone`
* `UnixStream::local_addr`
* `UnixStream::peer_addr`
* `UnixStream::set_read_timeout`
* `UnixStream::set_write_timeout`
* `UnixStream::read_timeout`
* `UnixStream::write_Timeout`
* `UnixStream::set_nonblocking`
* `UnixStream::take_error`
* `UnixStream::shutdown`
* Read/Write/RawFd impls for `UnixStream`
* `UnixListener::bind`
* `UnixListener::accept`
* `UnixListener::try_clone`
* `UnixListener::local_addr`
* `UnixListener::set_nonblocking`
* `UnixListener::take_error`
* `UnixListener::incoming`
* RawFd impls for `UnixListener`
* `UnixDatagram::bind`
* `UnixDatagram::unbound`
* `UnixDatagram::pair`
* `UnixDatagram::connect`
* `UnixDatagram::try_clone`
* `UnixDatagram::local_addr`
* `UnixDatagram::peer_addr`
* `UnixDatagram::recv_from`
* `UnixDatagram::recv`
* `UnixDatagram::send_to`
* `UnixDatagram::send`
* `UnixDatagram::set_read_timeout`
* `UnixDatagram::set_write_timeout`
* `UnixDatagram::read_timeout`
* `UnixDatagram::write_timeout`
* `UnixDatagram::set_nonblocking`
* `UnixDatagram::take_error`
* `UnixDatagram::shutdown`
* RawFd impls for `UnixDatagram`
* `{BTree,Hash}Map::values_mut`
* `<[_]>::binary_search_by_key`

Deprecated:

* `StaticCondvar` - this, and all other static synchronization primitives
                    below, are usable today through the lazy-static crate on
                    stable Rust today. Additionally, we'd like the non-static
                    versions to be directly usable in a static context one day,
                    so they're unlikely to be the final forms of the APIs in any
                    case.
* `CONDVAR_INIT`
* `StaticMutex`
* `MUTEX_INIT`
* `StaticRwLock`
* `RWLOCK_INIT`
* `iter::Peekable::is_empty`

Closes rust-lang#27717
Closes rust-lang#27720
cc rust-lang#27784 (but encode methods still exist)
Closes rust-lang#30014
Closes rust-lang#30425
Closes rust-lang#30449
Closes rust-lang#31190
Closes rust-lang#31399
Closes rust-lang#31767
Closes rust-lang#32111
Closes rust-lang#32281
Closes rust-lang#32312
Closes rust-lang#32551
Closes rust-lang#33018
bors added a commit that referenced this issue May 26, 2016
std: Stabilize APIs for the 1.10 release

This commit applies the FCP decisions made by the libs team for the 1.10 cycle,
including both new stabilizations and deprecations. Specifically, the list of
APIs is:

Stabilized:

* `os::windows::fs::OpenOptionsExt::access_mode`
* `os::windows::fs::OpenOptionsExt::share_mode`
* `os::windows::fs::OpenOptionsExt::custom_flags`
* `os::windows::fs::OpenOptionsExt::attributes`
* `os::windows::fs::OpenOptionsExt::security_qos_flags`
* `os::unix::fs::OpenOptionsExt::custom_flags`
* `sync::Weak::new`
* `Default for sync::Weak`
* `panic::set_hook`
* `panic::take_hook`
* `panic::PanicInfo`
* `panic::PanicInfo::payload`
* `panic::PanicInfo::location`
* `panic::Location`
* `panic::Location::file`
* `panic::Location::line`
* `ffi::CStr::from_bytes_with_nul`
* `ffi::CStr::from_bytes_with_nul_unchecked`
* `ffi::FromBytesWithNulError`
* `fs::Metadata::modified`
* `fs::Metadata::accessed`
* `fs::Metadata::created`
* `sync::atomic::Atomic{Usize,Isize,Bool,Ptr}::compare_exchange`
* `sync::atomic::Atomic{Usize,Isize,Bool,Ptr}::compare_exchange_weak`
* `collections::{btree,hash}_map::{Occupied,Vacant,}Entry::key`
* `os::unix::net::{UnixStream, UnixListener, UnixDatagram, SocketAddr}`
* `SocketAddr::is_unnamed`
* `SocketAddr::as_pathname`
* `UnixStream::connect`
* `UnixStream::pair`
* `UnixStream::try_clone`
* `UnixStream::local_addr`
* `UnixStream::peer_addr`
* `UnixStream::set_read_timeout`
* `UnixStream::set_write_timeout`
* `UnixStream::read_timeout`
* `UnixStream::write_Timeout`
* `UnixStream::set_nonblocking`
* `UnixStream::take_error`
* `UnixStream::shutdown`
* Read/Write/RawFd impls for `UnixStream`
* `UnixListener::bind`
* `UnixListener::accept`
* `UnixListener::try_clone`
* `UnixListener::local_addr`
* `UnixListener::set_nonblocking`
* `UnixListener::take_error`
* `UnixListener::incoming`
* RawFd impls for `UnixListener`
* `UnixDatagram::bind`
* `UnixDatagram::unbound`
* `UnixDatagram::pair`
* `UnixDatagram::connect`
* `UnixDatagram::try_clone`
* `UnixDatagram::local_addr`
* `UnixDatagram::peer_addr`
* `UnixDatagram::recv_from`
* `UnixDatagram::recv`
* `UnixDatagram::send_to`
* `UnixDatagram::send`
* `UnixDatagram::set_read_timeout`
* `UnixDatagram::set_write_timeout`
* `UnixDatagram::read_timeout`
* `UnixDatagram::write_timeout`
* `UnixDatagram::set_nonblocking`
* `UnixDatagram::take_error`
* `UnixDatagram::shutdown`
* RawFd impls for `UnixDatagram`
* `{BTree,Hash}Map::values_mut`
* `<[_]>::binary_search_by_key`

Deprecated:

* `StaticCondvar` - this, and all other static synchronization primitives
                    below, are usable today through the lazy-static crate on
                    stable Rust today. Additionally, we'd like the non-static
                    versions to be directly usable in a static context one day,
                    so they're unlikely to be the final forms of the APIs in any
                    case.
* `CONDVAR_INIT`
* `StaticMutex`
* `MUTEX_INIT`
* `StaticRwLock`
* `RWLOCK_INIT`
* `iter::Peekable::is_empty`

Closes #27717
Closes #27720
Closes #30014
Closes #30425
Closes #30449
Closes #31190
Closes #31399
Closes #31767
Closes #32111
Closes #32281
Closes #32312
Closes #32551
Closes #33018
alexcrichton added a commit to alexcrichton/rust that referenced this issue May 26, 2016
This commit applies the FCP decisions made by the libs team for the 1.10 cycle,
including both new stabilizations and deprecations. Specifically, the list of
APIs is:

Stabilized:

* `os::windows::fs::OpenOptionsExt::access_mode`
* `os::windows::fs::OpenOptionsExt::share_mode`
* `os::windows::fs::OpenOptionsExt::custom_flags`
* `os::windows::fs::OpenOptionsExt::attributes`
* `os::windows::fs::OpenOptionsExt::security_qos_flags`
* `os::unix::fs::OpenOptionsExt::custom_flags`
* `sync::Weak::new`
* `Default for sync::Weak`
* `panic::set_hook`
* `panic::take_hook`
* `panic::PanicInfo`
* `panic::PanicInfo::payload`
* `panic::PanicInfo::location`
* `panic::Location`
* `panic::Location::file`
* `panic::Location::line`
* `ffi::CStr::from_bytes_with_nul`
* `ffi::CStr::from_bytes_with_nul_unchecked`
* `ffi::FromBytesWithNulError`
* `fs::Metadata::modified`
* `fs::Metadata::accessed`
* `fs::Metadata::created`
* `sync::atomic::Atomic{Usize,Isize,Bool,Ptr}::compare_exchange`
* `sync::atomic::Atomic{Usize,Isize,Bool,Ptr}::compare_exchange_weak`
* `collections::{btree,hash}_map::{Occupied,Vacant,}Entry::key`
* `os::unix::net::{UnixStream, UnixListener, UnixDatagram, SocketAddr}`
* `SocketAddr::is_unnamed`
* `SocketAddr::as_pathname`
* `UnixStream::connect`
* `UnixStream::pair`
* `UnixStream::try_clone`
* `UnixStream::local_addr`
* `UnixStream::peer_addr`
* `UnixStream::set_read_timeout`
* `UnixStream::set_write_timeout`
* `UnixStream::read_timeout`
* `UnixStream::write_Timeout`
* `UnixStream::set_nonblocking`
* `UnixStream::take_error`
* `UnixStream::shutdown`
* Read/Write/RawFd impls for `UnixStream`
* `UnixListener::bind`
* `UnixListener::accept`
* `UnixListener::try_clone`
* `UnixListener::local_addr`
* `UnixListener::set_nonblocking`
* `UnixListener::take_error`
* `UnixListener::incoming`
* RawFd impls for `UnixListener`
* `UnixDatagram::bind`
* `UnixDatagram::unbound`
* `UnixDatagram::pair`
* `UnixDatagram::connect`
* `UnixDatagram::try_clone`
* `UnixDatagram::local_addr`
* `UnixDatagram::peer_addr`
* `UnixDatagram::recv_from`
* `UnixDatagram::recv`
* `UnixDatagram::send_to`
* `UnixDatagram::send`
* `UnixDatagram::set_read_timeout`
* `UnixDatagram::set_write_timeout`
* `UnixDatagram::read_timeout`
* `UnixDatagram::write_timeout`
* `UnixDatagram::set_nonblocking`
* `UnixDatagram::take_error`
* `UnixDatagram::shutdown`
* RawFd impls for `UnixDatagram`
* `{BTree,Hash}Map::values_mut`
* `<[_]>::binary_search_by_key`

Deprecated:

* `StaticCondvar` - this, and all other static synchronization primitives
                    below, are usable today through the lazy-static crate on
                    stable Rust today. Additionally, we'd like the non-static
                    versions to be directly usable in a static context one day,
                    so they're unlikely to be the final forms of the APIs in any
                    case.
* `CONDVAR_INIT`
* `StaticMutex`
* `MUTEX_INIT`
* `StaticRwLock`
* `RWLOCK_INIT`
* `iter::Peekable::is_empty`

Closes rust-lang#27717
Closes rust-lang#27720
cc rust-lang#27784 (but encode methods still exist)
Closes rust-lang#30014
Closes rust-lang#30425
Closes rust-lang#30449
Closes rust-lang#31190
Closes rust-lang#31399
Closes rust-lang#31767
Closes rust-lang#32111
Closes rust-lang#32281
Closes rust-lang#32312
Closes rust-lang#32551
Closes rust-lang#33018
@Amanieu
Copy link
Member

Amanieu commented May 2, 2018

It seems that we never got around to deprecating compare_and_swap.

Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this issue Dec 21, 2020
…=Amanieu

Deprecate atomic compare_and_swap method

Finish implementing [RFC 1443](https://github.com/rust-lang/rfcs/blob/master/text/1443-extended-compare-and-swap.md) (rust-lang/rfcs#1443).

It was decided to deprecate `compare_and_swap` [back in Rust 1.12 already](rust-lang#31767 (comment)). I can't find any info about that decision being reverted. My understanding is just that it has been forgotten. If there has been a decision on keeping `compare_and_swap` then it's hard to find, and even if this PR does not go through it can act as a place where people can find out about the decision being reverted.

Atomic operations are hard to understand, very hard. And it does not help that there are multiple similar methods to do compare and swap with. They are so similar that for a reader it might be hard to understand the difference. This PR aims to make that simpler by finally deprecating `compare_and_swap` which is essentially just a more limited version of `compare_exchange`. The documentation is also updated (according to the RFC text) to explain the differences a bit better.

Even if we decide to not deprecate `compare_and_swap`. I still think the documentation for the atomic operations should be improved to better describe their differences and similarities. And the documentation can be written nicer than the PR currently proposes, but I wanted to start somewhere. Most of it is just copied from the RFC.

The documentation for `compare_exchange` and `compare_exchange_weak` indeed describe how they work! The problem is that they are more complex and harder to understand than `compare_and_swap`. So for someone who does not fully grasp this they might fall back to using `compare_and_swap`. Making the documentation outline the similarities and differences might build a bridge for people so they can cross over to the more powerful and sometimes more efficient operations.

The conversions I do to avoid the `std` internal deprecation errors are very straight forward `compare_and_swap -> compare_exchange` changes where the orderings are just using the mapping in the new documentation. Only in one place did I use `compare_exchange_weak`. This can probably be improved further. But the goal here was not for those operations to be perfect. Just to not get worse and to allow the deprecation to happen.
Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this issue Dec 22, 2020
…=Amanieu

Deprecate atomic compare_and_swap method

Finish implementing [RFC 1443](https://github.com/rust-lang/rfcs/blob/master/text/1443-extended-compare-and-swap.md) (rust-lang/rfcs#1443).

It was decided to deprecate `compare_and_swap` [back in Rust 1.12 already](rust-lang#31767 (comment)). I can't find any info about that decision being reverted. My understanding is just that it has been forgotten. If there has been a decision on keeping `compare_and_swap` then it's hard to find, and even if this PR does not go through it can act as a place where people can find out about the decision being reverted.

Atomic operations are hard to understand, very hard. And it does not help that there are multiple similar methods to do compare and swap with. They are so similar that for a reader it might be hard to understand the difference. This PR aims to make that simpler by finally deprecating `compare_and_swap` which is essentially just a more limited version of `compare_exchange`. The documentation is also updated (according to the RFC text) to explain the differences a bit better.

Even if we decide to not deprecate `compare_and_swap`. I still think the documentation for the atomic operations should be improved to better describe their differences and similarities. And the documentation can be written nicer than the PR currently proposes, but I wanted to start somewhere. Most of it is just copied from the RFC.

The documentation for `compare_exchange` and `compare_exchange_weak` indeed describe how they work! The problem is that they are more complex and harder to understand than `compare_and_swap`. So for someone who does not fully grasp this they might fall back to using `compare_and_swap`. Making the documentation outline the similarities and differences might build a bridge for people so they can cross over to the more powerful and sometimes more efficient operations.

The conversions I do to avoid the `std` internal deprecation errors are very straight forward `compare_and_swap -> compare_exchange` changes where the orderings are just using the mapping in the new documentation. Only in one place did I use `compare_exchange_weak`. This can probably be improved further. But the goal here was not for those operations to be perfect. Just to not get worse and to allow the deprecation to happen.
Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this issue Dec 22, 2020
…=Amanieu

Deprecate atomic compare_and_swap method

Finish implementing [RFC 1443](https://github.com/rust-lang/rfcs/blob/master/text/1443-extended-compare-and-swap.md) (rust-lang/rfcs#1443).

It was decided to deprecate `compare_and_swap` [back in Rust 1.12 already](rust-lang#31767 (comment)). I can't find any info about that decision being reverted. My understanding is just that it has been forgotten. If there has been a decision on keeping `compare_and_swap` then it's hard to find, and even if this PR does not go through it can act as a place where people can find out about the decision being reverted.

Atomic operations are hard to understand, very hard. And it does not help that there are multiple similar methods to do compare and swap with. They are so similar that for a reader it might be hard to understand the difference. This PR aims to make that simpler by finally deprecating `compare_and_swap` which is essentially just a more limited version of `compare_exchange`. The documentation is also updated (according to the RFC text) to explain the differences a bit better.

Even if we decide to not deprecate `compare_and_swap`. I still think the documentation for the atomic operations should be improved to better describe their differences and similarities. And the documentation can be written nicer than the PR currently proposes, but I wanted to start somewhere. Most of it is just copied from the RFC.

The documentation for `compare_exchange` and `compare_exchange_weak` indeed describe how they work! The problem is that they are more complex and harder to understand than `compare_and_swap`. So for someone who does not fully grasp this they might fall back to using `compare_and_swap`. Making the documentation outline the similarities and differences might build a bridge for people so they can cross over to the more powerful and sometimes more efficient operations.

The conversions I do to avoid the `std` internal deprecation errors are very straight forward `compare_and_swap -> compare_exchange` changes where the orderings are just using the mapping in the new documentation. Only in one place did I use `compare_exchange_weak`. This can probably be improved further. But the goal here was not for those operations to be perfect. Just to not get worse and to allow the deprecation to happen.
bors added a commit to rust-lang-ci/rust that referenced this issue Dec 23, 2020
…manieu

Deprecate atomic compare_and_swap method

Finish implementing [RFC 1443](https://github.com/rust-lang/rfcs/blob/master/text/1443-extended-compare-and-swap.md) (rust-lang/rfcs#1443).

It was decided to deprecate `compare_and_swap` [back in Rust 1.12 already](rust-lang#31767 (comment)). I can't find any info about that decision being reverted. My understanding is just that it has been forgotten. If there has been a decision on keeping `compare_and_swap` then it's hard to find, and even if this PR does not go through it can act as a place where people can find out about the decision being reverted.

Atomic operations are hard to understand, very hard. And it does not help that there are multiple similar methods to do compare and swap with. They are so similar that for a reader it might be hard to understand the difference. This PR aims to make that simpler by finally deprecating `compare_and_swap` which is essentially just a more limited version of `compare_exchange`. The documentation is also updated (according to the RFC text) to explain the differences a bit better.

Even if we decide to not deprecate `compare_and_swap`. I still think the documentation for the atomic operations should be improved to better describe their differences and similarities. And the documentation can be written nicer than the PR currently proposes, but I wanted to start somewhere. Most of it is just copied from the RFC.

The documentation for `compare_exchange` and `compare_exchange_weak` indeed describe how they work! The problem is that they are more complex and harder to understand than `compare_and_swap`. So for someone who does not fully grasp this they might fall back to using `compare_and_swap`. Making the documentation outline the similarities and differences might build a bridge for people so they can cross over to the more powerful and sometimes more efficient operations.

The conversions I do to avoid the `std` internal deprecation errors are very straight forward `compare_and_swap -> compare_exchange` changes where the orderings are just using the mapping in the new documentation. Only in one place did I use `compare_exchange_weak`. This can probably be improved further. But the goal here was not for those operations to be perfect. Just to not get worse and to allow the deprecation to happen.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
B-unstable Blocker: Implemented in the nightly compiler and unstable. final-comment-period In the final comment period and will be merged soon unless new substantive objections are raised. 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

4 participants