crossbeam_channel/
utils.rs

1//! Miscellaneous utilities.
2
3use std::cell::Cell;
4use std::num::Wrapping;
5use std::thread;
6use std::time::{Duration, Instant};
7
8/// Randomly shuffles a slice.
9pub(crate) fn shuffle<T>(v: &mut [T]) {
10    let len = v.len();
11    if len <= 1 {
12        return;
13    }
14
15    std::thread_local! {
16        static RNG: Cell<Wrapping<u32>> = const { Cell::new(Wrapping(1_406_868_647)) };
17    }
18
19    let _ = RNG.try_with(|rng| {
20        for i in 1..len {
21            // This is the 32-bit variant of Xorshift.
22            //
23            // Source: https://en.wikipedia.org/wiki/Xorshift
24            let mut x = rng.get();
25            x ^= x << 13;
26            x ^= x >> 17;
27            x ^= x << 5;
28            rng.set(x);
29
30            let x = x.0;
31            let n = i + 1;
32
33            // This is a fast alternative to `let j = x % n`.
34            //
35            // Author: Daniel Lemire
36            // Source: https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/
37            let j = ((x as u64).wrapping_mul(n as u64) >> 32) as u32 as usize;
38
39            v.swap(i, j);
40        }
41    });
42}
43
44/// Sleeps until the deadline, or forever if the deadline isn't specified.
45pub(crate) fn sleep_until(deadline: Option<Instant>) {
46    loop {
47        match deadline {
48            None => thread::sleep(Duration::from_secs(1000)),
49            Some(d) => {
50                let now = Instant::now();
51                if now >= d {
52                    break;
53                }
54                thread::sleep(d - now);
55            }
56        }
57    }
58}