Show More
@@ -24,7 +24,7 b'' | |||||
24 |
|
24 | |||
25 | use crate::exceptions::AlreadyBorrowed; |
|
25 | use crate::exceptions::AlreadyBorrowed; | |
26 | use cpython::{exc, PyClone, PyErr, PyObject, PyResult, Python}; |
|
26 | use cpython::{exc, PyClone, PyErr, PyObject, PyResult, Python}; | |
27 |
use std::cell::{ |
|
27 | use std::cell::{Ref, RefCell, RefMut}; | |
28 | use std::ops::{Deref, DerefMut}; |
|
28 | use std::ops::{Deref, DerefMut}; | |
29 | use std::sync::atomic::{AtomicUsize, Ordering}; |
|
29 | use std::sync::atomic::{AtomicUsize, Ordering}; | |
30 |
|
30 | |||
@@ -48,7 +48,6 b' use std::sync::atomic::{AtomicUsize, Ord' | |||||
48 | /// `generation` at the time of `leak_immutable()`. |
|
48 | /// `generation` at the time of `leak_immutable()`. | |
49 | #[derive(Debug, Default)] |
|
49 | #[derive(Debug, Default)] | |
50 | struct PySharedState { |
|
50 | struct PySharedState { | |
51 | mutably_borrowed: Cell<bool>, |
|
|||
52 | // The counter variable could be Cell<usize> since any operation on |
|
51 | // The counter variable could be Cell<usize> since any operation on | |
53 | // PySharedState is synchronized by the GIL, but being "atomic" makes |
|
52 | // PySharedState is synchronized by the GIL, but being "atomic" makes | |
54 | // PySharedState inherently Sync. The ordering requirement doesn't |
|
53 | // PySharedState inherently Sync. The ordering requirement doesn't | |
@@ -57,26 +56,14 b' struct PySharedState {' | |||||
57 | generation: AtomicUsize, |
|
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 | impl PySharedState { |
|
59 | impl PySharedState { | |
65 | fn borrow_mut<'a, T>( |
|
60 | fn borrow_mut<'a, T>( | |
66 | &'a self, |
|
61 | &'a self, | |
67 | py: Python<'a>, |
|
62 | py: Python<'a>, | |
68 | pyrefmut: RefMut<'a, T>, |
|
63 | pyrefmut: RefMut<'a, T>, | |
69 | ) -> PyResult<PyRefMut<'a, T>> { |
|
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 | match self.current_borrow_count(py) { |
|
65 | match self.current_borrow_count(py) { | |
78 | 0 => { |
|
66 | 0 => { | |
79 | self.mutably_borrowed.replace(true); |
|
|||
80 | // Note that this wraps around to the same value if mutably |
|
67 | // Note that this wraps around to the same value if mutably | |
81 | // borrowed more than usize::MAX times, which wouldn't happen |
|
68 | // borrowed more than usize::MAX times, which wouldn't happen | |
82 | // in practice. |
|
69 | // in practice. | |
@@ -100,16 +87,9 b' impl PySharedState {' | |||||
100 | /// extended. Do not call this function directly. |
|
87 | /// extended. Do not call this function directly. | |
101 | unsafe fn leak_immutable<T>( |
|
88 | unsafe fn leak_immutable<T>( | |
102 | &self, |
|
89 | &self, | |
103 | py: Python, |
|
90 | _py: Python, | |
104 | data: Ref<T>, |
|
91 | data: Ref<T>, | |
105 | ) -> PyResult<(&'static T, &'static PySharedState)> { |
|
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 | let ptr: *const T = &*data; |
|
93 | let ptr: *const T = &*data; | |
114 | let state_ptr: *const PySharedState = self; |
|
94 | let state_ptr: *const PySharedState = self; | |
115 | Ok((&*ptr, &*state_ptr)) |
|
95 | Ok((&*ptr, &*state_ptr)) | |
@@ -130,20 +110,6 b' impl PySharedState {' | |||||
130 | assert!(prev_count > 0); |
|
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 | fn current_generation(&self, _py: Python) -> usize { |
|
113 | fn current_generation(&self, _py: Python) -> usize { | |
148 | self.generation.load(Ordering::Relaxed) |
|
114 | self.generation.load(Ordering::Relaxed) | |
149 | } |
|
115 | } | |
@@ -262,23 +228,19 b" impl<'a, T> PySharedRef<'a, T> {" | |||||
262 |
|
228 | |||
263 | /// Holds a mutable reference to data shared between Python and Rust. |
|
229 | /// Holds a mutable reference to data shared between Python and Rust. | |
264 | pub struct PyRefMut<'a, T> { |
|
230 | pub struct PyRefMut<'a, T> { | |
265 | py: Python<'a>, |
|
|||
266 | inner: RefMut<'a, T>, |
|
231 | inner: RefMut<'a, T>, | |
267 | py_shared_state: &'a PySharedState, |
|
|||
268 | } |
|
232 | } | |
269 |
|
233 | |||
270 | impl<'a, T> PyRefMut<'a, T> { |
|
234 | impl<'a, T> PyRefMut<'a, T> { | |
271 | // Must be constructed by PySharedState after checking its leak_count. |
|
235 | // Must be constructed by PySharedState after checking its leak_count. | |
272 | // Otherwise, drop() would incorrectly update the state. |
|
236 | // Otherwise, drop() would incorrectly update the state. | |
273 | fn new( |
|
237 | fn new( | |
274 | py: Python<'a>, |
|
238 | _py: Python<'a>, | |
275 | inner: RefMut<'a, T>, |
|
239 | inner: RefMut<'a, T>, | |
276 | py_shared_state: &'a PySharedState, |
|
240 | _py_shared_state: &'a PySharedState, | |
277 | ) -> Self { |
|
241 | ) -> Self { | |
278 | Self { |
|
242 | Self { | |
279 | py, |
|
|||
280 | inner, |
|
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 | /// Allows a `py_class!` generated struct to share references to one of its |
|
261 | /// Allows a `py_class!` generated struct to share references to one of its | |
306 | /// data members with Python. |
|
262 | /// data members with Python. | |
307 | /// |
|
263 | /// |
General Comments 0
You need to be logged in to leave comments.
Login now