##// END OF EJS Templates
rust-cpython: move $leaked struct out of macro...
Yuya Nishihara -
r43447:5cb8867c default
parent child Browse files
Show More
@@ -11,7 +11,8 b''
11 use cpython::{PyBytes, PyClone, PyDict, PyObject, PyResult, Python};
11 use cpython::{PyBytes, PyClone, PyDict, PyObject, PyResult, Python};
12 use std::cell::RefCell;
12 use std::cell::RefCell;
13
13
14 use crate::dirstate::dirstate_map::{DirstateMap, DirstateMapLeakedRef};
14 use crate::dirstate::dirstate_map::DirstateMap;
15 use crate::ref_sharing::PyLeakedRef;
15 use hg::{utils::hg_path::HgPathBuf, CopyMapIter};
16 use hg::{utils::hg_path::HgPathBuf, CopyMapIter};
16
17
17 py_class!(pub class CopyMap |py| {
18 py_class!(pub class CopyMap |py| {
@@ -103,7 +104,7 b' impl CopyMap {'
103
104
104 py_shared_iterator!(
105 py_shared_iterator!(
105 CopyMapKeysIterator,
106 CopyMapKeysIterator,
106 DirstateMapLeakedRef,
107 PyLeakedRef,
107 CopyMapIter<'static>,
108 CopyMapIter<'static>,
108 CopyMap::translate_key,
109 CopyMap::translate_key,
109 Option<PyBytes>
110 Option<PyBytes>
@@ -111,7 +112,7 b' py_shared_iterator!('
111
112
112 py_shared_iterator!(
113 py_shared_iterator!(
113 CopyMapItemsIterator,
114 CopyMapItemsIterator,
114 DirstateMapLeakedRef,
115 PyLeakedRef,
115 CopyMapIter<'static>,
116 CopyMapIter<'static>,
116 CopyMap::translate_key_value,
117 CopyMap::translate_key_value,
117 Option<(PyBytes, PyBytes)>
118 Option<(PyBytes, PyBytes)>
@@ -16,7 +16,8 b' use cpython::{'
16 Python,
16 Python,
17 };
17 };
18
18
19 use crate::{dirstate::extract_dirstate, ref_sharing::PySharedRefCell};
19 use crate::dirstate::extract_dirstate;
20 use crate::ref_sharing::{PyLeakedRef, PySharedRefCell};
20 use hg::{
21 use hg::{
21 utils::hg_path::{HgPath, HgPathBuf},
22 utils::hg_path::{HgPath, HgPathBuf},
22 DirsMultiset, DirsMultisetIter, DirstateMapError, DirstateParseError,
23 DirsMultiset, DirsMultisetIter, DirstateMapError, DirstateParseError,
@@ -106,7 +107,7 b' py_class!(pub class Dirs |py| {'
106 }
107 }
107 });
108 });
108
109
109 py_shared_ref!(Dirs, DirsMultiset, inner, DirsMultisetLeakedRef,);
110 py_shared_ref!(Dirs, DirsMultiset, inner);
110
111
111 impl Dirs {
112 impl Dirs {
112 pub fn from_inner(py: Python, d: DirsMultiset) -> PyResult<Self> {
113 pub fn from_inner(py: Python, d: DirsMultiset) -> PyResult<Self> {
@@ -123,7 +124,7 b' impl Dirs {'
123
124
124 py_shared_iterator!(
125 py_shared_iterator!(
125 DirsMultisetKeysIterator,
126 DirsMultisetKeysIterator,
126 DirsMultisetLeakedRef,
127 PyLeakedRef,
127 DirsMultisetIter<'static>,
128 DirsMultisetIter<'static>,
128 Dirs::translate_key,
129 Dirs::translate_key,
129 Option<PyBytes>
130 Option<PyBytes>
@@ -21,7 +21,7 b' use libc::c_char;'
21 use crate::{
21 use crate::{
22 dirstate::copymap::{CopyMap, CopyMapItemsIterator, CopyMapKeysIterator},
22 dirstate::copymap::{CopyMap, CopyMapItemsIterator, CopyMapKeysIterator},
23 dirstate::{decapsule_make_dirstate_tuple, dirs_multiset::Dirs},
23 dirstate::{decapsule_make_dirstate_tuple, dirs_multiset::Dirs},
24 ref_sharing::PySharedRefCell,
24 ref_sharing::{PyLeakedRef, PySharedRefCell},
25 };
25 };
26 use hg::{
26 use hg::{
27 utils::hg_path::{HgPath, HgPathBuf},
27 utils::hg_path::{HgPath, HgPathBuf},
@@ -501,11 +501,11 b' impl DirstateMap {'
501 }
501 }
502 }
502 }
503
503
504 py_shared_ref!(DirstateMap, RustDirstateMap, inner, DirstateMapLeakedRef,);
504 py_shared_ref!(DirstateMap, RustDirstateMap, inner);
505
505
506 py_shared_iterator!(
506 py_shared_iterator!(
507 DirstateMapKeysIterator,
507 DirstateMapKeysIterator,
508 DirstateMapLeakedRef,
508 PyLeakedRef,
509 StateMapIter<'static>,
509 StateMapIter<'static>,
510 DirstateMap::translate_key,
510 DirstateMap::translate_key,
511 Option<PyBytes>
511 Option<PyBytes>
@@ -513,7 +513,7 b' py_shared_iterator!('
513
513
514 py_shared_iterator!(
514 py_shared_iterator!(
515 DirstateMapItemsIterator,
515 DirstateMapItemsIterator,
516 DirstateMapLeakedRef,
516 PyLeakedRef,
517 StateMapIter<'static>,
517 StateMapIter<'static>,
518 DirstateMap::translate_key_value,
518 DirstateMap::translate_key_value,
519 Option<(PyBytes, PyObject)>
519 Option<(PyBytes, PyObject)>
@@ -23,7 +23,7 b''
23 //! Macros for use in the `hg-cpython` bridge library.
23 //! Macros for use in the `hg-cpython` bridge library.
24
24
25 use crate::exceptions::AlreadyBorrowed;
25 use crate::exceptions::AlreadyBorrowed;
26 use cpython::{PyResult, Python};
26 use cpython::{PyClone, PyObject, PyResult, Python};
27 use std::cell::{Cell, Ref, RefCell, RefMut};
27 use std::cell::{Cell, Ref, RefCell, RefMut};
28
28
29 /// Manages the shared state between Python and Rust
29 /// Manages the shared state between Python and Rust
@@ -219,9 +219,6 b" impl<'a, T> Drop for PyRefMut<'a, T> {"
219 /// * `$inner_struct` is the identifier of the underlying Rust struct
219 /// * `$inner_struct` is the identifier of the underlying Rust struct
220 /// * `$data_member` is the identifier of the data member of `$inner_struct`
220 /// * `$data_member` is the identifier of the data member of `$inner_struct`
221 /// that will be shared.
221 /// that will be shared.
222 /// * `$leaked` is the identifier to give to the struct that will manage
223 /// references to `$name`, to be used for example in other macros like
224 /// `py_shared_iterator`.
225 ///
222 ///
226 /// # Example
223 /// # Example
227 ///
224 ///
@@ -234,14 +231,13 b" impl<'a, T> Drop for PyRefMut<'a, T> {"
234 /// data inner: PySharedRefCell<MyStruct>;
231 /// data inner: PySharedRefCell<MyStruct>;
235 /// });
232 /// });
236 ///
233 ///
237 /// py_shared_ref!(MyType, MyStruct, inner, MyTypeLeakedRef);
234 /// py_shared_ref!(MyType, MyStruct, inner);
238 /// ```
235 /// ```
239 macro_rules! py_shared_ref {
236 macro_rules! py_shared_ref {
240 (
237 (
241 $name: ident,
238 $name: ident,
242 $inner_struct: ident,
239 $inner_struct: ident,
243 $data_member: ident,
240 $data_member: ident
244 $leaked: ident,
245 ) => {
241 ) => {
246 impl $name {
242 impl $name {
247 // TODO: remove this function in favor of inner(py).borrow_mut()
243 // TODO: remove this function in favor of inner(py).borrow_mut()
@@ -266,59 +262,59 b' macro_rules! py_shared_ref {'
266 unsafe fn leak_immutable<'a>(
262 unsafe fn leak_immutable<'a>(
267 &'a self,
263 &'a self,
268 py: Python<'a>,
264 py: Python<'a>,
269 ) -> PyResult<($leaked, &'static $inner_struct)> {
265 ) -> PyResult<(PyLeakedRef, &'static $inner_struct)> {
266 use cpython::PythonObject;
270 // assert $data_member type
267 // assert $data_member type
271 use crate::ref_sharing::PySharedRefCell;
268 use crate::ref_sharing::PySharedRefCell;
272 let data: &PySharedRefCell<_> = self.$data_member(py);
269 let data: &PySharedRefCell<_> = self.$data_member(py);
273 let (static_ref, static_state_ref) =
270 let (static_ref, static_state_ref) =
274 data.py_shared_state.leak_immutable(py, data)?;
271 data.py_shared_state.leak_immutable(py, data)?;
275 let leak_handle = $leaked::new(py, self, static_state_ref);
272 let leak_handle =
273 PyLeakedRef::new(py, self.as_object(), static_state_ref);
276 Ok((leak_handle, static_ref))
274 Ok((leak_handle, static_ref))
277 }
275 }
278 }
276 }
277 };
278 }
279
279
280 /// Manage immutable references to `$name` leaked into Python
280 /// Manage immutable references to `PyObject` leaked into Python iterators.
281 /// iterators.
281 ///
282 ///
282 /// In truth, this does not represent leaked references themselves;
283 /// In truth, this does not represent leaked references themselves;
283 /// it is instead useful alongside them to manage them.
284 /// it is instead useful alongside them to manage them.
284 pub struct PyLeakedRef {
285 pub struct $leaked {
285 _inner: PyObject,
286 _inner: $name,
286 py_shared_state: &'static PySharedState,
287 py_shared_state: &'static crate::ref_sharing::PySharedState,
287 }
288 }
289
288
290 impl $leaked {
289 impl PyLeakedRef {
291 /// # Safety
290 /// # Safety
292 ///
291 ///
293 /// The `py_shared_state` must be owned by the `inner` Python
292 /// The `py_shared_state` must be owned by the `inner` Python object.
294 /// object.
293 // Marked as unsafe so client code wouldn't construct PyLeakedRef
295 // Marked as unsafe so client code wouldn't construct $leaked
294 // struct by mistake. Its drop() is unsafe.
296 // struct by mistake. Its drop() is unsafe.
295 pub unsafe fn new(
297 unsafe fn new(
296 py: Python,
298 py: Python,
297 inner: &PyObject,
299 inner: &$name,
298 py_shared_state: &'static PySharedState,
300 py_shared_state: &'static crate::ref_sharing::PySharedState,
299 ) -> Self {
301 ) -> Self {
300 Self {
302 Self {
301 _inner: inner.clone_ref(py),
303 _inner: inner.clone_ref(py),
302 py_shared_state,
304 py_shared_state,
305 }
306 }
307 }
303 }
304 }
305 }
308
306
309 impl Drop for $leaked {
307 impl Drop for PyLeakedRef {
310 fn drop(&mut self) {
308 fn drop(&mut self) {
311 // py_shared_state should be alive since we do have
309 // py_shared_state should be alive since we do have
312 // a Python reference to the owner object. Taking GIL makes
310 // a Python reference to the owner object. Taking GIL makes
313 // sure that the state is only accessed by this thread.
311 // sure that the state is only accessed by this thread.
314 let gil = Python::acquire_gil();
312 let gil = Python::acquire_gil();
315 let py = gil.python();
313 let py = gil.python();
316 unsafe {
314 unsafe {
317 self.py_shared_state.decrease_leak_count(py, false);
315 self.py_shared_state.decrease_leak_count(py, false);
318 }
319 }
320 }
316 }
321 };
317 }
322 }
318 }
323
319
324 /// Defines a `py_class!` that acts as a Python iterator over a Rust iterator.
320 /// Defines a `py_class!` that acts as a Python iterator over a Rust iterator.
@@ -372,7 +368,7 b' macro_rules! py_shared_ref {'
372 ///
368 ///
373 /// py_shared_iterator!(
369 /// py_shared_iterator!(
374 /// MyTypeItemsIterator,
370 /// MyTypeItemsIterator,
375 /// MyTypeLeakedRef,
371 /// PyLeakedRef,
376 /// HashMap<'static, Vec<u8>, Vec<u8>>,
372 /// HashMap<'static, Vec<u8>, Vec<u8>>,
377 /// MyType::translate_key_value,
373 /// MyType::translate_key_value,
378 /// Option<(PyBytes, PyBytes)>
374 /// Option<(PyBytes, PyBytes)>
@@ -381,7 +377,7 b' macro_rules! py_shared_ref {'
381 macro_rules! py_shared_iterator {
377 macro_rules! py_shared_iterator {
382 (
378 (
383 $name: ident,
379 $name: ident,
384 $leaked: ident,
380 $leaked: ty,
385 $iterator_type: ty,
381 $iterator_type: ty,
386 $success_func: expr,
382 $success_func: expr,
387 $success_type: ty
383 $success_type: ty
General Comments 0
You need to be logged in to leave comments. Login now