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: |
|
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, |
|
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(); | |||
|
716 | } | |||
705 | } |
|
717 | } |
General Comments 0
You need to be logged in to leave comments.
Login now