@@ -952,6 +952,7 @@ macro_rules! atomic_int {
952
952
$stable_nand: meta,
953
953
$s_int_type: expr, $int_ref: expr,
954
954
$extra_feature: expr,
955
+ $min_fn: ident, $max_fn: ident,
955
956
$int_type: ident $atomic_type: ident $atomic_init: ident) => {
956
957
/// An integer type which can be safely shared between threads.
957
958
///
@@ -1421,6 +1422,128 @@ assert_eq!(foo.load(Ordering::SeqCst), 0b011110);
1421
1422
unsafe { atomic_xor( self . v. get( ) , val, order) }
1422
1423
}
1423
1424
}
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
+
1424
1547
}
1425
1548
}
1426
1549
}
@@ -1435,6 +1558,7 @@ atomic_int! {
1435
1558
unstable( feature = "atomic_nand" , issue = "13226" ) ,
1436
1559
"i8" , "../../../std/primitive.i8.html" ,
1437
1560
"#![feature(integer_atomics)]\n \n " ,
1561
+ atomic_min, atomic_max,
1438
1562
i8 AtomicI8 ATOMIC_I8_INIT
1439
1563
}
1440
1564
#[ cfg( target_has_atomic = "8" ) ]
@@ -1447,6 +1571,7 @@ atomic_int! {
1447
1571
unstable( feature = "atomic_nand" , issue = "13226" ) ,
1448
1572
"u8" , "../../../std/primitive.u8.html" ,
1449
1573
"#![feature(integer_atomics)]\n \n " ,
1574
+ atomic_umin, atomic_umax,
1450
1575
u8 AtomicU8 ATOMIC_U8_INIT
1451
1576
}
1452
1577
#[ cfg( target_has_atomic = "16" ) ]
@@ -1459,6 +1584,7 @@ atomic_int! {
1459
1584
unstable( feature = "atomic_nand" , issue = "13226" ) ,
1460
1585
"i16" , "../../../std/primitive.i16.html" ,
1461
1586
"#![feature(integer_atomics)]\n \n " ,
1587
+ atomic_min, atomic_max,
1462
1588
i16 AtomicI16 ATOMIC_I16_INIT
1463
1589
}
1464
1590
#[ cfg( target_has_atomic = "16" ) ]
@@ -1471,6 +1597,7 @@ atomic_int! {
1471
1597
unstable( feature = "atomic_nand" , issue = "13226" ) ,
1472
1598
"u16" , "../../../std/primitive.u16.html" ,
1473
1599
"#![feature(integer_atomics)]\n \n " ,
1600
+ atomic_umin, atomic_umax,
1474
1601
u16 AtomicU16 ATOMIC_U16_INIT
1475
1602
}
1476
1603
#[ cfg( target_has_atomic = "32" ) ]
@@ -1483,6 +1610,7 @@ atomic_int! {
1483
1610
unstable( feature = "atomic_nand" , issue = "13226" ) ,
1484
1611
"i32" , "../../../std/primitive.i32.html" ,
1485
1612
"#![feature(integer_atomics)]\n \n " ,
1613
+ atomic_min, atomic_max,
1486
1614
i32 AtomicI32 ATOMIC_I32_INIT
1487
1615
}
1488
1616
#[ cfg( target_has_atomic = "32" ) ]
@@ -1495,6 +1623,7 @@ atomic_int! {
1495
1623
unstable( feature = "atomic_nand" , issue = "13226" ) ,
1496
1624
"u32" , "../../../std/primitive.u32.html" ,
1497
1625
"#![feature(integer_atomics)]\n \n " ,
1626
+ atomic_umin, atomic_umax,
1498
1627
u32 AtomicU32 ATOMIC_U32_INIT
1499
1628
}
1500
1629
#[ cfg( target_has_atomic = "64" ) ]
@@ -1507,6 +1636,7 @@ atomic_int! {
1507
1636
unstable( feature = "atomic_nand" , issue = "13226" ) ,
1508
1637
"i64" , "../../../std/primitive.i64.html" ,
1509
1638
"#![feature(integer_atomics)]\n \n " ,
1639
+ atomic_min, atomic_max,
1510
1640
i64 AtomicI64 ATOMIC_I64_INIT
1511
1641
}
1512
1642
#[ cfg( target_has_atomic = "64" ) ]
@@ -1519,6 +1649,7 @@ atomic_int! {
1519
1649
unstable( feature = "atomic_nand" , issue = "13226" ) ,
1520
1650
"u64" , "../../../std/primitive.u64.html" ,
1521
1651
"#![feature(integer_atomics)]\n \n " ,
1652
+ atomic_umin, atomic_umax,
1522
1653
u64 AtomicU64 ATOMIC_U64_INIT
1523
1654
}
1524
1655
#[ cfg( target_has_atomic = "ptr" ) ]
@@ -1531,6 +1662,7 @@ atomic_int!{
1531
1662
unstable( feature = "atomic_nand" , issue = "13226" ) ,
1532
1663
"isize" , "../../../std/primitive.isize.html" ,
1533
1664
"" ,
1665
+ atomic_min, atomic_max,
1534
1666
isize AtomicIsize ATOMIC_ISIZE_INIT
1535
1667
}
1536
1668
#[ cfg( target_has_atomic = "ptr" ) ]
@@ -1543,6 +1675,7 @@ atomic_int!{
1543
1675
unstable( feature = "atomic_nand" , issue = "13226" ) ,
1544
1676
"usize" , "../../../std/primitive.usize.html" ,
1545
1677
"" ,
1678
+ atomic_umin, atomic_umax,
1546
1679
usize AtomicUsize ATOMIC_USIZE_INIT
1547
1680
}
1548
1681
@@ -1720,6 +1853,58 @@ unsafe fn atomic_xor<T>(dst: *mut T, val: T, order: Ordering) -> T {
1720
1853
}
1721
1854
}
1722
1855
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
+
1723
1908
/// An atomic fence.
1724
1909
///
1725
1910
/// Depending on the specified order, a fence prevents the compiler and CPU from
0 commit comments