feat: Add a fork() method (#49)

* Add a fork() method

* Fix doctest
This commit is contained in:
John Nunley 2023-02-17 15:01:38 -08:00 committed by GitHub
parent 0e0209a77c
commit 61adc59cc6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 39 additions and 9 deletions

View File

@ -255,15 +255,7 @@ impl Rng {
/// Creates a new random number generator.
#[inline]
pub fn new() -> Rng {
Rng::with_seed({
RNG.try_with(|rng| {
let current = rng.replace(Rng(0));
let mut restore = RestoreOnDrop { rng, current };
restore.current.gen_u64()
})
.unwrap_or(0x4d595df4d0f33173)
})
try_with_rng(Rng::fork).unwrap_or_else(|_| Rng::with_seed(0x4d595df4d0f33173))
}
/// Creates a new random number generator with the initial seed.
@ -276,6 +268,32 @@ impl Rng {
rng
}
/// Clones the generator by deterministically deriving a new generator based on the initial
/// seed.
///
/// # Example
///
/// ```
/// // Seed two generators equally, and clone both of them.
/// let mut base1 = fastrand::Rng::new();
/// base1.seed(0x4d595df4d0f33173);
/// base1.bool(); // Use the generator once.
///
/// let mut base2 = fastrand::Rng::new();
/// base2.seed(0x4d595df4d0f33173);
/// base2.bool(); // Use the generator once.
///
/// let mut rng1 = base1.clone();
/// let mut rng2 = base2.clone();
///
/// assert_eq!(rng1.u64(..), rng2.u64(..), "the cloned generators are identical");
/// ```
#[inline]
#[must_use = "this creates a new instance of `Rng`"]
pub fn fork(&mut self) -> Self {
Rng::with_seed(self.gen_u64())
}
/// Generates a random `char` in ranges a-z and A-Z.
#[inline]
pub fn alphabetic(&mut self) -> char {
@ -609,6 +627,18 @@ fn with_rng<R>(f: impl FnOnce(&mut Rng) -> R) -> R {
})
}
/// Try to run an operation with the current thread-local generator.
#[inline]
fn try_with_rng<R>(f: impl FnOnce(&mut Rng) -> R) -> Result<R, std::thread::AccessError> {
RNG.try_with(|rng| {
let current = rng.replace(Rng(0));
let mut restore = RestoreOnDrop { rng, current };
f(&mut restore.current)
})
}
/// Make sure the original RNG is restored even on panic.
struct RestoreOnDrop<'a> {
rng: &'a Cell<Rng>,