@@ -801,6 +801,64 @@ impl AtomicBool {
801801 pub fn as_mut_ptr ( & self ) -> * mut bool {
802802 self . v . get ( ) as * mut bool
803803 }
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+ }
804862}
805863
806864#[ cfg( target_has_atomic_load_store = "ptr" ) ]
@@ -1123,6 +1181,73 @@ impl<T> AtomicPtr<T> {
11231181 }
11241182 }
11251183 }
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+ }
11261251}
11271252
11281253#[ cfg( target_has_atomic_load_store = "8" ) ]
0 commit comments