@@ -949,6 +949,7 @@ macro_rules! atomic_int {
949949 $stable_nand: meta,
950950 $s_int_type: expr, $int_ref: expr,
951951 $extra_feature: expr,
952+ $min_fn: ident, $max_fn: ident,
952953 $int_type: ident $atomic_type: ident $atomic_init: ident) => {
953954 /// An integer type which can be safely shared between threads.
954955 ///
@@ -1418,6 +1419,128 @@ assert_eq!(foo.load(Ordering::SeqCst), 0b011110);
14181419 unsafe { atomic_xor( self . v. get( ) , val, order) }
14191420 }
14201421 }
1422+
1423+ doc_comment! {
1424+ concat!( "Fetches the value, and applies a function to it that returns an optional
1425+ new value. Returns a `Result` (`Ok(_)` if the function returned `Some(_)`, else `Err(_)`) of the
1426+ previous value.
1427+
1428+ Note: This may call the function multiple times if the value has been changed from other threads in
1429+ the meantime, as long as the function returns `Some(_)`, but the function will have been applied
1430+ but once to the stored value.
1431+
1432+ # Examples
1433+
1434+ ```rust
1435+ #![feature(no_more_cas)]
1436+ " , $extra_feature, "use std::sync::atomic::{" , stringify!( $atomic_type) , ", Ordering};
1437+
1438+ let x = " , stringify!( $atomic_type) , "::new(7);
1439+ assert_eq!(x.fetch_update(|_| None, Ordering::SeqCst, Ordering::SeqCst), Err(7));
1440+ assert_eq!(x.fetch_update(|x| Some(x + 1), Ordering::SeqCst, Ordering::SeqCst), Ok(7));
1441+ assert_eq!(x.fetch_update(|x| Some(x + 1), Ordering::SeqCst, Ordering::SeqCst), Ok(8));
1442+ assert_eq!(x.load(Ordering::SeqCst), 9);
1443+ ```" ) ,
1444+ #[ inline]
1445+ #[ unstable( feature = "no_more_cas" ,
1446+ reason = "no more CAS loops in user code" ,
1447+ issue = "48655" ) ]
1448+ pub fn fetch_update<F >( & self ,
1449+ mut f: F ,
1450+ fetch_order: Ordering ,
1451+ set_order: Ordering ) -> Result <$int_type, $int_type>
1452+ where F : FnMut ( $int_type) -> Option <$int_type> {
1453+ let mut prev = self . load( fetch_order) ;
1454+ while let Some ( next) = f( prev) {
1455+ match self . compare_exchange_weak( prev, next, set_order, fetch_order) {
1456+ x @ Ok ( _) => return x,
1457+ Err ( next_prev) => prev = next_prev
1458+ }
1459+ }
1460+ Err ( prev)
1461+ }
1462+ }
1463+
1464+ doc_comment! {
1465+ concat!( "Maximum with the current value.
1466+
1467+ Finds the maximum of the current value and the argument `val`, and
1468+ sets the new value to the result.
1469+
1470+ Returns the previous value.
1471+
1472+ # Examples
1473+
1474+ ```
1475+ #![feature(atomic_min_max)]
1476+ " , $extra_feature, "use std::sync::atomic::{" , stringify!( $atomic_type) , ", Ordering};
1477+
1478+ let foo = " , stringify!( $atomic_type) , "::new(23);
1479+ assert_eq!(foo.fetch_max(42, Ordering::SeqCst), 23);
1480+ assert_eq!(foo.load(Ordering::SeqCst), 42);
1481+ ```
1482+
1483+ If you want to obtain the maximum value in one step, you can use the following:
1484+
1485+ ```
1486+ #![feature(atomic_min_max)]
1487+ " , $extra_feature, "use std::sync::atomic::{" , stringify!( $atomic_type) , ", Ordering};
1488+
1489+ let foo = " , stringify!( $atomic_type) , "::new(23);
1490+ let bar = 42;
1491+ let max_foo = foo.fetch_max(bar, Ordering::SeqCst).max(bar);
1492+ assert!(max_foo == 42);
1493+ ```" ) ,
1494+ #[ inline]
1495+ #[ unstable( feature = "atomic_min_max" ,
1496+ reason = "easier and faster min/max than writing manual CAS loop" ,
1497+ issue = "48655" ) ]
1498+ pub fn fetch_max( & self , val: $int_type, order: Ordering ) -> $int_type {
1499+ unsafe { $max_fn( self . v. get( ) , val, order) }
1500+ }
1501+ }
1502+
1503+ doc_comment! {
1504+ concat!( "Minimum with the current value.
1505+
1506+ Finds the minimum of the current value and the argument `val`, and
1507+ sets the new value to the result.
1508+
1509+ Returns the previous value.
1510+
1511+ # Examples
1512+
1513+ ```
1514+ #![feature(atomic_min_max)]
1515+ " , $extra_feature, "use std::sync::atomic::{" , stringify!( $atomic_type) , ", Ordering};
1516+
1517+ let foo = " , stringify!( $atomic_type) , "::new(23);
1518+ assert_eq!(foo.fetch_min(42, Ordering::Relaxed), 23);
1519+ assert_eq!(foo.load(Ordering::Relaxed), 23);
1520+ assert_eq!(foo.fetch_min(22, Ordering::Relaxed), 23);
1521+ assert_eq!(foo.load(Ordering::Relaxed), 22);
1522+ ```
1523+
1524+ If you want to obtain the minimum value in one step, you can use the following:
1525+
1526+ ```
1527+ #![feature(atomic_min_max)]
1528+ " , $extra_feature, "use std::sync::atomic::{" , stringify!( $atomic_type) , ", Ordering};
1529+
1530+ let foo = " , stringify!( $atomic_type) , "::new(23);
1531+ let bar = 12;
1532+ let min_foo = foo.fetch_min(bar, Ordering::SeqCst).min(bar);
1533+ assert_eq!(min_foo, 12);
1534+ ```" ) ,
1535+ #[ inline]
1536+ #[ unstable( feature = "atomic_min_max" ,
1537+ reason = "easier and faster min/max than writing manual CAS loop" ,
1538+ issue = "48655" ) ]
1539+ pub fn fetch_min( & self , val: $int_type, order: Ordering ) -> $int_type {
1540+ unsafe { $min_fn( self . v. get( ) , val, order) }
1541+ }
1542+ }
1543+
14211544 }
14221545 }
14231546}
@@ -1432,6 +1555,7 @@ atomic_int! {
14321555 unstable( feature = "atomic_nand" , issue = "13226" ) ,
14331556 "i8" , "../../../std/primitive.i8.html" ,
14341557 "#![feature(integer_atomics)]\n \n " ,
1558+ atomic_min, atomic_max,
14351559 i8 AtomicI8 ATOMIC_I8_INIT
14361560}
14371561#[ cfg( target_has_atomic = "8" ) ]
@@ -1444,6 +1568,7 @@ atomic_int! {
14441568 unstable( feature = "atomic_nand" , issue = "13226" ) ,
14451569 "u8" , "../../../std/primitive.u8.html" ,
14461570 "#![feature(integer_atomics)]\n \n " ,
1571+ atomic_umin, atomic_umax,
14471572 u8 AtomicU8 ATOMIC_U8_INIT
14481573}
14491574#[ cfg( target_has_atomic = "16" ) ]
@@ -1456,6 +1581,7 @@ atomic_int! {
14561581 unstable( feature = "atomic_nand" , issue = "13226" ) ,
14571582 "i16" , "../../../std/primitive.i16.html" ,
14581583 "#![feature(integer_atomics)]\n \n " ,
1584+ atomic_min, atomic_max,
14591585 i16 AtomicI16 ATOMIC_I16_INIT
14601586}
14611587#[ cfg( target_has_atomic = "16" ) ]
@@ -1468,6 +1594,7 @@ atomic_int! {
14681594 unstable( feature = "atomic_nand" , issue = "13226" ) ,
14691595 "u16" , "../../../std/primitive.u16.html" ,
14701596 "#![feature(integer_atomics)]\n \n " ,
1597+ atomic_umin, atomic_umax,
14711598 u16 AtomicU16 ATOMIC_U16_INIT
14721599}
14731600#[ cfg( target_has_atomic = "32" ) ]
@@ -1480,6 +1607,7 @@ atomic_int! {
14801607 unstable( feature = "atomic_nand" , issue = "13226" ) ,
14811608 "i32" , "../../../std/primitive.i32.html" ,
14821609 "#![feature(integer_atomics)]\n \n " ,
1610+ atomic_min, atomic_max,
14831611 i32 AtomicI32 ATOMIC_I32_INIT
14841612}
14851613#[ cfg( target_has_atomic = "32" ) ]
@@ -1492,6 +1620,7 @@ atomic_int! {
14921620 unstable( feature = "atomic_nand" , issue = "13226" ) ,
14931621 "u32" , "../../../std/primitive.u32.html" ,
14941622 "#![feature(integer_atomics)]\n \n " ,
1623+ atomic_umin, atomic_umax,
14951624 u32 AtomicU32 ATOMIC_U32_INIT
14961625}
14971626#[ cfg( target_has_atomic = "64" ) ]
@@ -1504,6 +1633,7 @@ atomic_int! {
15041633 unstable( feature = "atomic_nand" , issue = "13226" ) ,
15051634 "i64" , "../../../std/primitive.i64.html" ,
15061635 "#![feature(integer_atomics)]\n \n " ,
1636+ atomic_min, atomic_max,
15071637 i64 AtomicI64 ATOMIC_I64_INIT
15081638}
15091639#[ cfg( target_has_atomic = "64" ) ]
@@ -1516,6 +1646,7 @@ atomic_int! {
15161646 unstable( feature = "atomic_nand" , issue = "13226" ) ,
15171647 "u64" , "../../../std/primitive.u64.html" ,
15181648 "#![feature(integer_atomics)]\n \n " ,
1649+ atomic_umin, atomic_umax,
15191650 u64 AtomicU64 ATOMIC_U64_INIT
15201651}
15211652#[ cfg( target_has_atomic = "ptr" ) ]
@@ -1528,6 +1659,7 @@ atomic_int!{
15281659 unstable( feature = "atomic_nand" , issue = "13226" ) ,
15291660 "isize" , "../../../std/primitive.isize.html" ,
15301661 "" ,
1662+ atomic_min, atomic_max,
15311663 isize AtomicIsize ATOMIC_ISIZE_INIT
15321664}
15331665#[ cfg( target_has_atomic = "ptr" ) ]
@@ -1540,6 +1672,7 @@ atomic_int!{
15401672 unstable( feature = "atomic_nand" , issue = "13226" ) ,
15411673 "usize" , "../../../std/primitive.usize.html" ,
15421674 "" ,
1675+ atomic_umin, atomic_umax,
15431676 usize AtomicUsize ATOMIC_USIZE_INIT
15441677}
15451678
@@ -1717,6 +1850,58 @@ unsafe fn atomic_xor<T>(dst: *mut T, val: T, order: Ordering) -> T {
17171850 }
17181851}
17191852
1853+ /// returns the max value (signed comparison)
1854+ #[ inline]
1855+ unsafe fn atomic_max < T > ( dst : * mut T , val : T , order : Ordering ) -> T {
1856+ match order {
1857+ Acquire => intrinsics:: atomic_max_acq ( dst, val) ,
1858+ Release => intrinsics:: atomic_max_rel ( dst, val) ,
1859+ AcqRel => intrinsics:: atomic_max_acqrel ( dst, val) ,
1860+ Relaxed => intrinsics:: atomic_max_relaxed ( dst, val) ,
1861+ SeqCst => intrinsics:: atomic_max ( dst, val) ,
1862+ __Nonexhaustive => panic ! ( "invalid memory ordering" ) ,
1863+ }
1864+ }
1865+
1866+ /// returns the min value (signed comparison)
1867+ #[ inline]
1868+ unsafe fn atomic_min < T > ( dst : * mut T , val : T , order : Ordering ) -> T {
1869+ match order {
1870+ Acquire => intrinsics:: atomic_min_acq ( dst, val) ,
1871+ Release => intrinsics:: atomic_min_rel ( dst, val) ,
1872+ AcqRel => intrinsics:: atomic_min_acqrel ( dst, val) ,
1873+ Relaxed => intrinsics:: atomic_min_relaxed ( dst, val) ,
1874+ SeqCst => intrinsics:: atomic_min ( dst, val) ,
1875+ __Nonexhaustive => panic ! ( "invalid memory ordering" ) ,
1876+ }
1877+ }
1878+
1879+ /// returns the max value (signed comparison)
1880+ #[ inline]
1881+ unsafe fn atomic_umax < T > ( dst : * mut T , val : T , order : Ordering ) -> T {
1882+ match order {
1883+ Acquire => intrinsics:: atomic_umax_acq ( dst, val) ,
1884+ Release => intrinsics:: atomic_umax_rel ( dst, val) ,
1885+ AcqRel => intrinsics:: atomic_umax_acqrel ( dst, val) ,
1886+ Relaxed => intrinsics:: atomic_umax_relaxed ( dst, val) ,
1887+ SeqCst => intrinsics:: atomic_umax ( dst, val) ,
1888+ __Nonexhaustive => panic ! ( "invalid memory ordering" ) ,
1889+ }
1890+ }
1891+
1892+ /// returns the min value (signed comparison)
1893+ #[ inline]
1894+ unsafe fn atomic_umin < T > ( dst : * mut T , val : T , order : Ordering ) -> T {
1895+ match order {
1896+ Acquire => intrinsics:: atomic_umin_acq ( dst, val) ,
1897+ Release => intrinsics:: atomic_umin_rel ( dst, val) ,
1898+ AcqRel => intrinsics:: atomic_umin_acqrel ( dst, val) ,
1899+ Relaxed => intrinsics:: atomic_umin_relaxed ( dst, val) ,
1900+ SeqCst => intrinsics:: atomic_umin ( dst, val) ,
1901+ __Nonexhaustive => panic ! ( "invalid memory ordering" ) ,
1902+ }
1903+ }
1904+
17201905/// An atomic fence.
17211906///
17221907/// Depending on the specified order, a fence prevents the compiler and CPU from
0 commit comments