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