comparison rust/hg-cpython/src/ref_sharing.rs @ 44203:2a24ead003f0

rust-cpython: add panicking version of borrow_mut() and use it The original borrow_mut() is renamed to try_borrow_mut(). Since leak_immutable() no longer incref the borrow count, the caller should know if the underlying value is borrowed or not. No Python world is involved. That's why we can simply use the panicking borrow_mut().
author Yuya Nishihara <yuya@tcha.org>
date Sat, 12 Oct 2019 23:34:05 +0900
parents 4a4c3b9fd91b
children bafdaf4858d8
comparison
equal deleted inserted replaced
44202:a7f8160cc4e4 44203:2a24ead003f0
200 200
201 pub fn borrow(&self) -> Ref<'a, T> { 201 pub fn borrow(&self) -> Ref<'a, T> {
202 self.data.borrow(self.py) 202 self.data.borrow(self.py)
203 } 203 }
204 204
205 pub fn borrow_mut(&self) -> PyResult<RefMut<'a, T>> { 205 /// Mutably borrows the wrapped value.
206 ///
207 /// # Panics
208 ///
209 /// Panics if the value is currently borrowed through `PySharedRef`
210 /// or `PyLeaked`.
211 pub fn borrow_mut(&self) -> RefMut<'a, T> {
212 self.try_borrow_mut().expect("already borrowed")
213 }
214
215 /// Mutably borrows the wrapped value, returning an error if the value
216 /// is currently borrowed.
217 pub fn try_borrow_mut(&self) -> PyResult<RefMut<'a, T>> {
206 self.data.try_borrow_mut(self.py) 218 self.data.try_borrow_mut(self.py)
207 } 219 }
208 220
209 /// Returns a leaked reference. 221 /// Returns a leaked reference.
210 /// 222 ///
570 #[test] 582 #[test]
571 fn test_leaked_borrow_after_mut() { 583 fn test_leaked_borrow_after_mut() {
572 let (gil, owner) = prepare_env(); 584 let (gil, owner) = prepare_env();
573 let py = gil.python(); 585 let py = gil.python();
574 let leaked = owner.string_shared(py).leak_immutable(); 586 let leaked = owner.string_shared(py).leak_immutable();
575 owner.string_shared(py).borrow_mut().unwrap().clear(); 587 owner.string_shared(py).borrow_mut().clear();
576 assert!(leaked.try_borrow(py).is_err()); 588 assert!(leaked.try_borrow(py).is_err());
577 } 589 }
578 590
579 #[test] 591 #[test]
580 fn test_leaked_borrow_mut_after_mut() { 592 fn test_leaked_borrow_mut_after_mut() {
581 let (gil, owner) = prepare_env(); 593 let (gil, owner) = prepare_env();
582 let py = gil.python(); 594 let py = gil.python();
583 let leaked = owner.string_shared(py).leak_immutable(); 595 let leaked = owner.string_shared(py).leak_immutable();
584 let mut leaked_iter = unsafe { leaked.map(py, |s| s.chars()) }; 596 let mut leaked_iter = unsafe { leaked.map(py, |s| s.chars()) };
585 owner.string_shared(py).borrow_mut().unwrap().clear(); 597 owner.string_shared(py).borrow_mut().clear();
586 assert!(leaked_iter.try_borrow_mut(py).is_err()); 598 assert!(leaked_iter.try_borrow_mut(py).is_err());
587 } 599 }
588 600
589 #[test] 601 #[test]
590 #[should_panic(expected = "map() over invalidated leaked reference")] 602 #[should_panic(expected = "map() over invalidated leaked reference")]
591 fn test_leaked_map_after_mut() { 603 fn test_leaked_map_after_mut() {
592 let (gil, owner) = prepare_env(); 604 let (gil, owner) = prepare_env();
593 let py = gil.python(); 605 let py = gil.python();
594 let leaked = owner.string_shared(py).leak_immutable(); 606 let leaked = owner.string_shared(py).leak_immutable();
595 owner.string_shared(py).borrow_mut().unwrap().clear(); 607 owner.string_shared(py).borrow_mut().clear();
596 let _leaked_iter = unsafe { leaked.map(py, |s| s.chars()) }; 608 let _leaked_iter = unsafe { leaked.map(py, |s| s.chars()) };
597 } 609 }
598 610
599 #[test] 611 #[test]
600 fn test_borrow_mut_while_leaked_ref() { 612 fn test_try_borrow_mut_while_leaked_ref() {
601 let (gil, owner) = prepare_env(); 613 let (gil, owner) = prepare_env();
602 let py = gil.python(); 614 let py = gil.python();
603 assert!(owner.string_shared(py).borrow_mut().is_ok()); 615 assert!(owner.string_shared(py).try_borrow_mut().is_ok());
604 let leaked = owner.string_shared(py).leak_immutable(); 616 let leaked = owner.string_shared(py).leak_immutable();
605 { 617 {
606 let _leaked_ref = leaked.try_borrow(py).unwrap(); 618 let _leaked_ref = leaked.try_borrow(py).unwrap();
607 assert!(owner.string_shared(py).borrow_mut().is_err()); 619 assert!(owner.string_shared(py).try_borrow_mut().is_err());
608 { 620 {
609 let _leaked_ref2 = leaked.try_borrow(py).unwrap(); 621 let _leaked_ref2 = leaked.try_borrow(py).unwrap();
610 assert!(owner.string_shared(py).borrow_mut().is_err()); 622 assert!(owner.string_shared(py).try_borrow_mut().is_err());
611 } 623 }
612 assert!(owner.string_shared(py).borrow_mut().is_err()); 624 assert!(owner.string_shared(py).try_borrow_mut().is_err());
613 } 625 }
614 assert!(owner.string_shared(py).borrow_mut().is_ok()); 626 assert!(owner.string_shared(py).try_borrow_mut().is_ok());
615 } 627 }
616 628
617 #[test] 629 #[test]
618 fn test_borrow_mut_while_leaked_ref_mut() { 630 fn test_try_borrow_mut_while_leaked_ref_mut() {
619 let (gil, owner) = prepare_env(); 631 let (gil, owner) = prepare_env();
620 let py = gil.python(); 632 let py = gil.python();
621 assert!(owner.string_shared(py).borrow_mut().is_ok()); 633 assert!(owner.string_shared(py).try_borrow_mut().is_ok());
622 let leaked = owner.string_shared(py).leak_immutable(); 634 let leaked = owner.string_shared(py).leak_immutable();
623 let mut leaked_iter = unsafe { leaked.map(py, |s| s.chars()) }; 635 let mut leaked_iter = unsafe { leaked.map(py, |s| s.chars()) };
624 { 636 {
625 let _leaked_ref = leaked_iter.try_borrow_mut(py).unwrap(); 637 let _leaked_ref = leaked_iter.try_borrow_mut(py).unwrap();
626 assert!(owner.string_shared(py).borrow_mut().is_err()); 638 assert!(owner.string_shared(py).try_borrow_mut().is_err());
627 } 639 }
628 assert!(owner.string_shared(py).borrow_mut().is_ok()); 640 assert!(owner.string_shared(py).try_borrow_mut().is_ok());
629 } 641 }
630 642
631 #[test] 643 #[test]
632 #[should_panic(expected = "mutably borrowed")] 644 #[should_panic(expected = "mutably borrowed")]
633 fn test_leak_while_borrow_mut() { 645 fn test_leak_while_borrow_mut() {
636 let _mut_ref = owner.string_shared(py).borrow_mut(); 648 let _mut_ref = owner.string_shared(py).borrow_mut();
637 owner.string_shared(py).leak_immutable(); 649 owner.string_shared(py).leak_immutable();
638 } 650 }
639 651
640 #[test] 652 #[test]
653 fn test_try_borrow_mut_while_borrow() {
654 let (gil, owner) = prepare_env();
655 let py = gil.python();
656 let _ref = owner.string_shared(py).borrow();
657 assert!(owner.string_shared(py).try_borrow_mut().is_err());
658 }
659
660 #[test]
661 #[should_panic(expected = "already borrowed")]
641 fn test_borrow_mut_while_borrow() { 662 fn test_borrow_mut_while_borrow() {
642 let (gil, owner) = prepare_env(); 663 let (gil, owner) = prepare_env();
643 let py = gil.python(); 664 let py = gil.python();
644 let _ref = owner.string_shared(py).borrow(); 665 let _ref = owner.string_shared(py).borrow();
645 assert!(owner.string_shared(py).borrow_mut().is_err()); 666 owner.string_shared(py).borrow_mut();
646 } 667 }
647 } 668 }