Skip to content

Commit 2095211

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 2095211

File tree

1 file changed

+146
-33
lines changed

1 file changed

+146
-33
lines changed

library/core/src/sync/atomic.rs

Lines changed: 146 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,14 @@ 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].
12771305
///
12781306
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
1307+
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
12791308
///
12801309
/// # Examples
12811310
///
@@ -1338,11 +1367,14 @@ impl AtomicBool {
13381367
///
13391368
/// # Considerations
13401369
///
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].
1370+
/// This method is not magic; it is not provided by the hardware, and does not act like a
1371+
/// critical section or mutex.
1372+
///
1373+
/// It is implemented on top of an atomic [compare-and-swap operation], and thus is subject to
1374+
/// the usual drawbacks of CAS operations. In particular, be careful of the [ABA problem].
13441375
///
13451376
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
1377+
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
13461378
///
13471379
/// # Examples
13481380
///
@@ -1393,11 +1425,14 @@ impl AtomicBool {
13931425
///
13941426
/// # Considerations
13951427
///
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].
1428+
/// This method is not magic; it is not provided by the hardware, and does not act like a
1429+
/// critical section or mutex.
1430+
///
1431+
/// It is implemented on top of an atomic [compare-and-swap operation], and thus is subject to
1432+
/// the usual drawbacks of CAS operations. In particular, be careful of the [ABA problem].
13991433
///
14001434
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
1435+
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
14011436
///
14021437
/// # Examples
14031438
///
@@ -1825,6 +1860,20 @@ impl<T> AtomicPtr<T> {
18251860
/// let value = some_ptr.compare_exchange(ptr, other_ptr,
18261861
/// Ordering::SeqCst, Ordering::Relaxed);
18271862
/// ```
1863+
///
1864+
/// # Considerations
1865+
///
1866+
/// `compare_exchange` is a [compare-and-swap operation] and thus exhibits the usual downsides
1867+
/// of CAS operations. In particular, a load of the value followed by a successful
1868+
/// `compare_exchange` with the previous load *does not ensure* that other threads have not
1869+
/// changed the value in the interim. This is usually important when the *equality* check in
1870+
/// the `compare_exchange` is being used to check the *identity* of a value, but equality
1871+
/// does not necessarily imply identity. This is a particularly common case for pointers, as
1872+
/// a pointer holding the same address does not imply that the same object exists at that
1873+
/// address! In this case, `compare_exchange` can lead to the [ABA problem].
1874+
///
1875+
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
1876+
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
18281877
#[inline]
18291878
#[stable(feature = "extended_compare_and_swap", since = "1.10.0")]
18301879
#[cfg(target_has_atomic = "ptr")]
@@ -1874,6 +1923,20 @@ impl<T> AtomicPtr<T> {
18741923
/// }
18751924
/// }
18761925
/// ```
1926+
///
1927+
/// # Considerations
1928+
///
1929+
/// `compare_exchange` is a [compare-and-swap operation] and thus exhibits the usual downsides
1930+
/// of CAS operations. In particular, a load of the value followed by a successful
1931+
/// `compare_exchange` with the previous load *does not ensure* that other threads have not
1932+
/// changed the value in the interim. This is usually important when the *equality* check in
1933+
/// the `compare_exchange` is being used to check the *identity* of a value, but equality
1934+
/// does not necessarily imply identity. This is a particularly common case for pointers, as
1935+
/// a pointer holding the same address does not imply that the same object exists at that
1936+
/// address! In this case, `compare_exchange` can lead to the [ABA problem].
1937+
///
1938+
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
1939+
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
18771940
#[inline]
18781941
#[stable(feature = "extended_compare_and_swap", since = "1.10.0")]
18791942
#[cfg(target_has_atomic = "ptr")]
@@ -1917,11 +1980,15 @@ impl<T> AtomicPtr<T> {
19171980
///
19181981
/// # Considerations
19191982
///
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].
1983+
/// This method is not magic; it is not provided by the hardware, and does not act like a
1984+
/// critical section or mutex.
1985+
///
1986+
/// It is implemented on top of an atomic [compare-and-swap operation], and thus is subject to
1987+
/// the usual drawbacks of CAS operations. In particular, be careful of the [ABA problem],
1988+
/// which is a particularly common pitfall for pointers!
19231989
///
19241990
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
1991+
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
19251992
///
19261993
/// # Examples
19271994
///
@@ -1992,11 +2059,15 @@ impl<T> AtomicPtr<T> {
19922059
///
19932060
/// # Considerations
19942061
///
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].
2062+
/// This method is not magic; it is not provided by the hardware, and does not act like a
2063+
/// critical section or mutex.
2064+
///
2065+
/// It is implemented on top of an atomic [compare-and-swap operation], and thus is subject to
2066+
/// the usual drawbacks of CAS operations. In particular, be careful of the [ABA problem],
2067+
/// which is a particularly common pitfall for pointers!
19982068
///
19992069
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
2070+
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
20002071
///
20012072
/// # Examples
20022073
///
@@ -2057,11 +2128,15 @@ impl<T> AtomicPtr<T> {
20572128
///
20582129
/// # Considerations
20592130
///
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].
2131+
/// This method is not magic; it is not provided by the hardware, and does not act like a
2132+
/// critical section or mutex.
2133+
///
2134+
/// It is implemented on top of an atomic [compare-and-swap operation], and thus is subject to
2135+
/// the usual drawbacks of CAS operations. In particular, be careful of the [ABA problem],
2136+
/// which is a particularly common pitfall for pointers!
20632137
///
20642138
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
2139+
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
20652140
///
20662141
/// # Examples
20672142
///
@@ -2967,6 +3042,20 @@ macro_rules! atomic_int {
29673042
/// Err(10));
29683043
/// assert_eq!(some_var.load(Ordering::Relaxed), 10);
29693044
/// ```
3045+
///
3046+
/// # Considerations
3047+
///
3048+
/// `compare_exchange` is a [compare-and-swap operation] and thus exhibits the usual downsides
3049+
/// of CAS operations. In particular, a load of the value followed by a successful
3050+
/// `compare_exchange` with the previous load *does not ensure* that other threads have not
3051+
/// changed the value in the interim! This is usually important when the *equality* check in
3052+
/// the `compare_exchange` is being used to check the *identity* of a value, but equality
3053+
/// does not necessarily imply identity. This is a particularly common case for pointers, as
3054+
/// a pointer holding the same address does not imply that the same object exists at that
3055+
/// address! In this case, `compare_exchange` can lead to the [ABA problem].
3056+
///
3057+
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
3058+
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
29703059
#[inline]
29713060
#[$stable_cxchg]
29723061
#[$cfg_cas]
@@ -3016,6 +3105,20 @@ macro_rules! atomic_int {
30163105
/// }
30173106
/// }
30183107
/// ```
3108+
///
3109+
/// # Considerations
3110+
///
3111+
/// `compare_exchange` is a [compare-and-swap operation] and thus exhibits the usual downsides
3112+
/// of CAS operations. In particular, a load of the value followed by a successful
3113+
/// `compare_exchange` with the previous load *does not ensure* that other threads have not
3114+
/// changed the value in the interim. This is usually important when the *equality* check in
3115+
/// the `compare_exchange` is being used to check the *identity* of a value, but equality
3116+
/// does not necessarily imply identity. This is a particularly common case for pointers, as
3117+
/// a pointer holding the same address does not imply that the same object exists at that
3118+
/// address! In this case, `compare_exchange` can lead to the [ABA problem].
3119+
///
3120+
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
3121+
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
30193122
#[inline]
30203123
#[$stable_cxchg]
30213124
#[$cfg_cas]
@@ -3246,13 +3349,16 @@ macro_rules! atomic_int {
32463349
///
32473350
/// # Considerations
32483351
///
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].
3352+
/// This method is not magic; it is not provided by the hardware, and does not act like a
3353+
/// critical section or mutex.
3354+
///
3355+
/// It is implemented on top of an atomic [compare-and-swap operation], and thus is subject to
3356+
/// the usual drawbacks of CAS operations. In particular, be careful of the [ABA problem]
3357+
/// if this atomic integer is an index or more generally if knowledge of only the *bitwise value*
3358+
/// of the atomic is not in and of itself sufficient to ensure any required preconditions.
32543359
///
32553360
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
3361+
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
32563362
///
32573363
/// # Examples
32583364
///
@@ -3309,13 +3415,16 @@ macro_rules! atomic_int {
33093415
///
33103416
/// # Considerations
33113417
///
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].
3418+
/// This method is not magic; it is not provided by the hardware, and does not act like a
3419+
/// critical section or mutex.
3420+
///
3421+
/// It is implemented on top of an atomic [compare-and-swap operation], and thus is subject to
3422+
/// the usual drawbacks of CAS operations. In particular, be careful of the [ABA problem]
3423+
/// if this atomic integer is an index or more generally if knowledge of only the *bitwise value*
3424+
/// of the atomic is not in and of itself sufficient to ensure any required preconditions.
33173425
///
33183426
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
3427+
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
33193428
///
33203429
/// # Examples
33213430
///
@@ -3367,13 +3476,17 @@ macro_rules! atomic_int {
33673476
///
33683477
/// # Considerations
33693478
///
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].
3479+
/// [CAS operation]: https://en.wikipedia.org/wiki/Compare-and-swap
3480+
/// This method is not magic; it is not provided by the hardware, and does not act like a
3481+
/// critical section or mutex.
3482+
///
3483+
/// It is implemented on top of an atomic [compare-and-swap operation], and thus is subject to
3484+
/// the usual drawbacks of CAS operations. In particular, be careful of the [ABA problem]
3485+
/// if this atomic integer is an index or more generally if knowledge of only the *bitwise value*
3486+
/// of the atomic is not in and of itself sufficient to ensure any required preconditions.
33753487
///
33763488
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
3489+
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
33773490
///
33783491
/// # Examples
33793492
///

0 commit comments

Comments
 (0)