Skip to content

Commit

Permalink
Remove the ReseedingRng abstraction from ThreadRng
Browse files Browse the repository at this point in the history
  • Loading branch information
Paul Dicker committed Sep 24, 2017
1 parent 37faeb5 commit fb58231
Showing 1 changed file with 47 additions and 15 deletions.
62 changes: 47 additions & 15 deletions src/thread_local.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,47 +15,79 @@ use std::rc::Rc;

use {Rng, StdRng, NewSeeded, Rand, Default, Result};

use reseeding::{ReseedingRng, ReseedWithNew};

const THREAD_RNG_RESEED_THRESHOLD: u64 = 32_768;
type ReseedingStdRng = ReseedingRng<StdRng, ReseedWithNew>;
const THREAD_RNG_RESEED_THRESHOLD: u64 = 32 * 1024;

/// The thread-local RNG.
#[derive(Clone)]
#[allow(missing_debug_implementations)]
pub struct ThreadRng {
rng: Rc<RefCell<ReseedingStdRng>>,
rng: Rc<RefCell<ThreadRngInner>>,
}

#[derive(Debug)]
pub struct ThreadRngInner {
rng: StdRng,
bytes_generated: u64,
}

impl Rng for ThreadRng {
fn next_u32(&mut self) -> u32 {
self.rng.borrow_mut().next_u32()
let mut inner = self.rng.borrow_mut();
inner.reseed_if_necessary();
inner.bytes_generated += 4;
inner.rng.next_u32()
}

fn next_u64(&mut self) -> u64 {
self.rng.borrow_mut().next_u64()
let mut inner = self.rng.borrow_mut();
inner.reseed_if_necessary();
inner.bytes_generated += 8;
inner.rng.next_u64()
}

#[cfg(feature = "i128_support")]
fn next_u128(&mut self) -> u128 {
self.rng.borrow_mut().next_u128()
let mut inner = self.rng.borrow_mut();
inner.reseed_if_necessary();
inner.bytes_generated += 16;
inner.rng.next_u128()
}

fn try_fill(&mut self, bytes: &mut [u8]) -> Result<()> {
self.rng.borrow_mut().try_fill(bytes)
let mut inner = self.rng.borrow_mut();
inner.reseed_if_necessary();
inner.bytes_generated += bytes.len() as u64;
inner.rng.try_fill(bytes)
}
}

impl ThreadRngInner {
/// Reseed the internal RNG if the number of bytes that have been
/// generated exceed the threshold.
pub fn reseed_if_necessary(&mut self) {
if self.bytes_generated >= THREAD_RNG_RESEED_THRESHOLD {
let rng = match StdRng::new() {
Ok(r) => r,
// TODO: should we ignore and continue without reseeding?
Err(e) => panic!("could not initialize thread_rng: {:?}", e)
};
self.rng = rng;
self.bytes_generated = 0;
}
}
}

thread_local!(
static THREAD_RNG_KEY: Rc<RefCell<ReseedingStdRng>> = {
let r = match StdRng::new() {
static THREAD_RNG_KEY: Rc<RefCell<ThreadRngInner>> = {
let rng = match StdRng::new() {
Ok(r) => r,
Err(e) => panic!("could not initialize thread_rng: {:?}", e)
};
let rng = ReseedingRng::new(r,
THREAD_RNG_RESEED_THRESHOLD,
ReseedWithNew);
Rc::new(RefCell::new(rng))
let inner = ThreadRngInner {
rng: rng,
bytes_generated: 0,
};
Rc::new(RefCell::new(inner))
}
);

Expand Down

0 comments on commit fb58231

Please sign in to comment.