Skip to content

Commit 663fa29

Browse files
committed
docs
1 parent 06bb693 commit 663fa29

File tree

1 file changed

+11
-12
lines changed

1 file changed

+11
-12
lines changed

src/random.rs

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -102,19 +102,17 @@ impl<'py> PyBitGeneratorMethods<'py> for Bound<'py, PyBitGenerator> {
102102
fn lock(&self) -> PyResult<PyBitGeneratorGuard> {
103103
let capsule = self.getattr("capsule")?.downcast_into::<PyCapsule>()?;
104104
let lock = self.getattr("lock")?;
105+
// we’re holding the GIL, so there’s no race condition checking the lock and acquiring it later.
105106
if lock.call_method0("locked")?.extract()? {
106107
return Err(PyRuntimeError::new_err("BitGenerator is already locked"));
107108
}
108109
lock.call_method0("acquire")?;
109110

110111
assert_eq!(capsule.name()?, Some(c"BitGenerator"));
111112
let ptr = capsule.pointer() as *mut npy_bitgen;
112-
let non_null = match NonNull::new(ptr) {
113-
Some(non_null) => non_null,
114-
None => {
115-
lock.call_method0("release")?;
116-
return Err(PyRuntimeError::new_err("Invalid BitGenerator capsule"));
117-
}
113+
let Some(non_null) = NonNull::new(ptr) else {
114+
lock.call_method0("release")?;
115+
return Err(PyRuntimeError::new_err("Invalid BitGenerator capsule"));
118116
};
119117
Ok(PyBitGeneratorGuard {
120118
raw_bitgen: non_null,
@@ -140,8 +138,8 @@ pub struct PyBitGeneratorGuard {
140138
lock: Py<PyAny>,
141139
}
142140

143-
// SAFETY: we can’t have public APIs that access the Python objects,
144-
// only the `raw_bitgen` pointer.
141+
// SAFETY: 1. We don’t hold the GIL, so we can’t access the Python objects.
142+
// 2. We only access `raw_bitgen` from `&mut self`, which protects it from parallel access.
145143
unsafe impl Send for PyBitGeneratorGuard {}
146144

147145
impl Drop for PyBitGeneratorGuard {
@@ -154,11 +152,10 @@ impl Drop for PyBitGeneratorGuard {
154152
}
155153
}
156154

157-
// SAFETY: We hold the `BitGenerator.lock`,
158-
// so nothing apart from us is allowed to change its state.
155+
// SAFETY: 1. We hold the `BitGenerator.lock`, so nothing apart from us is allowed to change its state.
156+
// 2. We hold the `BitGenerator.capsule`, so it can’t be deallocated.
159157
impl<'py> PyBitGeneratorGuard {
160158
/// Release the lock, allowing for checking for errors.
161-
#[allow(dead_code)]
162159
pub fn try_release(self, py: Python<'py>) -> PyResult<()> {
163160
self.lock.bind(py).call_method0("release")?;
164161
Ok(())
@@ -249,7 +246,7 @@ mod tests {
249246
let (_n_threads, chunk_size) = arr.dims().into_pattern();
250247
let slice = arr.as_slice_mut()?;
251248

252-
Python::allow_threads(py, || {
249+
py.allow_threads(|| {
253250
std::thread::scope(|s| {
254251
for chunk in slice.chunks_exact_mut(chunk_size) {
255252
let bitgen = Arc::clone(&bitgen);
@@ -260,6 +257,8 @@ mod tests {
260257
}
261258
})
262259
});
260+
261+
std::mem::drop(bitgen);
263262
Ok(())
264263
})
265264
}

0 commit comments

Comments
 (0)