Prototype Implementation of RefCell-like PyCell
This commit is contained in:
parent
5d4e7374e9
commit
c43fb9fcdf
|
@ -234,11 +234,7 @@ where
|
|||
|
||||
let slf = py.from_borrowed_ptr::<crate::PyCell<T>>(slf);
|
||||
let arg = py.from_borrowed_ptr::<crate::types::PyAny>(arg);
|
||||
|
||||
let result = match arg.extract() {
|
||||
Ok(arg) => slf.__getattr__(arg).into(),
|
||||
Err(e) => Err(e),
|
||||
};
|
||||
let result = call_ref!(slf, __getattr__, arg);
|
||||
crate::callback::cb_convert(PyObjectCallbackConverter, py, result)
|
||||
}
|
||||
Some(wrap::<T>)
|
||||
|
@ -512,10 +508,7 @@ where
|
|||
let arg = py.from_borrowed_ptr::<PyAny>(arg);
|
||||
|
||||
let res = match extract_op(op) {
|
||||
Ok(op) => match arg.extract() {
|
||||
Ok(arg) => slf.__richcmp__(arg, op).into(),
|
||||
Err(e) => Err(e),
|
||||
},
|
||||
Ok(op) => call_ref!(slf, __richcmp__, arg ; op),
|
||||
Err(e) => Err(e),
|
||||
};
|
||||
match res {
|
||||
|
|
|
@ -95,7 +95,7 @@ where
|
|||
let _pool = crate::GILPool::new(py);
|
||||
let slf = py.from_borrowed_ptr::<crate::PyCell<T>>(slf);
|
||||
|
||||
let result = slf.bf_getbuffer(arg1, arg2).into();
|
||||
let result = slf.borrow().bf_getbuffer(arg1, arg2).into();
|
||||
crate::callback::cb_convert(UnitCallbackConverter, py, result)
|
||||
}
|
||||
Some(wrap::<T>)
|
||||
|
|
|
@ -98,7 +98,7 @@ where
|
|||
arg,
|
||||
_py: py,
|
||||
};
|
||||
match slf.__traverse__(visit) {
|
||||
match slf.borrow().__traverse__(visit) {
|
||||
Ok(()) => 0,
|
||||
Err(PyTraverseError(code)) => code,
|
||||
}
|
||||
|
@ -135,7 +135,7 @@ where
|
|||
let _pool = crate::GILPool::new(py);
|
||||
let slf = py.from_borrowed_ptr::<PyCell<T>>(slf);
|
||||
|
||||
slf.__clear__();
|
||||
slf.borrow_mut().__clear__();
|
||||
0
|
||||
}
|
||||
Some(tp_clear::<T>)
|
||||
|
|
|
@ -12,7 +12,17 @@ macro_rules! py_unary_func {
|
|||
*mut $crate::ffi::PyObject
|
||||
);
|
||||
};
|
||||
($trait:ident, $class:ident :: $f:ident, $res_type:ty, $conv:expr, $ret_type:ty) => {{
|
||||
// Use call_ref! by default
|
||||
($trait:ident, $class:ident :: $f:ident, $res_type:ty, $conv:expr, $ret_type:ty) => {
|
||||
py_unary_func!($trait, $class::$f, $res_type, $conv, $ret_type, call_ref);
|
||||
};
|
||||
($trait:ident,
|
||||
$class:ident :: $f:ident,
|
||||
$res_type:ty,
|
||||
$conv:expr,
|
||||
$ret_type:ty,
|
||||
$call: ident
|
||||
) => {{
|
||||
unsafe extern "C" fn wrap<T>(slf: *mut $crate::ffi::PyObject) -> $ret_type
|
||||
where
|
||||
T: for<'p> $trait<'p>,
|
||||
|
@ -20,7 +30,7 @@ macro_rules! py_unary_func {
|
|||
let py = $crate::Python::assume_gil_acquired();
|
||||
let _pool = $crate::GILPool::new(py);
|
||||
let slf = py.from_borrowed_ptr::<$crate::PyCell<T>>(slf);
|
||||
let res = slf.$f().into();
|
||||
let res = $call!(slf, $f);
|
||||
$crate::callback::cb_convert($conv, py, res.map(|x| x))
|
||||
}
|
||||
Some(wrap::<$class>)
|
||||
|
@ -57,8 +67,7 @@ macro_rules! py_len_func {
|
|||
let py = Python::assume_gil_acquired();
|
||||
let _pool = $crate::GILPool::new(py);
|
||||
let slf = py.from_borrowed_ptr::<$crate::PyCell<T>>(slf);
|
||||
|
||||
let result = slf.$f().into();
|
||||
let result = call_ref!(slf, $f);
|
||||
$crate::callback::cb_convert($conv, py, result)
|
||||
}
|
||||
Some(wrap::<$class>)
|
||||
|
@ -77,8 +86,11 @@ macro_rules! py_binary_func {
|
|||
*mut $crate::ffi::PyObject
|
||||
)
|
||||
};
|
||||
// Use call_ref! by default
|
||||
($trait:ident, $class:ident :: $f:ident, $res_type:ty, $conv:expr, $return:ty) => {{
|
||||
#[allow(unused_mut)]
|
||||
py_binary_func!($trait, $class::$f, $res_type, $conv, $return, call_ref)
|
||||
}};
|
||||
($trait:ident, $class:ident :: $f:ident, $res_type:ty, $conv:expr, $return:ty, $call:ident) => {{
|
||||
unsafe extern "C" fn wrap<T>(slf: *mut ffi::PyObject, arg: *mut ffi::PyObject) -> $return
|
||||
where
|
||||
T: for<'p> $trait<'p>,
|
||||
|
@ -88,11 +100,7 @@ macro_rules! py_binary_func {
|
|||
let _pool = $crate::GILPool::new(py);
|
||||
let slf = py.from_borrowed_ptr::<$crate::PyCell<T>>(slf);
|
||||
let arg = py.from_borrowed_ptr::<$crate::types::PyAny>(arg);
|
||||
|
||||
let result = match arg.extract() {
|
||||
Ok(arg) => slf.$f(arg).into(),
|
||||
Err(e) => Err(e.into()),
|
||||
};
|
||||
let result = $call!(slf, $f, arg);
|
||||
$crate::callback::cb_convert($conv, py, result)
|
||||
}
|
||||
Some(wrap::<$class>)
|
||||
|
@ -103,7 +111,6 @@ macro_rules! py_binary_func {
|
|||
#[doc(hidden)]
|
||||
macro_rules! py_binary_num_func {
|
||||
($trait:ident, $class:ident :: $f:ident, $res_type:ty, $conv:expr) => {{
|
||||
#[allow(unused_mut)]
|
||||
unsafe extern "C" fn wrap<T>(
|
||||
lhs: *mut ffi::PyObject,
|
||||
rhs: *mut ffi::PyObject,
|
||||
|
@ -130,11 +137,12 @@ macro_rules! py_binary_num_func {
|
|||
}};
|
||||
}
|
||||
|
||||
// NOTE(kngwyu):
|
||||
// Now(2020 2/9) This macro is used only for inplace operation so I used call_refmut here.
|
||||
#[macro_export]
|
||||
#[doc(hidden)]
|
||||
macro_rules! py_binary_self_func {
|
||||
($trait:ident, $class:ident :: $f:ident) => {{
|
||||
#[allow(unused_mut)]
|
||||
unsafe extern "C" fn wrap<T>(
|
||||
slf: *mut ffi::PyObject,
|
||||
arg: *mut ffi::PyObject,
|
||||
|
@ -146,13 +154,9 @@ macro_rules! py_binary_self_func {
|
|||
|
||||
let py = $crate::Python::assume_gil_acquired();
|
||||
let _pool = $crate::GILPool::new(py);
|
||||
let slf1 = py.from_borrowed_ptr::<$crate::PyCell<T>>(slf);
|
||||
let slf_ = py.from_borrowed_ptr::<$crate::PyCell<T>>(slf);
|
||||
let arg = py.from_borrowed_ptr::<$crate::types::PyAny>(arg);
|
||||
|
||||
let result = match arg.extract() {
|
||||
Ok(arg) => slf1.$f(arg).into(),
|
||||
Err(e) => Err(e.into()),
|
||||
};
|
||||
let result = call_refmut!(slf_, $f, arg);
|
||||
match result {
|
||||
Ok(_) => {
|
||||
ffi::Py_INCREF(slf);
|
||||
|
@ -171,8 +175,17 @@ macro_rules! py_binary_self_func {
|
|||
#[macro_export]
|
||||
#[doc(hidden)]
|
||||
macro_rules! py_ssizearg_func {
|
||||
($trait:ident, $class:ident :: $f:ident, $res_type:ty, $conv:expr) => {{
|
||||
#[allow(unused_mut)]
|
||||
// Use call_ref! by default
|
||||
($trait:ident, $class:ident :: $f:ident, $res_type:ty, $conv:expr) => {
|
||||
py_ssizearg_func!(
|
||||
$trait,
|
||||
$class::$f,
|
||||
$res_type,
|
||||
$conv,
|
||||
call_ref
|
||||
)
|
||||
};
|
||||
($trait:ident, $class:ident :: $f:ident, $res_type:ty, $conv:expr, $call:ident) => {{
|
||||
unsafe extern "C" fn wrap<T>(
|
||||
slf: *mut ffi::PyObject,
|
||||
arg: $crate::ffi::Py_ssize_t,
|
||||
|
@ -183,7 +196,7 @@ macro_rules! py_ssizearg_func {
|
|||
let py = $crate::Python::assume_gil_acquired();
|
||||
let _pool = $crate::GILPool::new(py);
|
||||
let slf = py.from_borrowed_ptr::<$crate::PyCell<T>>(slf);
|
||||
let result = slf.$f(arg.into()).into();
|
||||
let result = $call!(slf, $f ; arg.into());
|
||||
$crate::callback::cb_convert($conv, py, result)
|
||||
}
|
||||
Some(wrap::<$class>)
|
||||
|
@ -219,13 +232,7 @@ macro_rules! py_ternary_func {
|
|||
let arg1 = py.from_borrowed_ptr::<$crate::types::PyAny>(arg1);
|
||||
let arg2 = py.from_borrowed_ptr::<$crate::types::PyAny>(arg2);
|
||||
|
||||
let result = match arg1.extract() {
|
||||
Ok(arg1) => match arg2.extract() {
|
||||
Ok(arg2) => slf.$f(arg1, arg2).into(),
|
||||
Err(e) => Err(e.into()),
|
||||
},
|
||||
Err(e) => Err(e.into()),
|
||||
};
|
||||
let result = call_ref!(slf, $f, arg1, arg2);
|
||||
$crate::callback::cb_convert($conv, py, result)
|
||||
}
|
||||
|
||||
|
@ -286,18 +293,10 @@ macro_rules! py_ternary_self_func {
|
|||
|
||||
let py = $crate::Python::assume_gil_acquired();
|
||||
let _pool = $crate::GILPool::new(py);
|
||||
let slf1 = py.from_borrowed_ptr::<$crate::PyCell<T>>(slf);
|
||||
let slf_cell = py.from_borrowed_ptr::<$crate::PyCell<T>>(slf);
|
||||
let arg1 = py.from_borrowed_ptr::<$crate::types::PyAny>(arg1);
|
||||
let arg2 = py.from_borrowed_ptr::<$crate::types::PyAny>(arg2);
|
||||
|
||||
let result = match arg1.extract() {
|
||||
Ok(arg1) => match arg2.extract() {
|
||||
Ok(arg2) => slf1.$f(arg1, arg2).into(),
|
||||
Err(e) => Err(e.into()),
|
||||
},
|
||||
Err(e) => Err(e.into()),
|
||||
};
|
||||
|
||||
let result = call_refmut!(slf_cell, $f, arg1, arg2);
|
||||
match result {
|
||||
Ok(_) => slf,
|
||||
Err(e) => {
|
||||
|
@ -337,13 +336,7 @@ macro_rules! py_func_set {
|
|||
} else {
|
||||
let name = py.from_borrowed_ptr::<$crate::types::PyAny>(name);
|
||||
let value = py.from_borrowed_ptr::<$crate::types::PyAny>(value);
|
||||
match name.extract() {
|
||||
Ok(name) => match value.extract() {
|
||||
Ok(value) => slf.$fn_set(name, value).into(),
|
||||
Err(e) => Err(e.into()),
|
||||
},
|
||||
Err(e) => Err(e.into()),
|
||||
}
|
||||
call_refmut!(slf, $fn_set, name, value)
|
||||
};
|
||||
match result {
|
||||
Ok(_) => 0,
|
||||
|
@ -378,10 +371,7 @@ macro_rules! py_func_del {
|
|||
let slf = py.from_borrowed_ptr::<$crate::PyCell<U>>(slf);
|
||||
let name = py.from_borrowed_ptr::<$crate::types::PyAny>(name);
|
||||
|
||||
match name.extract() {
|
||||
Ok(name) => slf.$fn_del(name).into(),
|
||||
Err(e) => Err(e.into()),
|
||||
}
|
||||
call_refmut!(slf, $fn_del, name)
|
||||
} else {
|
||||
Err(PyErr::new::<exceptions::NotImplementedError, _>(
|
||||
"Subscript assignment not supported",
|
||||
|
@ -419,19 +409,10 @@ macro_rules! py_func_set_del {
|
|||
let name = py.from_borrowed_ptr::<$crate::types::PyAny>(name);
|
||||
|
||||
let result = if value.is_null() {
|
||||
match name.extract() {
|
||||
Ok(name) => slf.$fn_del(name).into(),
|
||||
Err(e) => Err(e.into()),
|
||||
}
|
||||
call_refmut!(slf, $fn_del, name)
|
||||
} else {
|
||||
let value = py.from_borrowed_ptr::<$crate::types::PyAny>(value);
|
||||
match name.extract() {
|
||||
Ok(name) => match value.extract() {
|
||||
Ok(value) => slf.$fn_set(name, value).into(),
|
||||
Err(e) => Err(e.into()),
|
||||
},
|
||||
Err(e) => Err(e.into()),
|
||||
}
|
||||
call_refmut!(slf, $fn_set, name, value)
|
||||
};
|
||||
match result {
|
||||
Ok(_) => 0,
|
||||
|
@ -444,3 +425,34 @@ macro_rules! py_func_set_del {
|
|||
Some(wrap::<$generic>)
|
||||
}};
|
||||
}
|
||||
|
||||
// Utitlities for extract arguments + call method for PyCell<T>
|
||||
macro_rules! call_ref {
|
||||
($slf: expr, $fn: ident $(; $args: expr)*) => {
|
||||
match $slf.try_borrow_unguarded() {
|
||||
Ok(slf) => slf.$fn($($args,)*).into(),
|
||||
Err(e) => Err(e.into()),
|
||||
}
|
||||
};
|
||||
($slf: expr, $fn: ident, $raw_arg: expr $(,$raw_args: expr)* $(; $args: expr)*) => {
|
||||
match $raw_arg.extract() {
|
||||
Ok(arg) => call_ref!($slf, $fn $(,$raw_args)* ;arg $(;$args)*),
|
||||
Err(e) => Err(e.into()),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! call_refmut {
|
||||
($slf: expr, $fn: ident $(; $args: expr)*) => {
|
||||
match $slf.try_borrow_mut_unguarded() {
|
||||
Ok(slf) => slf.$fn($($args,)*).into(),
|
||||
Err(e) => Err(e.into()),
|
||||
}
|
||||
};
|
||||
($slf: expr, $fn: ident, $raw_arg: expr $(,$raw_args: expr)* $(; $args: expr)*) => {
|
||||
match $raw_arg.extract() {
|
||||
Ok(arg) => call_refmut!($slf, $fn $(,$raw_args)* ;arg $(;$args)*),
|
||||
Err(e) => Err(e.into()),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -242,7 +242,9 @@ mod anext {
|
|||
PyAsyncAnextProtocol,
|
||||
T::__anext__,
|
||||
Option<T::Success>,
|
||||
IterANextResultConverter
|
||||
IterANextResultConverter,
|
||||
*mut crate::ffi::PyObject,
|
||||
call_refmut
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -273,7 +273,10 @@ mod sq_ass_item_impl {
|
|||
} else {
|
||||
let value = py.from_borrowed_ptr::<PyAny>(value);
|
||||
match value.extract() {
|
||||
Ok(value) => slf.__setitem__(key.into(), value).into(),
|
||||
Ok(value) => match slf.try_borrow_mut_unguarded() {
|
||||
Ok(slf_) => slf_.__setitem__(key.into(), value).into(),
|
||||
Err(e) => e.into(),
|
||||
},
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
};
|
||||
|
@ -321,7 +324,7 @@ mod sq_ass_item_impl {
|
|||
let slf = py.from_borrowed_ptr::<crate::PyCell<T>>(slf);
|
||||
|
||||
let result = if value.is_null() {
|
||||
slf.__delitem__(key.into()).into()
|
||||
slf.borrow_mut().__delitem__(key.into()).into()
|
||||
} else {
|
||||
Err(PyErr::new::<exceptions::NotImplementedError, _>(format!(
|
||||
"Item assignment not supported by {:?}",
|
||||
|
@ -372,11 +375,14 @@ mod sq_ass_item_impl {
|
|||
let slf = py.from_borrowed_ptr::<crate::PyCell<T>>(slf);
|
||||
|
||||
let result = if value.is_null() {
|
||||
slf.__delitem__(key.into()).into()
|
||||
call_refmut!(slf, __delitem__; key.into())
|
||||
} else {
|
||||
let value = py.from_borrowed_ptr::<PyAny>(value);
|
||||
match value.extract() {
|
||||
Ok(value) => slf.__setitem__(key.into(), value).into(),
|
||||
Ok(value) => match slf.try_borrow_mut_unguarded() {
|
||||
Ok(slf_) => slf_.__setitem__(key.into(), value).into(),
|
||||
Err(e) => e.into(),
|
||||
},
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
};
|
||||
|
@ -497,7 +503,9 @@ where
|
|||
PySequenceInplaceConcatProtocol,
|
||||
T::__inplace_concat__,
|
||||
T,
|
||||
PyObjectCallbackConverter
|
||||
PyObjectCallbackConverter,
|
||||
*mut crate::ffi::PyObject,
|
||||
call_refmut
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -524,7 +532,8 @@ where
|
|||
PySequenceInplaceRepeatProtocol,
|
||||
T::__inplace_repeat__,
|
||||
T,
|
||||
PyObjectCallbackConverter
|
||||
PyObjectCallbackConverter,
|
||||
call_refmut
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -100,7 +100,8 @@ pub fn parse_fn_args<'p>(
|
|||
// Adjust the remaining args
|
||||
let args = if accept_args {
|
||||
let py = args.py();
|
||||
args.slice(used_args as isize, nargs as isize).as_ref(py)
|
||||
// args.slice(used_args as isize, nargs as isize).as_ref(py)
|
||||
unimplemented!()
|
||||
} else {
|
||||
args
|
||||
};
|
||||
|
|
|
@ -59,6 +59,9 @@ pub type PyResult<T> = Result<T, PyErr>;
|
|||
/// Marker type that indicates an error while downcasting
|
||||
pub struct PyDowncastError;
|
||||
|
||||
/// Marker type for `PyCell`.
|
||||
pub struct PyBorrowError;
|
||||
|
||||
/// Helper conversion trait that allows to use custom arguments for exception constructor.
|
||||
pub trait PyErrArguments {
|
||||
/// Arguments for exception
|
||||
|
@ -401,7 +404,7 @@ impl<'a> IntoPy<PyObject> for &'a PyErr {
|
|||
}
|
||||
}
|
||||
|
||||
/// Converts `PyDowncastError` to Python `TypeError`.
|
||||
/// Convert `PyDowncastError` to Python `TypeError`.
|
||||
impl std::convert::From<PyDowncastError> for PyErr {
|
||||
fn from(_err: PyDowncastError) -> PyErr {
|
||||
exceptions::TypeError.into()
|
||||
|
|
|
@ -23,3 +23,10 @@ macro_rules! private_impl {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! pyo3_exception {
|
||||
($name: ident, $base: ty) => {
|
||||
$crate::impl_exception_boilerplate!($name);
|
||||
$crate::create_exception_type_object!(pyo3_runtime, $name, $base);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -165,7 +165,6 @@ pub mod ffi;
|
|||
pub mod freelist;
|
||||
mod gil;
|
||||
mod instance;
|
||||
mod pyref;
|
||||
#[macro_use]
|
||||
mod internal_tricks;
|
||||
pub mod marshal;
|
||||
|
|
198
src/pycell.rs
198
src/pycell.rs
|
@ -6,10 +6,44 @@ use crate::pyclass_slots::{PyClassDict, PyClassWeakRef};
|
|||
use crate::type_object::{PyDowncastImpl, PyObjectLayout, PyObjectSizedLayout};
|
||||
use crate::types::PyAny;
|
||||
use crate::{ffi, gil, PyErr, PyObject, PyResult, PyTypeInfo, Python};
|
||||
use std::cell::{Cell, UnsafeCell};
|
||||
use std::fmt;
|
||||
use std::mem::ManuallyDrop;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::ptr::NonNull;
|
||||
|
||||
/// `PyCell` represents the concrete layout of `T: PyClass` when it is converted
|
||||
/// Inner type of `PyCell` without dict slots and reference counter.
|
||||
#[doc(hidden)]
|
||||
#[repr(C)]
|
||||
pub struct PyCellBase<T: PyClass> {
|
||||
ob_base: <T::BaseType as PyTypeInfo>::ConcreteLayout,
|
||||
value: ManuallyDrop<UnsafeCell<T>>,
|
||||
}
|
||||
|
||||
impl<T: PyClass> PyCellBase<T> {
|
||||
fn get(&self) -> &T {
|
||||
unsafe { &*self.value.get() }
|
||||
}
|
||||
fn get_mut(&mut self) -> &mut T {
|
||||
unsafe { &mut *self.value.get() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: PyClass> PyObjectLayout<T> for PyCellBase<T> {
|
||||
const IS_NATIVE_TYPE: bool = false;
|
||||
fn get_super_or(&mut self) -> Option<&mut <T::BaseType as PyTypeInfo>::ConcreteLayout> {
|
||||
Some(&mut self.ob_base)
|
||||
}
|
||||
unsafe fn py_init(&mut self, value: T) {
|
||||
self.value = ManuallyDrop::new(UnsafeCell::new(value));
|
||||
}
|
||||
unsafe fn py_drop(&mut self, py: Python) {
|
||||
ManuallyDrop::drop(&mut self.value);
|
||||
self.ob_base.py_drop(py);
|
||||
}
|
||||
}
|
||||
|
||||
/// `Pycell` represents the concrete layout of `T: PyClass` when it is converted
|
||||
/// to a Python class.
|
||||
///
|
||||
/// You can use it to test your `#[pyclass]` correctly works.
|
||||
|
@ -35,7 +69,8 @@ use std::ptr::NonNull;
|
|||
#[repr(C)]
|
||||
pub struct PyCell<T: PyClass> {
|
||||
ob_base: <T::BaseType as PyTypeInfo>::ConcreteLayout,
|
||||
pyclass: ManuallyDrop<T>,
|
||||
value: ManuallyDrop<UnsafeCell<T>>,
|
||||
borrow_flag: BorrowFlag,
|
||||
dict: T::Dict,
|
||||
weakref: T::WeakRef,
|
||||
}
|
||||
|
@ -54,14 +89,40 @@ impl<T: PyClass> PyCell<T> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Get the reference of base object.
|
||||
pub fn get_super(&self) -> &<T::BaseType as PyTypeInfo>::ConcreteLayout {
|
||||
&self.ob_base
|
||||
pub fn borrow(&self) -> PyRef<'_, T> {
|
||||
unsafe {
|
||||
unimplemented!()
|
||||
// if self.borrow.get() == usize::max_value() {
|
||||
// borrow_fail();
|
||||
// }
|
||||
// self.borrow.set(self.borrow.get() + 1);
|
||||
// Ref {
|
||||
// value: &*self.value.get(),
|
||||
// borrow: &self.borrow,
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the mutable reference of base object.
|
||||
pub fn get_super_mut(&mut self) -> &mut <T::BaseType as PyTypeInfo>::ConcreteLayout {
|
||||
&mut self.ob_base
|
||||
pub fn borrow_mut(&self) -> PyRefMut<'_, T> {
|
||||
unsafe {
|
||||
unimplemented!()
|
||||
// if self.borrow.get() != 0 {
|
||||
// borrow_fail();
|
||||
// }
|
||||
// self.borrow.set(usize::max_value());
|
||||
// RefMut {
|
||||
// value: &mut *self.value.get(),
|
||||
// borrow: &self.borrow,
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn try_borrow_unguarded(&self) -> Result<&T, PyBorrowError> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
pub unsafe fn try_borrow_mut_unguarded(&self) -> Result<&mut T, PyBorrowMutError> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
pub(crate) unsafe fn internal_new(py: Python) -> PyResult<*mut Self>
|
||||
|
@ -74,6 +135,7 @@ impl<T: PyClass> PyCell<T> {
|
|||
return Err(PyErr::fetch(py));
|
||||
}
|
||||
let self_ = base as *mut Self;
|
||||
(*self_).borrow_flag = BorrowFlag::UNUSED;
|
||||
(*self_).dict = T::Dict::new();
|
||||
(*self_).weakref = T::WeakRef::new();
|
||||
Ok(self_)
|
||||
|
@ -85,15 +147,15 @@ impl<T: PyClass> PyObjectLayout<T> for PyCell<T> {
|
|||
fn get_super_or(&mut self) -> Option<&mut <T::BaseType as PyTypeInfo>::ConcreteLayout> {
|
||||
Some(&mut self.ob_base)
|
||||
}
|
||||
unsafe fn py_init(&mut self, value: T) {
|
||||
self.value = ManuallyDrop::new(UnsafeCell::new(value));
|
||||
}
|
||||
unsafe fn py_drop(&mut self, py: Python) {
|
||||
ManuallyDrop::drop(&mut self.pyclass);
|
||||
ManuallyDrop::drop(&mut self.value);
|
||||
self.dict.clear_dict(py);
|
||||
self.weakref.clear_weakrefs(self.as_ptr(), py);
|
||||
self.ob_base.py_drop(py);
|
||||
}
|
||||
unsafe fn py_init(&mut self, value: T) {
|
||||
self.pyclass = ManuallyDrop::new(value);
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<'py, T: 'py + PyClass> PyDowncastImpl<'py> for PyCell<T> {
|
||||
|
@ -111,19 +173,6 @@ impl<T: PyClass> AsPyPointer for PyCell<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: PyClass> std::ops::Deref for PyCell<T> {
|
||||
type Target = T;
|
||||
fn deref(&self) -> &T {
|
||||
self.pyclass.deref()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: PyClass> std::ops::DerefMut for PyCell<T> {
|
||||
fn deref_mut(&mut self) -> &mut T {
|
||||
self.pyclass.deref_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: PyClass> ToPyObject for &PyCell<T> {
|
||||
fn to_object(&self, py: Python<'_>) -> PyObject {
|
||||
unsafe { PyObject::from_borrowed_ptr(py, self.as_ptr()) }
|
||||
|
@ -150,3 +199,102 @@ where
|
|||
NonNull::new(ptr).map(|p| &*(gil::register_borrowed(py, p).as_ptr() as *const PyCell<T>))
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PyRef<'p, T: PyClass> {
|
||||
value: &'p PyCellBase<T>,
|
||||
flag: &'p Cell<BorrowFlag>,
|
||||
}
|
||||
|
||||
impl<'p, T: PyClass> PyRef<'p, T> {
|
||||
fn get_super(&'p self) -> &'p T::BaseType {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'p, T: PyClass> Deref for PyRef<'p, T> {
|
||||
type Target = T;
|
||||
|
||||
#[inline]
|
||||
fn deref(&self) -> &T {
|
||||
self.value.get()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'p, T: PyClass> Drop for PyRef<'p, T> {
|
||||
fn drop(&mut self) {
|
||||
self.flag.set(self.flag.get());
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PyRefMut<'p, T: PyClass> {
|
||||
value: &'p mut PyCellBase<T>,
|
||||
flag: &'p Cell<BorrowFlag>,
|
||||
}
|
||||
|
||||
impl<'p, T: PyClass> Deref for PyRefMut<'p, T> {
|
||||
type Target = T;
|
||||
|
||||
#[inline]
|
||||
fn deref(&self) -> &T {
|
||||
self.value.get()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'p, T: PyClass> DerefMut for PyRefMut<'p, T> {
|
||||
#[inline]
|
||||
fn deref_mut(&mut self) -> &mut T {
|
||||
self.value.get_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'p, T: PyClass> Drop for PyRefMut<'p, T> {
|
||||
fn drop(&mut self) {
|
||||
self.flag.set(BorrowFlag::UNUSED);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Eq, PartialEq)]
|
||||
struct BorrowFlag(usize);
|
||||
|
||||
impl BorrowFlag {
|
||||
const UNUSED: BorrowFlag = BorrowFlag(0);
|
||||
const HAS_MUTABLE_BORROW: BorrowFlag = BorrowFlag(usize::max_value());
|
||||
fn decrement(self) -> Self {
|
||||
Self(self.0 - 1)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PyBorrowError {
|
||||
_private: (),
|
||||
}
|
||||
|
||||
impl fmt::Debug for PyBorrowError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("PyBorrowError").finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for PyBorrowError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Display::fmt("Already mutably borrowed", f)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PyBorrowMutError {
|
||||
_private: (),
|
||||
}
|
||||
|
||||
impl fmt::Debug for PyBorrowMutError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("PyBorrowMutError").finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for PyBorrowMutError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Display::fmt("Already borrowed", f)
|
||||
}
|
||||
}
|
||||
|
||||
pyo3_exception!(PyBorrowError, crate::exceptions::Exception);
|
||||
pyo3_exception!(PyBorrowMutError, crate::exceptions::Exception);
|
||||
|
|
|
@ -53,9 +53,11 @@ pub mod type_flags {
|
|||
}
|
||||
|
||||
/// Reference abstraction for `PyClass` and `PyNativeType`.
|
||||
// NOTE: This trait is separated from PyTypeInfo since make it PyTypeInfo<`py> is confusing...
|
||||
// When GAT and type Ref<'py> becomes stable, let's merge this trait to
|
||||
// PyConcreteLayout or Py
|
||||
// DEVELOPPER NOTE(kngwyu):
|
||||
// `&PyCell` is a pointer but `&PyAny` is a pointer of a pointer, so we need
|
||||
// two different abstraction for them.
|
||||
// This mismatch eventually should be fixed with https://github.com/PyO3/pyo3/issues/679,
|
||||
// but now it's not the time.
|
||||
pub unsafe trait PyDowncastImpl<'py> {
|
||||
unsafe fn unchecked_downcast(obj: &PyAny) -> &'py Self;
|
||||
private_decl! {}
|
||||
|
|
Loading…
Reference in New Issue