@@ -1203,6 +1203,66 @@ impl AtomicBool {
12031203 }
12041204 Err ( prev)
12051205 }
1206+
1207+ /// Fetches the value, applies a function to it that it return a new value.
1208+ /// The new value is stored and the old value is returned.
1209+ ///
1210+ /// Note: This may call the function multiple times if the value has been changed from other threads in
1211+ /// the meantime, but the function will have been applied only once to the stored value.
1212+ ///
1213+ /// `fetch_update_infallible` takes two [`Ordering`] arguments to describe the memory
1214+ /// ordering of this operation. The first describes the required ordering for
1215+ /// when the operation finally succeeds while the second describes the
1216+ /// required ordering for loads. These correspond to the success and failure
1217+ /// orderings of [`AtomicBool::compare_exchange`] respectively.
1218+ ///
1219+ /// Using [`Acquire`] as success ordering makes the store part
1220+ /// of this operation [`Relaxed`], and using [`Release`] makes the final successful load
1221+ /// [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
1222+ ///
1223+ /// **Note:** This method is only available on platforms that support atomic operations on `u8`.
1224+ ///
1225+ /// # Considerations
1226+ ///
1227+ /// This method is not magic; it is not provided by the hardware.
1228+ /// It is implemented in terms of [`AtomicBool::compare_exchange_weak`], and suffers from the same drawbacks.
1229+ /// In particular, this method will not circumvent the [ABA Problem].
1230+ ///
1231+ /// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
1232+ ///
1233+ /// # Examples
1234+ ///
1235+ /// ```rust
1236+ /// #![feature(fetch_update_infallible)]
1237+ ///
1238+ /// use std::sync::atomic::{AtomicBool, Ordering};
1239+ ///
1240+ /// let x = AtomicBool::new(false);
1241+ /// assert_eq!(x.fetch_update_infallible(Ordering::SeqCst, Ordering::SeqCst, |x| !x), false);
1242+ /// assert_eq!(x.fetch_update_infallible(Ordering::SeqCst, Ordering::SeqCst, |x| !x), true);
1243+ /// assert_eq!(x.load(Ordering::SeqCst), false);
1244+ /// ```
1245+ #[ inline]
1246+ #[ unstable( feature = "fetch_update_infallible" , issue = "none" ) ]
1247+ #[ cfg( target_has_atomic = "8" ) ]
1248+ #[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
1249+ pub fn fetch_update_infallible < F > (
1250+ & self ,
1251+ set_order : Ordering ,
1252+ fetch_order : Ordering ,
1253+ mut f : F ,
1254+ ) -> bool
1255+ where
1256+ F : FnMut ( bool ) -> bool ,
1257+ {
1258+ let mut prev = self . load ( fetch_order) ;
1259+ loop {
1260+ match self . compare_exchange_weak ( prev, f ( prev) , set_order, fetch_order) {
1261+ Ok ( x) => break x,
1262+ Err ( next_prev) => prev = next_prev,
1263+ }
1264+ }
1265+ }
12061266}
12071267
12081268#[ cfg( target_has_atomic_load_store = "ptr" ) ]
@@ -1733,6 +1793,70 @@ impl<T> AtomicPtr<T> {
17331793 Err ( prev)
17341794 }
17351795
1796+ /// Fetches the value, applies a function to it that it return a new value.
1797+ /// The new value is stored and the old value is returned.
1798+ ///
1799+ /// Note: This may call the function multiple times if the value has been changed from other threads in
1800+ /// the meantime, but the function will have been applied only once to the stored value.
1801+ ///
1802+ /// `fetch_update_infallible` takes two [`Ordering`] arguments to describe the memory
1803+ /// ordering of this operation. The first describes the required ordering for
1804+ /// when the operation finally succeeds while the second describes the
1805+ /// required ordering for loads. These correspond to the success and failure
1806+ /// orderings of [`AtomicPtr::compare_exchange`] respectively.
1807+ ///
1808+ /// Using [`Acquire`] as success ordering makes the store part
1809+ /// of this operation [`Relaxed`], and using [`Release`] makes the final successful load
1810+ /// [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
1811+ ///
1812+ /// **Note:** This method is only available on platforms that support atomic
1813+ /// operations on pointers.
1814+ ///
1815+ /// # Considerations
1816+ ///
1817+ /// This method is not magic; it is not provided by the hardware.
1818+ /// It is implemented in terms of [`AtomicPtr::compare_exchange_weak`], and suffers from the same drawbacks.
1819+ /// In particular, this method will not circumvent the [ABA Problem].
1820+ ///
1821+ /// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
1822+ ///
1823+ /// # Examples
1824+ ///
1825+ /// ```rust
1826+ /// #![feature(fetch_update_infallible)]
1827+ ///
1828+ /// use std::sync::atomic::{AtomicPtr, Ordering};
1829+ ///
1830+ /// let ptr: *mut _ = &mut 5;
1831+ /// let some_ptr = AtomicPtr::new(ptr);
1832+ ///
1833+ /// let new: *mut _ = &mut 10;
1834+ /// let result = some_ptr.fetch_update_infallible(Ordering::SeqCst, Ordering::SeqCst, |_| new);
1835+ /// assert_eq!(result, ptr);
1836+ /// assert_eq!(some_ptr.load(Ordering::SeqCst), new);
1837+ /// ```
1838+ #[ inline]
1839+ #[ unstable( feature = "fetch_update_infallible" , issue = "none" ) ]
1840+ #[ cfg( target_has_atomic = "8" ) ]
1841+ #[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
1842+ pub fn fetch_update_infallible < F > (
1843+ & self ,
1844+ set_order : Ordering ,
1845+ fetch_order : Ordering ,
1846+ mut f : F ,
1847+ ) -> * mut T
1848+ where
1849+ F : FnMut ( * mut T ) -> * mut T ,
1850+ {
1851+ let mut prev = self . load ( fetch_order) ;
1852+ loop {
1853+ match self . compare_exchange_weak ( prev, f ( prev) , set_order, fetch_order) {
1854+ Ok ( x) => break x,
1855+ Err ( next_prev) => prev = next_prev,
1856+ }
1857+ }
1858+ }
1859+
17361860 /// Offsets the pointer's address by adding `val` (in units of `T`),
17371861 /// returning the previous pointer.
17381862 ///
@@ -2913,6 +3037,68 @@ macro_rules! atomic_int {
29133037 Err ( prev)
29143038 }
29153039
3040+ /// Fetches the value, applies a function to it that it return a new value.
3041+ /// The new value is stored and the old value is returned.
3042+ ///
3043+ /// Note: This may call the function multiple times if the value has been changed from other threads in
3044+ /// the meantime, but the function will have been applied only once to the stored value.
3045+ ///
3046+ /// `fetch_update_infallible` takes two [`Ordering`] arguments to describe the memory ordering of this operation.
3047+ /// The first describes the required ordering for when the operation finally succeeds while the second
3048+ /// describes the required ordering for loads. These correspond to the success and failure orderings of
3049+ #[ doc = concat!( "[`" , stringify!( $atomic_type) , "::compare_exchange`]" ) ]
3050+ /// respectively.
3051+ ///
3052+ /// Using [`Acquire`] as success ordering makes the store part
3053+ /// of this operation [`Relaxed`], and using [`Release`] makes the final successful load
3054+ /// [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
3055+ ///
3056+ /// **Note**: This method is only available on platforms that support atomic operations on
3057+ #[ doc = concat!( "[`" , $s_int_type, "`]." ) ]
3058+ ///
3059+ /// # Considerations
3060+ ///
3061+ /// This method is not magic; it is not provided by the hardware.
3062+ /// It is implemented in terms of
3063+ #[ doc = concat!( "[`" , stringify!( $atomic_type) , "::compare_exchange_weak`]," ) ]
3064+ /// and suffers from the same drawbacks.
3065+ /// In particular, this method will not circumvent the [ABA Problem].
3066+ ///
3067+ /// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
3068+ ///
3069+ /// # Examples
3070+ ///
3071+ /// ```rust
3072+ /// #![feature(fetch_update_infallible)]
3073+ #[ doc = concat!( $extra_feature, "use std::sync::atomic::{" , stringify!( $atomic_type) , ", Ordering};" ) ]
3074+ ///
3075+ #[ doc = concat!( "let x = " , stringify!( $atomic_type) , "::new(7);" ) ]
3076+ /// assert_eq!(x.fetch_update_infallible(Ordering::SeqCst, Ordering::SeqCst, |x| x + 1), 7);
3077+ /// assert_eq!(x.fetch_update_infallible(Ordering::SeqCst, Ordering::SeqCst, |x| x + 1), 8);
3078+ /// assert_eq!(x.load(Ordering::SeqCst), 9);
3079+ /// ```
3080+ #[ inline]
3081+ #[ unstable( feature = "fetch_update_infallible" , issue = "none" ) ]
3082+ #[ $cfg_cas]
3083+ #[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
3084+ pub fn fetch_update_infallible<F >(
3085+ & self ,
3086+ set_order: Ordering ,
3087+ fetch_order: Ordering ,
3088+ mut f: F ,
3089+ ) -> $int_type
3090+ where
3091+ F : FnMut ( $int_type) -> $int_type,
3092+ {
3093+ let mut prev = self . load( fetch_order) ;
3094+ loop {
3095+ match self . compare_exchange_weak( prev, f( prev) , set_order, fetch_order) {
3096+ Ok ( x) => break x,
3097+ Err ( next_prev) => prev = next_prev,
3098+ }
3099+ }
3100+ }
3101+
29163102 /// Maximum with the current value.
29173103 ///
29183104 /// Finds the maximum of the current value and the argument `val`, and
0 commit comments