Skip to content

Commit

Permalink
Add PyCriticalSection lock to Dict iterator
Browse files Browse the repository at this point in the history
  • Loading branch information
bschoenmaeckers committed Aug 14, 2024
1 parent f869d16 commit d90dc42
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 1 deletion.
10 changes: 10 additions & 0 deletions pyo3-ffi/src/cpython/criticalsection.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
use crate::PyObject;
use std::os::raw::c_void;

#[repr(C)]
pub struct PyCriticalSection(*mut c_void, *mut c_void);

extern "C" {
pub fn PyCriticalSection_Begin(m: *mut PyCriticalSection, op: *mut PyObject);
pub fn PyCriticalSection_End(m: *mut PyCriticalSection);
}
4 changes: 4 additions & 0 deletions pyo3-ffi/src/cpython/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ pub(crate) mod pymem;
pub(crate) mod pystate;
pub(crate) mod pythonrun;
// skipped sysmodule.h
#[cfg(Py_GIL_DISABLED)]
pub(crate) mod criticalsection;
pub(crate) mod floatobject;
pub(crate) mod pyframe;
pub(crate) mod tupleobject;
Expand All @@ -43,6 +45,8 @@ pub use self::bytesobject::*;
pub use self::ceval::*;
pub use self::code::*;
pub use self::compile::*;
#[cfg(Py_GIL_DISABLED)]
pub use self::criticalsection::*;
pub use self::descrobject::*;
#[cfg(not(PyPy))]
pub use self::dictobject::*;
Expand Down
48 changes: 47 additions & 1 deletion src/types/dict.rs
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,8 @@ pub struct BoundDictIterator<'py> {
ppos: ffi::Py_ssize_t,
di_used: ffi::Py_ssize_t,
len: ffi::Py_ssize_t,
#[cfg(Py_GIL_DISABLED)]
cs: ffi::PyCriticalSection,
}

impl<'py> Iterator for BoundDictIterator<'py> {
Expand Down Expand Up @@ -441,14 +443,33 @@ impl<'py> ExactSizeIterator for BoundDictIterator<'py> {
}
}

#[cfg(Py_GIL_DISABLED)]
impl Drop for BoundDictIterator<'_> {
fn drop(&mut self) {
unsafe {
ffi::PyCriticalSection_End(& mut self.cs);
}
}
}

impl<'py> BoundDictIterator<'py> {
fn new(dict: Bound<'py, PyDict>) -> Self {
let len = dict_len(&dict);

#[cfg(Py_GIL_DISABLED)]
let cs = unsafe {
let mut cs = std::mem::MaybeUninit::zeroed();
ffi::PyCriticalSection_Begin(cs.as_mut_ptr(), dict.as_ptr());
cs.assume_init()
};

BoundDictIterator {
dict,
ppos: 0,
di_used: len,
len,
#[cfg(Py_GIL_DISABLED)]
cs,
}
}
}
Expand Down Expand Up @@ -481,6 +502,8 @@ mod borrowed_iter {
dict: Borrowed<'a, 'py, PyDict>,
ppos: ffi::Py_ssize_t,
len: ffi::Py_ssize_t,
#[cfg(Py_GIL_DISABLED)]
cs: ffi::PyCriticalSection,
}

impl<'a, 'py> Iterator for BorrowedDictIter<'a, 'py> {
Expand Down Expand Up @@ -519,10 +542,33 @@ mod borrowed_iter {
}
}

#[cfg(Py_GIL_DISABLED)]
impl Drop for BorrowedDictIter<'_, '_> {
fn drop(&mut self) {
unsafe {
ffi::PyCriticalSection_End(& mut self.cs);
}
}
}

impl<'a, 'py> BorrowedDictIter<'a, 'py> {
pub(super) fn new(dict: Borrowed<'a, 'py, PyDict>) -> Self {
let len = dict_len(&dict);
BorrowedDictIter { dict, ppos: 0, len }

#[cfg(Py_GIL_DISABLED)]
let cs = unsafe {
let mut cs = std::mem::MaybeUninit::zeroed();
ffi::PyCriticalSection_Begin(cs.as_mut_ptr(), dict.as_ptr());
cs.assume_init()
};

BorrowedDictIter {
dict,
ppos: 0,
len,
#[cfg(Py_GIL_DISABLED)]
cs,
}
}
}
}
Expand Down

0 comments on commit d90dc42

Please sign in to comment.