rust/pyo3-sharedref/src/lib.rs
changeset 52609 d1e304025b90
parent 52608 d85514a88706
child 52610 c25d345f5aa5
equal deleted inserted replaced
52608:d85514a88706 52609:d1e304025b90
    91 ///     }
    91 ///     }
    92 ///
    92 ///
    93 ///     fn add(slf: &Bound<'_, Self>, i: i32) -> PyResult<()> {
    93 ///     fn add(slf: &Bound<'_, Self>, i: i32) -> PyResult<()> {
    94 ///         let rust_set = &slf.borrow().rust_set;
    94 ///         let rust_set = &slf.borrow().rust_set;
    95 ///         let shared_ref = unsafe { rust_set.borrow_with_owner(slf) };
    95 ///         let shared_ref = unsafe { rust_set.borrow_with_owner(slf) };
    96 ///         let mut set_ref = shared_ref.borrow_mut();
    96 ///         let mut set_ref = shared_ref.write();
    97 ///         set_ref.insert(i);
    97 ///         set_ref.insert(i);
    98 ///         Ok(())
    98 ///         Ok(())
    99 ///     }
    99 ///     }
   100 /// }
   100 /// }
   101 ///
   101 ///
   228     state: &'py PySharedState,
   228     state: &'py PySharedState,
   229     data: &'py RwLock<T>, // TODO perhaps this needs Pin
   229     data: &'py RwLock<T>, // TODO perhaps this needs Pin
   230 }
   230 }
   231 
   231 
   232 impl<'py, T: ?Sized> PySharedRef<'py, T> {
   232 impl<'py, T: ?Sized> PySharedRef<'py, T> {
   233     /// Immutably borrows the wrapped value.
   233     /// Take the lock on the wrapped value for read-only operations.
   234     ///
   234     ///
   235     /// # Panics
   235     /// # Panics
   236     ///
   236     ///
   237     /// Panics if the value is currently mutably borrowed.
   237     /// Panics if the lock is currently held for write operations.
   238     pub fn borrow(&self) -> RwLockReadGuard<'py, T> {
   238     pub fn read(&self) -> RwLockReadGuard<'py, T> {
   239         self.try_borrow().expect("already mutably borrowed")
   239         self.try_read().expect("already mutably borrowed")
   240     }
   240     }
   241 
   241 
   242     /// Immutably borrows the wrapped value, returning an error if the value
   242     /// Immutably borrows the wrapped value, returning an error if the value
   243     /// is currently mutably borrowed.
   243     /// is currently mutably borrowed.
   244     pub fn try_borrow(&self) -> TryLockResult<RwLockReadGuard<'py, T>> {
   244     pub fn try_read(&self) -> TryLockResult<RwLockReadGuard<'py, T>> {
   245         // state isn't involved since
   245         // state isn't involved since
   246         // - data.try_borrow() would fail if self is mutably borrowed,
   246         // - data.try_read() would fail if self is mutably borrowed,
   247         // - and data.try_borrow_mut() would fail while self is borrowed.
   247         // - and data.try_write() would fail while self is borrowed.
   248         self.data.try_read()
   248         self.data.try_read()
   249     }
   249     }
   250 
   250 
   251     /// Mutably borrows the wrapped value.
   251     /// Take the lock on the wrapped value for write operations.
   252     ///
   252     ///
   253     /// Any existing leaked references will be invalidated.
   253     /// Any existing leaked references will be invalidated.
   254     ///
   254     ///
   255     /// # Panics
   255     /// # Panics
   256     ///
   256     ///
   257     /// Panics if the value is currently borrowed.
   257     /// Panics if the lock is currently held.
   258     pub fn borrow_mut(&self) -> RwLockWriteGuard<'py, T> {
   258     pub fn write(&self) -> RwLockWriteGuard<'py, T> {
   259         self.try_borrow_mut().expect("already borrowed")
   259         self.try_write().expect("already borrowed")
   260     }
   260     }
   261 
   261 
   262     /// Mutably borrows the wrapped value, returning an error if the value
   262     /// Mutably borrows the wrapped value, returning an error if the value
   263     /// is currently borrowed.
   263     /// is currently borrowed.
   264     pub fn try_borrow_mut(&self) -> TryLockResult<RwLockWriteGuard<'py, T>> {
   264     pub fn try_write(&self) -> TryLockResult<RwLockWriteGuard<'py, T>> {
   265         // the value may be immutably borrowed through UnsafePyLeaked
   265         // the value may be immutably borrowed through UnsafePyLeaked
   266         if self.state.current_borrow_count(self.py()) > 0 {
   266         if self.state.current_borrow_count(self.py()) > 0 {
   267             // propagate borrow-by-leaked state to data to get BorrowMutError
   267             // propagate borrow-by-leaked state to data to get BorrowMutError
   268             let _dummy = self.data.read();
   268             let _dummy = self.data.read();
   269             let _unused = self.data.try_write()?;
   269             let _unused = self.data.try_write()?;
   289     pub fn try_leak_immutable(
   289     pub fn try_leak_immutable(
   290         &self,
   290         &self,
   291     ) -> Result<UnsafePyLeaked<&'static T>, TryLeakError> {
   291     ) -> Result<UnsafePyLeaked<&'static T>, TryLeakError> {
   292         // make sure self.data isn't mutably borrowed; otherwise the
   292         // make sure self.data isn't mutably borrowed; otherwise the
   293         // generation number wouldn't be trusted.
   293         // generation number wouldn't be trusted.
   294         let data_ref = self.try_borrow()?;
   294         let data_ref = self.try_read()?;
   295 
   295 
   296         // keep reference to the owner so the data and state are alive,
   296         // keep reference to the owner so the data and state are alive,
   297         // but the data pointer can be invalidated by borrow_mut().
   297         // but the data pointer can be invalidated by write().
   298         // the state wouldn't since it is immutable.
   298         // the state wouldn't since it is immutable.
   299         let state_ptr: *const PySharedState = self.state;
   299         let state_ptr: *const PySharedState = self.state;
   300         let data_ptr: *const T = &*data_ref;
   300         let data_ptr: *const T = &*data_ref;
   301         Ok(UnsafePyLeaked::<&'static T> {
   301         Ok(UnsafePyLeaked::<&'static T> {
   302             owner: self.owner.clone().unbind(),
   302             owner: self.owner.clone().unbind(),
   320 /// `PySharedState` is owned by `PySharedRefCell`, and is shared across its
   320 /// `PySharedState` is owned by `PySharedRefCell`, and is shared across its
   321 /// derived references. The consistency of these references are guaranteed
   321 /// derived references. The consistency of these references are guaranteed
   322 /// as follows:
   322 /// as follows:
   323 ///
   323 ///
   324 /// - The immutability of `PycCass` object fields. Any mutation of
   324 /// - The immutability of `PycCass` object fields. Any mutation of
   325 ///   [`PySharedRefCell`] is allowed only through its `borrow_mut()`.
   325 ///   [`PySharedRefCell`] is allowed only through its `write()`.
   326 /// - The `py: Python<'_>` token, which makes sure that any data access is
   326 /// - The `py: Python<'_>` token, which makes sure that any data access is
   327 ///   synchronized by the GIL.
   327 ///   synchronized by the GIL.
   328 /// - The underlying `RefCell`, which prevents `PySharedRefCell` value from
   328 /// - The underlying `RefCell`, which prevents `PySharedRefCell` value from
   329 ///   being directly borrowed or leaked while it is mutably borrowed.
   329 ///   being directly borrowed or leaked while it is mutably borrowed.
   330 /// - The `borrow_count`, which is the number of references borrowed from
   330 /// - The `borrow_count`, which is the number of references borrowed from
   331 ///   `UnsafePyLeaked`. Just like `RefCell`, mutation is prohibited while
   331 ///   `UnsafePyLeaked`. Just like `RefCell`, mutation is prohibited while
   332 ///   `UnsafePyLeaked` is borrowed.
   332 ///   `UnsafePyLeaked` is borrowed.
   333 /// - The `generation` counter, which increments on `borrow_mut()`.
   333 /// - The `generation` counter, which increments on `write()`. `UnsafePyLeaked`
   334 ///   `UnsafePyLeaked` reference is valid only if the `current_generation()`
   334 ///   reference is valid only if the `current_generation()` equals to the
   335 ///   equals to the `generation` at the time of `leak_immutable()`.
   335 ///   `generation` at the time of `leak_immutable()`.
   336 #[derive(Debug)]
   336 #[derive(Debug)]
   337 struct PySharedState {
   337 struct PySharedState {
   338     // The counter variable could be Cell<usize> since any operation on
   338     // The counter variable could be Cell<usize> since any operation on
   339     // PySharedState is synchronized by the GIL, but being "atomic" makes
   339     // PySharedState is synchronized by the GIL, but being "atomic" makes
   340     // PySharedState inherently Sync. The ordering requirement doesn't
   340     // PySharedState inherently Sync. The ordering requirement doesn't