rust/hg-cpython/src/ref_sharing.rs
changeset 44205 f015d679f08c
parent 44204 bafdaf4858d8
child 44206 9804badd5970
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,