1 //! Miscellaneous utilities. 2 3 use std::cell::Cell; 4 use std::num::Wrapping; 5 use std::thread; 6 use std::time::{Duration, Instant}; 7 8 /// Randomly shuffles a slice. shuffle<T>(v: &mut [T])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. sleep_until(deadline: Option<Instant>)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 } 59