comparison rust/hg-cpython/src/ref_sharing.rs @ 43176:aaec70a5f9a8

rust-cpython: store leaked reference to PySharedState in $leaked struct I want to move it out of the macro, and allow multiple sharable objects per PyObject.
author Yuya Nishihara <yuya@tcha.org>
date Sun, 15 Sep 2019 16:04:45 +0900
parents a1908eb08342
children 5cb8867c9e2b
comparison
equal deleted inserted replaced
43175:a1908eb08342 43176:aaec70a5f9a8
72 immutable references in Python objects", 72 immutable references in Python objects",
73 )), 73 )),
74 } 74 }
75 } 75 }
76 76
77 /// Return a reference to the wrapped data with an artificial static 77 /// Return a reference to the wrapped data and its state with an
78 /// lifetime. 78 /// artificial static lifetime.
79 /// We need to be protected by the GIL for thread-safety. 79 /// We need to be protected by the GIL for thread-safety.
80 /// 80 ///
81 /// # Safety 81 /// # Safety
82 /// 82 ///
83 /// This is highly unsafe since the lifetime of the given data can be 83 /// This is highly unsafe since the lifetime of the given data can be
84 /// extended. Do not call this function directly. 84 /// extended. Do not call this function directly.
85 pub unsafe fn leak_immutable<T>( 85 pub unsafe fn leak_immutable<T>(
86 &self, 86 &self,
87 py: Python, 87 py: Python,
88 data: &PySharedRefCell<T>, 88 data: &PySharedRefCell<T>,
89 ) -> PyResult<&'static T> { 89 ) -> PyResult<(&'static T, &'static PySharedState)> {
90 if self.mutably_borrowed.get() { 90 if self.mutably_borrowed.get() {
91 return Err(AlreadyBorrowed::new( 91 return Err(AlreadyBorrowed::new(
92 py, 92 py,
93 "Cannot borrow immutably while there is a \ 93 "Cannot borrow immutably while there is a \
94 mutable reference in Python objects", 94 mutable reference in Python objects",
95 )); 95 ));
96 } 96 }
97 // TODO: it's weird that self is data.py_shared_state. Maybe we
98 // can move stuff to PySharedRefCell?
97 let ptr = data.as_ptr(); 99 let ptr = data.as_ptr();
100 let state_ptr: *const PySharedState = &data.py_shared_state;
98 self.leak_count.replace(self.leak_count.get() + 1); 101 self.leak_count.replace(self.leak_count.get() + 1);
99 Ok(&*ptr) 102 Ok((&*ptr, &*state_ptr))
100 } 103 }
101 104
102 /// # Safety 105 /// # Safety
103 /// 106 ///
104 /// It's unsafe to update the reference count without knowing the 107 /// It's unsafe to update the reference count without knowing the
265 py: Python<'a>, 268 py: Python<'a>,
266 ) -> PyResult<($leaked, &'static $inner_struct)> { 269 ) -> PyResult<($leaked, &'static $inner_struct)> {
267 // assert $data_member type 270 // assert $data_member type
268 use crate::ref_sharing::PySharedRefCell; 271 use crate::ref_sharing::PySharedRefCell;
269 let data: &PySharedRefCell<_> = self.$data_member(py); 272 let data: &PySharedRefCell<_> = self.$data_member(py);
270 let static_ref = 273 let (static_ref, static_state_ref) =
271 data.py_shared_state.leak_immutable(py, data)?; 274 data.py_shared_state.leak_immutable(py, data)?;
272 let leak_handle = $leaked::new(py, self); 275 let leak_handle = $leaked::new(py, self, static_state_ref);
273 Ok((leak_handle, static_ref)) 276 Ok((leak_handle, static_ref))
274 } 277 }
275 } 278 }
276 279
277 /// Manage immutable references to `$name` leaked into Python 280 /// Manage immutable references to `$name` leaked into Python
278 /// iterators. 281 /// iterators.
279 /// 282 ///
280 /// In truth, this does not represent leaked references themselves; 283 /// In truth, this does not represent leaked references themselves;
281 /// it is instead useful alongside them to manage them. 284 /// it is instead useful alongside them to manage them.
282 pub struct $leaked { 285 pub struct $leaked {
283 inner: $name, 286 _inner: $name,
287 py_shared_state: &'static crate::ref_sharing::PySharedState,
284 } 288 }
285 289
286 impl $leaked { 290 impl $leaked {
291 /// # Safety
292 ///
293 /// The `py_shared_state` must be owned by the `inner` Python
294 /// object.
287 // Marked as unsafe so client code wouldn't construct $leaked 295 // Marked as unsafe so client code wouldn't construct $leaked
288 // struct by mistake. Its drop() is unsafe. 296 // struct by mistake. Its drop() is unsafe.
289 unsafe fn new(py: Python, inner: &$name) -> Self { 297 unsafe fn new(
298 py: Python,
299 inner: &$name,
300 py_shared_state: &'static crate::ref_sharing::PySharedState,
301 ) -> Self {
290 Self { 302 Self {
291 inner: inner.clone_ref(py), 303 _inner: inner.clone_ref(py),
304 py_shared_state,
292 } 305 }
293 } 306 }
294 } 307 }
295 308
296 impl Drop for $leaked { 309 impl Drop for $leaked {
297 fn drop(&mut self) { 310 fn drop(&mut self) {
311 // py_shared_state should be alive since we do have
312 // a Python reference to the owner object. Taking GIL makes
313 // sure that the state is only accessed by this thread.
298 let gil = Python::acquire_gil(); 314 let gil = Python::acquire_gil();
299 let py = gil.python(); 315 let py = gil.python();
300 let state = &self.inner.$data_member(py).py_shared_state;
301 unsafe { 316 unsafe {
302 state.decrease_leak_count(py, false); 317 self.py_shared_state.decrease_leak_count(py, false);
303 } 318 }
304 } 319 }
305 } 320 }
306 }; 321 };
307 } 322 }