Remove register_gil
This commit is contained in:
parent
7849b74dbf
commit
581e6e0924
|
@ -12,10 +12,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- Update `parking_lot` dependency to `0.11`. [#1010](https://github.com/PyO3/pyo3/pull/1010)
|
- Update `parking_lot` dependency to `0.11`. [#1010](https://github.com/PyO3/pyo3/pull/1010)
|
||||||
- `PyString::to_string` is now renamed to `to_str` and returns `&str` instead of `Cow<str>`. [#1023](https://github.com/PyO3/pyo3/pull/1023)
|
- `PyString::to_string` is now renamed `to_str` and returns `&str` instead of `Cow<str>`. [#1023](https://github.com/PyO3/pyo3/pull/1023)
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
- Remove `PyString::as_bytes` is removed. [#1023](https://github.com/PyO3/pyo3/pull/1023)
|
- Remove `PyString::as_bytes`. [#1023](https://github.com/PyO3/pyo3/pull/1023)
|
||||||
|
- Remove `Python::register_gil`. [#1023](https://github.com/PyO3/pyo3/pull/1023)
|
||||||
|
|
||||||
## [0.11.0] - 2020-06-28
|
## [0.11.0] - 2020-06-28
|
||||||
### Added
|
### Added
|
||||||
|
|
104
src/gil.rs
104
src/gil.rs
|
@ -5,30 +5,10 @@
|
||||||
use crate::{ffi, internal_tricks::Unsendable, Python};
|
use crate::{ffi, internal_tricks::Unsendable, Python};
|
||||||
use parking_lot::{const_mutex, Mutex};
|
use parking_lot::{const_mutex, Mutex};
|
||||||
use std::cell::{Cell, RefCell};
|
use std::cell::{Cell, RefCell};
|
||||||
use std::{any, mem::ManuallyDrop, ptr::NonNull, sync};
|
use std::{mem::ManuallyDrop, ptr::NonNull, sync};
|
||||||
|
|
||||||
static START: sync::Once = sync::Once::new();
|
static START: sync::Once = sync::Once::new();
|
||||||
|
|
||||||
/// Holds temporally owned objects.
|
|
||||||
struct ObjectHolder {
|
|
||||||
/// Objects owned by the current thread
|
|
||||||
obj: Vec<NonNull<ffi::PyObject>>,
|
|
||||||
/// Non-python objects(e.g., String) owned by the current thread
|
|
||||||
any: Vec<Box<dyn any::Any>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ObjectHolder {
|
|
||||||
fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
obj: Vec::with_capacity(256),
|
|
||||||
any: Vec::with_capacity(4),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn len(&self) -> (usize, usize) {
|
|
||||||
(self.obj.len(), self.any.len())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
thread_local! {
|
thread_local! {
|
||||||
/// This is a internal counter in pyo3 monitoring whether this thread has the GIL.
|
/// This is a internal counter in pyo3 monitoring whether this thread has the GIL.
|
||||||
///
|
///
|
||||||
|
@ -41,7 +21,7 @@ thread_local! {
|
||||||
pub(crate) static GIL_COUNT: Cell<u32> = Cell::new(0);
|
pub(crate) static GIL_COUNT: Cell<u32> = Cell::new(0);
|
||||||
|
|
||||||
/// Temporally hold objects that will be released when the GILPool drops.
|
/// Temporally hold objects that will be released when the GILPool drops.
|
||||||
static OWNED_OBJECTS: RefCell<ObjectHolder> = RefCell::new(ObjectHolder::new());
|
static OWNED_OBJECTS: RefCell<Vec<NonNull<ffi::PyObject>>> = RefCell::new(Vec::with_capacity(256));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check whether the GIL is acquired.
|
/// Check whether the GIL is acquired.
|
||||||
|
@ -51,7 +31,7 @@ thread_local! {
|
||||||
/// 2) PyGILState_Check always returns 1 if the sub-interpreter APIs have ever been called,
|
/// 2) PyGILState_Check always returns 1 if the sub-interpreter APIs have ever been called,
|
||||||
/// which could lead to incorrect conclusions that the GIL is held.
|
/// which could lead to incorrect conclusions that the GIL is held.
|
||||||
fn gil_is_acquired() -> bool {
|
fn gil_is_acquired() -> bool {
|
||||||
GIL_COUNT.with(|c| c.get() > 0)
|
GIL_COUNT.try_with(|c| c.get() > 0).unwrap_or(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Prepares the use of Python in a free-threaded context.
|
/// Prepares the use of Python in a free-threaded context.
|
||||||
|
@ -159,21 +139,19 @@ impl GILGuard {
|
||||||
pub fn acquire() -> GILGuard {
|
pub fn acquire() -> GILGuard {
|
||||||
prepare_freethreaded_python();
|
prepare_freethreaded_python();
|
||||||
|
|
||||||
unsafe {
|
let gstate = unsafe { ffi::PyGILState_Ensure() }; // acquire GIL
|
||||||
let gstate = ffi::PyGILState_Ensure(); // acquire GIL
|
|
||||||
|
|
||||||
// If there's already a GILPool, we should not create another or this could lead to
|
// If there's already a GILPool, we should not create another or this could lead to
|
||||||
// incorrect dangling references in safe code (see #864).
|
// incorrect dangling references in safe code (see #864).
|
||||||
let pool = if !gil_is_acquired() {
|
let pool = if !gil_is_acquired() {
|
||||||
Some(GILPool::new())
|
Some(unsafe { GILPool::new() })
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
GILGuard {
|
GILGuard {
|
||||||
gstate,
|
gstate,
|
||||||
pool: ManuallyDrop::new(pool),
|
pool: ManuallyDrop::new(pool),
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -252,7 +230,7 @@ static POOL: ReferencePool = ReferencePool::new();
|
||||||
pub struct GILPool {
|
pub struct GILPool {
|
||||||
/// Initial length of owned objects and anys.
|
/// Initial length of owned objects and anys.
|
||||||
/// `Option` is used since TSL can be broken when `new` is called from `atexit`.
|
/// `Option` is used since TSL can be broken when `new` is called from `atexit`.
|
||||||
start: Option<(usize, usize)>,
|
start: Option<usize>,
|
||||||
no_send: Unsendable,
|
no_send: Unsendable,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -283,20 +261,19 @@ impl GILPool {
|
||||||
|
|
||||||
impl Drop for GILPool {
|
impl Drop for GILPool {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
unsafe {
|
if let Some(obj_len_start) = self.start {
|
||||||
if let Some((obj_len_start, any_len_start)) = self.start {
|
let dropping_obj = OWNED_OBJECTS.with(|holder| {
|
||||||
let dropping_obj = OWNED_OBJECTS.with(|holder| {
|
// `holder` must be dropped before calling Py_DECREF, or Py_DECREF may call
|
||||||
// `holder` must be dropped before calling Py_DECREF, or Py_DECREF may call
|
// `GILPool::drop` recursively, resulting in invalid borrowing.
|
||||||
// `GILPool::drop` recursively, resulting in invalid borrowing.
|
let mut holder = holder.borrow_mut();
|
||||||
let mut holder = holder.borrow_mut();
|
if obj_len_start < holder.len() {
|
||||||
holder.any.truncate(any_len_start);
|
holder.split_off(obj_len_start)
|
||||||
if obj_len_start < holder.obj.len() {
|
} else {
|
||||||
holder.obj.split_off(obj_len_start)
|
Vec::new()
|
||||||
} else {
|
}
|
||||||
Vec::new()
|
});
|
||||||
}
|
for obj in dropping_obj {
|
||||||
});
|
unsafe {
|
||||||
for obj in dropping_obj {
|
|
||||||
ffi::Py_DECREF(obj.as_ptr());
|
ffi::Py_DECREF(obj.as_ptr());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -343,36 +320,21 @@ pub unsafe fn register_decref(obj: NonNull<ffi::PyObject>) {
|
||||||
/// The object must be an owned Python reference.
|
/// The object must be an owned Python reference.
|
||||||
pub unsafe fn register_owned(_py: Python, obj: NonNull<ffi::PyObject>) {
|
pub unsafe fn register_owned(_py: Python, obj: NonNull<ffi::PyObject>) {
|
||||||
debug_assert!(gil_is_acquired());
|
debug_assert!(gil_is_acquired());
|
||||||
// Ignoring the error means we do nothing if the TLS is broken.
|
// Ignores the error in case this function called from `atexit`.
|
||||||
let _ = OWNED_OBJECTS.try_with(|holder| holder.borrow_mut().obj.push(obj));
|
let _ = OWNED_OBJECTS.try_with(|holder| holder.borrow_mut().push(obj));
|
||||||
}
|
|
||||||
|
|
||||||
/// Register any value inside the GILPool.
|
|
||||||
///
|
|
||||||
/// # Safety
|
|
||||||
/// It is the caller's responsibility to ensure that the inferred lifetime 'p is not inferred by
|
|
||||||
/// the Rust compiler to outlast the current GILPool.
|
|
||||||
pub unsafe fn register_any<'p, T: 'static>(obj: T) -> &'p T {
|
|
||||||
debug_assert!(gil_is_acquired());
|
|
||||||
OWNED_OBJECTS.with(|holder| {
|
|
||||||
let boxed = Box::new(obj);
|
|
||||||
let value_ref: *const T = &*boxed;
|
|
||||||
holder.borrow_mut().any.push(boxed);
|
|
||||||
&*value_ref
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Increment pyo3's internal GIL count - to be called whenever GILPool or GILGuard is created.
|
/// Increment pyo3's internal GIL count - to be called whenever GILPool or GILGuard is created.
|
||||||
// Ignores the error in case this function called from `atexit`.
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn increment_gil_count() {
|
fn increment_gil_count() {
|
||||||
|
// Ignores the error in case this function called from `atexit`.
|
||||||
let _ = GIL_COUNT.with(|c| c.set(c.get() + 1));
|
let _ = GIL_COUNT.with(|c| c.set(c.get() + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Decrement pyo3's internal GIL count - to be called whenever GILPool or GILGuard is dropped.
|
/// Decrement pyo3's internal GIL count - to be called whenever GILPool or GILGuard is dropped.
|
||||||
// Ignores the error in case this function called from `atexit`.
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn decrement_gil_count() {
|
fn decrement_gil_count() {
|
||||||
|
// Ignores the error in case this function called from `atexit`.
|
||||||
let _ = GIL_COUNT.try_with(|c| {
|
let _ = GIL_COUNT.try_with(|c| {
|
||||||
let current = c.get();
|
let current = c.get();
|
||||||
debug_assert!(
|
debug_assert!(
|
||||||
|
@ -431,7 +393,7 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn owned_object_count() -> usize {
|
fn owned_object_count() -> usize {
|
||||||
OWNED_OBJECTS.with(|holder| holder.borrow().obj.len())
|
OWNED_OBJECTS.with(|holder| holder.borrow().len())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -435,13 +435,6 @@ impl<'p> Python<'p> {
|
||||||
FromPyPointer::from_borrowed_ptr_or_opt(self, ptr)
|
FromPyPointer::from_borrowed_ptr_or_opt(self, ptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc(hidden)]
|
|
||||||
/// Passes value ownership to `Python` object and get reference back.
|
|
||||||
/// Value get cleaned up on the GIL release.
|
|
||||||
pub fn register_any<T: 'static>(self, ob: T) -> &'p T {
|
|
||||||
unsafe { gil::register_any(ob) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Releases a PyObject reference.
|
/// Releases a PyObject reference.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn release<T>(self, ob: T)
|
pub fn release<T>(self, ob: T)
|
||||||
|
|
Loading…
Reference in a new issue