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 | |