##// END OF EJS Templates
rust-cpython: put leaked reference in PyLeakedRef...
Yuya Nishihara -
r43578:ce6dd1ce default
parent child Browse files
Show More
@@ -13,6 +13,7 b' 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::PyLeakedRef;
15 use crate::ref_sharing::PyLeakedRef;
16 use hg::DirstateMap as RustDirstateMap;
16 use hg::{utils::hg_path::HgPathBuf, CopyMapIter};
17 use hg::{utils::hg_path::HgPathBuf, CopyMapIter};
17
18
18 py_class!(pub class CopyMap |py| {
19 py_class!(pub class CopyMap |py| {
@@ -104,7 +105,7 b' impl CopyMap {'
104
105
105 py_shared_iterator!(
106 py_shared_iterator!(
106 CopyMapKeysIterator,
107 CopyMapKeysIterator,
107 PyLeakedRef,
108 PyLeakedRef<&'static RustDirstateMap>,
108 CopyMapIter<'static>,
109 CopyMapIter<'static>,
109 CopyMap::translate_key,
110 CopyMap::translate_key,
110 Option<PyBytes>
111 Option<PyBytes>
@@ -112,7 +113,7 b' py_shared_iterator!('
112
113
113 py_shared_iterator!(
114 py_shared_iterator!(
114 CopyMapItemsIterator,
115 CopyMapItemsIterator,
115 PyLeakedRef,
116 PyLeakedRef<&'static RustDirstateMap>,
116 CopyMapIter<'static>,
117 CopyMapIter<'static>,
117 CopyMap::translate_key_value,
118 CopyMap::translate_key_value,
118 Option<(PyBytes, PyBytes)>
119 Option<(PyBytes, PyBytes)>
@@ -92,8 +92,9 b' py_class!(pub class Dirs |py| {'
92 })
92 })
93 }
93 }
94 def __iter__(&self) -> PyResult<DirsMultisetKeysIterator> {
94 def __iter__(&self) -> PyResult<DirsMultisetKeysIterator> {
95 let (leak_handle, leaked_ref) =
95 let mut leak_handle =
96 unsafe { self.inner_shared(py).leak_immutable()? };
96 unsafe { self.inner_shared(py).leak_immutable()? };
97 let leaked_ref = leak_handle.data.take().unwrap();
97 DirsMultisetKeysIterator::from_inner(
98 DirsMultisetKeysIterator::from_inner(
98 py,
99 py,
99 leak_handle,
100 leak_handle,
@@ -125,7 +126,7 b' impl Dirs {'
125
126
126 py_shared_iterator!(
127 py_shared_iterator!(
127 DirsMultisetKeysIterator,
128 DirsMultisetKeysIterator,
128 PyLeakedRef,
129 PyLeakedRef<&'static DirsMultiset>,
129 DirsMultisetIter<'static>,
130 DirsMultisetIter<'static>,
130 Dirs::translate_key,
131 Dirs::translate_key,
131 Option<PyBytes>
132 Option<PyBytes>
@@ -304,8 +304,9 b' py_class!(pub class DirstateMap |py| {'
304 }
304 }
305
305
306 def keys(&self) -> PyResult<DirstateMapKeysIterator> {
306 def keys(&self) -> PyResult<DirstateMapKeysIterator> {
307 let (leak_handle, leaked_ref) =
307 let mut leak_handle =
308 unsafe { self.inner_shared(py).leak_immutable()? };
308 unsafe { self.inner_shared(py).leak_immutable()? };
309 let leaked_ref = leak_handle.data.take().unwrap();
309 DirstateMapKeysIterator::from_inner(
310 DirstateMapKeysIterator::from_inner(
310 py,
311 py,
311 leak_handle,
312 leak_handle,
@@ -314,8 +315,9 b' py_class!(pub class DirstateMap |py| {'
314 }
315 }
315
316
316 def items(&self) -> PyResult<DirstateMapItemsIterator> {
317 def items(&self) -> PyResult<DirstateMapItemsIterator> {
317 let (leak_handle, leaked_ref) =
318 let mut leak_handle =
318 unsafe { self.inner_shared(py).leak_immutable()? };
319 unsafe { self.inner_shared(py).leak_immutable()? };
320 let leaked_ref = leak_handle.data.take().unwrap();
319 DirstateMapItemsIterator::from_inner(
321 DirstateMapItemsIterator::from_inner(
320 py,
322 py,
321 leak_handle,
323 leak_handle,
@@ -324,8 +326,9 b' py_class!(pub class DirstateMap |py| {'
324 }
326 }
325
327
326 def __iter__(&self) -> PyResult<DirstateMapKeysIterator> {
328 def __iter__(&self) -> PyResult<DirstateMapKeysIterator> {
327 let (leak_handle, leaked_ref) =
329 let mut leak_handle =
328 unsafe { self.inner_shared(py).leak_immutable()? };
330 unsafe { self.inner_shared(py).leak_immutable()? };
331 let leaked_ref = leak_handle.data.take().unwrap();
329 DirstateMapKeysIterator::from_inner(
332 DirstateMapKeysIterator::from_inner(
330 py,
333 py,
331 leak_handle,
334 leak_handle,
@@ -443,8 +446,9 b' py_class!(pub class DirstateMap |py| {'
443 }
446 }
444
447
445 def copymapiter(&self) -> PyResult<CopyMapKeysIterator> {
448 def copymapiter(&self) -> PyResult<CopyMapKeysIterator> {
446 let (leak_handle, leaked_ref) =
449 let mut leak_handle =
447 unsafe { self.inner_shared(py).leak_immutable()? };
450 unsafe { self.inner_shared(py).leak_immutable()? };
451 let leaked_ref = leak_handle.data.take().unwrap();
448 CopyMapKeysIterator::from_inner(
452 CopyMapKeysIterator::from_inner(
449 py,
453 py,
450 leak_handle,
454 leak_handle,
@@ -453,8 +457,9 b' py_class!(pub class DirstateMap |py| {'
453 }
457 }
454
458
455 def copymapitemsiter(&self) -> PyResult<CopyMapItemsIterator> {
459 def copymapitemsiter(&self) -> PyResult<CopyMapItemsIterator> {
456 let (leak_handle, leaked_ref) =
460 let mut leak_handle =
457 unsafe { self.inner_shared(py).leak_immutable()? };
461 unsafe { self.inner_shared(py).leak_immutable()? };
462 let leaked_ref = leak_handle.data.take().unwrap();
458 CopyMapItemsIterator::from_inner(
463 CopyMapItemsIterator::from_inner(
459 py,
464 py,
460 leak_handle,
465 leak_handle,
@@ -493,7 +498,7 b' py_shared_ref!(DirstateMap, RustDirstate'
493
498
494 py_shared_iterator!(
499 py_shared_iterator!(
495 DirstateMapKeysIterator,
500 DirstateMapKeysIterator,
496 PyLeakedRef,
501 PyLeakedRef<&'static RustDirstateMap>,
497 StateMapIter<'static>,
502 StateMapIter<'static>,
498 DirstateMap::translate_key,
503 DirstateMap::translate_key,
499 Option<PyBytes>
504 Option<PyBytes>
@@ -501,7 +506,7 b' py_shared_iterator!('
501
506
502 py_shared_iterator!(
507 py_shared_iterator!(
503 DirstateMapItemsIterator,
508 DirstateMapItemsIterator,
504 PyLeakedRef,
509 PyLeakedRef<&'static RustDirstateMap>,
505 StateMapIter<'static>,
510 StateMapIter<'static>,
506 DirstateMap::translate_key_value,
511 DirstateMap::translate_key_value,
507 Option<(PyBytes, PyObject)>
512 Option<(PyBytes, PyObject)>
@@ -187,23 +187,24 b" impl<'a, T> PySharedRef<'a, T> {"
187 self.data.borrow_mut(self.py)
187 self.data.borrow_mut(self.py)
188 }
188 }
189
189
190 /// Returns a leaked reference and its management object.
190 /// Returns a leaked reference temporarily held by its management object.
191 ///
191 ///
192 /// # Safety
192 /// # Safety
193 ///
193 ///
194 /// It's up to you to make sure that the management object lives
194 /// It's up to you to make sure that the management object lives
195 /// longer than the leaked reference. Otherwise, you'll get a
195 /// longer than the leaked reference. Otherwise, you'll get a
196 /// dangling reference.
196 /// dangling reference.
197 pub unsafe fn leak_immutable(
197 pub unsafe fn leak_immutable(&self) -> PyResult<PyLeakedRef<&'static T>> {
198 &self,
199 ) -> PyResult<(PyLeakedRef, &'static T)> {
200 let (static_ref, static_state_ref) = self
198 let (static_ref, static_state_ref) = self
201 .data
199 .data
202 .py_shared_state
200 .py_shared_state
203 .leak_immutable(self.py, self.data)?;
201 .leak_immutable(self.py, self.data)?;
204 let leak_handle =
202 Ok(PyLeakedRef::new(
205 PyLeakedRef::new(self.py, self.owner, static_state_ref);
203 self.py,
206 Ok((leak_handle, static_ref))
204 self.owner,
205 static_ref,
206 static_state_ref,
207 ))
207 }
208 }
208 }
209 }
209
210
@@ -318,12 +319,13 b' macro_rules! py_shared_ref {'
318 ///
319 ///
319 /// In truth, this does not represent leaked references themselves;
320 /// In truth, this does not represent leaked references themselves;
320 /// it is instead useful alongside them to manage them.
321 /// it is instead useful alongside them to manage them.
321 pub struct PyLeakedRef {
322 pub struct PyLeakedRef<T> {
322 _inner: PyObject,
323 _inner: PyObject,
324 pub data: Option<T>, // TODO: remove pub
323 py_shared_state: &'static PySharedState,
325 py_shared_state: &'static PySharedState,
324 }
326 }
325
327
326 impl PyLeakedRef {
328 impl<T> PyLeakedRef<T> {
327 /// # Safety
329 /// # Safety
328 ///
330 ///
329 /// The `py_shared_state` must be owned by the `inner` Python object.
331 /// The `py_shared_state` must be owned by the `inner` Python object.
@@ -332,16 +334,18 b' impl PyLeakedRef {'
332 pub unsafe fn new(
334 pub unsafe fn new(
333 py: Python,
335 py: Python,
334 inner: &PyObject,
336 inner: &PyObject,
337 data: T,
335 py_shared_state: &'static PySharedState,
338 py_shared_state: &'static PySharedState,
336 ) -> Self {
339 ) -> Self {
337 Self {
340 Self {
338 _inner: inner.clone_ref(py),
341 _inner: inner.clone_ref(py),
342 data: Some(data),
339 py_shared_state,
343 py_shared_state,
340 }
344 }
341 }
345 }
342 }
346 }
343
347
344 impl Drop for PyLeakedRef {
348 impl<T> Drop for PyLeakedRef<T> {
345 fn drop(&mut self) {
349 fn drop(&mut self) {
346 // py_shared_state should be alive since we do have
350 // py_shared_state should be alive since we do have
347 // a Python reference to the owner object. Taking GIL makes
351 // a Python reference to the owner object. Taking GIL makes
@@ -379,8 +383,9 b' impl Drop for PyLeakedRef {'
379 /// data inner: PySharedRefCell<MyStruct>;
383 /// data inner: PySharedRefCell<MyStruct>;
380 ///
384 ///
381 /// def __iter__(&self) -> PyResult<MyTypeItemsIterator> {
385 /// def __iter__(&self) -> PyResult<MyTypeItemsIterator> {
382 /// let (leak_handle, leaked_ref) =
386 /// let mut leak_handle =
383 /// unsafe { self.inner_shared(py).leak_immutable()? };
387 /// unsafe { self.inner_shared(py).leak_immutable()? };
388 /// let leaked_ref = leak_handle.data.take().unwrap();
384 /// MyTypeItemsIterator::from_inner(
389 /// MyTypeItemsIterator::from_inner(
385 /// py,
390 /// py,
386 /// leak_handle,
391 /// leak_handle,
@@ -406,7 +411,7 b' impl Drop for PyLeakedRef {'
406 ///
411 ///
407 /// py_shared_iterator!(
412 /// py_shared_iterator!(
408 /// MyTypeItemsIterator,
413 /// MyTypeItemsIterator,
409 /// PyLeakedRef,
414 /// PyLeakedRef<&'static MyStruct>,
410 /// HashMap<'static, Vec<u8>, Vec<u8>>,
415 /// HashMap<'static, Vec<u8>, Vec<u8>>,
411 /// MyType::translate_key_value,
416 /// MyType::translate_key_value,
412 /// Option<(PyBytes, PyBytes)>
417 /// Option<(PyBytes, PyBytes)>
General Comments 0
You need to be logged in to leave comments. Login now