Skip to content

Commit 6c55fba

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 6c55fba

File tree

1 file changed

+155
-33
lines changed

1 file changed

+155
-33
lines changed

library/core/src/sync/atomic.rs

Lines changed: 155 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 thus exhibits 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 thus exhibits 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,15 @@ 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.
1302+
///
1303+
/// It is implemented on top of an atomic [compare-and-swap operation], and thus is subject to
1304+
/// the usual drawbacks of CAS operations. In particular, be careful of the [ABA problem].
1305+
///
12771306
///
12781307
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
1308+
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
12791309
///
12801310
/// # Examples
12811311
///
@@ -1338,11 +1368,15 @@ impl AtomicBool {
13381368
///
13391369
/// # Considerations
13401370
///
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].
1371+
/// This method is not magic; it is not provided by the hardware, and does not act like a
1372+
/// critical section or mutex.
1373+
///
1374+
/// It is implemented on top of an atomic [compare-and-swap operation], and thus is subject to
1375+
/// the usual drawbacks of CAS operations. In particular, be careful of the [ABA problem].
1376+
///
13441377
///
13451378
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
1379+
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
13461380
///
13471381
/// # Examples
13481382
///
@@ -1393,11 +1427,15 @@ impl AtomicBool {
13931427
///
13941428
/// # Considerations
13951429
///
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].
1430+
/// This method is not magic; it is not provided by the hardware, and does not act like a
1431+
/// critical section or mutex.
1432+
///
1433+
/// It is implemented on top of an atomic [compare-and-swap operation], and thus is subject to
1434+
/// the usual drawbacks of CAS operations. In particular, be careful of the [ABA problem].
1435+
///
13991436
///
14001437
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
1438+
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
14011439
///
14021440
/// # Examples
14031441
///
@@ -1825,6 +1863,20 @@ impl<T> AtomicPtr<T> {
18251863
/// let value = some_ptr.compare_exchange(ptr, other_ptr,
18261864
/// Ordering::SeqCst, Ordering::Relaxed);
18271865
/// ```
1866+
///
1867+
/// # Considerations
1868+
///
1869+
/// `compare_exchange` is a [compare-and-swap operation] and thus exhibits the usual downsides
1870+
/// of CAS operations. In particular, a load of the value followed by a successful
1871+
/// `compare_exchange` with the previous load *does not ensure* that other threads have not
1872+
/// changed the value in the interim. This is usually important when the *equality* check in
1873+
/// the `compare_exchange` is being used to check the *identity* of a value, but equality
1874+
/// does not necessarily imply identity. This is a particularly common case for pointers, as
1875+
/// a pointer holding the same address does not imply that the same object exists at that
1876+
/// address! In this case, `compare_exchange` can lead to the [ABA problem].
1877+
///
1878+
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
1879+
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
18281880
#[inline]
18291881
#[stable(feature = "extended_compare_and_swap", since = "1.10.0")]
18301882
#[cfg(target_has_atomic = "ptr")]
@@ -1874,6 +1926,20 @@ impl<T> AtomicPtr<T> {
18741926
/// }
18751927
/// }
18761928
/// ```
1929+
///
1930+
/// # Considerations
1931+
///
1932+
/// `compare_exchange` is a [compare-and-swap operation] and thus exhibits the usual downsides
1933+
/// of CAS operations. In particular, a load of the value followed by a successful
1934+
/// `compare_exchange` with the previous load *does not ensure* that other threads have not
1935+
/// changed the value in the interim. This is usually important when the *equality* check in
1936+
/// the `compare_exchange` is being used to check the *identity* of a value, but equality
1937+
/// does not necessarily imply identity. This is a particularly common case for pointers, as
1938+
/// a pointer holding the same address does not imply that the same object exists at that
1939+
/// address! In this case, `compare_exchange` can lead to the [ABA problem].
1940+
///
1941+
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
1942+
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
18771943
#[inline]
18781944
#[stable(feature = "extended_compare_and_swap", since = "1.10.0")]
18791945
#[cfg(target_has_atomic = "ptr")]
@@ -1917,11 +1983,16 @@ impl<T> AtomicPtr<T> {
19171983
///
19181984
/// # Considerations
19191985
///
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].
1986+
/// This method is not magic; it is not provided by the hardware, and does not act like a
1987+
/// critical section or mutex.
1988+
///
1989+
/// It is implemented on top of an atomic [compare-and-swap operation], and thus is subject to
1990+
/// the usual drawbacks of CAS operations. In particular, be careful of the [ABA problem],
1991+
/// which is a particularly common pitfall for pointers!
1992+
///
19231993
///
19241994
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
1995+
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
19251996
///
19261997
/// # Examples
19271998
///
@@ -1992,11 +2063,16 @@ impl<T> AtomicPtr<T> {
19922063
///
19932064
/// # Considerations
19942065
///
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].
2066+
/// This method is not magic; it is not provided by the hardware, and does not act like a
2067+
/// critical section or mutex.
2068+
///
2069+
/// It is implemented on top of an atomic [compare-and-swap operation], and thus is subject to
2070+
/// the usual drawbacks of CAS operations. In particular, be careful of the [ABA problem],
2071+
/// which is a particularly common pitfall for pointers!
2072+
///
19982073
///
19992074
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
2075+
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
20002076
///
20012077
/// # Examples
20022078
///
@@ -2057,11 +2133,16 @@ impl<T> AtomicPtr<T> {
20572133
///
20582134
/// # Considerations
20592135
///
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].
2136+
/// This method is not magic; it is not provided by the hardware, and does not act like a
2137+
/// critical section or mutex.
2138+
///
2139+
/// It is implemented on top of an atomic [compare-and-swap operation], and thus is subject to
2140+
/// the usual drawbacks of CAS operations. In particular, be careful of the [ABA problem],
2141+
/// which is a particularly common pitfall for pointers!
2142+
///
20632143
///
20642144
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
2145+
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
20652146
///
20662147
/// # Examples
20672148
///
@@ -2967,6 +3048,20 @@ macro_rules! atomic_int {
29673048
/// Err(10));
29683049
/// assert_eq!(some_var.load(Ordering::Relaxed), 10);
29693050
/// ```
3051+
///
3052+
/// # Considerations
3053+
///
3054+
/// `compare_exchange` is a [compare-and-swap operation] and thus exhibits the usual downsides
3055+
/// of CAS operations. In particular, a load of the value followed by a successful
3056+
/// `compare_exchange` with the previous load *does not ensure* that other threads have not
3057+
/// changed the value in the interim! This is usually important when the *equality* check in
3058+
/// the `compare_exchange` is being used to check the *identity* of a value, but equality
3059+
/// does not necessarily imply identity. This is a particularly common case for pointers, as
3060+
/// a pointer holding the same address does not imply that the same object exists at that
3061+
/// address! In this case, `compare_exchange` can lead to the [ABA problem].
3062+
///
3063+
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
3064+
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
29703065
#[inline]
29713066
#[$stable_cxchg]
29723067
#[$cfg_cas]
@@ -3016,6 +3111,20 @@ macro_rules! atomic_int {
30163111
/// }
30173112
/// }
30183113
/// ```
3114+
///
3115+
/// # Considerations
3116+
///
3117+
/// `compare_exchange` is a [compare-and-swap operation] and thus exhibits the usual downsides
3118+
/// of CAS operations. In particular, a load of the value followed by a successful
3119+
/// `compare_exchange` with the previous load *does not ensure* that other threads have not
3120+
/// changed the value in the interim. This is usually important when the *equality* check in
3121+
/// the `compare_exchange` is being used to check the *identity* of a value, but equality
3122+
/// does not necessarily imply identity. This is a particularly common case for pointers, as
3123+
/// a pointer holding the same address does not imply that the same object exists at that
3124+
/// address! In this case, `compare_exchange` can lead to the [ABA problem].
3125+
///
3126+
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
3127+
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
30193128
#[inline]
30203129
#[$stable_cxchg]
30213130
#[$cfg_cas]
@@ -3246,13 +3355,17 @@ macro_rules! atomic_int {
32463355
///
32473356
/// # Considerations
32483357
///
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].
3358+
/// This method is not magic; it is not provided by the hardware, and does not act like a
3359+
/// critical section or mutex.
3360+
///
3361+
/// It is implemented on top of an atomic [compare-and-swap operation], and thus is subject to
3362+
/// the usual drawbacks of CAS operations. In particular, be careful of the [ABA problem],
3363+
/// if this atomic integer is an index or more generally if knowledge of only the *bitwise value*
3364+
/// of the atomic is not in and of itself sufficient to ensure any required preconditions.
3365+
///
32543366
///
32553367
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
3368+
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
32563369
///
32573370
/// # Examples
32583371
///
@@ -3309,13 +3422,17 @@ macro_rules! atomic_int {
33093422
///
33103423
/// # Considerations
33113424
///
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].
3425+
/// This method is not magic; it is not provided by the hardware, and does not act like a
3426+
/// critical section or mutex.
3427+
///
3428+
/// It is implemented on top of an atomic [compare-and-swap operation], and thus is subject to
3429+
/// the usual drawbacks of CAS operations. In particular, be careful of the [ABA problem],
3430+
/// if this atomic integer is an index or more generally if knowledge of only the *bitwise value*
3431+
/// of the atomic is not in and of itself sufficient to ensure any required preconditions.
3432+
///
33173433
///
33183434
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
3435+
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
33193436
///
33203437
/// # Examples
33213438
///
@@ -3367,13 +3484,18 @@ macro_rules! atomic_int {
33673484
///
33683485
/// # Considerations
33693486
///
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].
3487+
/// [CAS operation]: https://en.wikipedia.org/wiki/Compare-and-swap
3488+
/// This method is not magic; it is not provided by the hardware, and does not act like a
3489+
/// critical section or mutex.
3490+
///
3491+
/// It is implemented on top of an atomic [compare-and-swap operation], and thus is subject to
3492+
/// the usual drawbacks of CAS operations. In particular, be careful of the [ABA problem],
3493+
/// if this atomic integer is an index or more generally if knowledge of only the *bitwise value*
3494+
/// of the atomic is not in and of itself sufficient to ensure any required preconditions.
3495+
///
33753496
///
33763497
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
3498+
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
33773499
///
33783500
/// # Examples
33793501
///

0 commit comments

Comments
 (0)