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:: |
|
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 |
|
|
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 |
|
|
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:: |
|
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 |
|
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 |
|
|
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 |
|
504 | py_shared_ref!(DirstateMap, RustDirstateMap, inner); | |
505 |
|
505 | |||
506 | py_shared_iterator!( |
|
506 | py_shared_iterator!( | |
507 | DirstateMapKeysIterator, |
|
507 | DirstateMapKeysIterator, | |
508 |
|
|
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 |
|
|
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 |
|
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<( |
|
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 = |
|
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 |
|
|
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 |
|
|
289 | impl PyLeakedRef { | |
291 |
|
|
290 | /// # Safety | |
292 |
|
|
291 | /// | |
293 |
|
|
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 |
|
|
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 |
|
|
307 | impl Drop for PyLeakedRef { | |
310 |
|
|
308 | fn drop(&mut self) { | |
311 |
|
|
309 | // py_shared_state should be alive since we do have | |
312 |
|
|
310 | // a Python reference to the owner object. Taking GIL makes | |
313 |
|
|
311 | // sure that the state is only accessed by this thread. | |
314 |
|
|
312 | let gil = Python::acquire_gil(); | |
315 |
|
|
313 | let py = gil.python(); | |
316 |
|
|
314 | unsafe { | |
317 |
|
|
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 |
/// |
|
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: |
|
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