@@ -258,6 +258,40 @@ impl<T: Copy + Eq> AtomicCell<T> {
258
258
pub fn compare_exchange ( & self , current : T , new : T ) -> Result < T , T > {
259
259
unsafe { atomic_compare_exchange_weak ( self . value . get ( ) , current, new) }
260
260
}
261
+
262
+ /// Fetches the value, and applies a function to it that returns an optional
263
+ /// new value. Returns a `Result` of `Ok(previous_value)` if the function returned `Some(_)`, else
264
+ /// `Err(previous_value)`.
265
+ ///
266
+ /// Note: This may call the function multiple times if the value has been changed from other threads in
267
+ /// the meantime, as long as the function returns `Some(_)`, but the function will have been applied
268
+ /// only once to the stored value.
269
+ ///
270
+ /// # Examples
271
+ ///
272
+ /// ```rust
273
+ /// use crossbeam_utils::atomic::AtomicCell;
274
+ ///
275
+ /// let a = AtomicCell::new(7);
276
+ /// assert_eq!(a.fetch_update(|_| None), Err(7));
277
+ /// assert_eq!(a.fetch_update(|a| Some(a + 1)), Ok(7));
278
+ /// assert_eq!(a.fetch_update(|a| Some(a + 1)), Ok(8));
279
+ /// assert_eq!(a.load(), 9);
280
+ /// ```
281
+ #[ inline]
282
+ pub fn fetch_update < F > ( & self , mut f : F ) -> Result < T , T >
283
+ where
284
+ F : FnMut ( T ) -> Option < T > ,
285
+ {
286
+ let mut prev = self . load ( ) ;
287
+ while let Some ( next) = f ( prev) {
288
+ match self . compare_exchange ( prev, next) {
289
+ x @ Ok ( _) => return x,
290
+ Err ( next_prev) => prev = next_prev,
291
+ }
292
+ }
293
+ Err ( prev)
294
+ }
261
295
}
262
296
263
297
macro_rules! impl_arithmetic {
0 commit comments