Show More
@@ -12,7 +12,7 b' use cpython::{PyBytes, PyClone, PyDict, ' | |||||
12 | use std::cell::RefCell; |
|
12 | use std::cell::RefCell; | |
13 |
|
13 | |||
14 | use crate::dirstate::dirstate_map::DirstateMap; |
|
14 | use crate::dirstate::dirstate_map::DirstateMap; | |
15 |
use crate::ref_sharing::PyLeaked |
|
15 | use crate::ref_sharing::PyLeaked; | |
16 | use hg::{utils::hg_path::HgPathBuf, CopyMapIter}; |
|
16 | use hg::{utils::hg_path::HgPathBuf, CopyMapIter}; | |
17 |
|
17 | |||
18 | py_class!(pub class CopyMap |py| { |
|
18 | py_class!(pub class CopyMap |py| { | |
@@ -104,14 +104,14 b' impl CopyMap {' | |||||
104 |
|
104 | |||
105 | py_shared_iterator!( |
|
105 | py_shared_iterator!( | |
106 | CopyMapKeysIterator, |
|
106 | CopyMapKeysIterator, | |
107 |
PyLeaked |
|
107 | PyLeaked<CopyMapIter<'static>>, | |
108 | CopyMap::translate_key, |
|
108 | CopyMap::translate_key, | |
109 | Option<PyBytes> |
|
109 | Option<PyBytes> | |
110 | ); |
|
110 | ); | |
111 |
|
111 | |||
112 | py_shared_iterator!( |
|
112 | py_shared_iterator!( | |
113 | CopyMapItemsIterator, |
|
113 | CopyMapItemsIterator, | |
114 |
PyLeaked |
|
114 | PyLeaked<CopyMapIter<'static>>, | |
115 | CopyMap::translate_key_value, |
|
115 | CopyMap::translate_key_value, | |
116 | Option<(PyBytes, PyBytes)> |
|
116 | Option<(PyBytes, PyBytes)> | |
117 | ); |
|
117 | ); |
@@ -17,7 +17,7 b' use cpython::{' | |||||
17 | }; |
|
17 | }; | |
18 |
|
18 | |||
19 | use crate::dirstate::extract_dirstate; |
|
19 | use crate::dirstate::extract_dirstate; | |
20 |
use crate::ref_sharing::{PyLeaked |
|
20 | use crate::ref_sharing::{PyLeaked, PySharedRefCell}; | |
21 | use hg::{ |
|
21 | use hg::{ | |
22 | utils::hg_path::{HgPath, HgPathBuf}, |
|
22 | utils::hg_path::{HgPath, HgPathBuf}, | |
23 | DirsMultiset, DirsMultisetIter, DirstateMapError, DirstateParseError, |
|
23 | DirsMultiset, DirsMultisetIter, DirstateMapError, DirstateParseError, | |
@@ -123,7 +123,7 b' impl Dirs {' | |||||
123 |
|
123 | |||
124 | py_shared_iterator!( |
|
124 | py_shared_iterator!( | |
125 | DirsMultisetKeysIterator, |
|
125 | DirsMultisetKeysIterator, | |
126 |
PyLeaked |
|
126 | PyLeaked<DirsMultisetIter<'static>>, | |
127 | Dirs::translate_key, |
|
127 | Dirs::translate_key, | |
128 | Option<PyBytes> |
|
128 | Option<PyBytes> | |
129 | ); |
|
129 | ); |
@@ -20,7 +20,7 b' use cpython::{' | |||||
20 | use crate::{ |
|
20 | use crate::{ | |
21 | dirstate::copymap::{CopyMap, CopyMapItemsIterator, CopyMapKeysIterator}, |
|
21 | dirstate::copymap::{CopyMap, CopyMapItemsIterator, CopyMapKeysIterator}, | |
22 | dirstate::{dirs_multiset::Dirs, make_dirstate_tuple}, |
|
22 | dirstate::{dirs_multiset::Dirs, make_dirstate_tuple}, | |
23 |
ref_sharing::{PyLeaked |
|
23 | ref_sharing::{PyLeaked, PySharedRefCell}, | |
24 | }; |
|
24 | }; | |
25 | use hg::{ |
|
25 | use hg::{ | |
26 | utils::hg_path::{HgPath, HgPathBuf}, |
|
26 | utils::hg_path::{HgPath, HgPathBuf}, | |
@@ -483,14 +483,14 b' py_shared_ref!(DirstateMap, RustDirstate' | |||||
483 |
|
483 | |||
484 | py_shared_iterator!( |
|
484 | py_shared_iterator!( | |
485 | DirstateMapKeysIterator, |
|
485 | DirstateMapKeysIterator, | |
486 |
PyLeaked |
|
486 | PyLeaked<StateMapIter<'static>>, | |
487 | DirstateMap::translate_key, |
|
487 | DirstateMap::translate_key, | |
488 | Option<PyBytes> |
|
488 | Option<PyBytes> | |
489 | ); |
|
489 | ); | |
490 |
|
490 | |||
491 | py_shared_iterator!( |
|
491 | py_shared_iterator!( | |
492 | DirstateMapItemsIterator, |
|
492 | DirstateMapItemsIterator, | |
493 |
PyLeaked |
|
493 | PyLeaked<StateMapIter<'static>>, | |
494 | DirstateMap::translate_key_value, |
|
494 | DirstateMap::translate_key_value, | |
495 | Option<(PyBytes, PyObject)> |
|
495 | Option<(PyBytes, PyObject)> | |
496 | ); |
|
496 | ); |
@@ -186,12 +186,12 b" impl<'a, T> PySharedRef<'a, T> {" | |||||
186 | } |
|
186 | } | |
187 |
|
187 | |||
188 | /// Returns a leaked reference. |
|
188 | /// Returns a leaked reference. | |
189 |
pub fn leak_immutable(&self) -> PyResult<PyLeaked |
|
189 | pub fn leak_immutable(&self) -> PyResult<PyLeaked<&'static T>> { | |
190 | let state = &self.data.py_shared_state; |
|
190 | let state = &self.data.py_shared_state; | |
191 | unsafe { |
|
191 | unsafe { | |
192 | let (static_ref, static_state_ref) = |
|
192 | let (static_ref, static_state_ref) = | |
193 | state.leak_immutable(self.py, self.data)?; |
|
193 | state.leak_immutable(self.py, self.data)?; | |
194 |
Ok(PyLeaked |
|
194 | Ok(PyLeaked::new( | |
195 | self.py, |
|
195 | self.py, | |
196 | self.owner, |
|
196 | self.owner, | |
197 | static_ref, |
|
197 | static_ref, | |
@@ -307,16 +307,16 b' macro_rules! py_shared_ref {' | |||||
307 | } |
|
307 | } | |
308 |
|
308 | |||
309 | /// Manage immutable references to `PyObject` leaked into Python iterators. |
|
309 | /// Manage immutable references to `PyObject` leaked into Python iterators. | |
310 |
pub struct PyLeaked |
|
310 | pub struct PyLeaked<T> { | |
311 | inner: PyObject, |
|
311 | inner: PyObject, | |
312 | data: Option<T>, |
|
312 | data: Option<T>, | |
313 | py_shared_state: &'static PySharedState, |
|
313 | py_shared_state: &'static PySharedState, | |
314 | } |
|
314 | } | |
315 |
|
315 | |||
316 |
// DO NOT implement Deref for PyLeaked |
|
316 | // DO NOT implement Deref for PyLeaked<T>! Dereferencing PyLeaked | |
317 | // without taking Python GIL wouldn't be safe. |
|
317 | // without taking Python GIL wouldn't be safe. | |
318 |
|
318 | |||
319 |
impl<T> PyLeaked |
|
319 | impl<T> PyLeaked<T> { | |
320 | /// # Safety |
|
320 | /// # Safety | |
321 | /// |
|
321 | /// | |
322 | /// The `py_shared_state` must be owned by the `inner` Python object. |
|
322 | /// The `py_shared_state` must be owned by the `inner` Python object. | |
@@ -355,19 +355,19 b' impl<T> PyLeakedRef<T> {' | |||||
355 | /// |
|
355 | /// | |
356 | /// The lifetime of the object passed in to the function `f` is cheated. |
|
356 | /// The lifetime of the object passed in to the function `f` is cheated. | |
357 | /// It's typically a static reference, but is valid only while the |
|
357 | /// It's typically a static reference, but is valid only while the | |
358 |
/// corresponding `PyLeaked |
|
358 | /// corresponding `PyLeaked` is alive. Do not copy it out of the | |
359 | /// function call. |
|
359 | /// function call. | |
360 | pub unsafe fn map<U>( |
|
360 | pub unsafe fn map<U>( | |
361 | mut self, |
|
361 | mut self, | |
362 | py: Python, |
|
362 | py: Python, | |
363 | f: impl FnOnce(T) -> U, |
|
363 | f: impl FnOnce(T) -> U, | |
364 |
) -> PyLeaked |
|
364 | ) -> PyLeaked<U> { | |
365 | // f() could make the self.data outlive. That's why map() is unsafe. |
|
365 | // f() could make the self.data outlive. That's why map() is unsafe. | |
366 | // In order to make this function safe, maybe we'll need a way to |
|
366 | // In order to make this function safe, maybe we'll need a way to | |
367 | // temporarily restrict the lifetime of self.data and translate the |
|
367 | // temporarily restrict the lifetime of self.data and translate the | |
368 | // returned object back to Something<'static>. |
|
368 | // returned object back to Something<'static>. | |
369 | let new_data = f(self.data.take().unwrap()); |
|
369 | let new_data = f(self.data.take().unwrap()); | |
370 |
PyLeaked |
|
370 | PyLeaked { | |
371 | inner: self.inner.clone_ref(py), |
|
371 | inner: self.inner.clone_ref(py), | |
372 | data: Some(new_data), |
|
372 | data: Some(new_data), | |
373 | py_shared_state: self.py_shared_state, |
|
373 | py_shared_state: self.py_shared_state, | |
@@ -375,7 +375,7 b' impl<T> PyLeakedRef<T> {' | |||||
375 | } |
|
375 | } | |
376 | } |
|
376 | } | |
377 |
|
377 | |||
378 |
impl<T> Drop for PyLeaked |
|
378 | impl<T> Drop for PyLeaked<T> { | |
379 | fn drop(&mut self) { |
|
379 | fn drop(&mut self) { | |
380 | // py_shared_state should be alive since we do have |
|
380 | // py_shared_state should be alive since we do have | |
381 | // a Python reference to the owner object. Taking GIL makes |
|
381 | // a Python reference to the owner object. Taking GIL makes | |
@@ -383,7 +383,7 b' impl<T> Drop for PyLeakedRef<T> {' | |||||
383 | let gil = Python::acquire_gil(); |
|
383 | let gil = Python::acquire_gil(); | |
384 | let py = gil.python(); |
|
384 | let py = gil.python(); | |
385 | if self.data.is_none() { |
|
385 | if self.data.is_none() { | |
386 |
return; // moved to another PyLeaked |
|
386 | return; // moved to another PyLeaked | |
387 | } |
|
387 | } | |
388 | self.py_shared_state.decrease_leak_count(py, false); |
|
388 | self.py_shared_state.decrease_leak_count(py, false); | |
389 | } |
|
389 | } | |
@@ -439,7 +439,7 b' impl<T> Drop for PyLeakedRef<T> {' | |||||
439 | /// |
|
439 | /// | |
440 | /// py_shared_iterator!( |
|
440 | /// py_shared_iterator!( | |
441 | /// MyTypeItemsIterator, |
|
441 | /// MyTypeItemsIterator, | |
442 |
/// PyLeaked |
|
442 | /// PyLeaked<HashMap<'static, Vec<u8>, Vec<u8>>>, | |
443 | /// MyType::translate_key_value, |
|
443 | /// MyType::translate_key_value, | |
444 | /// Option<(PyBytes, PyBytes)> |
|
444 | /// Option<(PyBytes, PyBytes)> | |
445 | /// ); |
|
445 | /// ); |
General Comments 0
You need to be logged in to leave comments.
Login now