tlid

Crates.iotlid
lib.rstlid
version0.2.2
sourcesrc
created_at2020-01-26 16:07:31.475507
updated_at2020-02-05 23:15:29.990414
descriptionThread Local ID generator by predefined range without atomics/locks/random/time
homepagehttps://gitlab.com/xMAC94x/tlid
repositoryhttps://gitlab.com/xMAC94x/tlid
max_upload_size
id202190
size47,114
Marcel Märtens (xMAC94x)

documentation

https://docs.rs/tlid

README

pipeline status coverage report lines of code

TLID

low level generation of unique ids by assigning a range per thread.

Pros:

  • unique number, simple incremented
  • no locks, no atomic for ::next()
  • all dependencies are optional
  • speed: 600,000,000/s
  • example coding
  • strict ci tests

Cons:

  • range needs to be know before, e.g. u64, with 1024 threads only leaves 2^54 usable ids per thread
  • not cryptographic secure (simple inc)
  • creation and deletion of pools requieres syncronisation
  • beta: before 0.9 tlid isn't production ready, expect bugs or non-optimal ID return behavior

There are alot of Id crates but almost all use either some random values, timing, or atomic behavior to be unique over multiple threads. Tlid (thread local unique id) aims to archive uniqueness by assigning a initial range to every thread. This requieres setting a range for each pool (and subpool), which makes ::next() super fast.

There are 3 options behaviors for ::next(), which cannot not be mixed

  • Checked: gurantees a unique id at the cost of a range check with each operation
  • Wrapping: has the same check, but instead of rendering the Pool useless after all IDs are used, it wraps around. IDs are not unique anymore but this is useful for short buffers like for networking
  • Unchecked: fastes method with no guarantee, bounds are not checked in ::next() method.

Dependencies

[dependencies]
tlid = "0.2"

Examples

// see examples folder

use tlid::{Pool, Checked};
use std::{
    thread,
    time::Duration,
    result::Result,
    error::Error,
};

fn worker(thread: u8, p: &mut Pool<Checked<u64>>) {
    //work
    for _ in 0..2 {
        thread::sleep(Duration::from_millis(1));
        println!("[{}] did work: {}", thread, p.next().unwrap());
    }
}

fn main() -> Result<(), Box<dyn Error>> {
    let mut p = Pool::new_full();
    for i in 0..5 {
        let mut local_pool = p.subpool(5)?;
        thread::spawn(move ||
            worker(i, &mut local_pool)
        );
    }
    thread::sleep(Duration::from_millis(100));
    Ok(())
}

Example output (as you see, all ids are unique):

[0] did work: 0
[1] did work: 2
[2] did work: 4
[0] did work: 1
[1] did work: 3
[3] did work: 6
[4] did work: 8
[2] did work: 5
[3] did work: 7
[4] did work: 9

License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

Commit count: 6

cargo fmt