55 borrow_count: AtomicUsize, |
55 borrow_count: AtomicUsize, |
56 generation: AtomicUsize, |
56 generation: AtomicUsize, |
57 } |
57 } |
58 |
58 |
59 impl PySharedState { |
59 impl PySharedState { |
60 /// Return a reference to the wrapped data and its state with an |
|
61 /// artificial static lifetime. |
|
62 /// We need to be protected by the GIL for thread-safety. |
|
63 /// |
|
64 /// # Safety |
|
65 /// |
|
66 /// This is highly unsafe since the lifetime of the given data can be |
|
67 /// extended. Do not call this function directly. |
|
68 unsafe fn leak_immutable<T>( |
|
69 &self, |
|
70 _py: Python, |
|
71 data: Ref<T>, |
|
72 ) -> (&'static T, &'static PySharedState) { |
|
73 let ptr: *const T = &*data; |
|
74 let state_ptr: *const PySharedState = self; |
|
75 (&*ptr, &*state_ptr) |
|
76 } |
|
77 |
|
78 fn current_borrow_count(&self, _py: Python) -> usize { |
60 fn current_borrow_count(&self, _py: Python) -> usize { |
79 self.borrow_count.load(Ordering::Relaxed) |
61 self.borrow_count.load(Ordering::Relaxed) |
80 } |
62 } |
81 |
63 |
82 fn increase_borrow_count(&self, _py: Python) { |
64 fn increase_borrow_count(&self, _py: Python) { |
221 pub fn leak_immutable(&self) -> PyLeaked<&'static T> { |
203 pub fn leak_immutable(&self) -> PyLeaked<&'static T> { |
222 let state = &self.data.py_shared_state; |
204 let state = &self.data.py_shared_state; |
223 // make sure self.data isn't mutably borrowed; otherwise the |
205 // make sure self.data isn't mutably borrowed; otherwise the |
224 // generation number can't be trusted. |
206 // generation number can't be trusted. |
225 let data_ref = self.borrow(); |
207 let data_ref = self.borrow(); |
226 unsafe { |
208 |
227 let (static_ref, static_state_ref) = |
209 // &'static cast is safe because data_ptr and state_ptr are owned |
228 state.leak_immutable(self.py, data_ref); |
210 // by self.owner, and we do have the GIL for thread safety. |
229 PyLeaked::new(self.py, self.owner, static_ref, static_state_ref) |
211 let data_ptr: *const T = &*data_ref; |
|
212 let state_ptr: *const PySharedState = state; |
|
213 PyLeaked::<&'static T> { |
|
214 inner: self.owner.clone_ref(self.py), |
|
215 data: unsafe { &*data_ptr }, |
|
216 py_shared_state: unsafe { &*state_ptr }, |
|
217 generation: state.current_generation(self.py), |
230 } |
218 } |
231 } |
219 } |
232 } |
220 } |
233 |
221 |
234 /// Allows a `py_class!` generated struct to share references to one of its |
222 /// Allows a `py_class!` generated struct to share references to one of its |
302 // DO NOT implement Deref for PyLeaked<T>! Dereferencing PyLeaked |
290 // DO NOT implement Deref for PyLeaked<T>! Dereferencing PyLeaked |
303 // without taking Python GIL wouldn't be safe. Also, the underling reference |
291 // without taking Python GIL wouldn't be safe. Also, the underling reference |
304 // is invalid if generation != py_shared_state.generation. |
292 // is invalid if generation != py_shared_state.generation. |
305 |
293 |
306 impl<T> PyLeaked<T> { |
294 impl<T> PyLeaked<T> { |
307 /// # Safety |
|
308 /// |
|
309 /// The `py_shared_state` must be owned by the `inner` Python object. |
|
310 fn new( |
|
311 py: Python, |
|
312 inner: &PyObject, |
|
313 data: T, |
|
314 py_shared_state: &'static PySharedState, |
|
315 ) -> Self { |
|
316 Self { |
|
317 inner: inner.clone_ref(py), |
|
318 data: data, |
|
319 py_shared_state, |
|
320 generation: py_shared_state.current_generation(py), |
|
321 } |
|
322 } |
|
323 |
|
324 /// Immutably borrows the wrapped value. |
295 /// Immutably borrows the wrapped value. |
325 /// |
296 /// |
326 /// Borrowing fails if the underlying reference has been invalidated. |
297 /// Borrowing fails if the underlying reference has been invalidated. |
327 pub fn try_borrow<'a>( |
298 pub fn try_borrow<'a>( |
328 &'a self, |
299 &'a self, |