Change `GILGuard` to be able to represent a GIL that was already held (#4187)
See #4181
This commit is contained in:
parent
7790dab480
commit
8de1787580
39
src/gil.rs
39
src/gil.rs
|
@ -148,20 +148,26 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
/// RAII type that represents the Global Interpreter Lock acquisition.
|
/// RAII type that represents the Global Interpreter Lock acquisition.
|
||||||
pub(crate) struct GILGuard {
|
pub(crate) enum GILGuard {
|
||||||
gstate: ffi::PyGILState_STATE,
|
/// Indicates the GIL was already held with this GILGuard was acquired.
|
||||||
#[allow(deprecated)] // TODO: remove this with the gil-refs feature in 0.22
|
Assumed,
|
||||||
pool: mem::ManuallyDrop<GILPool>,
|
/// Indicates that we actually acquired the GIL when this GILGuard was acquired
|
||||||
|
Ensured {
|
||||||
|
gstate: ffi::PyGILState_STATE,
|
||||||
|
#[allow(deprecated)] // TODO: remove this with the gil-refs feature in 0.22
|
||||||
|
pool: mem::ManuallyDrop<GILPool>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GILGuard {
|
impl GILGuard {
|
||||||
/// PyO3 internal API for acquiring the GIL. The public API is Python::with_gil.
|
/// PyO3 internal API for acquiring the GIL. The public API is Python::with_gil.
|
||||||
///
|
///
|
||||||
/// If the GIL was already acquired via PyO3, this returns `None`. Otherwise,
|
/// If the GIL was already acquired via PyO3, this returns
|
||||||
/// the GIL will be acquired and a new `GILPool` created.
|
/// `GILGuard::Assumed`. Otherwise, the GIL will be acquired and
|
||||||
pub(crate) fn acquire() -> Option<Self> {
|
/// `GILGuard::Ensured` will be returned.
|
||||||
|
pub(crate) fn acquire() -> Self {
|
||||||
if gil_is_acquired() {
|
if gil_is_acquired() {
|
||||||
return None;
|
return GILGuard::Assumed;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Maybe auto-initialize the GIL:
|
// Maybe auto-initialize the GIL:
|
||||||
|
@ -207,27 +213,30 @@ impl GILGuard {
|
||||||
/// This can be called in "unsafe" contexts where the normal interpreter state
|
/// This can be called in "unsafe" contexts where the normal interpreter state
|
||||||
/// checking performed by `GILGuard::acquire` may fail. This includes calling
|
/// checking performed by `GILGuard::acquire` may fail. This includes calling
|
||||||
/// as part of multi-phase interpreter initialization.
|
/// as part of multi-phase interpreter initialization.
|
||||||
pub(crate) fn acquire_unchecked() -> Option<Self> {
|
pub(crate) fn acquire_unchecked() -> Self {
|
||||||
if gil_is_acquired() {
|
if gil_is_acquired() {
|
||||||
return None;
|
return GILGuard::Assumed;
|
||||||
}
|
}
|
||||||
|
|
||||||
let gstate = unsafe { ffi::PyGILState_Ensure() }; // acquire GIL
|
let gstate = unsafe { ffi::PyGILState_Ensure() }; // acquire GIL
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
let pool = unsafe { mem::ManuallyDrop::new(GILPool::new()) };
|
let pool = unsafe { mem::ManuallyDrop::new(GILPool::new()) };
|
||||||
|
|
||||||
Some(GILGuard { gstate, pool })
|
GILGuard::Ensured { gstate, pool }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The Drop implementation for `GILGuard` will release the GIL.
|
/// The Drop implementation for `GILGuard` will release the GIL.
|
||||||
impl Drop for GILGuard {
|
impl Drop for GILGuard {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
unsafe {
|
match self {
|
||||||
// Drop the objects in the pool before attempting to release the thread state
|
GILGuard::Assumed => {}
|
||||||
mem::ManuallyDrop::drop(&mut self.pool);
|
GILGuard::Ensured { gstate, pool } => unsafe {
|
||||||
|
// Drop the objects in the pool before attempting to release the thread state
|
||||||
|
mem::ManuallyDrop::drop(pool);
|
||||||
|
|
||||||
ffi::PyGILState_Release(self.gstate);
|
ffi::PyGILState_Release(*gstate);
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue