Skip to content

Commit 1713890

Browse files
committed
made multithreaded deterministic
1 parent 37615a2 commit 1713890

3 files changed

Lines changed: 49 additions & 10 deletions

File tree

Cargo.lock

Lines changed: 6 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ features = ["std", "sys_rng"]
1616
rustdoc-args = ["--cfg", "getrandom_backend=\"extern_impl\""]
1717

1818
[features]
19+
default = ["unsafe_deterministic_testing"]
1920
# Implement From<getrandom::Error> for std::io::Error and
2021
# use std to retrieve OS error descriptions
2122
std = []

src/backends/deterministic.rs

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,22 +11,32 @@ use crate::Error;
1111
use chacha20::ChaCha12Rng;
1212
use core::mem::MaybeUninit;
1313
use rand_core::{Rng, SeedableRng};
14-
use std::sync::{Mutex, OnceLock};
14+
use std::{
15+
collections::HashMap,
16+
sync::{Mutex, OnceLock},
17+
};
1518

1619
/// The RNG, initialised exactly once on first use.
17-
static RNG: OnceLock<Mutex<ChaCha12Rng>> = OnceLock::new();
20+
static RNG: OnceLock<Mutex<HashMap<std::thread::ThreadId, ChaCha12Rng>>> = OnceLock::new();
1821

1922
#[inline]
2023
pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
21-
let rng = RNG.get_or_init(|| Mutex::new(ChaCha12Rng::from_seed([42u8; 32])));
24+
// get current thread id
25+
let id = std::thread::current().id();
26+
27+
let rng = RNG.get_or_init(|| HashMap::new().into());
2228

2329
let mut guard = rng.lock().unwrap();
2430

31+
let entry = guard
32+
.entry(id)
33+
.or_insert_with(|| ChaCha12Rng::from_seed([42u8; 32]));
34+
2535
// SAFETY: `fill_bytes` fully overwrites every byte of the slice, so
2636
// treating uninitialized `MaybeUninit<u8>` as `u8` for the purpose of
2737
// writing (never reading) is sound.
2838
let dest_init = unsafe { dest.assume_init_mut() };
29-
guard.fill_bytes(dest_init);
39+
entry.fill_bytes(dest_init);
3040

3141
Ok(())
3242
}
@@ -48,4 +58,32 @@ mod tests {
4858
buf
4959
);
5060
}
61+
use std::thread;
62+
#[test]
63+
fn test_deterministic_multithread() {
64+
thread::spawn(|| {
65+
let mut buf = [0u8; 32];
66+
crate::fill(&mut buf).unwrap();
67+
assert_eq!(
68+
[
69+
0x1b, 0x8c, 0x20, 0xcd, 0xe2, 0xdb, 0xb4, 0x3c, 0xd3, 0xc7, 0x9, 0xb2, 0x90,
70+
0xac, 0x50, 0xdc, 0xd2, 0xbe, 0x2a, 0x87, 0xa3, 0xa2, 0x45, 0x44, 0xb5, 0xa5,
71+
0x10, 0x9b, 0xc7, 0x6e, 0xa7, 0xfb,
72+
],
73+
buf
74+
);
75+
});
76+
thread::spawn(|| {
77+
let mut buf = [0u8; 32];
78+
crate::fill(&mut buf).unwrap();
79+
assert_eq!(
80+
[
81+
0x1b, 0x8c, 0x20, 0xcd, 0xe2, 0xdb, 0xb4, 0x3c, 0xd3, 0xc7, 0x9, 0xb2, 0x90,
82+
0xac, 0x50, 0xdc, 0xd2, 0xbe, 0x2a, 0x87, 0xa3, 0xa2, 0x45, 0x44, 0xb5, 0xa5,
83+
0x10, 0x9b, 0xc7, 0x6e, 0xa7, 0xfb,
84+
],
85+
buf
86+
);
87+
});
88+
}
5189
}

0 commit comments

Comments
 (0)