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(dur:Duration::from_secs(1000)),
49 Some(d: Instant) => {
50 let now: Instant = Instant::now();
51 if now >= d {
52 break;
53 }
54 thread::sleep(dur:d - now);
55 }
56 }
57 }
58}
59