@@ -952,6 +952,7 @@ macro_rules! atomic_int {
952952 $stable_nand: meta,
953953 $s_int_type: expr, $int_ref: expr,
954954 $extra_feature: expr,
955+ $min_fn: ident, $max_fn: ident,
955956 $int_type: ident $atomic_type: ident $atomic_init: ident) => {
956957 /// An integer type which can be safely shared between threads.
957958 ///
@@ -1421,6 +1422,128 @@ assert_eq!(foo.load(Ordering::SeqCst), 0b011110);
14211422 unsafe { atomic_xor( self . v. get( ) , val, order) }
14221423 }
14231424 }
1425+
1426+ doc_comment! {
1427+ concat!( "Fetches the value, and applies a function to it that returns an optional
1428+ new value. Returns a `Result` (`Ok(_)` if the function returned `Some(_)`, else `Err(_)`) of the
1429+ previous value.
1430+
1431+ Note: This may call the function multiple times if the value has been changed from other threads in
1432+ the meantime, as long as the function returns `Some(_)`, but the function will have been applied
1433+ but once to the stored value.
1434+
1435+ # Examples
1436+
1437+ ```rust
1438+ #![feature(no_more_cas)]
1439+ " , $extra_feature, "use std::sync::atomic::{" , stringify!( $atomic_type) , ", Ordering};
1440+
1441+ let x = " , stringify!( $atomic_type) , "::new(7);
1442+ assert_eq!(x.fetch_update(|_| None, Ordering::SeqCst, Ordering::SeqCst), Err(7));
1443+ assert_eq!(x.fetch_update(|x| Some(x + 1), Ordering::SeqCst, Ordering::SeqCst), Ok(7));
1444+ assert_eq!(x.fetch_update(|x| Some(x + 1), Ordering::SeqCst, Ordering::SeqCst), Ok(8));
1445+ assert_eq!(x.load(Ordering::SeqCst), 9);
1446+ ```" ) ,
1447+ #[ inline]
1448+ #[ unstable( feature = "no_more_cas" ,
1449+ reason = "no more CAS loops in user code" ,
1450+ issue = "48655" ) ]
1451+ pub fn fetch_update<F >( & self ,
1452+ mut f: F ,
1453+ fetch_order: Ordering ,
1454+ set_order: Ordering ) -> Result <$int_type, $int_type>
1455+ where F : FnMut ( $int_type) -> Option <$int_type> {
1456+ let mut prev = self . load( fetch_order) ;
1457+ while let Some ( next) = f( prev) {
1458+ match self . compare_exchange_weak( prev, next, set_order, fetch_order) {
1459+ x @ Ok ( _) => return x,
1460+ Err ( next_prev) => prev = next_prev
1461+ }
1462+ }
1463+ Err ( prev)
1464+ }
1465+ }
1466+
1467+ doc_comment! {
1468+ concat!( "Maximum with the current value.
1469+
1470+ Finds the maximum of the current value and the argument `val`, and
1471+ sets the new value to the result.
1472+
1473+ Returns the previous value.
1474+
1475+ # Examples
1476+
1477+ ```
1478+ #![feature(atomic_min_max)]
1479+ " , $extra_feature, "use std::sync::atomic::{" , stringify!( $atomic_type) , ", Ordering};
1480+
1481+ let foo = " , stringify!( $atomic_type) , "::new(23);
1482+ assert_eq!(foo.fetch_max(42, Ordering::SeqCst), 23);
1483+ assert_eq!(foo.load(Ordering::SeqCst), 42);
1484+ ```
1485+
1486+ If you want to obtain the maximum value in one step, you can use the following:
1487+
1488+ ```
1489+ #![feature(atomic_min_max)]
1490+ " , $extra_feature, "use std::sync::atomic::{" , stringify!( $atomic_type) , ", Ordering};
1491+
1492+ let foo = " , stringify!( $atomic_type) , "::new(23);
1493+ let bar = 42;
1494+ let max_foo = foo.fetch_max(bar, Ordering::SeqCst).max(bar);
1495+ assert!(max_foo == 42);
1496+ ```" ) ,
1497+ #[ inline]
1498+ #[ unstable( feature = "atomic_min_max" ,
1499+ reason = "easier and faster min/max than writing manual CAS loop" ,
1500+ issue = "48655" ) ]
1501+ pub fn fetch_max( & self , val: $int_type, order: Ordering ) -> $int_type {
1502+ unsafe { $max_fn( self . v. get( ) , val, order) }
1503+ }
1504+ }
1505+
1506+ doc_comment! {
1507+ concat!( "Minimum with the current value.
1508+
1509+ Finds the minimum of the current value and the argument `val`, and
1510+ sets the new value to the result.
1511+
1512+ Returns the previous value.
1513+
1514+ # Examples
1515+
1516+ ```
1517+ #![feature(atomic_min_max)]
1518+ " , $extra_feature, "use std::sync::atomic::{" , stringify!( $atomic_type) , ", Ordering};
1519+
1520+ let foo = " , stringify!( $atomic_type) , "::new(23);
1521+ assert_eq!(foo.fetch_min(42, Ordering::Relaxed), 23);
1522+ assert_eq!(foo.load(Ordering::Relaxed), 23);
1523+ assert_eq!(foo.fetch_min(22, Ordering::Relaxed), 23);
1524+ assert_eq!(foo.load(Ordering::Relaxed), 22);
1525+ ```
1526+
1527+ If you want to obtain the minimum value in one step, you can use the following:
1528+
1529+ ```
1530+ #![feature(atomic_min_max)]
1531+ " , $extra_feature, "use std::sync::atomic::{" , stringify!( $atomic_type) , ", Ordering};
1532+
1533+ let foo = " , stringify!( $atomic_type) , "::new(23);
1534+ let bar = 12;
1535+ let min_foo = foo.fetch_min(bar, Ordering::SeqCst).min(bar);
1536+ assert_eq!(min_foo, 12);
1537+ ```" ) ,
1538+ #[ inline]
1539+ #[ unstable( feature = "atomic_min_max" ,
1540+ reason = "easier and faster min/max than writing manual CAS loop" ,
1541+ issue = "48655" ) ]
1542+ pub fn fetch_min( & self , val: $int_type, order: Ordering ) -> $int_type {
1543+ unsafe { $min_fn( self . v. get( ) , val, order) }
1544+ }
1545+ }
1546+
14241547 }
14251548 }
14261549}
@@ -1435,6 +1558,7 @@ atomic_int! {
14351558 unstable( feature = "atomic_nand" , issue = "13226" ) ,
14361559 "i8" , "../../../std/primitive.i8.html" ,
14371560 "#![feature(integer_atomics)]\n \n " ,
1561+ atomic_min, atomic_max,
14381562 i8 AtomicI8 ATOMIC_I8_INIT
14391563}
14401564#[ cfg( target_has_atomic = "8" ) ]
@@ -1447,6 +1571,7 @@ atomic_int! {
14471571 unstable( feature = "atomic_nand" , issue = "13226" ) ,
14481572 "u8" , "../../../std/primitive.u8.html" ,
14491573 "#![feature(integer_atomics)]\n \n " ,
1574+ atomic_umin, atomic_umax,
14501575 u8 AtomicU8 ATOMIC_U8_INIT
14511576}
14521577#[ cfg( target_has_atomic = "16" ) ]
@@ -1459,6 +1584,7 @@ atomic_int! {
14591584 unstable( feature = "atomic_nand" , issue = "13226" ) ,
14601585 "i16" , "../../../std/primitive.i16.html" ,
14611586 "#![feature(integer_atomics)]\n \n " ,
1587+ atomic_min, atomic_max,
14621588 i16 AtomicI16 ATOMIC_I16_INIT
14631589}
14641590#[ cfg( target_has_atomic = "16" ) ]
@@ -1471,6 +1597,7 @@ atomic_int! {
14711597 unstable( feature = "atomic_nand" , issue = "13226" ) ,
14721598 "u16" , "../../../std/primitive.u16.html" ,
14731599 "#![feature(integer_atomics)]\n \n " ,
1600+ atomic_umin, atomic_umax,
14741601 u16 AtomicU16 ATOMIC_U16_INIT
14751602}
14761603#[ cfg( target_has_atomic = "32" ) ]
@@ -1483,6 +1610,7 @@ atomic_int! {
14831610 unstable( feature = "atomic_nand" , issue = "13226" ) ,
14841611 "i32" , "../../../std/primitive.i32.html" ,
14851612 "#![feature(integer_atomics)]\n \n " ,
1613+ atomic_min, atomic_max,
14861614 i32 AtomicI32 ATOMIC_I32_INIT
14871615}
14881616#[ cfg( target_has_atomic = "32" ) ]
@@ -1495,6 +1623,7 @@ atomic_int! {
14951623 unstable( feature = "atomic_nand" , issue = "13226" ) ,
14961624 "u32" , "../../../std/primitive.u32.html" ,
14971625 "#![feature(integer_atomics)]\n \n " ,
1626+ atomic_umin, atomic_umax,
14981627 u32 AtomicU32 ATOMIC_U32_INIT
14991628}
15001629#[ cfg( target_has_atomic = "64" ) ]
@@ -1507,6 +1636,7 @@ atomic_int! {
15071636 unstable( feature = "atomic_nand" , issue = "13226" ) ,
15081637 "i64" , "../../../std/primitive.i64.html" ,
15091638 "#![feature(integer_atomics)]\n \n " ,
1639+ atomic_min, atomic_max,
15101640 i64 AtomicI64 ATOMIC_I64_INIT
15111641}
15121642#[ cfg( target_has_atomic = "64" ) ]
@@ -1519,6 +1649,7 @@ atomic_int! {
15191649 unstable( feature = "atomic_nand" , issue = "13226" ) ,
15201650 "u64" , "../../../std/primitive.u64.html" ,
15211651 "#![feature(integer_atomics)]\n \n " ,
1652+ atomic_umin, atomic_umax,
15221653 u64 AtomicU64 ATOMIC_U64_INIT
15231654}
15241655#[ cfg( target_has_atomic = "ptr" ) ]
@@ -1531,6 +1662,7 @@ atomic_int!{
15311662 unstable( feature = "atomic_nand" , issue = "13226" ) ,
15321663 "isize" , "../../../std/primitive.isize.html" ,
15331664 "" ,
1665+ atomic_min, atomic_max,
15341666 isize AtomicIsize ATOMIC_ISIZE_INIT
15351667}
15361668#[ cfg( target_has_atomic = "ptr" ) ]
@@ -1543,6 +1675,7 @@ atomic_int!{
15431675 unstable( feature = "atomic_nand" , issue = "13226" ) ,
15441676 "usize" , "../../../std/primitive.usize.html" ,
15451677 "" ,
1678+ atomic_umin, atomic_umax,
15461679 usize AtomicUsize ATOMIC_USIZE_INIT
15471680}
15481681
@@ -1720,6 +1853,58 @@ unsafe fn atomic_xor<T>(dst: *mut T, val: T, order: Ordering) -> T {
17201853 }
17211854}
17221855
1856+ /// returns the max value (signed comparison)
1857+ #[ inline]
1858+ unsafe fn atomic_max < T > ( dst : * mut T , val : T , order : Ordering ) -> T {
1859+ match order {
1860+ Acquire => intrinsics:: atomic_max_acq ( dst, val) ,
1861+ Release => intrinsics:: atomic_max_rel ( dst, val) ,
1862+ AcqRel => intrinsics:: atomic_max_acqrel ( dst, val) ,
1863+ Relaxed => intrinsics:: atomic_max_relaxed ( dst, val) ,
1864+ SeqCst => intrinsics:: atomic_max ( dst, val) ,
1865+ __Nonexhaustive => panic ! ( "invalid memory ordering" ) ,
1866+ }
1867+ }
1868+
1869+ /// returns the min value (signed comparison)
1870+ #[ inline]
1871+ unsafe fn atomic_min < T > ( dst : * mut T , val : T , order : Ordering ) -> T {
1872+ match order {
1873+ Acquire => intrinsics:: atomic_min_acq ( dst, val) ,
1874+ Release => intrinsics:: atomic_min_rel ( dst, val) ,
1875+ AcqRel => intrinsics:: atomic_min_acqrel ( dst, val) ,
1876+ Relaxed => intrinsics:: atomic_min_relaxed ( dst, val) ,
1877+ SeqCst => intrinsics:: atomic_min ( dst, val) ,
1878+ __Nonexhaustive => panic ! ( "invalid memory ordering" ) ,
1879+ }
1880+ }
1881+
1882+ /// returns the max value (signed comparison)
1883+ #[ inline]
1884+ unsafe fn atomic_umax < T > ( dst : * mut T , val : T , order : Ordering ) -> T {
1885+ match order {
1886+ Acquire => intrinsics:: atomic_umax_acq ( dst, val) ,
1887+ Release => intrinsics:: atomic_umax_rel ( dst, val) ,
1888+ AcqRel => intrinsics:: atomic_umax_acqrel ( dst, val) ,
1889+ Relaxed => intrinsics:: atomic_umax_relaxed ( dst, val) ,
1890+ SeqCst => intrinsics:: atomic_umax ( dst, val) ,
1891+ __Nonexhaustive => panic ! ( "invalid memory ordering" ) ,
1892+ }
1893+ }
1894+
1895+ /// returns the min value (signed comparison)
1896+ #[ inline]
1897+ unsafe fn atomic_umin < T > ( dst : * mut T , val : T , order : Ordering ) -> T {
1898+ match order {
1899+ Acquire => intrinsics:: atomic_umin_acq ( dst, val) ,
1900+ Release => intrinsics:: atomic_umin_rel ( dst, val) ,
1901+ AcqRel => intrinsics:: atomic_umin_acqrel ( dst, val) ,
1902+ Relaxed => intrinsics:: atomic_umin_relaxed ( dst, val) ,
1903+ SeqCst => intrinsics:: atomic_umin ( dst, val) ,
1904+ __Nonexhaustive => panic ! ( "invalid memory ordering" ) ,
1905+ }
1906+ }
1907+
17231908/// An atomic fence.
17241909///
17251910/// Depending on the specified order, a fence prevents the compiler and CPU from
0 commit comments