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.
new(seed: RngSeed) -> Self22     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.
next_seed(&self) -> RngSeed29     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.
next_generator(&self) -> Self42     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.
replace_seed(&mut self, seed: RngSeed) -> RngSeed53     pub(crate) fn replace_seed(&mut self, seed: RngSeed) -> RngSeed {
54         let old_seed = 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