Replace XorShiftRng with a custom RNG (#466)

This commit is contained in:
Stjepan Glavina
2018-07-06 13:33:52 -07:00
committed by Carl Lerche
parent f1a7caea3f
commit dc7202cfa9
+20 -37
View File
@@ -21,13 +21,14 @@ use worker::{self, Worker, WorkerId};
use futures::Poll; use futures::Poll;
use futures::task::AtomicTask; use futures::task::AtomicTask;
use std::cell::UnsafeCell; use std::cell::Cell;
use std::sync::atomic::Ordering::{Acquire, AcqRel, Relaxed}; use std::num::Wrapping;
use std::sync::atomic::Ordering::{Acquire, AcqRel};
use std::sync::atomic::AtomicUsize; use std::sync::atomic::AtomicUsize;
use std::sync::Arc; use std::sync::Arc;
use std::thread; use std::thread;
use rand::{Rng, SeedableRng, XorShiftRng}; use rand;
#[derive(Debug)] #[derive(Debug)]
pub(crate) struct Pool { pub(crate) struct Pool {
@@ -50,9 +51,6 @@ pub(crate) struct Pool {
// shutdown process has completed. // shutdown process has completed.
pub num_workers: AtomicUsize, pub num_workers: AtomicUsize,
// Used to generate a thread local RNG seed
pub next_thread_id: AtomicUsize,
// Worker state // Worker state
// //
// A worker is a thread that is processing the work queue and polling // A worker is a thread that is processing the work queue and polling
@@ -112,7 +110,6 @@ impl Pool {
state: AtomicUsize::new(State::new().into()), state: AtomicUsize::new(State::new().into()),
sleep_stack: worker::Stack::new(), sleep_stack: worker::Stack::new(),
num_workers: AtomicUsize::new(0), num_workers: AtomicUsize::new(0),
next_thread_id: AtomicUsize::new(0),
workers, workers,
backup, backup,
backup_stack, backup_stack,
@@ -518,39 +515,25 @@ impl Pool {
/// Generates a random number /// Generates a random number
/// ///
/// Uses a thread-local seeded XorShift. /// Uses a thread-local random number generator based on XorShift.
pub fn rand_usize(&self) -> usize { pub fn rand_usize(&self) -> usize {
// Use a thread-local random number generator. If the thread does not thread_local! {
// have one yet, then seed a new one static RNG: Cell<Wrapping<u32>> = {
thread_local!(static THREAD_RNG_KEY: UnsafeCell<Option<XorShiftRng>> = UnsafeCell::new(None)); // The initial seed must be non-zero.
let init = rand::random::<u32>() | 1;
THREAD_RNG_KEY.with(|t| { Cell::new(Wrapping(init))
#[cfg(target_pointer_width = "32")]
fn new_rng(thread_id: usize) -> XorShiftRng {
XorShiftRng::from_seed([
thread_id as u32,
0x00000000,
0xa8a7d469,
0x97830e05])
} }
}
#[cfg(target_pointer_width = "64")] RNG.with(|rng| {
fn new_rng(thread_id: usize) -> XorShiftRng { // This is the 32-bit variant of Xorshift.
XorShiftRng::from_seed([ // https://en.wikipedia.org/wiki/Xorshift
thread_id as u32, let mut x = rng.get();
(thread_id >> 32) as u32, x ^= x << 13;
0xa8a7d469, x ^= x >> 17;
0x97830e05]) x ^= x << 5;
} rng.set(x);
x.0 as usize
let thread_id = self.next_thread_id.fetch_add(1, Relaxed);
let rng = unsafe { &mut *t.get() };
if rng.is_none() {
*rng = Some(new_rng(thread_id));
}
rng.as_mut().unwrap().next_u32() as usize
}) })
} }
} }