Remove register_gil

This commit is contained in:
kngwyu 2020-07-06 21:49:09 +09:00
parent 7849b74dbf
commit 581e6e0924
3 changed files with 36 additions and 80 deletions

View file

@ -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

View file

@ -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]

View file

@ -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)