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: |
|
|
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, |
|
|
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