@@ -1203,6 +1203,66 @@ impl AtomicBool {
1203
1203
}
1204
1204
Err ( prev)
1205
1205
}
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
+ }
1206
1266
}
1207
1267
1208
1268
#[ cfg( target_has_atomic_load_store = "ptr" ) ]
@@ -1733,6 +1793,70 @@ impl<T> AtomicPtr<T> {
1733
1793
Err ( prev)
1734
1794
}
1735
1795
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
+
1736
1860
/// Offsets the pointer's address by adding `val` (in units of `T`),
1737
1861
/// returning the previous pointer.
1738
1862
///
@@ -2913,6 +3037,68 @@ macro_rules! atomic_int {
2913
3037
Err ( prev)
2914
3038
}
2915
3039
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
+
2916
3102
/// Maximum with the current value.
2917
3103
///
2918
3104
/// Finds the maximum of the current value and the argument `val`, and
0 commit comments