Skip to content

Commit f019c4d

Browse files
committed
core docs: improve clarity of considerations about atomic CAS operations
- 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 - Add Considerations to `compare_exchange` and `compare_exchange_weak` which details similar considerations and when they may be relevant.
1 parent 14863ea commit f019c4d

File tree

1 file changed

+154
-33
lines changed

1 file changed

+154
-33
lines changed

library/core/src/sync/atomic.rs

Lines changed: 154 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -891,6 +891,19 @@ impl AtomicBool {
891891
/// Err(false));
892892
/// assert_eq!(some_bool.load(Ordering::Relaxed), false);
893893
/// ```
894+
///
895+
/// # Considerations
896+
///
897+
/// `compare_exchange` is a [compare-and-swap operation] and suffers from the usual downsides
898+
/// of CAS operations. In particular, a load of the value followed by a successful
899+
/// `compare_exchange` with the previous load *does not ensure* that other threads have not
900+
/// changed the value in the interim. This is usually important when the *equality* check in
901+
/// the `compare_exchange` is being used to check the *identity* of a value, but equality
902+
/// does not necessarily imply identity. In this case, `compare_exchange` can lead to the
903+
/// [ABA problem].
904+
///
905+
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
906+
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
894907
#[inline]
895908
#[stable(feature = "extended_compare_and_swap", since = "1.10.0")]
896909
#[doc(alias = "compare_and_swap")]
@@ -973,6 +986,19 @@ impl AtomicBool {
973986
/// }
974987
/// }
975988
/// ```
989+
///
990+
/// # Considerations
991+
///
992+
/// `compare_exchange` is a [compare-and-swap operation] and suffers from the usual downsides
993+
/// of CAS operations. In particular, a load of the value followed by a successful
994+
/// `compare_exchange` with the previous load *does not ensure* that other threads have not
995+
/// changed the value in the interim. This is usually important when the *equality* check in
996+
/// the `compare_exchange` is being used to check the *identity* of a value, but equality
997+
/// does not necessarily imply identity. In this case, `compare_exchange` can lead to the
998+
/// [ABA problem].
999+
///
1000+
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
1001+
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
9761002
#[inline]
9771003
#[stable(feature = "extended_compare_and_swap", since = "1.10.0")]
9781004
#[doc(alias = "compare_and_swap")]
@@ -1271,11 +1297,16 @@ impl AtomicBool {
12711297
///
12721298
/// # Considerations
12731299
///
1274-
/// This method is not magic; it is not provided by the hardware.
1275-
/// It is implemented in terms of [`AtomicBool::compare_exchange_weak`], and suffers from the same drawbacks.
1276-
/// In particular, this method will not circumvent the [ABA Problem].
1300+
/// This method is not magic; it is not provided by the hardware, and does not act like a
1301+
/// critical section or mutex. It is implemented in terms of
1302+
/// [`compare_exchange`][Self::compare_exchange]\*, which is a [CAS operation], and thus
1303+
/// suffers from the usual drawbacks of CAS operations, in particular the [ABA problem].
1304+
///
1305+
/// \* It is actually implemented using [`compare_exchange_weak`][Self::compare_exchange_weak],
1306+
/// but that distinction does not change the considerations inherent to a [CAS operation].
12771307
///
12781308
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
1309+
/// [CAS operation]: https://en.wikipedia.org/wiki/Compare-and-swap
12791310
///
12801311
/// # Examples
12811312
///
@@ -1338,11 +1369,16 @@ impl AtomicBool {
13381369
///
13391370
/// # Considerations
13401371
///
1341-
/// This method is not magic; it is not provided by the hardware.
1342-
/// It is implemented in terms of [`AtomicBool::compare_exchange_weak`], and suffers from the same drawbacks.
1343-
/// In particular, this method will not circumvent the [ABA Problem].
1372+
/// This method is not magic; it is not provided by the hardware, and does not act like a
1373+
/// critical section or mutex. It is implemented in terms of
1374+
/// [`compare_exchange`][Self::compare_exchange]\*, which is a [CAS operation], and thus
1375+
/// suffers from the usual drawbacks of CAS operations, in particular the [ABA problem].
1376+
///
1377+
/// \* It is actually implemented using [`compare_exchange_weak`][Self::compare_exchange_weak],
1378+
/// but that distinction does not change the considerations inherent to a [CAS operation].
13441379
///
13451380
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
1381+
/// [CAS operation]: https://en.wikipedia.org/wiki/Compare-and-swap
13461382
///
13471383
/// # Examples
13481384
///
@@ -1393,11 +1429,16 @@ impl AtomicBool {
13931429
///
13941430
/// # Considerations
13951431
///
1396-
/// This method is not magic; it is not provided by the hardware.
1397-
/// It is implemented in terms of [`AtomicBool::compare_exchange_weak`], and suffers from the same drawbacks.
1398-
/// In particular, this method will not circumvent the [ABA Problem].
1432+
/// This method is not magic; it is not provided by the hardware, and does not act like a
1433+
/// critical section or mutex. It is implemented in terms of
1434+
/// [`compare_exchange`][Self::compare_exchange]\*, which is a [CAS operation], and thus
1435+
/// suffers from the usual drawbacks of CAS operations, in particular the [ABA problem].
1436+
///
1437+
/// \* It is actually implemented using [`compare_exchange_weak`][Self::compare_exchange_weak],
1438+
/// but that distinction does not change the considerations inherent to a [CAS operation].
13991439
///
14001440
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
1441+
/// [CAS operation]: https://en.wikipedia.org/wiki/Compare-and-swap
14011442
///
14021443
/// # Examples
14031444
///
@@ -1825,6 +1866,20 @@ impl<T> AtomicPtr<T> {
18251866
/// let value = some_ptr.compare_exchange(ptr, other_ptr,
18261867
/// Ordering::SeqCst, Ordering::Relaxed);
18271868
/// ```
1869+
///
1870+
/// # Considerations
1871+
///
1872+
/// `compare_exchange` is a [compare-and-swap operation] and suffers from the usual downsides
1873+
/// of CAS operations. In particular, a load of the value followed by a successful
1874+
/// `compare_exchange` with the previous load *does not ensure* that other threads have not
1875+
/// changed the value in the interim. This is usually important when the *equality* check in
1876+
/// the `compare_exchange` is being used to check the *identity* of a value, but equality
1877+
/// does not necessarily imply identity. This is a particularly common case for pointers, as
1878+
/// a pointer holding the same address does not imply that the same object exists at that
1879+
/// address! In this case, `compare_exchange` can lead to the [ABA problem].
1880+
///
1881+
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
1882+
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
18281883
#[inline]
18291884
#[stable(feature = "extended_compare_and_swap", since = "1.10.0")]
18301885
#[cfg(target_has_atomic = "ptr")]
@@ -1874,6 +1929,20 @@ impl<T> AtomicPtr<T> {
18741929
/// }
18751930
/// }
18761931
/// ```
1932+
///
1933+
/// # Considerations
1934+
///
1935+
/// `compare_exchange` is a [compare-and-swap operation] and suffers from the usual downsides
1936+
/// of CAS operations. In particular, a load of the value followed by a successful
1937+
/// `compare_exchange` with the previous load *does not ensure* that other threads have not
1938+
/// changed the value in the interim. This is usually important when the *equality* check in
1939+
/// the `compare_exchange` is being used to check the *identity* of a value, but equality
1940+
/// does not necessarily imply identity. This is a particularly common case for pointers, as
1941+
/// a pointer holding the same address does not imply that the same object exists at that
1942+
/// address! In this case, `compare_exchange` can lead to the [ABA problem].
1943+
///
1944+
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
1945+
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
18771946
#[inline]
18781947
#[stable(feature = "extended_compare_and_swap", since = "1.10.0")]
18791948
#[cfg(target_has_atomic = "ptr")]
@@ -1917,11 +1986,16 @@ impl<T> AtomicPtr<T> {
19171986
///
19181987
/// # Considerations
19191988
///
1920-
/// This method is not magic; it is not provided by the hardware.
1921-
/// It is implemented in terms of [`AtomicPtr::compare_exchange_weak`], and suffers from the same drawbacks.
1922-
/// In particular, this method will not circumvent the [ABA Problem].
1989+
/// This method is not magic; it is not provided by the hardware, and does not act like a
1990+
/// critical section or mutex. It is implemented in terms of
1991+
/// [`compare_exchange`][Self::compare_exchange]\*, which is a [CAS operation], and thus
1992+
/// suffers from the usual drawbacks of CAS operations, in particular the [ABA problem].
1993+
///
1994+
/// \* It is actually implemented using [`compare_exchange_weak`][Self::compare_exchange_weak],
1995+
/// but that distinction does not change the considerations inherent to a [CAS operation].
19231996
///
19241997
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
1998+
/// [CAS operation]: https://en.wikipedia.org/wiki/Compare-and-swap
19251999
///
19262000
/// # Examples
19272001
///
@@ -1992,11 +2066,16 @@ impl<T> AtomicPtr<T> {
19922066
///
19932067
/// # Considerations
19942068
///
1995-
/// This method is not magic; it is not provided by the hardware.
1996-
/// It is implemented in terms of [`AtomicPtr::compare_exchange_weak`], and suffers from the same drawbacks.
1997-
/// In particular, this method will not circumvent the [ABA Problem].
2069+
/// This method is not magic; it is not provided by the hardware, and does not act like a
2070+
/// critical section or mutex. It is implemented in terms of
2071+
/// [`compare_exchange`][Self::compare_exchange]\*, which is a [CAS operation], and thus
2072+
/// suffers from the usual drawbacks of CAS operations, in particular the [ABA problem].
2073+
///
2074+
/// \* It is actually implemented using [`compare_exchange_weak`][Self::compare_exchange_weak],
2075+
/// but that distinction does not change the considerations inherent to a [CAS operation].
19982076
///
19992077
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
2078+
/// [CAS operation]: https://en.wikipedia.org/wiki/Compare-and-swap
20002079
///
20012080
/// # Examples
20022081
///
@@ -2057,11 +2136,16 @@ impl<T> AtomicPtr<T> {
20572136
///
20582137
/// # Considerations
20592138
///
2060-
/// This method is not magic; it is not provided by the hardware.
2061-
/// It is implemented in terms of [`AtomicPtr::compare_exchange_weak`], and suffers from the same drawbacks.
2062-
/// In particular, this method will not circumvent the [ABA Problem].
2139+
/// This method is not magic; it is not provided by the hardware, and does not act like a
2140+
/// critical section or mutex. It is implemented in terms of
2141+
/// [`compare_exchange`][Self::compare_exchange]\*, which is a [CAS operation], and thus
2142+
/// suffers from the usual drawbacks of CAS operations, in particular the [ABA problem].
2143+
///
2144+
/// \* It is actually implemented using [`compare_exchange_weak`][Self::compare_exchange_weak],
2145+
/// but that distinction does not change the considerations inherent to a [CAS operation].
20632146
///
20642147
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
2148+
/// [CAS operation]: https://en.wikipedia.org/wiki/Compare-and-swap
20652149
///
20662150
/// # Examples
20672151
///
@@ -2967,6 +3051,20 @@ macro_rules! atomic_int {
29673051
/// Err(10));
29683052
/// assert_eq!(some_var.load(Ordering::Relaxed), 10);
29693053
/// ```
3054+
///
3055+
/// # Considerations
3056+
///
3057+
/// `compare_exchange` is a [compare-and-swap operation] and suffers from the usual downsides
3058+
/// of CAS operations. In particular, a load of the value followed by a successful
3059+
/// `compare_exchange` with the previous load *does not ensure* that other threads have not
3060+
/// changed the value in the interim! This is usually important when the *equality* check in
3061+
/// the `compare_exchange` is being used to check the *identity* of a value, but equality
3062+
/// does not necessarily imply identity. This is a particularly common case for pointers, as
3063+
/// a pointer holding the same address does not imply that the same object exists at that
3064+
/// address! In this case, `compare_exchange` can lead to the [ABA problem].
3065+
///
3066+
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
3067+
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
29703068
#[inline]
29713069
#[$stable_cxchg]
29723070
#[$cfg_cas]
@@ -3016,6 +3114,20 @@ macro_rules! atomic_int {
30163114
/// }
30173115
/// }
30183116
/// ```
3117+
///
3118+
/// # Considerations
3119+
///
3120+
/// `compare_exchange` is a [compare-and-swap operation] and suffers from the usual downsides
3121+
/// of CAS operations. In particular, a load of the value followed by a successful
3122+
/// `compare_exchange` with the previous load *does not ensure* that other threads have not
3123+
/// changed the value in the interim. This is usually important when the *equality* check in
3124+
/// the `compare_exchange` is being used to check the *identity* of a value, but equality
3125+
/// does not necessarily imply identity. This is a particularly common case for pointers, as
3126+
/// a pointer holding the same address does not imply that the same object exists at that
3127+
/// address! In this case, `compare_exchange` can lead to the [ABA problem].
3128+
///
3129+
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
3130+
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
30193131
#[inline]
30203132
#[$stable_cxchg]
30213133
#[$cfg_cas]
@@ -3246,13 +3358,16 @@ macro_rules! atomic_int {
32463358
///
32473359
/// # Considerations
32483360
///
3249-
/// This method is not magic; it is not provided by the hardware.
3250-
/// It is implemented in terms of
3251-
#[doc = concat!("[`", stringify!($atomic_type), "::compare_exchange_weak`],")]
3252-
/// and suffers from the same drawbacks.
3253-
/// In particular, this method will not circumvent the [ABA Problem].
3361+
/// This method is not magic; it is not provided by the hardware, and does not act like a
3362+
/// critical section or mutex. It is implemented in terms of
3363+
/// [`compare_exchange`][Self::compare_exchange]\*, which is a [CAS operation], and thus
3364+
/// suffers from the usual drawbacks of CAS operations, in particular the [ABA problem].
3365+
///
3366+
/// \* It is actually implemented using [`compare_exchange_weak`][Self::compare_exchange_weak],
3367+
/// but that distinction does not change the considerations inherent to a [CAS operation].
32543368
///
32553369
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
3370+
/// [CAS operation]: https://en.wikipedia.org/wiki/Compare-and-swap
32563371
///
32573372
/// # Examples
32583373
///
@@ -3309,13 +3424,16 @@ macro_rules! atomic_int {
33093424
///
33103425
/// # Considerations
33113426
///
3312-
/// This method is not magic; it is not provided by the hardware.
3313-
/// It is implemented in terms of
3314-
#[doc = concat!("[`", stringify!($atomic_type), "::compare_exchange_weak`],")]
3315-
/// and suffers from the same drawbacks.
3316-
/// In particular, this method will not circumvent the [ABA Problem].
3427+
/// This method is not magic; it is not provided by the hardware, and does not act like a
3428+
/// critical section or mutex. It is implemented in terms of
3429+
/// [`compare_exchange`][Self::compare_exchange]\*, which is a [CAS operation], and thus
3430+
/// suffers from the usual drawbacks of CAS operations, in particular the [ABA problem].
3431+
///
3432+
/// \* It is actually implemented using [`compare_exchange_weak`][Self::compare_exchange_weak],
3433+
/// but that distinction does not change the considerations inherent to a [CAS operation].
33173434
///
33183435
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
3436+
/// [CAS operation]: https://en.wikipedia.org/wiki/Compare-and-swap
33193437
///
33203438
/// # Examples
33213439
///
@@ -3367,13 +3485,16 @@ macro_rules! atomic_int {
33673485
///
33683486
/// # Considerations
33693487
///
3370-
/// This method is not magic; it is not provided by the hardware.
3371-
/// It is implemented in terms of
3372-
#[doc = concat!("[`", stringify!($atomic_type), "::compare_exchange_weak`],")]
3373-
/// and suffers from the same drawbacks.
3374-
/// In particular, this method will not circumvent the [ABA Problem].
3488+
/// This method is not magic; it is not provided by the hardware, and does not act like a
3489+
/// critical section or mutex. It is implemented in terms of
3490+
/// [`compare_exchange`][Self::compare_exchange]\*, which is a [CAS operation], and thus
3491+
/// suffers from the usual drawbacks of CAS operations, in particular the [ABA problem].
3492+
///
3493+
/// \* It is actually implemented using [`compare_exchange_weak`][Self::compare_exchange_weak],
3494+
/// but that distinction does not change the considerations inherent to a [CAS operation].
33753495
///
33763496
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
3497+
/// [CAS operation]: https://en.wikipedia.org/wiki/Compare-and-swap
33773498
///
33783499
/// # Examples
33793500
///

0 commit comments

Comments
 (0)