about summary refs log tree commit diff
diff options
context:
space:
mode:
authorThe8472 <git@infinite-source.de>2021-09-17 18:42:16 +0200
committerThe8472 <git@infinite-source.de>2021-09-17 18:54:24 +0200
commit57465d9c1bb979a64c6e7c5220b4ab20291547aa (patch)
tree407293f7f3b24af9f04bd35855eb65f39cc624ce
parent2b512cc329a87202003d41828fe8f6f2fbeaf720 (diff)
downloadrust-57465d9c1bb979a64c6e7c5220b4ab20291547aa.tar.gz
rust-57465d9c1bb979a64c6e7c5220b4ab20291547aa.zip
use AtomicU64::fetch_update instead of handrolled RMW-loop
-rw-r--r--library/std/src/lib.rs1
-rw-r--r--library/std/src/time/monotonic.rs23
2 files changed, 10 insertions, 14 deletions
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 83c6ba0e6ea..f1640ab8b1e 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -234,6 +234,7 @@
 #![feature(atomic_mut_ptr)]
 #![feature(auto_traits)]
 #![feature(bench_black_box)]
+#![feature(bool_to_option)]
 #![feature(box_syntax)]
 #![feature(c_unwind)]
 #![feature(c_variadic)]
diff --git a/library/std/src/time/monotonic.rs b/library/std/src/time/monotonic.rs
index fb1c8932756..198ae739b55 100644
--- a/library/std/src/time/monotonic.rs
+++ b/library/std/src/time/monotonic.rs
@@ -37,20 +37,15 @@ pub mod inner {
         // This could be a problem for programs that call instants at intervals greater
         // than 68 years. Interstellar probes may want to ensure that actually_monotonic() is true.
         let packed = (secs << 32) | nanos;
-        let mut old = mono.load(Relaxed);
-        loop {
-            if old == UNINITIALIZED || packed.wrapping_sub(old) < u64::MAX / 2 {
-                match mono.compare_exchange_weak(old, packed, Relaxed, Relaxed) {
-                    Ok(_) => return raw,
-                    Err(x) => {
-                        old = x;
-                        continue;
-                    }
-                }
-            } else {
+        let updated = mono.fetch_update(Relaxed, Relaxed, |old| {
+            (old == UNINITIALIZED || packed.wrapping_sub(old) < u64::MAX / 2).then_some(packed)
+        });
+        match updated {
+            Ok(_) => raw,
+            Err(newer) => {
                 // Backslide occurred. We reconstruct monotonized time from the upper 32 bit of the
                 // passed in value and the 64bits loaded from the atomic
-                let seconds_lower = old >> 32;
+                let seconds_lower = newer >> 32;
                 let mut seconds_upper = secs & 0xffff_ffff_0000_0000;
                 if secs & 0xffff_ffff > seconds_lower {
                     // Backslide caused the lower 32bit of the seconds part to wrap.
@@ -69,8 +64,8 @@ pub mod inner {
                     seconds_upper = seconds_upper.wrapping_add(0x1_0000_0000);
                 }
                 let secs = seconds_upper | seconds_lower;
-                let nanos = old as u32;
-                return ZERO.checked_add_duration(&Duration::new(secs, nanos)).unwrap();
+                let nanos = newer as u32;
+                ZERO.checked_add_duration(&Duration::new(secs, nanos)).unwrap()
             }
         }
     }