qlib_rs/data/
snowflake.rs1use std::sync::atomic::{AtomicU64, Ordering};
2use std::time::{SystemTime, UNIX_EPOCH};
3use std::thread::yield_now;
4use std::env;
5
6const NODE_ID_BITS: u64 = 10;
7const SEQUENCE_BITS: u64 = 12;
8
9const MAX_SEQUENCE: u64 = (1 << SEQUENCE_BITS) - 1;
10
11const NODE_ID_SHIFT: u64 = SEQUENCE_BITS;
12const TIMESTAMP_SHIFT: u64 = SEQUENCE_BITS + NODE_ID_BITS;
13
14#[derive(Default)]
15pub struct Snowflake {
16 node_id: u64,
17 state: AtomicU64, }
19
20impl Snowflake {
21 pub fn new() -> Self {
22 match env::var("Q_NODE_ID") {
23 Ok(value) => Self::from(value.parse::<u64>().unwrap_or(0)),
24 Err(_) => Self::from(0),
25 }
26 }
27
28 pub fn generate(&self) -> u64 {
29 loop {
30 let now = current_timestamp();
31
32 let last = self.state.load(Ordering::Relaxed);
33 let last_ts = last >> SEQUENCE_BITS;
34 let last_seq = last & MAX_SEQUENCE;
35
36 if now > last_ts {
37 let next = (now << SEQUENCE_BITS) | 0;
38 if self
39 .state
40 .compare_exchange(last, next, Ordering::SeqCst, Ordering::Relaxed)
41 .is_ok()
42 {
43 return (now << TIMESTAMP_SHIFT) | (self.node_id << NODE_ID_SHIFT);
44 }
45 } else if now == last_ts {
46 let seq = (last_seq + 1) & MAX_SEQUENCE;
47 if seq == 0 {
48 while current_timestamp() <= now {
50 yield_now(); }
52 continue;
53 }
54
55 let next = (last_ts << SEQUENCE_BITS) | seq;
56 if self
57 .state
58 .compare_exchange(last, next, Ordering::SeqCst, Ordering::Relaxed)
59 .is_ok()
60 {
61 return (now << TIMESTAMP_SHIFT)
62 | (self.node_id << NODE_ID_SHIFT)
63 | seq;
64 }
65 } else {
66 panic!("Clock moved backwards!");
67 }
68 }
69 }
70}
71
72impl From<u64> for Snowflake {
73 fn from(node_id: u64) -> Self {
74 Self {
75 node_id,
76 state: AtomicU64::new(0),
77 }
78 }
79}
80
81fn current_timestamp() -> u64 {
82 SystemTime::now()
83 .duration_since(UNIX_EPOCH)
84 .expect("System time before UNIX_EPOCH")
85 .as_millis() as u64
86}