comparison rust/hg-cpython/src/ref_sharing.rs @ 44205:f015d679f08c

rust-cpython: inline PySharedState::leak_immutable() and PyLeaked::new() For the same reason as the previous patch. The unsafe stuff can be better documented if these functions are inlined.
author Yuya Nishihara <yuya@tcha.org>
date Sat, 19 Oct 2019 16:48:34 +0900
parents bafdaf4858d8
children 9804badd5970
comparison
equal deleted inserted replaced
44204:bafdaf4858d8 44205:f015d679f08c
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,