Remove static mut from PyTypeInfo implementation
This commit is contained in:
parent
99a7856dad
commit
5cbdef6471
|
@ -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"
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {}
|
||||
|
|
|
@ -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),
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue