Skip to main content

atomic_time/
instant.rs

1use std::time::Instant;
2
3use super::*;
4
5/// Atomic version of [`Instant`].
6///
7/// Values are encoded relative to a process-local baseline pairing
8/// `std::time::SystemTime::now()` with `std::time::Instant::now()` (see
9/// [`crate::utils::encode_instant_to_duration`] and
10/// [`crate::utils::decode_instant_from_duration`]). Within the same process,
11/// values in the platform's representable `Instant` range round-trip exactly.
12/// Encodings are not portable across processes or restarts: there they only
13/// approximate wall-clock time and must not be used as persistent deadlines.
14/// System clock adjustments can affect that cross-process interpretation, while
15/// behavior across system sleep follows the platform's `Instant` semantics.
16///
17/// With the `serde` feature, this type retains its `Duration` proxy wire
18/// format. For persistent wall-clock values, use [`crate::AtomicSystemTime`].
19#[repr(transparent)]
20pub struct AtomicInstant(AtomicDuration);
21
22impl core::fmt::Debug for AtomicInstant {
23  fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
24    f.debug_tuple("AtomicInstant")
25      .field(&self.load(Ordering::SeqCst))
26      .finish()
27  }
28}
29impl From<Instant> for AtomicInstant {
30  #[inline(always)]
31  fn from(instant: Instant) -> Self {
32    Self::new(instant)
33  }
34}
35impl AtomicInstant {
36  /// Returns the instant corresponding to "now".
37  ///
38  /// # Examples
39  /// ```
40  /// use atomic_time::AtomicInstant;
41  ///
42  /// let now = AtomicInstant::now();
43  /// ```
44  #[inline(always)]
45  pub fn now() -> Self {
46    Self::new(Instant::now())
47  }
48
49  /// Creates a new `AtomicInstant` with the given `Instant` value.
50  #[inline(always)]
51  pub fn new(instant: Instant) -> Self {
52    Self(AtomicDuration::new(encode_instant_to_duration(instant)))
53  }
54
55  /// Loads a value from the atomic instant.
56  #[inline(always)]
57  pub fn load(&self, order: Ordering) -> Instant {
58    decode_instant_from_duration(self.0.load(order))
59  }
60
61  /// Stores a value into the atomic instant.
62  #[inline(always)]
63  pub fn store(&self, instant: Instant, order: Ordering) {
64    self.0.store(encode_instant_to_duration(instant), order)
65  }
66
67  /// Stores a value into the atomic instant, returning the previous value.
68  #[inline(always)]
69  pub fn swap(&self, instant: Instant, order: Ordering) -> Instant {
70    decode_instant_from_duration(self.0.swap(encode_instant_to_duration(instant), order))
71  }
72
73  /// Stores a value into the atomic instant if the current value is the same as the `current`
74  /// value.
75  #[inline(always)]
76  pub fn compare_exchange(
77    &self,
78    current: Instant,
79    new: Instant,
80    success: Ordering,
81    failure: Ordering,
82  ) -> Result<Instant, Instant> {
83    match self.0.compare_exchange(
84      encode_instant_to_duration(current),
85      encode_instant_to_duration(new),
86      success,
87      failure,
88    ) {
89      Ok(duration) => Ok(decode_instant_from_duration(duration)),
90      Err(duration) => Err(decode_instant_from_duration(duration)),
91    }
92  }
93
94  /// Stores a value into the atomic instant if the current value is the same as the `current`
95  /// value.
96  #[inline(always)]
97  pub fn compare_exchange_weak(
98    &self,
99    current: Instant,
100    new: Instant,
101    success: Ordering,
102    failure: Ordering,
103  ) -> Result<Instant, Instant> {
104    match self.0.compare_exchange_weak(
105      encode_instant_to_duration(current),
106      encode_instant_to_duration(new),
107      success,
108      failure,
109    ) {
110      Ok(duration) => Ok(decode_instant_from_duration(duration)),
111      Err(duration) => Err(decode_instant_from_duration(duration)),
112    }
113  }
114
115  /// Fetches the value and applies a function that can choose whether to store
116  /// a new value.
117  ///
118  /// Returns `Ok(previous_value)` when `f` returns `Some(_)`, and
119  /// `Err(previous_value)` when it returns `None`. The closure can run more
120  /// than once when another thread changes the value concurrently, but it is
121  /// applied only once to the value that is stored.
122  ///
123  /// `set_order` describes the ordering of the successful update and
124  /// `fetch_order` describes failed compare-and-exchange loads. They have the
125  /// same requirements as the success and failure orderings of
126  /// [`compare_exchange`](Self::compare_exchange).
127  ///
128  /// # Examples
129  ///
130  /// ```rust
131  /// use atomic_time::AtomicInstant;
132  /// use std::{sync::atomic::Ordering, time::{Duration, Instant}};
133  ///
134  /// let start = Instant::now();
135  /// let x = AtomicInstant::new(start);
136  /// assert_eq!(x.try_update(Ordering::SeqCst, Ordering::SeqCst, |_| None), Err(start));
137  /// assert_eq!(x.try_update(Ordering::SeqCst, Ordering::SeqCst, |old| Some(old + Duration::from_secs(1))), Ok(start));
138  /// ```
139  #[inline(always)]
140  pub fn try_update<F>(
141    &self,
142    set_order: Ordering,
143    fetch_order: Ordering,
144    mut f: F,
145  ) -> Result<Instant, Instant>
146  where
147    F: FnMut(Instant) -> Option<Instant>,
148  {
149    self
150      .0
151      .try_update(set_order, fetch_order, |duration| {
152        f(decode_instant_from_duration(duration)).map(encode_instant_to_duration)
153      })
154      .map(decode_instant_from_duration)
155      .map_err(decode_instant_from_duration)
156  }
157
158  /// Fetches the value, and applies a function to it that returns an optional
159  /// new value. Returns a `Result` of `Ok(previous_value)` if the function returned `Some(_)`, else
160  /// `Err(previous_value)`.
161  ///
162  /// Note: This may call the function multiple times if the value has been changed from other threads in
163  /// the meantime, as long as the function returns `Some(_)`, but the function will have been applied
164  /// only once to the stored value.
165  ///
166  /// `fetch_update` takes two [`Ordering`] arguments to describe the memory ordering of this operation.
167  /// The first describes the required ordering for when the operation finally succeeds while the second
168  /// describes the required ordering for loads. These correspond to the success and failure orderings of
169  /// [`compare_exchange`] respectively.
170  ///
171  /// Using [`Acquire`](Ordering::Acquire) as success ordering makes the store part
172  /// of this operation [`Relaxed`](Ordering::Relaxed), and using [`Release`](Ordering::Release) makes the final successful load
173  /// [`Relaxed`](Ordering::Relaxed). The (failed) load ordering can only be [`SeqCst`](Ordering::SeqCst), [`Acquire`](Ordering::Acquire) or [`Relaxed`](Ordering::Relaxed)
174  /// and must be equivalent to or weaker than the success ordering.
175  ///
176  /// [`compare_exchange`]: #method.compare_exchange
177  ///
178  /// # Examples
179  ///
180  /// ```rust
181  /// use atomic_time::AtomicInstant;
182  /// use std::{time::{Duration, Instant}, sync::atomic::Ordering};
183  ///
184  /// let now = Instant::now();
185  /// let x = AtomicInstant::new(now);
186  /// assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |_| None), Err(now));
187  ///
188  /// assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(x + Duration::from_secs(1))), Ok(now));
189  /// assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(x + Duration::from_secs(1))), Ok(now + Duration::from_secs(1)));
190  /// assert_eq!(x.load(Ordering::SeqCst), now + Duration::from_secs(2));
191  /// ```
192  #[inline(always)]
193  pub fn fetch_update<F>(
194    &self,
195    set_order: Ordering,
196    fetch_order: Ordering,
197    f: F,
198  ) -> Result<Instant, Instant>
199  where
200    F: FnMut(Instant) -> Option<Instant>,
201  {
202    self.try_update(set_order, fetch_order, f)
203  }
204
205  /// Fetches the value, applies a function to produce a new value, stores it,
206  /// and returns the previous value.
207  ///
208  /// The closure can run more than once when another thread changes the value
209  /// concurrently, but it is applied only once to the value that is stored.
210  /// `set_order` and `fetch_order` have the same requirements as the success
211  /// and failure orderings of [`compare_exchange`](Self::compare_exchange).
212  ///
213  /// # Examples
214  ///
215  /// ```rust
216  /// use atomic_time::AtomicInstant;
217  /// use std::{sync::atomic::Ordering, time::{Duration, Instant}};
218  ///
219  /// let start = Instant::now();
220  /// let x = AtomicInstant::new(start);
221  /// assert_eq!(x.update(Ordering::SeqCst, Ordering::SeqCst, |old| old + Duration::from_secs(1)), start);
222  /// assert_eq!(x.load(Ordering::SeqCst), start + Duration::from_secs(1));
223  /// ```
224  #[inline(always)]
225  pub fn update<F>(&self, set_order: Ordering, fetch_order: Ordering, mut f: F) -> Instant
226  where
227    F: FnMut(Instant) -> Instant,
228  {
229    decode_instant_from_duration(self.0.update(set_order, fetch_order, |duration| {
230      encode_instant_to_duration(f(decode_instant_from_duration(duration)))
231    }))
232  }
233
234  /// Atomically stores the smaller of the current value and `val`, returning
235  /// the previous value.
236  ///
237  /// The ordering compares values encoded with this process's baseline. It is
238  /// meaningful only for `Instant` values using the same process-local
239  /// baseline; it does not assign ordering semantics across processes or
240  /// process restarts. `order` describes the memory ordering of the
241  /// read-modify-write operation. Using [`Acquire`](Ordering::Acquire) makes
242  /// its store part relaxed, and using [`Release`](Ordering::Release) makes its
243  /// load part relaxed.
244  ///
245  /// # Examples
246  ///
247  /// ```rust
248  /// use atomic_time::AtomicInstant;
249  /// use std::{sync::atomic::Ordering, time::{Duration, Instant}};
250  ///
251  /// let middle = Instant::now();
252  /// let low = middle - Duration::from_secs(1);
253  /// let high = middle + Duration::from_secs(1);
254  /// let x = AtomicInstant::new(middle);
255  /// assert_eq!(x.fetch_min(high, Ordering::SeqCst), middle);
256  /// assert_eq!(x.fetch_min(low, Ordering::SeqCst), middle);
257  /// assert_eq!(x.load(Ordering::SeqCst), low);
258  /// ```
259  #[inline(always)]
260  pub fn fetch_min(&self, val: Instant, order: Ordering) -> Instant {
261    decode_instant_from_duration(self.0.fetch_min(encode_instant_to_duration(val), order))
262  }
263
264  /// Atomically stores the larger of the current value and `val`, returning
265  /// the previous value.
266  ///
267  /// The ordering compares values encoded with this process's baseline. It is
268  /// meaningful only for `Instant` values using the same process-local
269  /// baseline; it does not assign ordering semantics across processes or
270  /// process restarts. `order` describes the memory ordering of the
271  /// read-modify-write operation. Using [`Acquire`](Ordering::Acquire) makes
272  /// its store part relaxed, and using [`Release`](Ordering::Release) makes its
273  /// load part relaxed.
274  ///
275  /// # Examples
276  ///
277  /// ```rust
278  /// use atomic_time::AtomicInstant;
279  /// use std::{sync::atomic::Ordering, time::{Duration, Instant}};
280  ///
281  /// let middle = Instant::now();
282  /// let low = middle - Duration::from_secs(1);
283  /// let high = middle + Duration::from_secs(1);
284  /// let x = AtomicInstant::new(middle);
285  /// assert_eq!(x.fetch_max(low, Ordering::SeqCst), middle);
286  /// assert_eq!(x.fetch_max(high, Ordering::SeqCst), middle);
287  /// assert_eq!(x.load(Ordering::SeqCst), high);
288  /// ```
289  #[inline(always)]
290  pub fn fetch_max(&self, val: Instant, order: Ordering) -> Instant {
291    decode_instant_from_duration(self.0.fetch_max(encode_instant_to_duration(val), order))
292  }
293
294  /// Returns `true` if operations on values of this type are lock-free.
295  /// If the compiler or the platform doesn't support the necessary
296  /// atomic instructions, global locks for every potentially
297  /// concurrent atomic operation will be used.
298  ///
299  /// # Examples
300  /// ```
301  /// use atomic_time::AtomicInstant;
302  ///
303  /// let is_lock_free = AtomicInstant::is_lock_free();
304  /// ```
305  #[inline(always)]
306  pub fn is_lock_free() -> bool {
307    AtomicU128::is_lock_free()
308  }
309
310  /// Returns whether operations on values of this type are always lock-free.
311  ///
312  /// A `false` result does not preclude lock-free operations selected through
313  /// runtime CPU feature detection; use [`is_lock_free`](Self::is_lock_free)
314  /// to query the current target at runtime.
315  ///
316  /// # Examples
317  ///
318  /// ```rust
319  /// use atomic_time::AtomicInstant;
320  ///
321  /// const ALWAYS_LOCK_FREE: bool = AtomicInstant::is_always_lock_free();
322  /// let _ = ALWAYS_LOCK_FREE;
323  /// ```
324  #[inline(always)]
325  pub const fn is_always_lock_free() -> bool {
326    AtomicDuration::is_always_lock_free()
327  }
328
329  /// Consumes the atomic and returns the contained value.
330  ///
331  /// This is safe because passing `self` by value guarantees that no other threads are
332  /// concurrently accessing the atomic data.
333  #[inline(always)]
334  pub fn into_inner(self) -> Instant {
335    decode_instant_from_duration(self.0.into_inner())
336  }
337}
338
339#[cfg(feature = "serde")]
340const _: () = {
341  use core::time::Duration;
342  use serde::{Deserialize, Serialize};
343
344  impl Serialize for AtomicInstant {
345    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
346      self.0.load(Ordering::SeqCst).serialize(serializer)
347    }
348  }
349
350  impl<'de> Deserialize<'de> for AtomicInstant {
351    fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
352      Ok(Self::new(decode_instant_from_duration(
353        Duration::deserialize(deserializer)?,
354      )))
355    }
356  }
357};
358
359#[cfg(test)]
360mod tests {
361  use super::*;
362  use std::time::Duration;
363
364  #[test]
365  fn test_atomic_instant_now() {
366    let atomic_instant = AtomicInstant::now();
367    // Check that the time is reasonable (not too far from now).
368    let now = Instant::now();
369    let loaded_instant = atomic_instant.load(Ordering::SeqCst);
370    assert!(loaded_instant <= now);
371    assert!(loaded_instant >= now - Duration::from_secs(1));
372  }
373
374  #[test]
375  fn test_atomic_instant_new_and_load() {
376    let now = Instant::now();
377    let atomic_instant = AtomicInstant::new(now);
378    assert_eq!(atomic_instant.load(Ordering::SeqCst), now);
379  }
380
381  #[test]
382  fn test_atomic_instant_store_and_load() {
383    let now = Instant::now();
384    let after_one_sec = now + Duration::from_secs(1);
385    let atomic_instant = AtomicInstant::new(now);
386    atomic_instant.store(after_one_sec, Ordering::SeqCst);
387    assert_eq!(atomic_instant.load(Ordering::SeqCst), after_one_sec);
388  }
389
390  #[test]
391  fn test_atomic_instant_swap() {
392    let now = Instant::now();
393    let after_one_sec = now + Duration::from_secs(1);
394    let atomic_instant = AtomicInstant::new(now);
395    let prev_instant = atomic_instant.swap(after_one_sec, Ordering::SeqCst);
396    assert_eq!(prev_instant, now);
397    assert_eq!(atomic_instant.load(Ordering::SeqCst), after_one_sec);
398  }
399
400  #[test]
401  fn test_atomic_instant_compare_exchange() {
402    let now = Instant::now();
403    let after_one_sec = now + Duration::from_secs(1);
404    let atomic_instant = AtomicInstant::new(now);
405    let result =
406      atomic_instant.compare_exchange(now, after_one_sec, Ordering::SeqCst, Ordering::SeqCst);
407    assert!(result.is_ok());
408    assert_eq!(atomic_instant.load(Ordering::SeqCst), after_one_sec);
409  }
410
411  #[test]
412  fn test_atomic_instant_compare_exchange_weak() {
413    let now = Instant::now();
414    let after_one_sec = now + Duration::from_secs(1);
415    let atomic_instant = AtomicInstant::new(now);
416
417    let mut result;
418    loop {
419      result = atomic_instant.compare_exchange_weak(
420        now,
421        after_one_sec,
422        Ordering::SeqCst,
423        Ordering::SeqCst,
424      );
425      if result.is_ok() {
426        break;
427      }
428    }
429    assert!(result.is_ok());
430    assert_eq!(atomic_instant.load(Ordering::SeqCst), after_one_sec);
431  }
432
433  #[test]
434  fn test_atomic_instant_fetch_update() {
435    let now = Instant::now();
436    let atomic_instant = AtomicInstant::new(now);
437
438    let result = atomic_instant.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |prev| {
439      Some(prev + Duration::from_secs(1))
440    });
441    assert!(result.is_ok());
442    assert_eq!(result.unwrap(), now);
443    assert_eq!(
444      atomic_instant.load(Ordering::SeqCst),
445      now + Duration::from_secs(1)
446    );
447  }
448
449  #[test]
450  fn test_atomic_instant_try_update() {
451    let start = Instant::now();
452    let atomic_instant = AtomicInstant::new(start);
453
454    assert_eq!(
455      atomic_instant.try_update(Ordering::SeqCst, Ordering::SeqCst, |_| None),
456      Err(start)
457    );
458    assert_eq!(
459      atomic_instant.try_update(Ordering::SeqCst, Ordering::SeqCst, |current| {
460        Some(current + Duration::from_secs(2))
461      }),
462      Ok(start)
463    );
464    assert_eq!(
465      atomic_instant.load(Ordering::SeqCst),
466      start + Duration::from_secs(2)
467    );
468  }
469
470  #[test]
471  fn test_atomic_instant_update_returns_previous_value() {
472    let start = Instant::now();
473    let atomic_instant = AtomicInstant::new(start);
474
475    assert_eq!(
476      atomic_instant.update(Ordering::SeqCst, Ordering::SeqCst, |current| {
477        current + Duration::from_secs(2)
478      }),
479      start
480    );
481    assert_eq!(
482      atomic_instant.load(Ordering::SeqCst),
483      start + Duration::from_secs(2)
484    );
485  }
486
487  #[test]
488  fn test_atomic_instant_fetch_min_and_max() {
489    let middle = Instant::now();
490    let low = middle.checked_sub(Duration::from_secs(2)).unwrap();
491    let high = middle.checked_add(Duration::from_secs(2)).unwrap();
492    let atomic_instant = AtomicInstant::new(middle);
493
494    assert_eq!(atomic_instant.fetch_min(high, Ordering::SeqCst), middle);
495    assert_eq!(atomic_instant.load(Ordering::SeqCst), middle);
496    assert_eq!(atomic_instant.fetch_min(middle, Ordering::SeqCst), middle);
497    assert_eq!(atomic_instant.load(Ordering::SeqCst), middle);
498    assert_eq!(atomic_instant.fetch_min(low, Ordering::SeqCst), middle);
499    assert_eq!(atomic_instant.load(Ordering::SeqCst), low);
500
501    atomic_instant.store(middle, Ordering::SeqCst);
502    assert_eq!(atomic_instant.fetch_max(low, Ordering::SeqCst), middle);
503    assert_eq!(atomic_instant.load(Ordering::SeqCst), middle);
504    assert_eq!(atomic_instant.fetch_max(middle, Ordering::SeqCst), middle);
505    assert_eq!(atomic_instant.load(Ordering::SeqCst), middle);
506    assert_eq!(atomic_instant.fetch_max(high, Ordering::SeqCst), middle);
507    assert_eq!(atomic_instant.load(Ordering::SeqCst), high);
508  }
509
510  #[test]
511  fn test_atomic_instant_always_lock_free_implies_lock_free() {
512    assert!(!AtomicInstant::is_always_lock_free() || AtomicInstant::is_lock_free());
513  }
514
515  #[test]
516  fn test_atomic_instant_thread_safety() {
517    use std::sync::Arc;
518    use std::thread;
519
520    // Start from a fixed, known value so we can assert an *exact*
521    // final result. The previous version did `load + add + store`,
522    // which loses updates under contention (two threads load the
523    // same value, each writes load+50ms, only one write survives).
524    // Its assertion — "within 200 ms of now" — was satisfied even
525    // when 3 of 4 updates were dropped.
526    let start = Instant::now();
527    let atomic_instant = Arc::new(AtomicInstant::new(start));
528    let mut handles = vec![];
529
530    for _ in 0..4 {
531      let atomic_clone = atomic_instant.clone();
532      let handle = thread::spawn(move || {
533        // `fetch_update` retries on conflict, so every thread's
534        // increment is guaranteed to stick.
535        atomic_clone
536          .fetch_update(Ordering::SeqCst, Ordering::SeqCst, |current| {
537            Some(current + Duration::from_millis(50))
538          })
539          .expect("closure never returns None");
540      });
541      handles.push(handle);
542    }
543
544    for handle in handles {
545      handle.join().unwrap();
546    }
547
548    // 4 threads × 50 ms = 200 ms, no lost updates.
549    assert_eq!(
550      atomic_instant.load(Ordering::SeqCst),
551      start + Duration::from_millis(200)
552    );
553  }
554
555  #[test]
556  fn test_atomic_instant_debug() {
557    let atomic_instant = AtomicInstant::now();
558    let debug_str = format!("{:?}", atomic_instant);
559    assert!(debug_str.contains("AtomicInstant"));
560  }
561
562  #[test]
563  fn test_atomic_instant_from() {
564    let now = Instant::now();
565    let atomic_instant = AtomicInstant::from(now);
566    assert_eq!(atomic_instant.load(Ordering::SeqCst), now);
567  }
568
569  #[test]
570  fn test_atomic_instant_into_inner() {
571    let now = Instant::now();
572    let atomic_instant = AtomicInstant::new(now);
573    assert_eq!(atomic_instant.into_inner(), now);
574  }
575
576  #[test]
577  fn test_atomic_instant_compare_exchange_failure() {
578    let now = Instant::now();
579    let other = now + Duration::from_secs(5);
580    let atomic_instant = AtomicInstant::new(now);
581    let result = atomic_instant.compare_exchange(other, other, Ordering::SeqCst, Ordering::SeqCst);
582    assert!(result.is_err());
583    assert_eq!(result.unwrap_err(), now);
584  }
585
586  #[test]
587  fn test_atomic_instant_fetch_update_failure() {
588    let now = Instant::now();
589    let atomic_instant = AtomicInstant::new(now);
590    let result = atomic_instant.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |_| None);
591    assert!(result.is_err());
592    assert_eq!(result.unwrap_err(), now);
593  }
594
595  #[cfg(feature = "serde")]
596  #[test]
597  fn test_atomic_instant_serde_round_trip_past_and_future() {
598    let now = Instant::now();
599    for instant in [
600      now.checked_sub(Duration::from_secs(1)).unwrap(),
601      now.checked_add(Duration::from_secs(1)).unwrap(),
602    ] {
603      let atomic = AtomicInstant::new(instant);
604      let serialized = serde_json::to_string(&atomic).unwrap();
605      let deserialized: AtomicInstant = serde_json::from_str(&serialized).unwrap();
606      assert_eq!(deserialized.load(Ordering::SeqCst), instant);
607    }
608  }
609
610  #[cfg(feature = "serde")]
611  #[test]
612  fn test_atomic_instant_serde_matches_duration_wire_model() {
613    let instant = Instant::now();
614    let atomic = AtomicInstant::new(instant);
615    let wire_model = crate::utils::encode_instant_to_duration(instant);
616    assert_eq!(
617      serde_json::to_string(&atomic).unwrap(),
618      serde_json::to_string(&wire_model).unwrap()
619    );
620  }
621
622  #[test]
623  fn test_atomic_instant_past_value() {
624    use std::thread;
625
626    let past = Instant::now();
627    thread::sleep(Duration::from_millis(10));
628    let now = Instant::now();
629
630    // Store a past instant and verify roundtrip
631    let atomic = AtomicInstant::new(now);
632    atomic.store(past, Ordering::SeqCst);
633    let loaded = atomic.load(Ordering::SeqCst);
634    assert!(loaded < now);
635    assert_eq!(loaded, past);
636  }
637
638  #[test]
639  fn decode_extreme_instant_falls_back_to_baseline() {
640    // Inputs outside the platform Instant range use the process baseline as a
641    // fallback rather than saturating an Instant value.
642    let max_dur = Duration::new(u64::MAX, 999_999_999);
643    let decoded = crate::utils::decode_instant_from_duration(max_dur);
644    let other_extreme = Duration::new(u64::MAX, 999_999_998);
645    assert_eq!(
646      decoded,
647      crate::utils::decode_instant_from_duration(other_extreme)
648    );
649  }
650
651  #[cfg(feature = "serde")]
652  #[test]
653  fn deserialize_extreme_instant_uses_baseline_fallback() {
654    // Preserve the existing Ok deserialization behavior for an extreme wire
655    // value; its decoded Instant falls back to the process baseline.
656    let json = r#"{"secs":18446744073709551615,"nanos":999999999}"#;
657    let result: Result<AtomicInstant, _> = serde_json::from_str(json);
658    let atomic = result.expect("extreme Instant deserialization remains Ok");
659    assert_eq!(
660      atomic.load(Ordering::SeqCst),
661      crate::utils::decode_instant_from_duration(Duration::new(u64::MAX, 999_999_999))
662    );
663  }
664}