Show More
@@ -24,7 +24,7 b'' | |||
|
24 | 24 | |
|
25 | 25 | use crate::exceptions::AlreadyBorrowed; |
|
26 | 26 | use cpython::{exc, PyClone, PyErr, PyObject, PyResult, Python}; |
|
27 |
use std::cell::{ |
|
|
27 | use std::cell::{Ref, RefCell, RefMut}; | |
|
28 | 28 | use std::ops::{Deref, DerefMut}; |
|
29 | 29 | use std::sync::atomic::{AtomicUsize, Ordering}; |
|
30 | 30 | |
@@ -48,7 +48,6 b' use std::sync::atomic::{AtomicUsize, Ord' | |||
|
48 | 48 | /// `generation` at the time of `leak_immutable()`. |
|
49 | 49 | #[derive(Debug, Default)] |
|
50 | 50 | struct PySharedState { |
|
51 | mutably_borrowed: Cell<bool>, | |
|
52 | 51 | // The counter variable could be Cell<usize> since any operation on |
|
53 | 52 | // PySharedState is synchronized by the GIL, but being "atomic" makes |
|
54 | 53 | // PySharedState inherently Sync. The ordering requirement doesn't |
@@ -57,26 +56,14 b' struct PySharedState {' | |||
|
57 | 56 | generation: AtomicUsize, |
|
58 | 57 | } |
|
59 | 58 | |
|
60 | // &PySharedState can be Send because any access to inner cells is | |
|
61 | // synchronized by the GIL. | |
|
62 | unsafe impl Sync for PySharedState {} | |
|
63 | ||
|
64 | 59 | impl PySharedState { |
|
65 | 60 | fn borrow_mut<'a, T>( |
|
66 | 61 | &'a self, |
|
67 | 62 | py: Python<'a>, |
|
68 | 63 | pyrefmut: RefMut<'a, T>, |
|
69 | 64 | ) -> PyResult<PyRefMut<'a, T>> { |
|
70 | if self.mutably_borrowed.get() { | |
|
71 | return Err(AlreadyBorrowed::new( | |
|
72 | py, | |
|
73 | "Cannot borrow mutably while there exists another \ | |
|
74 | mutable reference in a Python object", | |
|
75 | )); | |
|
76 | } | |
|
77 | 65 | match self.current_borrow_count(py) { |
|
78 | 66 | 0 => { |
|
79 | self.mutably_borrowed.replace(true); | |
|
80 | 67 | // Note that this wraps around to the same value if mutably |
|
81 | 68 | // borrowed more than usize::MAX times, which wouldn't happen |
|
82 | 69 | // in practice. |
@@ -100,16 +87,9 b' impl PySharedState {' | |||
|
100 | 87 | /// extended. Do not call this function directly. |
|
101 | 88 | unsafe fn leak_immutable<T>( |
|
102 | 89 | &self, |
|
103 | py: Python, | |
|
90 | _py: Python, | |
|
104 | 91 | data: Ref<T>, |
|
105 | 92 | ) -> PyResult<(&'static T, &'static PySharedState)> { |
|
106 | if self.mutably_borrowed.get() { | |
|
107 | return Err(AlreadyBorrowed::new( | |
|
108 | py, | |
|
109 | "Cannot borrow immutably while there is a \ | |
|
110 | mutable reference in Python objects", | |
|
111 | )); | |
|
112 | } | |
|
113 | 93 | let ptr: *const T = &*data; |
|
114 | 94 | let state_ptr: *const PySharedState = self; |
|
115 | 95 | Ok((&*ptr, &*state_ptr)) |
@@ -130,20 +110,6 b' impl PySharedState {' | |||
|
130 | 110 | assert!(prev_count > 0); |
|
131 | 111 | } |
|
132 | 112 | |
|
133 | /// # Safety | |
|
134 | /// | |
|
135 | /// It's up to you to make sure the reference is about to be deleted | |
|
136 | /// when updating the leak count. | |
|
137 | fn decrease_leak_count(&self, py: Python, mutable: bool) { | |
|
138 | if mutable { | |
|
139 | assert_eq!(self.current_borrow_count(py), 0); | |
|
140 | assert!(self.mutably_borrowed.get()); | |
|
141 | self.mutably_borrowed.replace(false); | |
|
142 | } else { | |
|
143 | unimplemented!(); | |
|
144 | } | |
|
145 | } | |
|
146 | ||
|
147 | 113 | fn current_generation(&self, _py: Python) -> usize { |
|
148 | 114 | self.generation.load(Ordering::Relaxed) |
|
149 | 115 | } |
@@ -262,23 +228,19 b" impl<'a, T> PySharedRef<'a, T> {" | |||
|
262 | 228 | |
|
263 | 229 | /// Holds a mutable reference to data shared between Python and Rust. |
|
264 | 230 | pub struct PyRefMut<'a, T> { |
|
265 | py: Python<'a>, | |
|
266 | 231 | inner: RefMut<'a, T>, |
|
267 | py_shared_state: &'a PySharedState, | |
|
268 | 232 | } |
|
269 | 233 | |
|
270 | 234 | impl<'a, T> PyRefMut<'a, T> { |
|
271 | 235 | // Must be constructed by PySharedState after checking its leak_count. |
|
272 | 236 | // Otherwise, drop() would incorrectly update the state. |
|
273 | 237 | fn new( |
|
274 | py: Python<'a>, | |
|
238 | _py: Python<'a>, | |
|
275 | 239 | inner: RefMut<'a, T>, |
|
276 | py_shared_state: &'a PySharedState, | |
|
240 | _py_shared_state: &'a PySharedState, | |
|
277 | 241 | ) -> Self { |
|
278 | 242 | Self { |
|
279 | py, | |
|
280 | 243 | inner, |
|
281 | py_shared_state, | |
|
282 | 244 | } |
|
283 | 245 | } |
|
284 | 246 | } |
@@ -296,12 +258,6 b" impl<'a, T> std::ops::DerefMut for PyRef" | |||
|
296 | 258 | } |
|
297 | 259 | } |
|
298 | 260 | |
|
299 | impl<'a, T> Drop for PyRefMut<'a, T> { | |
|
300 | fn drop(&mut self) { | |
|
301 | self.py_shared_state.decrease_leak_count(self.py, true); | |
|
302 | } | |
|
303 | } | |
|
304 | ||
|
305 | 261 | /// Allows a `py_class!` generated struct to share references to one of its |
|
306 | 262 | /// data members with Python. |
|
307 | 263 | /// |
General Comments 0
You need to be logged in to leave comments.
Login now