Mercurial > hg-stable
changeset 43284:ce6dd1cee4c8
rust-cpython: put leaked reference in PyLeakedRef
The next patch will make PyLeakedRef manage the lifetime of the underlying
object. leak_handle.data.take() will be removed soon.
author | Yuya Nishihara <yuya@tcha.org> |
---|---|
date | Sun, 15 Sep 2019 22:06:19 +0900 |
parents | 96eb9ef777a8 |
children | ffc1fbd7d1f5 |
files | rust/hg-cpython/src/dirstate/copymap.rs rust/hg-cpython/src/dirstate/dirs_multiset.rs rust/hg-cpython/src/dirstate/dirstate_map.rs rust/hg-cpython/src/ref_sharing.rs |
diffstat | 4 files changed, 35 insertions(+), 23 deletions(-) [+] |
line wrap: on
line diff
--- a/rust/hg-cpython/src/dirstate/copymap.rs Thu Oct 17 20:40:12 2019 -0700 +++ b/rust/hg-cpython/src/dirstate/copymap.rs Sun Sep 15 22:06:19 2019 +0900 @@ -13,6 +13,7 @@ use crate::dirstate::dirstate_map::DirstateMap; use crate::ref_sharing::PyLeakedRef; +use hg::DirstateMap as RustDirstateMap; use hg::{utils::hg_path::HgPathBuf, CopyMapIter}; py_class!(pub class CopyMap |py| { @@ -104,7 +105,7 @@ py_shared_iterator!( CopyMapKeysIterator, - PyLeakedRef, + PyLeakedRef<&'static RustDirstateMap>, CopyMapIter<'static>, CopyMap::translate_key, Option<PyBytes> @@ -112,7 +113,7 @@ py_shared_iterator!( CopyMapItemsIterator, - PyLeakedRef, + PyLeakedRef<&'static RustDirstateMap>, CopyMapIter<'static>, CopyMap::translate_key_value, Option<(PyBytes, PyBytes)>
--- a/rust/hg-cpython/src/dirstate/dirs_multiset.rs Thu Oct 17 20:40:12 2019 -0700 +++ b/rust/hg-cpython/src/dirstate/dirs_multiset.rs Sun Sep 15 22:06:19 2019 +0900 @@ -92,8 +92,9 @@ }) } def __iter__(&self) -> PyResult<DirsMultisetKeysIterator> { - let (leak_handle, leaked_ref) = + let mut leak_handle = unsafe { self.inner_shared(py).leak_immutable()? }; + let leaked_ref = leak_handle.data.take().unwrap(); DirsMultisetKeysIterator::from_inner( py, leak_handle, @@ -125,7 +126,7 @@ py_shared_iterator!( DirsMultisetKeysIterator, - PyLeakedRef, + PyLeakedRef<&'static DirsMultiset>, DirsMultisetIter<'static>, Dirs::translate_key, Option<PyBytes>
--- a/rust/hg-cpython/src/dirstate/dirstate_map.rs Thu Oct 17 20:40:12 2019 -0700 +++ b/rust/hg-cpython/src/dirstate/dirstate_map.rs Sun Sep 15 22:06:19 2019 +0900 @@ -304,8 +304,9 @@ } def keys(&self) -> PyResult<DirstateMapKeysIterator> { - let (leak_handle, leaked_ref) = + let mut leak_handle = unsafe { self.inner_shared(py).leak_immutable()? }; + let leaked_ref = leak_handle.data.take().unwrap(); DirstateMapKeysIterator::from_inner( py, leak_handle, @@ -314,8 +315,9 @@ } def items(&self) -> PyResult<DirstateMapItemsIterator> { - let (leak_handle, leaked_ref) = + let mut leak_handle = unsafe { self.inner_shared(py).leak_immutable()? }; + let leaked_ref = leak_handle.data.take().unwrap(); DirstateMapItemsIterator::from_inner( py, leak_handle, @@ -324,8 +326,9 @@ } def __iter__(&self) -> PyResult<DirstateMapKeysIterator> { - let (leak_handle, leaked_ref) = + let mut leak_handle = unsafe { self.inner_shared(py).leak_immutable()? }; + let leaked_ref = leak_handle.data.take().unwrap(); DirstateMapKeysIterator::from_inner( py, leak_handle, @@ -443,8 +446,9 @@ } def copymapiter(&self) -> PyResult<CopyMapKeysIterator> { - let (leak_handle, leaked_ref) = + let mut leak_handle = unsafe { self.inner_shared(py).leak_immutable()? }; + let leaked_ref = leak_handle.data.take().unwrap(); CopyMapKeysIterator::from_inner( py, leak_handle, @@ -453,8 +457,9 @@ } def copymapitemsiter(&self) -> PyResult<CopyMapItemsIterator> { - let (leak_handle, leaked_ref) = + let mut leak_handle = unsafe { self.inner_shared(py).leak_immutable()? }; + let leaked_ref = leak_handle.data.take().unwrap(); CopyMapItemsIterator::from_inner( py, leak_handle, @@ -493,7 +498,7 @@ py_shared_iterator!( DirstateMapKeysIterator, - PyLeakedRef, + PyLeakedRef<&'static RustDirstateMap>, StateMapIter<'static>, DirstateMap::translate_key, Option<PyBytes> @@ -501,7 +506,7 @@ py_shared_iterator!( DirstateMapItemsIterator, - PyLeakedRef, + PyLeakedRef<&'static RustDirstateMap>, StateMapIter<'static>, DirstateMap::translate_key_value, Option<(PyBytes, PyObject)>
--- a/rust/hg-cpython/src/ref_sharing.rs Thu Oct 17 20:40:12 2019 -0700 +++ b/rust/hg-cpython/src/ref_sharing.rs Sun Sep 15 22:06:19 2019 +0900 @@ -187,23 +187,24 @@ self.data.borrow_mut(self.py) } - /// Returns a leaked reference and its management object. + /// Returns a leaked reference temporarily held by its management object. /// /// # Safety /// /// It's up to you to make sure that the management object lives /// longer than the leaked reference. Otherwise, you'll get a /// dangling reference. - pub unsafe fn leak_immutable( - &self, - ) -> PyResult<(PyLeakedRef, &'static T)> { + pub unsafe fn leak_immutable(&self) -> PyResult<PyLeakedRef<&'static T>> { let (static_ref, static_state_ref) = self .data .py_shared_state .leak_immutable(self.py, self.data)?; - let leak_handle = - PyLeakedRef::new(self.py, self.owner, static_state_ref); - Ok((leak_handle, static_ref)) + Ok(PyLeakedRef::new( + self.py, + self.owner, + static_ref, + static_state_ref, + )) } } @@ -318,12 +319,13 @@ /// /// In truth, this does not represent leaked references themselves; /// it is instead useful alongside them to manage them. -pub struct PyLeakedRef { +pub struct PyLeakedRef<T> { _inner: PyObject, + pub data: Option<T>, // TODO: remove pub py_shared_state: &'static PySharedState, } -impl PyLeakedRef { +impl<T> PyLeakedRef<T> { /// # Safety /// /// The `py_shared_state` must be owned by the `inner` Python object. @@ -332,16 +334,18 @@ pub unsafe fn new( py: Python, inner: &PyObject, + data: T, py_shared_state: &'static PySharedState, ) -> Self { Self { _inner: inner.clone_ref(py), + data: Some(data), py_shared_state, } } } -impl Drop for PyLeakedRef { +impl<T> Drop for PyLeakedRef<T> { fn drop(&mut self) { // py_shared_state should be alive since we do have // a Python reference to the owner object. Taking GIL makes @@ -379,8 +383,9 @@ /// data inner: PySharedRefCell<MyStruct>; /// /// def __iter__(&self) -> PyResult<MyTypeItemsIterator> { -/// let (leak_handle, leaked_ref) = +/// let mut leak_handle = /// unsafe { self.inner_shared(py).leak_immutable()? }; +/// let leaked_ref = leak_handle.data.take().unwrap(); /// MyTypeItemsIterator::from_inner( /// py, /// leak_handle, @@ -406,7 +411,7 @@ /// /// py_shared_iterator!( /// MyTypeItemsIterator, -/// PyLeakedRef, +/// PyLeakedRef<&'static MyStruct>, /// HashMap<'static, Vec<u8>, Vec<u8>>, /// MyType::translate_key_value, /// Option<(PyBytes, PyBytes)>