comparison rust/hg-cpython/src/dirstate/dirstate_map.rs @ 43285:ffc1fbd7d1f5

rust-cpython: make PyLeakedRef operations relatively safe This patch encapsulates the access to the leaked reference to make most leaked-ref operations safe. The only exception is leaked_ref.map(). I couldn't figure out how to allow arbitrary map operation safely over an unsafe static reference. See the docstring and inline comment for details. Now leak_immutable() can be safely implemented as the PyLeakedRef owns its inner data.
author Yuya Nishihara <yuya@tcha.org>
date Sun, 15 Sep 2019 22:19:10 +0900
parents ce6dd1cee4c8
children f8c114f20d2d
comparison
equal deleted inserted replaced
43284:ce6dd1cee4c8 43285:ffc1fbd7d1f5
302 )), 302 )),
303 } 303 }
304 } 304 }
305 305
306 def keys(&self) -> PyResult<DirstateMapKeysIterator> { 306 def keys(&self) -> PyResult<DirstateMapKeysIterator> {
307 let mut leak_handle = 307 let leaked_ref = self.inner_shared(py).leak_immutable()?;
308 unsafe { self.inner_shared(py).leak_immutable()? };
309 let leaked_ref = leak_handle.data.take().unwrap();
310 DirstateMapKeysIterator::from_inner( 308 DirstateMapKeysIterator::from_inner(
311 py, 309 py,
312 leak_handle, 310 unsafe { leaked_ref.map(py, |o| o.iter()) },
313 leaked_ref.iter(),
314 ) 311 )
315 } 312 }
316 313
317 def items(&self) -> PyResult<DirstateMapItemsIterator> { 314 def items(&self) -> PyResult<DirstateMapItemsIterator> {
318 let mut leak_handle = 315 let leaked_ref = self.inner_shared(py).leak_immutable()?;
319 unsafe { self.inner_shared(py).leak_immutable()? };
320 let leaked_ref = leak_handle.data.take().unwrap();
321 DirstateMapItemsIterator::from_inner( 316 DirstateMapItemsIterator::from_inner(
322 py, 317 py,
323 leak_handle, 318 unsafe { leaked_ref.map(py, |o| o.iter()) },
324 leaked_ref.iter(),
325 ) 319 )
326 } 320 }
327 321
328 def __iter__(&self) -> PyResult<DirstateMapKeysIterator> { 322 def __iter__(&self) -> PyResult<DirstateMapKeysIterator> {
329 let mut leak_handle = 323 let leaked_ref = self.inner_shared(py).leak_immutable()?;
330 unsafe { self.inner_shared(py).leak_immutable()? };
331 let leaked_ref = leak_handle.data.take().unwrap();
332 DirstateMapKeysIterator::from_inner( 324 DirstateMapKeysIterator::from_inner(
333 py, 325 py,
334 leak_handle, 326 unsafe { leaked_ref.map(py, |o| o.iter()) },
335 leaked_ref.iter(),
336 ) 327 )
337 } 328 }
338 329
339 def getdirs(&self) -> PyResult<Dirs> { 330 def getdirs(&self) -> PyResult<Dirs> {
340 // TODO don't copy, share the reference 331 // TODO don't copy, share the reference
444 None => Ok(default), 435 None => Ok(default),
445 } 436 }
446 } 437 }
447 438
448 def copymapiter(&self) -> PyResult<CopyMapKeysIterator> { 439 def copymapiter(&self) -> PyResult<CopyMapKeysIterator> {
449 let mut leak_handle = 440 let leaked_ref = self.inner_shared(py).leak_immutable()?;
450 unsafe { self.inner_shared(py).leak_immutable()? };
451 let leaked_ref = leak_handle.data.take().unwrap();
452 CopyMapKeysIterator::from_inner( 441 CopyMapKeysIterator::from_inner(
453 py, 442 py,
454 leak_handle, 443 unsafe { leaked_ref.map(py, |o| o.copy_map.iter()) },
455 leaked_ref.copy_map.iter(),
456 ) 444 )
457 } 445 }
458 446
459 def copymapitemsiter(&self) -> PyResult<CopyMapItemsIterator> { 447 def copymapitemsiter(&self) -> PyResult<CopyMapItemsIterator> {
460 let mut leak_handle = 448 let leaked_ref = self.inner_shared(py).leak_immutable()?;
461 unsafe { self.inner_shared(py).leak_immutable()? };
462 let leaked_ref = leak_handle.data.take().unwrap();
463 CopyMapItemsIterator::from_inner( 449 CopyMapItemsIterator::from_inner(
464 py, 450 py,
465 leak_handle, 451 unsafe { leaked_ref.map(py, |o| o.copy_map.iter()) },
466 leaked_ref.copy_map.iter(),
467 ) 452 )
468 } 453 }
469 454
470 }); 455 });
471 456
496 481
497 py_shared_ref!(DirstateMap, RustDirstateMap, inner, inner_shared); 482 py_shared_ref!(DirstateMap, RustDirstateMap, inner, inner_shared);
498 483
499 py_shared_iterator!( 484 py_shared_iterator!(
500 DirstateMapKeysIterator, 485 DirstateMapKeysIterator,
501 PyLeakedRef<&'static RustDirstateMap>, 486 PyLeakedRef<StateMapIter<'static>>,
502 StateMapIter<'static>,
503 DirstateMap::translate_key, 487 DirstateMap::translate_key,
504 Option<PyBytes> 488 Option<PyBytes>
505 ); 489 );
506 490
507 py_shared_iterator!( 491 py_shared_iterator!(
508 DirstateMapItemsIterator, 492 DirstateMapItemsIterator,
509 PyLeakedRef<&'static RustDirstateMap>, 493 PyLeakedRef<StateMapIter<'static>>,
510 StateMapIter<'static>,
511 DirstateMap::translate_key_value, 494 DirstateMap::translate_key_value,
512 Option<(PyBytes, PyObject)> 495 Option<(PyBytes, PyObject)>
513 ); 496 );
514 497
515 fn extract_node_id(py: Python, obj: &PyObject) -> PyResult<[u8; PARENT_SIZE]> { 498 fn extract_node_id(py: Python, obj: &PyObject) -> PyResult<[u8; PARENT_SIZE]> {