Mercurial > public > mercurial-scm > hg
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> { |