atomr_remote/
address_uid.rs1use std::sync::atomic::{AtomicU64, Ordering};
10use std::sync::Arc;
11use std::time::{SystemTime, UNIX_EPOCH};
12
13#[derive(Debug, Clone)]
14pub struct AddressUid {
15 inner: Arc<AddressUidInner>,
16}
17
18#[derive(Debug)]
19struct AddressUidInner {
20 value: AtomicU64,
21}
22
23impl Default for AddressUid {
24 fn default() -> Self {
25 Self::new()
26 }
27}
28
29impl AddressUid {
30 pub fn new() -> Self {
33 let nanos = SystemTime::now()
34 .duration_since(UNIX_EPOCH)
35 .map(|d| d.as_nanos() as u64)
36 .unwrap_or_else(|_| next_fallback());
37 let mixed = nanos.wrapping_mul(2862933555777941757).wrapping_add(3037000493);
40 Self { inner: Arc::new(AddressUidInner { value: AtomicU64::new(mixed) }) }
41 }
42
43 pub fn get(&self) -> u64 {
44 self.inner.value.load(Ordering::Acquire)
45 }
46}
47
48fn next_fallback() -> u64 {
49 static COUNTER: AtomicU64 = AtomicU64::new(1);
50 COUNTER.fetch_add(1, Ordering::SeqCst)
51}
52
53#[cfg(test)]
54mod tests {
55 use super::*;
56
57 #[test]
58 fn distinct_systems_get_distinct_uids() {
59 let a = AddressUid::new();
60 std::thread::sleep(std::time::Duration::from_micros(10));
61 let b = AddressUid::new();
62 assert_ne!(a.get(), b.get());
63 }
64
65 #[test]
66 fn cloned_handle_observes_same_uid() {
67 let a = AddressUid::new();
68 let b = a.clone();
69 assert_eq!(a.get(), b.get());
70 }
71}