@@ -801,6 +801,64 @@ impl AtomicBool {
801
801
pub fn as_mut_ptr ( & self ) -> * mut bool {
802
802
self . v . get ( ) as * mut bool
803
803
}
804
+
805
+ /// Fetches the value, and applies a function to it that returns an optional
806
+ /// new value. Returns a `Result` of `Ok(previous_value)` if the function
807
+ /// returned `Some(_)`, else `Err(previous_value)`.
808
+ ///
809
+ /// Note: This may call the function multiple times if the value has been
810
+ /// changed from other threads in the meantime, as long as the function
811
+ /// returns `Some(_)`, but the function will have been applied only once to
812
+ /// the stored value.
813
+ ///
814
+ /// `fetch_update` takes two [`Ordering`] arguments to describe the memory
815
+ /// ordering of this operation. The first describes the required ordering for
816
+ /// when the operation finally succeeds while the second describes the
817
+ /// required ordering for loads. These correspond to the success and failure
818
+ /// orderings of [`AtomicBool::compare_exchange`] respectively.
819
+ ///
820
+ /// Using [`Acquire`] as success ordering makes the store part of this
821
+ /// operation [`Relaxed`], and using [`Release`] makes the final successful
822
+ /// load [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`],
823
+ /// [`Acquire`] or [`Relaxed`] and must be equivalent to or weaker than the
824
+ /// success ordering.
825
+ ///
826
+ /// **Note:** This method is only available on platforms that support atomic
827
+ /// operations on `u8`.
828
+ ///
829
+ /// # Examples
830
+ ///
831
+ /// ```rust
832
+ /// #![feature(atomic_fetch_update)]
833
+ /// use std::sync::atomic::{AtomicBool, Ordering};
834
+ ///
835
+ /// let x = AtomicBool::new(false);
836
+ /// assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |_| None), Err(false));
837
+ /// assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(!x)), Ok(false));
838
+ /// assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(!x)), Ok(true));
839
+ /// assert_eq!(x.load(Ordering::SeqCst), false);
840
+ /// ```
841
+ #[ inline]
842
+ #[ unstable( feature = "atomic_fetch_update" , reason = "recently added" , issue = "78639" ) ]
843
+ #[ cfg( target_has_atomic = "8" ) ]
844
+ pub fn fetch_update < F > (
845
+ & self ,
846
+ set_order : Ordering ,
847
+ fetch_order : Ordering ,
848
+ mut f : F ,
849
+ ) -> Result < bool , bool >
850
+ where
851
+ F : FnMut ( bool ) -> Option < bool > ,
852
+ {
853
+ let mut prev = self . load ( fetch_order) ;
854
+ while let Some ( next) = f ( prev) {
855
+ match self . compare_exchange_weak ( prev, next, set_order, fetch_order) {
856
+ x @ Ok ( _) => return x,
857
+ Err ( next_prev) => prev = next_prev,
858
+ }
859
+ }
860
+ Err ( prev)
861
+ }
804
862
}
805
863
806
864
#[ cfg( target_has_atomic_load_store = "ptr" ) ]
@@ -1123,6 +1181,73 @@ impl<T> AtomicPtr<T> {
1123
1181
}
1124
1182
}
1125
1183
}
1184
+
1185
+ /// Fetches the value, and applies a function to it that returns an optional
1186
+ /// new value. Returns a `Result` of `Ok(previous_value)` if the function
1187
+ /// returned `Some(_)`, else `Err(previous_value)`.
1188
+ ///
1189
+ /// Note: This may call the function multiple times if the value has been
1190
+ /// changed from other threads in the meantime, as long as the function
1191
+ /// returns `Some(_)`, but the function will have been applied only once to
1192
+ /// the stored value.
1193
+ ///
1194
+ /// `fetch_update` takes two [`Ordering`] arguments to describe the memory
1195
+ /// ordering of this operation. The first describes the required ordering for
1196
+ /// when the operation finally succeeds while the second describes the
1197
+ /// required ordering for loads. These correspond to the success and failure
1198
+ /// orderings of [`AtomicPtr::compare_exchange`] respectively.
1199
+ ///
1200
+ /// Using [`Acquire`] as success ordering makes the store part of this
1201
+ /// operation [`Relaxed`], and using [`Release`] makes the final successful
1202
+ /// load [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`],
1203
+ /// [`Acquire`] or [`Relaxed`] and must be equivalent to or weaker than the
1204
+ /// success ordering.
1205
+ ///
1206
+ /// **Note:** This method is only available on platforms that support atomic
1207
+ /// operations on pointers.
1208
+ ///
1209
+ /// # Examples
1210
+ ///
1211
+ /// ```rust
1212
+ /// #![feature(atomic_fetch_update)]
1213
+ /// use std::sync::atomic::{AtomicPtr, Ordering};
1214
+ ///
1215
+ /// let ptr: *mut _ = &mut 5;
1216
+ /// let some_ptr = AtomicPtr::new(ptr);
1217
+ ///
1218
+ /// let new: *mut _ = &mut 10;
1219
+ /// assert_eq!(some_ptr.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |_| None), Err(ptr));
1220
+ /// let result = some_ptr.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| {
1221
+ /// if x == ptr {
1222
+ /// Some(new)
1223
+ /// } else {
1224
+ /// None
1225
+ /// }
1226
+ /// });
1227
+ /// assert_eq!(result, Ok(ptr));
1228
+ /// assert_eq!(some_ptr.load(Ordering::SeqCst), new);
1229
+ /// ```
1230
+ #[ inline]
1231
+ #[ unstable( feature = "atomic_fetch_update" , reason = "recently added" , issue = "78639" ) ]
1232
+ #[ cfg( target_has_atomic = "ptr" ) ]
1233
+ pub fn fetch_update < F > (
1234
+ & self ,
1235
+ set_order : Ordering ,
1236
+ fetch_order : Ordering ,
1237
+ mut f : F ,
1238
+ ) -> Result < * mut T , * mut T >
1239
+ where
1240
+ F : FnMut ( * mut T ) -> Option < * mut T > ,
1241
+ {
1242
+ let mut prev = self . load ( fetch_order) ;
1243
+ while let Some ( next) = f ( prev) {
1244
+ match self . compare_exchange_weak ( prev, next, set_order, fetch_order) {
1245
+ x @ Ok ( _) => return x,
1246
+ Err ( next_prev) => prev = next_prev,
1247
+ }
1248
+ }
1249
+ Err ( prev)
1250
+ }
1126
1251
}
1127
1252
1128
1253
#[ cfg( target_has_atomic_load_store = "8" ) ]
0 commit comments