snowflake_multi_threaded/
lib.rs1extern crate time;
27
28use std::sync::{Arc, Mutex};
29
30#[derive(Default, Debug)]
31pub struct SnowFlakeId{
32
33 twepoch: i64,
34
35 worker_id_bits: u8,
36 datacenter_id_bits: u8,
37 sequence_bits: u8,
38
39 worker_id: i64,
40 datacenter_id: i64,
41 sequence: i64,
42
43 worker_id_shift: u8,
44 datacenter_id_shift: u8,
45 timestamp_left_shift: u8,
46 sequence_mask: i64,
47
48 last_timestamp:Arc<Mutex<i64>>
49
50}
51
52impl SnowFlakeId{
53
54 pub fn new(worker_id:i64, datacenter_id:i64)->SnowFlakeId{
65 SnowFlakeId{
66 twepoch:1514736000_000i64,
67
68 worker_id_bits:5,
69 datacenter_id_bits:5,
70 sequence_bits :12,
71
72 worker_id : worker_id,
73 datacenter_id : datacenter_id,
74 sequence : 0i64,
75
76 worker_id_shift : 12,
77 datacenter_id_shift: 17,
78 timestamp_left_shift: 22,
79
80 sequence_mask : -1i64 ^ (-1i64 << 12),
81
82 last_timestamp:Arc::new(Mutex::new(0)),
83 }
84 }
85
86 pub fn generate_id(&mut self) -> Result<i64,String> {
98 let mut last_timestamp = self.last_timestamp.lock().unwrap();
99 let mut timestamp = SnowFlakeId::curr_time();
100 if timestamp < *last_timestamp{
101 return Err(format!("Clock moved backwards. Refusing to generate id for {} milliseconds", *last_timestamp));
102 }
103 if timestamp == *last_timestamp {
104 self.sequence = (self.sequence + 1) & self.sequence_mask;
105 if self.sequence == 0 {
106 if timestamp == *last_timestamp {
108 timestamp = self.til_next_millis(*last_timestamp);
109 }
110 }
111 } else {
112 self.sequence = 0i64;
113 }
114 *last_timestamp = timestamp;
116 Ok(((timestamp - self.twepoch) << self.timestamp_left_shift)
117 | (self.datacenter_id << self.datacenter_id_shift)
118 | (self.worker_id << self.worker_id_shift)
119 | self.sequence)
120 }
121
122 fn til_next_millis(&self, last_timestamp:i64) -> i64{
123 let mut timestamp = SnowFlakeId::curr_time();
124 while timestamp <= last_timestamp {
125 timestamp = SnowFlakeId::curr_time()
126 }
127 timestamp
128 }
129
130 fn curr_time() -> i64{
131 let ctime = time::get_time();
132 ctime.sec * 1000 + ctime.nsec as i64/ 1000_000
133 }
134}
135
136#[cfg(test)]
137mod test {
138 use SnowFlakeId;
139 use std::thread;
140 use std::time::Instant;
141
142 #[test]
143 fn loop_test(){
144 let mut id_gen = SnowFlakeId::new(2,2);
145 println!("{:?}",&id_gen);
146 for _ in 1..1000 {
147 let t = &mut id_gen;
148 assert!(t.generate_id().is_ok());
149 }
150 }
151 #[test]
152 fn multi_thread(){
153
154 let now = Instant::now();
155 for i in 1 .. 10{
156 let mut id_gen = SnowFlakeId::new(i,1);
157 thread::spawn(move || {
158 for _ in 1..1000 {
159 let t = &mut id_gen;
160 let _new_id = t.generate_id().unwrap();
161 let id = t.generate_id();
162 assert!(id.is_ok());
163 println!("{:?}",id.unwrap());
164 }
165 });
166 }
167 let elapsed = now.elapsed();
168 println!("{}.{}",elapsed.as_secs(),elapsed.subsec_nanos());
169 }
170}