##// 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 /// `PySharedRefCell` is allowed only through its `borrow_mut()`.
38 /// `PySharedRefCell` is allowed only through its `borrow_mut()`.
39 /// - The `py: Python<'_>` token, which makes sure that any data access is
39 /// - The `py: Python<'_>` token, which makes sure that any data access is
40 /// synchronized by the GIL.
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 /// - The `borrow_count`, which is the number of references borrowed from
43 /// - The `borrow_count`, which is the number of references borrowed from
42 /// `PyLeaked`. Just like `RefCell`, mutation is prohibited while `PyLeaked`
44 /// `PyLeaked`. Just like `RefCell`, mutation is prohibited while `PyLeaked`
43 /// is borrowed.
45 /// is borrowed.
@@ -99,7 +101,7 b' impl PySharedState {'
99 unsafe fn leak_immutable<T>(
101 unsafe fn leak_immutable<T>(
100 &self,
102 &self,
101 py: Python,
103 py: Python,
102 data: &PySharedRefCell<T>,
104 data: Ref<T>,
103 ) -> PyResult<(&'static T, &'static PySharedState)> {
105 ) -> PyResult<(&'static T, &'static PySharedState)> {
104 if self.mutably_borrowed.get() {
106 if self.mutably_borrowed.get() {
105 return Err(AlreadyBorrowed::new(
107 return Err(AlreadyBorrowed::new(
@@ -108,10 +110,8 b' impl PySharedState {'
108 mutable reference in Python objects",
110 mutable reference in Python objects",
109 ));
111 ));
110 }
112 }
111 // TODO: it's weird that self is data.py_shared_state. Maybe we
113 let ptr: *const T = &*data;
112 // can move stuff to PySharedRefCell?
114 let state_ptr: *const PySharedState = self;
113 let ptr = data.as_ptr();
114 let state_ptr: *const PySharedState = &data.py_shared_state;
115 Ok((&*ptr, &*state_ptr))
115 Ok((&*ptr, &*state_ptr))
116 }
116 }
117
117
@@ -200,10 +200,6 b' impl<T> PySharedRefCell<T> {'
200 self.inner.borrow()
200 self.inner.borrow()
201 }
201 }
202
202
203 fn as_ptr(&self) -> *mut T {
204 self.inner.as_ptr()
205 }
206
207 // TODO: maybe this should be named as try_borrow_mut(), and use
203 // TODO: maybe this should be named as try_borrow_mut(), and use
208 // inner.try_borrow_mut(). The current implementation panics if
204 // inner.try_borrow_mut(). The current implementation panics if
209 // self.inner has been borrowed, but returns error if py_shared_state
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 /// Returns a leaked reference.
240 /// Returns a leaked reference.
241 ///
242 /// # Panics
243 ///
244 /// Panics if this is mutably borrowed.
245 pub fn leak_immutable(&self) -> PyResult<PyLeaked<&'static T>> {
245 pub fn leak_immutable(&self) -> PyResult<PyLeaked<&'static T>> {
246 let state = &self.data.py_shared_state;
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 unsafe {
250 unsafe {
248 let (static_ref, static_state_ref) =
251 let (static_ref, static_state_ref) =
249 state.leak_immutable(self.py, self.data)?;
252 state.leak_immutable(self.py, data_ref)?;
250 Ok(PyLeaked::new(
253 Ok(PyLeaked::new(
251 self.py,
254 self.py,
252 self.owner,
255 self.owner,
@@ -702,4 +705,13 b' mod test {'
702 }
705 }
703 assert!(owner.string_shared(py).borrow_mut().is_ok());
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();
705 }
716 }
717 }
General Comments 0
You need to be logged in to leave comments. Login now