@@ -949,6 +949,7 @@ macro_rules! atomic_int {
949
949
$stable_nand: meta,
950
950
$s_int_type: expr, $int_ref: expr,
951
951
$extra_feature: expr,
952
+ $min_fn: ident, $max_fn: ident,
952
953
$int_type: ident $atomic_type: ident $atomic_init: ident) => {
953
954
/// An integer type which can be safely shared between threads.
954
955
///
@@ -1418,6 +1419,128 @@ assert_eq!(foo.load(Ordering::SeqCst), 0b011110);
1418
1419
unsafe { atomic_xor( self . v. get( ) , val, order) }
1419
1420
}
1420
1421
}
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
+
1421
1544
}
1422
1545
}
1423
1546
}
@@ -1432,6 +1555,7 @@ atomic_int! {
1432
1555
unstable( feature = "atomic_nand" , issue = "13226" ) ,
1433
1556
"i8" , "../../../std/primitive.i8.html" ,
1434
1557
"#![feature(integer_atomics)]\n \n " ,
1558
+ atomic_min, atomic_max,
1435
1559
i8 AtomicI8 ATOMIC_I8_INIT
1436
1560
}
1437
1561
#[ cfg( target_has_atomic = "8" ) ]
@@ -1444,6 +1568,7 @@ atomic_int! {
1444
1568
unstable( feature = "atomic_nand" , issue = "13226" ) ,
1445
1569
"u8" , "../../../std/primitive.u8.html" ,
1446
1570
"#![feature(integer_atomics)]\n \n " ,
1571
+ atomic_umin, atomic_umax,
1447
1572
u8 AtomicU8 ATOMIC_U8_INIT
1448
1573
}
1449
1574
#[ cfg( target_has_atomic = "16" ) ]
@@ -1456,6 +1581,7 @@ atomic_int! {
1456
1581
unstable( feature = "atomic_nand" , issue = "13226" ) ,
1457
1582
"i16" , "../../../std/primitive.i16.html" ,
1458
1583
"#![feature(integer_atomics)]\n \n " ,
1584
+ atomic_min, atomic_max,
1459
1585
i16 AtomicI16 ATOMIC_I16_INIT
1460
1586
}
1461
1587
#[ cfg( target_has_atomic = "16" ) ]
@@ -1468,6 +1594,7 @@ atomic_int! {
1468
1594
unstable( feature = "atomic_nand" , issue = "13226" ) ,
1469
1595
"u16" , "../../../std/primitive.u16.html" ,
1470
1596
"#![feature(integer_atomics)]\n \n " ,
1597
+ atomic_umin, atomic_umax,
1471
1598
u16 AtomicU16 ATOMIC_U16_INIT
1472
1599
}
1473
1600
#[ cfg( target_has_atomic = "32" ) ]
@@ -1480,6 +1607,7 @@ atomic_int! {
1480
1607
unstable( feature = "atomic_nand" , issue = "13226" ) ,
1481
1608
"i32" , "../../../std/primitive.i32.html" ,
1482
1609
"#![feature(integer_atomics)]\n \n " ,
1610
+ atomic_min, atomic_max,
1483
1611
i32 AtomicI32 ATOMIC_I32_INIT
1484
1612
}
1485
1613
#[ cfg( target_has_atomic = "32" ) ]
@@ -1492,6 +1620,7 @@ atomic_int! {
1492
1620
unstable( feature = "atomic_nand" , issue = "13226" ) ,
1493
1621
"u32" , "../../../std/primitive.u32.html" ,
1494
1622
"#![feature(integer_atomics)]\n \n " ,
1623
+ atomic_umin, atomic_umax,
1495
1624
u32 AtomicU32 ATOMIC_U32_INIT
1496
1625
}
1497
1626
#[ cfg( target_has_atomic = "64" ) ]
@@ -1504,6 +1633,7 @@ atomic_int! {
1504
1633
unstable( feature = "atomic_nand" , issue = "13226" ) ,
1505
1634
"i64" , "../../../std/primitive.i64.html" ,
1506
1635
"#![feature(integer_atomics)]\n \n " ,
1636
+ atomic_min, atomic_max,
1507
1637
i64 AtomicI64 ATOMIC_I64_INIT
1508
1638
}
1509
1639
#[ cfg( target_has_atomic = "64" ) ]
@@ -1516,6 +1646,7 @@ atomic_int! {
1516
1646
unstable( feature = "atomic_nand" , issue = "13226" ) ,
1517
1647
"u64" , "../../../std/primitive.u64.html" ,
1518
1648
"#![feature(integer_atomics)]\n \n " ,
1649
+ atomic_umin, atomic_umax,
1519
1650
u64 AtomicU64 ATOMIC_U64_INIT
1520
1651
}
1521
1652
#[ cfg( target_has_atomic = "ptr" ) ]
@@ -1528,6 +1659,7 @@ atomic_int!{
1528
1659
unstable( feature = "atomic_nand" , issue = "13226" ) ,
1529
1660
"isize" , "../../../std/primitive.isize.html" ,
1530
1661
"" ,
1662
+ atomic_min, atomic_max,
1531
1663
isize AtomicIsize ATOMIC_ISIZE_INIT
1532
1664
}
1533
1665
#[ cfg( target_has_atomic = "ptr" ) ]
@@ -1540,6 +1672,7 @@ atomic_int!{
1540
1672
unstable( feature = "atomic_nand" , issue = "13226" ) ,
1541
1673
"usize" , "../../../std/primitive.usize.html" ,
1542
1674
"" ,
1675
+ atomic_umin, atomic_umax,
1543
1676
usize AtomicUsize ATOMIC_USIZE_INIT
1544
1677
}
1545
1678
@@ -1717,6 +1850,58 @@ unsafe fn atomic_xor<T>(dst: *mut T, val: T, order: Ordering) -> T {
1717
1850
}
1718
1851
}
1719
1852
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
+
1720
1905
/// An atomic fence.
1721
1906
///
1722
1907
/// Depending on the specified order, a fence prevents the compiler and CPU from
0 commit comments