| 1 | use super::{FastRand, RngSeed}; |
| 2 | |
| 3 | use std::sync::Mutex; |
| 4 | |
| 5 | /// A deterministic generator for seeds (and other generators). |
| 6 | /// |
| 7 | /// Given the same initial seed, the generator will output the same sequence of seeds. |
| 8 | /// |
| 9 | /// Since the seed generator will be kept in a runtime handle, we need to wrap `FastRand` |
| 10 | /// in a Mutex to make it thread safe. Different to the `FastRand` that we keep in a |
| 11 | /// thread local store, the expectation is that seed generation will not need to happen |
| 12 | /// very frequently, so the cost of the mutex should be minimal. |
| 13 | #[derive (Debug)] |
| 14 | pub(crate) struct RngSeedGenerator { |
| 15 | /// Internal state for the seed generator. We keep it in a Mutex so that we can safely |
| 16 | /// use it across multiple threads. |
| 17 | state: Mutex<FastRand>, |
| 18 | } |
| 19 | |
| 20 | impl RngSeedGenerator { |
| 21 | /// Returns a new generator from the provided seed. |
| 22 | pub(crate) fn new(seed: RngSeed) -> Self { |
| 23 | Self { |
| 24 | state: Mutex::new(FastRand::from_seed(seed)), |
| 25 | } |
| 26 | } |
| 27 | |
| 28 | /// Returns the next seed in the sequence. |
| 29 | pub(crate) fn next_seed(&self) -> RngSeed { |
| 30 | let mut rng = self |
| 31 | .state |
| 32 | .lock() |
| 33 | .expect("RNG seed generator is internally corrupt" ); |
| 34 | |
| 35 | let s = rng.fastrand(); |
| 36 | let r = rng.fastrand(); |
| 37 | |
| 38 | RngSeed::from_pair(s, r) |
| 39 | } |
| 40 | |
| 41 | /// Directly creates a generator using the next seed. |
| 42 | pub(crate) fn next_generator(&self) -> Self { |
| 43 | RngSeedGenerator::new(self.next_seed()) |
| 44 | } |
| 45 | } |
| 46 | |
| 47 | impl FastRand { |
| 48 | /// Replaces the state of the random number generator with the provided seed, returning |
| 49 | /// the seed that represents the previous state of the random number generator. |
| 50 | /// |
| 51 | /// The random number generator will become equivalent to one created with |
| 52 | /// the same seed. |
| 53 | pub(crate) fn replace_seed(&mut self, seed: RngSeed) -> RngSeed { |
| 54 | let old_seed: RngSeed = RngSeed::from_pair(self.one, self.two); |
| 55 | |
| 56 | self.one = seed.s; |
| 57 | self.two = seed.r; |
| 58 | |
| 59 | old_seed |
| 60 | } |
| 61 | } |
| 62 | |