Remove static mut from PyTypeInfo implementation

This commit is contained in:
David Hewitt 2020-01-30 00:11:54 +00:00
parent 99a7856dad
commit 5cbdef6471
8 changed files with 47 additions and 17 deletions

View file

@ -29,6 +29,7 @@ parking_lot = { version = "0.10", features = ["nightly"] }
paste = "0.1.6"
pyo3cls = { path = "pyo3cls", version = "=0.9.0-alpha.1" }
unindent = "0.1.4"
once_cell = "1.3.1"
[dev-dependencies]
assert_approx_eq = "1.1.0"

View file

@ -43,9 +43,10 @@ impl pyo3::PyTypeInfo for MyClass {
const FLAGS: usize = 0;
#[inline]
unsafe fn type_object() -> &'static mut pyo3::ffi::PyTypeObject {
static mut TYPE_OBJECT: pyo3::ffi::PyTypeObject = pyo3::ffi::PyTypeObject_INIT;
&mut TYPE_OBJECT
fn type_object() -> *mut pyo3::ffi::PyTypeObject {
static TYPE_OBJECT: pyo3::derive_utils::LazyTypeObject =
pyo3::derive_utils::LazyTypeObject::new();
TYPE_OBJECT.get()
}
}

View file

@ -384,9 +384,10 @@ fn impl_class(
const FLAGS: usize = #(#flags)|* | #extended;
#[inline]
unsafe fn type_object() -> &'static mut pyo3::ffi::PyTypeObject {
static mut TYPE_OBJECT: pyo3::ffi::PyTypeObject = pyo3::ffi::PyTypeObject_INIT;
&mut TYPE_OBJECT
fn type_object() -> *mut pyo3::ffi::PyTypeObject {
static TYPE_OBJECT: pyo3::derive_utils::LazyTypeObject =
pyo3::derive_utils::LazyTypeObject::new();
TYPE_OBJECT.get()
}
}

View file

@ -12,6 +12,8 @@ use crate::pyclass::PyClass;
use crate::pyclass_init::PyClassInitializer;
use crate::types::{PyAny, PyDict, PyModule, PyTuple};
use crate::{ffi, GILPool, IntoPy, PyObject, Python};
use once_cell::sync::OnceCell;
use std::cell::UnsafeCell;
use std::ptr;
/// Description of a python parameter; used for `parse_args()`.
@ -199,3 +201,28 @@ impl<T: PyClass, I: Into<PyClassInitializer<T>>> IntoPyNewResult<T, I> for PyRes
self
}
}
/// Type used to store type objects
pub struct LazyTypeObject {
cell: OnceCell<UnsafeCell<ffi::PyTypeObject>>,
}
impl LazyTypeObject {
pub const fn new() -> Self {
Self {
cell: OnceCell::new(),
}
}
pub fn get(&self) -> *mut ffi::PyTypeObject {
self.cell
.get_or_init(|| UnsafeCell::new(ffi::PyTypeObject_INIT))
.get()
}
}
// This is necessary for making static `LazyTypeObject`s
//
// Type objects are shared between threads by the Python interpreter anyway, so it is no worse
// to allow sharing on the Rust side too.
unsafe impl Sync for LazyTypeObject {}

View file

@ -90,7 +90,7 @@ where
}
if let Some(obj) = <Self as PyClassWithFreeList>::get_free_list().insert(obj) {
match Self::type_object().tp_free {
match (*Self::type_object()).tp_free {
Some(free) => free(obj as *mut c_void),
None => tp_free_fallback(obj),
}

View file

@ -47,7 +47,7 @@ pub trait PyClassAlloc: PyTypeInfo + Sized {
return;
}
match Self::type_object().tp_free {
match (*Self::type_object()).tp_free {
Some(free) => free(obj as *mut c_void),
None => tp_free_fallback(obj),
}
@ -88,9 +88,10 @@ where
{
fn init_type() -> NonNull<ffi::PyTypeObject> {
<T::BaseType as PyTypeObject>::init_type();
let type_object = unsafe { <Self as PyTypeInfo>::type_object() };
let type_object = <Self as PyTypeInfo>::type_object();
let type_flags = unsafe { (*type_object).tp_flags };
if (type_object.tp_flags & ffi::Py_TPFLAGS_READY) == 0 {
if (type_flags & ffi::Py_TPFLAGS_READY) == 0 {
// automatically initialize the class on-demand
let gil = Python::acquire_gil();
let py = gil.python();
@ -282,9 +283,8 @@ pub fn initialize_type<T>(py: Python, module_name: Option<&str>) -> PyResult<*mu
where
T: PyClass,
{
let type_object: &mut ffi::PyTypeObject = unsafe { T::type_object() };
let base_type_object: &mut ffi::PyTypeObject =
unsafe { <T::BaseType as PyTypeInfo>::type_object() };
let type_object: &mut ffi::PyTypeObject = unsafe { &mut *T::type_object() };
let base_type_object = <T::BaseType as PyTypeInfo>::type_object();
// PyPy will segfault if passed only a nul terminator as `tp_doc`.
// ptr::null() is OK though.

View file

@ -87,7 +87,7 @@ pub trait PyTypeInfo: Sized {
/// PyTypeObject instance for this type, which might still need to
/// be initialized
unsafe fn type_object() -> &'static mut ffi::PyTypeObject;
fn type_object() -> *mut ffi::PyTypeObject;
/// Check if `*mut ffi::PyObject` is instance of this type
fn is_instance(object: &PyAny) -> bool {

View file

@ -111,8 +111,8 @@ macro_rules! pyobject_native_type_convert(
const MODULE: Option<&'static str> = $module;
#[inline]
unsafe fn type_object() -> &'static mut $crate::ffi::PyTypeObject {
&mut $typeobject
fn type_object() -> *mut $crate::ffi::PyTypeObject {
unsafe { &mut $typeobject as *mut _ }
}
#[allow(unused_unsafe)]
@ -127,7 +127,7 @@ macro_rules! pyobject_native_type_convert(
fn init_type() -> std::ptr::NonNull<$crate::ffi::PyTypeObject> {
unsafe {
std::ptr::NonNull::new_unchecked(
<Self as $crate::type_object::PyTypeInfo>::type_object() as *mut _
<Self as $crate::type_object::PyTypeInfo>::type_object()
)
}
}