comparison rust/hg-cpython/src/ref_sharing.rs @ 44204:bafdaf4858d8

rust-cpython: inline PySharedState::try_borrow_mut() Since the core borrowing/leaking logic has been moved to PySharedRef* and PyLeaked*, it doesn't make sense that PySharedState had a function named "try_borrow_mut". Let's turn it into a pure data struct.
author Yuya Nishihara <yuya@tcha.org>
date Sat, 19 Oct 2019 16:34:02 +0900
parents 2a24ead003f0
children f015d679f08c
comparison
equal deleted inserted replaced
44203:2a24ead003f0 44204:bafdaf4858d8
55 borrow_count: AtomicUsize, 55 borrow_count: AtomicUsize,
56 generation: AtomicUsize, 56 generation: AtomicUsize,
57 } 57 }
58 58
59 impl PySharedState { 59 impl PySharedState {
60 fn try_borrow_mut<'a, T>(
61 &'a self,
62 py: Python<'a>,
63 pyrefmut: RefMut<'a, T>,
64 ) -> PyResult<RefMut<'a, T>> {
65 match self.current_borrow_count(py) {
66 0 => {
67 // Note that this wraps around to the same value if mutably
68 // borrowed more than usize::MAX times, which wouldn't happen
69 // in practice.
70 self.generation.fetch_add(1, Ordering::Relaxed);
71 Ok(pyrefmut)
72 }
73 _ => Err(AlreadyBorrowed::new(
74 py,
75 "Cannot borrow mutably while immutably borrowed",
76 )),
77 }
78 }
79
80 /// Return a reference to the wrapped data and its state with an 60 /// Return a reference to the wrapped data and its state with an
81 /// artificial static lifetime. 61 /// artificial static lifetime.
82 /// We need to be protected by the GIL for thread-safety. 62 /// We need to be protected by the GIL for thread-safety.
83 /// 63 ///
84 /// # Safety 64 /// # Safety
111 } 91 }
112 92
113 fn current_generation(&self, _py: Python) -> usize { 93 fn current_generation(&self, _py: Python) -> usize {
114 self.generation.load(Ordering::Relaxed) 94 self.generation.load(Ordering::Relaxed)
115 } 95 }
96
97 fn increment_generation(&self, py: Python) {
98 assert_eq!(self.current_borrow_count(py), 0);
99 // Note that this wraps around to the same value if mutably
100 // borrowed more than usize::MAX times, which wouldn't happen
101 // in practice.
102 self.generation.fetch_add(1, Ordering::Relaxed);
103 }
116 } 104 }
117 105
118 /// Helper to keep the borrow count updated while the shared object is 106 /// Helper to keep the borrow count updated while the shared object is
119 /// immutably borrowed without using the `RefCell` interface. 107 /// immutably borrowed without using the `RefCell` interface.
120 struct BorrowPyShared<'a> { 108 struct BorrowPyShared<'a> {
168 156
169 fn try_borrow_mut<'a>( 157 fn try_borrow_mut<'a>(
170 &'a self, 158 &'a self,
171 py: Python<'a>, 159 py: Python<'a>,
172 ) -> PyResult<RefMut<'a, T>> { 160 ) -> PyResult<RefMut<'a, T>> {
161 if self.py_shared_state.current_borrow_count(py) > 0 {
162 return Err(AlreadyBorrowed::new(
163 py,
164 "Cannot borrow mutably while immutably borrowed",
165 ));
166 }
173 let inner_ref = self 167 let inner_ref = self
174 .inner 168 .inner
175 .try_borrow_mut() 169 .try_borrow_mut()
176 .map_err(|e| AlreadyBorrowed::new(py, e.to_string()))?; 170 .map_err(|e| AlreadyBorrowed::new(py, e.to_string()))?;
177 self.py_shared_state.try_borrow_mut(py, inner_ref) 171 self.py_shared_state.increment_generation(py);
172 Ok(inner_ref)
178 } 173 }
179 } 174 }
180 175
181 /// Sharable data member of type `T` borrowed from the `PyObject`. 176 /// Sharable data member of type `T` borrowed from the `PyObject`.
182 pub struct PySharedRef<'a, T> { 177 pub struct PySharedRef<'a, T> {