Mercurial > hg
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]> { |