diff rust/hg-cpython/src/ref_sharing.rs @ 43173:070a38737334

rust-cpython: move py_shared_state to PySharedRefCell object The goal of this series is to encapsulate more "py_shared" thingy and reduce the size of the macro, which is hard to debug. Since py_shared_state manages the borrowing state of the object owned by PySharedRefCell, this change makes more sense. If a PyObject has more than one data to be leaked into Python world, each PySharedState should incref the parent PyObject, and keep track of the corresponding borrowing state.
author Yuya Nishihara <yuya@tcha.org>
date Sat, 14 Sep 2019 23:01:51 +0900
parents fdfe5cfb3723
children 1c675c5fe5fe
line wrap: on
line diff
--- a/rust/hg-cpython/src/ref_sharing.rs	Thu Oct 10 21:37:12 2019 +0200
+++ b/rust/hg-cpython/src/ref_sharing.rs	Sat Sep 14 23:01:51 2019 +0900
@@ -27,7 +27,7 @@
 use std::cell::{Cell, Ref, RefCell, RefMut};
 
 /// Manages the shared state between Python and Rust
-#[derive(Default)]
+#[derive(Debug, Default)]
 pub struct PySharedState {
     leak_count: Cell<usize>,
     mutably_borrowed: Cell<bool>,
@@ -118,12 +118,14 @@
 #[derive(Debug)]
 pub struct PySharedRefCell<T> {
     inner: RefCell<T>,
+    pub py_shared_state: PySharedState, // TODO: remove pub
 }
 
 impl<T> PySharedRefCell<T> {
-    pub const fn new(value: T) -> PySharedRefCell<T> {
+    pub fn new(value: T) -> PySharedRefCell<T> {
         Self {
             inner: RefCell::new(value),
+            py_shared_state: PySharedState::default(),
         }
     }
 
@@ -193,12 +195,6 @@
 ///
 /// # Warning
 ///
-/// The targeted `py_class!` needs to have the
-/// `data py_shared_state: PySharedState;` data attribute to compile.
-/// A better, more complicated macro is needed to automatically insert it,
-/// but this one is not yet really battle tested (what happens when
-/// multiple references are needed?). See the example below.
-///
 /// TODO allow Python container types: for now, integration with the garbage
 ///     collector does not extend to Rust structs holding references to Python
 ///     objects. Should the need surface, `__traverse__` and `__clear__` will
@@ -223,7 +219,6 @@
 ///
 /// py_class!(pub class MyType |py| {
 ///     data inner: PySharedRefCell<MyStruct>;
-///     data py_shared_state: PySharedState;
 /// });
 ///
 /// py_shared_ref!(MyType, MyStruct, inner, MyTypeLeakedRef);
@@ -244,7 +239,7 @@
                 // assert $data_member type
                 use crate::ref_sharing::PySharedRefCell;
                 let data: &PySharedRefCell<_> = self.$data_member(py);
-                self.py_shared_state(py)
+                data.py_shared_state
                     .borrow_mut(py, unsafe { data.borrow_mut() })
             }
 
@@ -263,7 +258,7 @@
                 use crate::ref_sharing::PySharedRefCell;
                 let data: &PySharedRefCell<_> = self.$data_member(py);
                 let static_ref =
-                    self.py_shared_state(py).leak_immutable(py, data)?;
+                    data.py_shared_state.leak_immutable(py, data)?;
                 let leak_handle = $leaked::new(py, self);
                 Ok((leak_handle, static_ref))
             }
@@ -292,7 +287,7 @@
             fn drop(&mut self) {
                 let gil = Python::acquire_gil();
                 let py = gil.python();
-                let state = self.inner.py_shared_state(py);
+                let state = &self.inner.$data_member(py).py_shared_state;
                 unsafe {
                     state.decrease_leak_count(py, false);
                 }
@@ -324,7 +319,6 @@
 ///
 /// py_class!(pub class MyType |py| {
 ///     data inner: PySharedRefCell<MyStruct>;
-///     data py_shared_state: PySharedState;
 ///
 ///     def __iter__(&self) -> PyResult<MyTypeItemsIterator> {
 ///         let (leak_handle, leaked_ref) = unsafe { self.leak_immutable(py)? };