use pi_time::{now_millisecond, run_millis, start_secs};
use std::sync::atomic::{AtomicU64, Ordering};
#[derive(Debug, Default, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct Guid64(pub u64);
impl Guid64 {
#[inline]
pub fn time(&self) -> u64 {
self.0 >> 16
}
#[inline]
pub fn node_id(&self) -> u16 {
self.0 as u16
}
}
#[derive(Default, Debug)]
pub struct GuidGen64 {
time: AtomicU64, node_start_ms: u64,
node_id: u16,
}
impl GuidGen64 {
pub fn new(node_start_ms: u64, node_id: u16) -> Self {
println!("node_start_ms : {:?}", node_start_ms);
let sec = if node_start_ms == 0 {
start_secs() * 1000
} else {
node_start_ms
};
println!("sec ---- {:?}", sec);
GuidGen64 {
time: AtomicU64::new(run_millis()),
node_start_ms: sec,
node_id: node_id,
}
}
pub fn node_time(&self) -> u64 {
self.node_start_ms
}
pub fn node_id(&self) -> u16 {
self.node_id
}
#[inline]
pub fn time(&self) -> u64 {
let now = run_millis();
loop {
let t = self.time.load(Ordering::Relaxed);
if t < now {
match self
.time
.compare_exchange(t, now, Ordering::SeqCst, Ordering::Relaxed)
{
Ok(_) => return now,
Err(_) => (),
}
} else {
return self.time.fetch_add(1, Ordering::SeqCst) + 1;
}
}
}
#[inline]
pub fn gen(&self) -> Guid64 {
let t = self.time() + self.node_start_ms;
Guid64(t << 16 | self.node_id as u64)
}
}
#[test]
fn test_guid() {
use std::collections::HashMap;
let guid = GuidGen64::new(0, 0);
let mut map = HashMap::new();
let mut i = 1000000;
while i > 0 {
let uuid = guid.gen().0;
map.insert(uuid, "");
i = i - 1;
}
assert_eq!(map.len(), 1000000);
}