snowflake_multi_threaded/
lib.rs

1// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
2// file at the top-level directory of this distribution and at
3// http://rust-lang.org/COPYRIGHT.
4//
5// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8// option. This file may not be copied, modified, or distributed
9// except according to those terms.
10//!Generate id with the  type i64
11//!
12//!
13//!
14//! # Examples
15//!
16//! ```
17//!use snowflake_multi_threaded::SnowFlakeId;
18//!
19//! let worker_id:i64 = 1;
20//! let datacenter_id:i64 = 1;
21//! let mut id_gen = SnowFlakeId::new(worker_id,datacenter_id);
22//! assert!(id_gen.generate_id().is_ok());
23//! ```
24//!
25//!
26extern 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    /// Returns the instance of SnowFlakeId
55    ///
56    /// # Examples
57    ///
58    /// ```
59    /// use snowflake_multi_threaded::SnowFlakeId;
60    ///
61    /// let var = SnowFlakeId::new(1,1);
62    ///
63    /// ```
64    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    /// Return a number type of i64, it will always grow
87    /// `When Clock  moved backwards ,it will be panic`
88    /// # Examples
89    ///
90    /// ```
91    /// use snowflake_multi_threaded::SnowFlakeId;
92    ///
93    /// let var = SnowFlakeId::new(1,1).generate_id();
94    ///
95    /// println!("the new id is {}", var.unwrap());
96    /// ```
97    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                //milliseconds overflow
107                if timestamp == *last_timestamp {
108                    timestamp = self.til_next_millis(*last_timestamp);
109                }
110            }
111        } else {
112            self.sequence = 0i64;
113        }
114        // println!("{}-<<<{}-{}-{}-{}-{}", self.sequence_mask, self.timestamp_left_shift, (*last_timestamp), self.datacenter_id, self.worker_id, self.sequence);
115        *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}