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"
|
paste = "0.1.6"
|
||||||
pyo3cls = { path = "pyo3cls", version = "=0.9.0-alpha.1" }
|
pyo3cls = { path = "pyo3cls", version = "=0.9.0-alpha.1" }
|
||||||
unindent = "0.1.4"
|
unindent = "0.1.4"
|
||||||
|
once_cell = "1.3.1"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
assert_approx_eq = "1.1.0"
|
assert_approx_eq = "1.1.0"
|
||||||
|
|
|
@ -43,9 +43,10 @@ impl pyo3::PyTypeInfo for MyClass {
|
||||||
const FLAGS: usize = 0;
|
const FLAGS: usize = 0;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn type_object() -> &'static mut pyo3::ffi::PyTypeObject {
|
fn type_object() -> *mut pyo3::ffi::PyTypeObject {
|
||||||
static mut TYPE_OBJECT: pyo3::ffi::PyTypeObject = pyo3::ffi::PyTypeObject_INIT;
|
static TYPE_OBJECT: pyo3::derive_utils::LazyTypeObject =
|
||||||
&mut TYPE_OBJECT
|
pyo3::derive_utils::LazyTypeObject::new();
|
||||||
|
TYPE_OBJECT.get()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -384,9 +384,10 @@ fn impl_class(
|
||||||
const FLAGS: usize = #(#flags)|* | #extended;
|
const FLAGS: usize = #(#flags)|* | #extended;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn type_object() -> &'static mut pyo3::ffi::PyTypeObject {
|
fn type_object() -> *mut pyo3::ffi::PyTypeObject {
|
||||||
static mut TYPE_OBJECT: pyo3::ffi::PyTypeObject = pyo3::ffi::PyTypeObject_INIT;
|
static TYPE_OBJECT: pyo3::derive_utils::LazyTypeObject =
|
||||||
&mut TYPE_OBJECT
|
pyo3::derive_utils::LazyTypeObject::new();
|
||||||
|
TYPE_OBJECT.get()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,8 @@ use crate::pyclass::PyClass;
|
||||||
use crate::pyclass_init::PyClassInitializer;
|
use crate::pyclass_init::PyClassInitializer;
|
||||||
use crate::types::{PyAny, PyDict, PyModule, PyTuple};
|
use crate::types::{PyAny, PyDict, PyModule, PyTuple};
|
||||||
use crate::{ffi, GILPool, IntoPy, PyObject, Python};
|
use crate::{ffi, GILPool, IntoPy, PyObject, Python};
|
||||||
|
use once_cell::sync::OnceCell;
|
||||||
|
use std::cell::UnsafeCell;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
|
||||||
/// Description of a python parameter; used for `parse_args()`.
|
/// 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
|
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) {
|
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),
|
Some(free) => free(obj as *mut c_void),
|
||||||
None => tp_free_fallback(obj),
|
None => tp_free_fallback(obj),
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,7 @@ pub trait PyClassAlloc: PyTypeInfo + Sized {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
match Self::type_object().tp_free {
|
match (*Self::type_object()).tp_free {
|
||||||
Some(free) => free(obj as *mut c_void),
|
Some(free) => free(obj as *mut c_void),
|
||||||
None => tp_free_fallback(obj),
|
None => tp_free_fallback(obj),
|
||||||
}
|
}
|
||||||
|
@ -88,9 +88,10 @@ where
|
||||||
{
|
{
|
||||||
fn init_type() -> NonNull<ffi::PyTypeObject> {
|
fn init_type() -> NonNull<ffi::PyTypeObject> {
|
||||||
<T::BaseType as PyTypeObject>::init_type();
|
<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
|
// automatically initialize the class on-demand
|
||||||
let gil = Python::acquire_gil();
|
let gil = Python::acquire_gil();
|
||||||
let py = gil.python();
|
let py = gil.python();
|
||||||
|
@ -282,9 +283,8 @@ pub fn initialize_type<T>(py: Python, module_name: Option<&str>) -> PyResult<*mu
|
||||||
where
|
where
|
||||||
T: PyClass,
|
T: PyClass,
|
||||||
{
|
{
|
||||||
let type_object: &mut ffi::PyTypeObject = unsafe { T::type_object() };
|
let type_object: &mut ffi::PyTypeObject = unsafe { &mut *T::type_object() };
|
||||||
let base_type_object: &mut ffi::PyTypeObject =
|
let base_type_object = <T::BaseType as PyTypeInfo>::type_object();
|
||||||
unsafe { <T::BaseType as PyTypeInfo>::type_object() };
|
|
||||||
|
|
||||||
// PyPy will segfault if passed only a nul terminator as `tp_doc`.
|
// PyPy will segfault if passed only a nul terminator as `tp_doc`.
|
||||||
// ptr::null() is OK though.
|
// ptr::null() is OK though.
|
||||||
|
|
|
@ -87,7 +87,7 @@ pub trait PyTypeInfo: Sized {
|
||||||
|
|
||||||
/// PyTypeObject instance for this type, which might still need to
|
/// PyTypeObject instance for this type, which might still need to
|
||||||
/// be initialized
|
/// 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
|
/// Check if `*mut ffi::PyObject` is instance of this type
|
||||||
fn is_instance(object: &PyAny) -> bool {
|
fn is_instance(object: &PyAny) -> bool {
|
||||||
|
|
|
@ -111,8 +111,8 @@ macro_rules! pyobject_native_type_convert(
|
||||||
const MODULE: Option<&'static str> = $module;
|
const MODULE: Option<&'static str> = $module;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn type_object() -> &'static mut $crate::ffi::PyTypeObject {
|
fn type_object() -> *mut $crate::ffi::PyTypeObject {
|
||||||
&mut $typeobject
|
unsafe { &mut $typeobject as *mut _ }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused_unsafe)]
|
#[allow(unused_unsafe)]
|
||||||
|
@ -127,7 +127,7 @@ macro_rules! pyobject_native_type_convert(
|
||||||
fn init_type() -> std::ptr::NonNull<$crate::ffi::PyTypeObject> {
|
fn init_type() -> std::ptr::NonNull<$crate::ffi::PyTypeObject> {
|
||||||
unsafe {
|
unsafe {
|
||||||
std::ptr::NonNull::new_unchecked(
|
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 New Issue