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