##// END OF EJS Templates
rust-cpython: leverage RefCell::borrow() to guarantee there's no mutable ref...
Yuya Nishihara -
r43608:b7ab3a0a default
parent child Browse files
Show More
@@ -38,6 +38,8 b' use std::sync::atomic::{AtomicUsize, Ord'
38 38 /// `PySharedRefCell` is allowed only through its `borrow_mut()`.
39 39 /// - The `py: Python<'_>` token, which makes sure that any data access is
40 40 /// synchronized by the GIL.
41 /// - The underlying `RefCell`, which prevents `PySharedRefCell` data from
42 /// being directly borrowed or leaked while it is mutably borrowed.
41 43 /// - The `borrow_count`, which is the number of references borrowed from
42 44 /// `PyLeaked`. Just like `RefCell`, mutation is prohibited while `PyLeaked`
43 45 /// is borrowed.
@@ -99,7 +101,7 b' impl PySharedState {'
99 101 unsafe fn leak_immutable<T>(
100 102 &self,
101 103 py: Python,
102 data: &PySharedRefCell<T>,
104 data: Ref<T>,
103 105 ) -> PyResult<(&'static T, &'static PySharedState)> {
104 106 if self.mutably_borrowed.get() {
105 107 return Err(AlreadyBorrowed::new(
@@ -108,10 +110,8 b' impl PySharedState {'
108 110 mutable reference in Python objects",
109 111 ));
110 112 }
111 // TODO: it's weird that self is data.py_shared_state. Maybe we
112 // can move stuff to PySharedRefCell?
113 let ptr = data.as_ptr();
114 let state_ptr: *const PySharedState = &data.py_shared_state;
113 let ptr: *const T = &*data;
114 let state_ptr: *const PySharedState = self;
115 115 Ok((&*ptr, &*state_ptr))
116 116 }
117 117
@@ -200,10 +200,6 b' impl<T> PySharedRefCell<T> {'
200 200 self.inner.borrow()
201 201 }
202 202
203 fn as_ptr(&self) -> *mut T {
204 self.inner.as_ptr()
205 }
206
207 203 // TODO: maybe this should be named as try_borrow_mut(), and use
208 204 // inner.try_borrow_mut(). The current implementation panics if
209 205 // self.inner has been borrowed, but returns error if py_shared_state
@@ -242,11 +238,18 b" impl<'a, T> PySharedRef<'a, T> {"
242 238 }
243 239
244 240 /// Returns a leaked reference.
241 ///
242 /// # Panics
243 ///
244 /// Panics if this is mutably borrowed.
245 245 pub fn leak_immutable(&self) -> PyResult<PyLeaked<&'static T>> {
246 246 let state = &self.data.py_shared_state;
247 // make sure self.data isn't mutably borrowed; otherwise the
248 // generation number can't be trusted.
249 let data_ref = self.borrow();
247 250 unsafe {
248 251 let (static_ref, static_state_ref) =
249 state.leak_immutable(self.py, self.data)?;
252 state.leak_immutable(self.py, data_ref)?;
250 253 Ok(PyLeaked::new(
251 254 self.py,
252 255 self.owner,
@@ -702,4 +705,13 b' mod test {'
702 705 }
703 706 assert!(owner.string_shared(py).borrow_mut().is_ok());
704 707 }
708
709 #[test]
710 #[should_panic(expected = "mutably borrowed")]
711 fn test_leak_while_borrow_mut() {
712 let (gil, owner) = prepare_env();
713 let py = gil.python();
714 let _mut_ref = owner.string_shared(py).borrow_mut();
715 let _ = owner.string_shared(py).leak_immutable();
716 }
705 717 }
General Comments 0
You need to be logged in to leave comments. Login now