Skip to content

Commit 7967d30

Browse files
authored
Merge pull request #1939 from RustPython/coolreader18/random-std-rng
Use StdRng instead of ThreadRng in _random
2 parents 6ed172d + 63873e3 commit 7967d30

File tree

1 file changed

+26
-63
lines changed

1 file changed

+26
-63
lines changed

vm/src/stdlib/random.rs

+26-63
Original file line numberDiff line numberDiff line change
@@ -9,21 +9,21 @@ mod _random {
99
use crate::obj::objtype::PyClassRef;
1010
use crate::pyobject::{PyClassImpl, PyRef, PyResult, PyValue};
1111
use crate::VirtualMachine;
12-
use generational_arena::{self, Arena};
1312
use num_bigint::{BigInt, Sign};
1413
use num_traits::Signed;
15-
use rand::RngCore;
16-
use std::cell::RefCell;
14+
use rand::{rngs::StdRng, RngCore, SeedableRng};
15+
16+
use std::sync::Mutex;
1717

1818
#[derive(Debug)]
1919
enum PyRng {
20-
Std(rand::rngs::ThreadRng),
20+
Std(Box<StdRng>),
2121
MT(Box<mt19937::MT19937>),
2222
}
2323

2424
impl Default for PyRng {
2525
fn default() -> Self {
26-
PyRng::Std(rand::thread_rng())
26+
PyRng::Std(Box::new(StdRng::from_entropy()))
2727
}
2828
}
2929

@@ -54,47 +54,10 @@ mod _random {
5454
}
5555
}
5656

57-
thread_local!(static RNG_HANDLES: RefCell<Arena<PyRng>> = RefCell::new(Arena::new()));
58-
59-
#[derive(Debug)]
60-
struct RngHandle(generational_arena::Index);
61-
impl RngHandle {
62-
fn new(rng: PyRng) -> Self {
63-
let idx = RNG_HANDLES.with(|arena| arena.borrow_mut().insert(rng));
64-
RngHandle(idx)
65-
}
66-
fn exec<F, R>(&self, func: F) -> R
67-
where
68-
F: Fn(&mut PyRng) -> R,
69-
{
70-
RNG_HANDLES.with(|arena| {
71-
func(
72-
arena
73-
.borrow_mut()
74-
.get_mut(self.0)
75-
.expect("index was removed"),
76-
)
77-
})
78-
}
79-
fn replace(&self, rng: PyRng) {
80-
RNG_HANDLES.with(|arena| {
81-
*arena
82-
.borrow_mut()
83-
.get_mut(self.0)
84-
.expect("index was removed") = rng
85-
})
86-
}
87-
}
88-
impl Drop for RngHandle {
89-
fn drop(&mut self) {
90-
RNG_HANDLES.with(|arena| arena.borrow_mut().remove(self.0));
91-
}
92-
}
93-
9457
#[pyclass(name = "Random")]
9558
#[derive(Debug)]
9659
struct PyRandom {
97-
rng: RngHandle,
60+
rng: Mutex<PyRng>,
9861
}
9962

10063
impl PyValue for PyRandom {
@@ -108,14 +71,15 @@ mod _random {
10871
#[pyslot(new)]
10972
fn new(cls: PyClassRef, vm: &VirtualMachine) -> PyResult<PyRef<Self>> {
11073
PyRandom {
111-
rng: RngHandle::new(PyRng::default()),
74+
rng: Mutex::default(),
11275
}
11376
.into_ref_with_type(vm, cls)
11477
}
11578

11679
#[pymethod]
11780
fn random(&self) -> f64 {
118-
self.rng.exec(mt19937::gen_res53)
81+
let mut rng = self.rng.lock().unwrap();
82+
mt19937::gen_res53(&mut *rng)
11983
}
12084

12185
#[pymethod]
@@ -131,32 +95,31 @@ mod _random {
13195
}
13296
};
13397

134-
self.rng.replace(new_rng);
98+
*self.rng.lock().unwrap() = new_rng;
13599
}
136100

137101
#[pymethod]
138102
fn getrandbits(&self, k: usize) -> BigInt {
139-
self.rng.exec(|rng| {
140-
let mut k = k;
141-
let mut gen_u32 = |k| rng.next_u32() >> (32 - k) as u32;
103+
let mut rng = self.rng.lock().unwrap();
104+
let mut k = k;
105+
let mut gen_u32 = |k| rng.next_u32() >> (32 - k) as u32;
142106

143-
if k <= 32 {
144-
return gen_u32(k).into();
145-
}
107+
if k <= 32 {
108+
return gen_u32(k).into();
109+
}
146110

147-
let words = (k - 1) / 8 + 1;
148-
let mut wordarray = vec![0u32; words];
111+
let words = (k - 1) / 8 + 1;
112+
let mut wordarray = vec![0u32; words];
149113

150-
let it = wordarray.iter_mut();
151-
#[cfg(target_endian = "big")]
152-
let it = it.rev();
153-
for word in it {
154-
*word = gen_u32(k);
155-
k -= 32;
156-
}
114+
let it = wordarray.iter_mut();
115+
#[cfg(target_endian = "big")]
116+
let it = it.rev();
117+
for word in it {
118+
*word = gen_u32(k);
119+
k -= 32;
120+
}
157121

158-
BigInt::from_slice(Sign::NoSign, &wordarray)
159-
})
122+
BigInt::from_slice(Sign::NoSign, &wordarray)
160123
}
161124
}
162125
}

0 commit comments

Comments
 (0)