tokio/util/rand/
rt.rs

1use super::{FastRand, RngSeed};
2
3use 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)]
14pub(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
20impl 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
47impl 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::from_pair(self.one, self.two);
55
56        self.one = seed.s;
57        self.two = seed.r;
58
59        old_seed
60    }
61}