Rollup merge of #142252 - fu5ha:doc-cas-ops, r=ibraheemdev
Improve clarity of `core::sync::atomic` docs about "Considerations" in regards to CAS operations ## Motivation The existing documentation for atomic `fetch_update` (and other similar methods) has a section that reads like so: > ### Considerations > This method is not magic; it is not provided by the hardware. It is implemented in > terms of `AtomicBlah::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 The wording here seems to imply that the drawbacks being discusses are caused by the *`weak` version* of `compare_exchange`, and that one may avoid those drawbacks by using `compare_exchange` instead. Indeed, a conversation in the `#dark-arts` channel on the Rust community discord based on this interpretation led to this PR. In reality, the drawbacks are inherent to implementing such an operation based on *any* compare-and-swap style operation, as opposed to an [LL,SC](https://en.wikipedia.org/wiki/Load-link/store-conditional) operation, and they apply equally to `compare_exchange` and `compare_exchange_weak` as well. ## Changes - Rewords existing Considerations section on `fetch_update` and friends to make clear that the limitations are inherent to an implementation based on any CAS operation, rather than the weak version of `compare_exchange` in particular. New version: > ### Considerations > > This method is not magic; it is not provided by the hardware, and does not act like a > critical section or mutex. > > It is implemented on top of an atomic [compare-and-swap operation], and thus is subject to > the usual drawbacks of CAS operations. In particular, be careful of the [ABA problem] > if this atomic integer is an index or more generally if knowledge of only the *bitwise value* > of the atomic is not in and of itself sufficient to ensure any required preconditions. > > [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem > [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap - Add Considerations to `compare_exchange` and `compare_exchange_weak` which details similar considerations and when they may be relevant. New version: > ### Considerations > > `compare_exchange` is a [compare-and-swap operation] and thus exhibits the usual downsides > of CAS operations. In particular, a load of the value followed by a successful > `compare_exchange` with the previous load *does not ensure* that other threads have not > changed the value in the interim. This is usually important when the *equality* check in > the `compare_exchange` is being used to check the *identity* of a value, but equality > does not necessarily imply identity. In this case, `compare_exchange` can lead to the > [ABA problem]. > > [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem > [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
This commit is contained in:
commit
764be85223
1 changed files with 146 additions and 33 deletions
|
|
@ -891,6 +891,19 @@ impl AtomicBool {
|
|||
/// Err(false));
|
||||
/// assert_eq!(some_bool.load(Ordering::Relaxed), false);
|
||||
/// ```
|
||||
///
|
||||
/// # Considerations
|
||||
///
|
||||
/// `compare_exchange` is a [compare-and-swap operation] and thus exhibits the usual downsides
|
||||
/// of CAS operations. In particular, a load of the value followed by a successful
|
||||
/// `compare_exchange` with the previous load *does not ensure* that other threads have not
|
||||
/// changed the value in the interim. This is usually important when the *equality* check in
|
||||
/// the `compare_exchange` is being used to check the *identity* of a value, but equality
|
||||
/// does not necessarily imply identity. In this case, `compare_exchange` can lead to the
|
||||
/// [ABA problem].
|
||||
///
|
||||
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
|
||||
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
|
||||
#[inline]
|
||||
#[stable(feature = "extended_compare_and_swap", since = "1.10.0")]
|
||||
#[doc(alias = "compare_and_swap")]
|
||||
|
|
@ -973,6 +986,19 @@ impl AtomicBool {
|
|||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// # Considerations
|
||||
///
|
||||
/// `compare_exchange` is a [compare-and-swap operation] and thus exhibits the usual downsides
|
||||
/// of CAS operations. In particular, a load of the value followed by a successful
|
||||
/// `compare_exchange` with the previous load *does not ensure* that other threads have not
|
||||
/// changed the value in the interim. This is usually important when the *equality* check in
|
||||
/// the `compare_exchange` is being used to check the *identity* of a value, but equality
|
||||
/// does not necessarily imply identity. In this case, `compare_exchange` can lead to the
|
||||
/// [ABA problem].
|
||||
///
|
||||
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
|
||||
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
|
||||
#[inline]
|
||||
#[stable(feature = "extended_compare_and_swap", since = "1.10.0")]
|
||||
#[doc(alias = "compare_and_swap")]
|
||||
|
|
@ -1271,11 +1297,14 @@ impl AtomicBool {
|
|||
///
|
||||
/// # Considerations
|
||||
///
|
||||
/// This method is not magic; it is not provided by the hardware.
|
||||
/// It is implemented in terms of [`AtomicBool::compare_exchange_weak`], and suffers from the same drawbacks.
|
||||
/// In particular, this method will not circumvent the [ABA Problem].
|
||||
/// This method is not magic; it is not provided by the hardware, and does not act like a
|
||||
/// critical section or mutex.
|
||||
///
|
||||
/// It is implemented on top of an atomic [compare-and-swap operation], and thus is subject to
|
||||
/// the usual drawbacks of CAS operations. In particular, be careful of the [ABA problem].
|
||||
///
|
||||
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
|
||||
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
|
@ -1338,11 +1367,14 @@ impl AtomicBool {
|
|||
///
|
||||
/// # Considerations
|
||||
///
|
||||
/// This method is not magic; it is not provided by the hardware.
|
||||
/// It is implemented in terms of [`AtomicBool::compare_exchange_weak`], and suffers from the same drawbacks.
|
||||
/// In particular, this method will not circumvent the [ABA Problem].
|
||||
/// This method is not magic; it is not provided by the hardware, and does not act like a
|
||||
/// critical section or mutex.
|
||||
///
|
||||
/// It is implemented on top of an atomic [compare-and-swap operation], and thus is subject to
|
||||
/// the usual drawbacks of CAS operations. In particular, be careful of the [ABA problem].
|
||||
///
|
||||
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
|
||||
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
|
@ -1393,11 +1425,14 @@ impl AtomicBool {
|
|||
///
|
||||
/// # Considerations
|
||||
///
|
||||
/// This method is not magic; it is not provided by the hardware.
|
||||
/// It is implemented in terms of [`AtomicBool::compare_exchange_weak`], and suffers from the same drawbacks.
|
||||
/// In particular, this method will not circumvent the [ABA Problem].
|
||||
/// This method is not magic; it is not provided by the hardware, and does not act like a
|
||||
/// critical section or mutex.
|
||||
///
|
||||
/// It is implemented on top of an atomic [compare-and-swap operation], and thus is subject to
|
||||
/// the usual drawbacks of CAS operations. In particular, be careful of the [ABA problem].
|
||||
///
|
||||
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
|
||||
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
|
@ -1825,6 +1860,20 @@ impl<T> AtomicPtr<T> {
|
|||
/// let value = some_ptr.compare_exchange(ptr, other_ptr,
|
||||
/// Ordering::SeqCst, Ordering::Relaxed);
|
||||
/// ```
|
||||
///
|
||||
/// # Considerations
|
||||
///
|
||||
/// `compare_exchange` is a [compare-and-swap operation] and thus exhibits the usual downsides
|
||||
/// of CAS operations. In particular, a load of the value followed by a successful
|
||||
/// `compare_exchange` with the previous load *does not ensure* that other threads have not
|
||||
/// changed the value in the interim. This is usually important when the *equality* check in
|
||||
/// the `compare_exchange` is being used to check the *identity* of a value, but equality
|
||||
/// does not necessarily imply identity. This is a particularly common case for pointers, as
|
||||
/// a pointer holding the same address does not imply that the same object exists at that
|
||||
/// address! In this case, `compare_exchange` can lead to the [ABA problem].
|
||||
///
|
||||
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
|
||||
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
|
||||
#[inline]
|
||||
#[stable(feature = "extended_compare_and_swap", since = "1.10.0")]
|
||||
#[cfg(target_has_atomic = "ptr")]
|
||||
|
|
@ -1874,6 +1923,20 @@ impl<T> AtomicPtr<T> {
|
|||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// # Considerations
|
||||
///
|
||||
/// `compare_exchange` is a [compare-and-swap operation] and thus exhibits the usual downsides
|
||||
/// of CAS operations. In particular, a load of the value followed by a successful
|
||||
/// `compare_exchange` with the previous load *does not ensure* that other threads have not
|
||||
/// changed the value in the interim. This is usually important when the *equality* check in
|
||||
/// the `compare_exchange` is being used to check the *identity* of a value, but equality
|
||||
/// does not necessarily imply identity. This is a particularly common case for pointers, as
|
||||
/// a pointer holding the same address does not imply that the same object exists at that
|
||||
/// address! In this case, `compare_exchange` can lead to the [ABA problem].
|
||||
///
|
||||
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
|
||||
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
|
||||
#[inline]
|
||||
#[stable(feature = "extended_compare_and_swap", since = "1.10.0")]
|
||||
#[cfg(target_has_atomic = "ptr")]
|
||||
|
|
@ -1917,11 +1980,15 @@ impl<T> AtomicPtr<T> {
|
|||
///
|
||||
/// # Considerations
|
||||
///
|
||||
/// This method is not magic; it is not provided by the hardware.
|
||||
/// It is implemented in terms of [`AtomicPtr::compare_exchange_weak`], and suffers from the same drawbacks.
|
||||
/// In particular, this method will not circumvent the [ABA Problem].
|
||||
/// This method is not magic; it is not provided by the hardware, and does not act like a
|
||||
/// critical section or mutex.
|
||||
///
|
||||
/// It is implemented on top of an atomic [compare-and-swap operation], and thus is subject to
|
||||
/// the usual drawbacks of CAS operations. In particular, be careful of the [ABA problem],
|
||||
/// which is a particularly common pitfall for pointers!
|
||||
///
|
||||
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
|
||||
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
|
@ -1992,11 +2059,15 @@ impl<T> AtomicPtr<T> {
|
|||
///
|
||||
/// # Considerations
|
||||
///
|
||||
/// This method is not magic; it is not provided by the hardware.
|
||||
/// It is implemented in terms of [`AtomicPtr::compare_exchange_weak`], and suffers from the same drawbacks.
|
||||
/// In particular, this method will not circumvent the [ABA Problem].
|
||||
/// This method is not magic; it is not provided by the hardware, and does not act like a
|
||||
/// critical section or mutex.
|
||||
///
|
||||
/// It is implemented on top of an atomic [compare-and-swap operation], and thus is subject to
|
||||
/// the usual drawbacks of CAS operations. In particular, be careful of the [ABA problem],
|
||||
/// which is a particularly common pitfall for pointers!
|
||||
///
|
||||
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
|
||||
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
|
@ -2057,11 +2128,15 @@ impl<T> AtomicPtr<T> {
|
|||
///
|
||||
/// # Considerations
|
||||
///
|
||||
/// This method is not magic; it is not provided by the hardware.
|
||||
/// It is implemented in terms of [`AtomicPtr::compare_exchange_weak`], and suffers from the same drawbacks.
|
||||
/// In particular, this method will not circumvent the [ABA Problem].
|
||||
/// This method is not magic; it is not provided by the hardware, and does not act like a
|
||||
/// critical section or mutex.
|
||||
///
|
||||
/// It is implemented on top of an atomic [compare-and-swap operation], and thus is subject to
|
||||
/// the usual drawbacks of CAS operations. In particular, be careful of the [ABA problem],
|
||||
/// which is a particularly common pitfall for pointers!
|
||||
///
|
||||
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
|
||||
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
|
@ -2967,6 +3042,20 @@ macro_rules! atomic_int {
|
|||
/// Err(10));
|
||||
/// assert_eq!(some_var.load(Ordering::Relaxed), 10);
|
||||
/// ```
|
||||
///
|
||||
/// # Considerations
|
||||
///
|
||||
/// `compare_exchange` is a [compare-and-swap operation] and thus exhibits the usual downsides
|
||||
/// of CAS operations. In particular, a load of the value followed by a successful
|
||||
/// `compare_exchange` with the previous load *does not ensure* that other threads have not
|
||||
/// changed the value in the interim! This is usually important when the *equality* check in
|
||||
/// the `compare_exchange` is being used to check the *identity* of a value, but equality
|
||||
/// does not necessarily imply identity. This is a particularly common case for pointers, as
|
||||
/// a pointer holding the same address does not imply that the same object exists at that
|
||||
/// address! In this case, `compare_exchange` can lead to the [ABA problem].
|
||||
///
|
||||
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
|
||||
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
|
||||
#[inline]
|
||||
#[$stable_cxchg]
|
||||
#[$cfg_cas]
|
||||
|
|
@ -3016,6 +3105,20 @@ macro_rules! atomic_int {
|
|||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// # Considerations
|
||||
///
|
||||
/// `compare_exchange` is a [compare-and-swap operation] and thus exhibits the usual downsides
|
||||
/// of CAS operations. In particular, a load of the value followed by a successful
|
||||
/// `compare_exchange` with the previous load *does not ensure* that other threads have not
|
||||
/// changed the value in the interim. This is usually important when the *equality* check in
|
||||
/// the `compare_exchange` is being used to check the *identity* of a value, but equality
|
||||
/// does not necessarily imply identity. This is a particularly common case for pointers, as
|
||||
/// a pointer holding the same address does not imply that the same object exists at that
|
||||
/// address! In this case, `compare_exchange` can lead to the [ABA problem].
|
||||
///
|
||||
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
|
||||
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
|
||||
#[inline]
|
||||
#[$stable_cxchg]
|
||||
#[$cfg_cas]
|
||||
|
|
@ -3246,13 +3349,16 @@ macro_rules! atomic_int {
|
|||
///
|
||||
/// # 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].
|
||||
/// This method is not magic; it is not provided by the hardware, and does not act like a
|
||||
/// critical section or mutex.
|
||||
///
|
||||
/// It is implemented on top of an atomic [compare-and-swap operation], and thus is subject to
|
||||
/// the usual drawbacks of CAS operations. In particular, be careful of the [ABA problem]
|
||||
/// if this atomic integer is an index or more generally if knowledge of only the *bitwise value*
|
||||
/// of the atomic is not in and of itself sufficient to ensure any required preconditions.
|
||||
///
|
||||
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
|
||||
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
|
@ -3309,13 +3415,16 @@ macro_rules! atomic_int {
|
|||
///
|
||||
/// # 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].
|
||||
/// This method is not magic; it is not provided by the hardware, and does not act like a
|
||||
/// critical section or mutex.
|
||||
///
|
||||
/// It is implemented on top of an atomic [compare-and-swap operation], and thus is subject to
|
||||
/// the usual drawbacks of CAS operations. In particular, be careful of the [ABA problem]
|
||||
/// if this atomic integer is an index or more generally if knowledge of only the *bitwise value*
|
||||
/// of the atomic is not in and of itself sufficient to ensure any required preconditions.
|
||||
///
|
||||
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
|
||||
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
|
@ -3367,13 +3476,17 @@ macro_rules! atomic_int {
|
|||
///
|
||||
/// # 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].
|
||||
/// [CAS operation]: https://en.wikipedia.org/wiki/Compare-and-swap
|
||||
/// This method is not magic; it is not provided by the hardware, and does not act like a
|
||||
/// critical section or mutex.
|
||||
///
|
||||
/// It is implemented on top of an atomic [compare-and-swap operation], and thus is subject to
|
||||
/// the usual drawbacks of CAS operations. In particular, be careful of the [ABA problem]
|
||||
/// if this atomic integer is an index or more generally if knowledge of only the *bitwise value*
|
||||
/// of the atomic is not in and of itself sufficient to ensure any required preconditions.
|
||||
///
|
||||
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
|
||||
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue