Struct qcell::QCellOwnerSeq

source ·
pub struct QCellOwnerSeq { /* private fields */ }
Expand description

Borrowing-owner of zero or more QCell instances, using an ID sequence.

The owner will have a unique(-ish) ID associated with it to detect use of the wrong owner to access a cell at runtime, which is a programming error. This type allocates the owner ID from a wrapping sequence sourced from a global atomic variable, so it is very fast to allocate.

Safety

A malicious coder could cause an intentional ID collision, e.g. by creating 2^63 owners on a 64-bit build (or 2^31 on 32-bit, etc), which would cause the ID to wrap. This would allow that coder to cause undefined behaviour in their own code. So at a stretch this could allow a coder to hide unsound code from a safety review. Because of that the QCellOwnerSeq::new method is marked as unsafe. However it is not possible to use it unsafely by accident, only through making an intentional, determined and CPU-intensive effort to exploit it.

See crate documentation.

Implementations§

source§

impl QCellOwnerSeq

source

pub unsafe fn new() -> Self

Create an owner that can be used for creating many QCell instances.

Safety

The contract with the caller is that the caller must not intentionally create an owner-ID collision and exploit it to create undefined behaviour. The caller could do this by creating 2^63 more owners on a 64-bit build (or 2^31 on 32-bit, etc), causing the ID to wrap, and then using two owners that they know to have the same ID to access the same memory mutably from two references at the same time. This is totally impossible to do by accident, so any normal use of this call will be 100% safe.

To get unsound behaviour requires both an owner ID collision (which might just about happen by accident in very unusual situations), and then also intentionally using the wrong owner to access a cell. Usually using the wrong owner to access a cell would cause an immediate panic because it is a programming error. It is extremely unlikely that there would always be the same ID collision in testing, so this panic would soon be fixed. Once it is fixed, there is absolutely no way that even an accidental collision could cause any unsound behaviour, because the bug has been eliminated, and the correct owner is always used to access each cell.

source

pub fn id(&self) -> QCellOwnerID

Get the internal owner ID. This may be used to create QCell instances without needing a borrow on this structure, which is useful if this structure is already borrowed.

source

pub fn cell<T>(&self, value: T) -> QCell<T>

Create a new cell owned by this owner instance. See also QCell::new.

source

pub fn ro<'a, T: ?Sized>(&'a self, qc: &'a QCell<T>) -> &'a T

Borrow contents of a QCell immutably (read-only). Many QCell instances can be borrowed immutably at the same time from the same owner. Panics if the QCell is not owned by this QCellOwnerSeq.

source

pub fn rw<'a, T: ?Sized>(&'a mut self, qc: &'a QCell<T>) -> &'a mut T

Borrow contents of a QCell mutably (read-write). Only one QCell at a time can be borrowed from the owner using this call. The returned reference must go out of scope before another can be borrowed. Panics if the QCell is not owned by this QCellOwnerSeq.

source

pub fn rw2<'a, T: ?Sized, U: ?Sized>( &'a mut self, qc1: &'a QCell<T>, qc2: &'a QCell<U> ) -> (&'a mut T, &'a mut U)

Borrow contents of two QCell instances mutably. Panics if the two QCell instances point to the same memory. Panics if either QCell is not owned by this QCellOwnerSeq.

source

pub fn rw3<'a, T: ?Sized, U: ?Sized, V: ?Sized>( &'a mut self, qc1: &'a QCell<T>, qc2: &'a QCell<U>, qc3: &'a QCell<V> ) -> (&'a mut T, &'a mut U, &'a mut V)

Borrow contents of three QCell instances mutably. Panics if any pair of QCell instances point to the same memory. Panics if any QCell is not owned by this QCellOwnerSeq.

Trait Implementations§

source§

impl From<&QCellOwnerSeq> for QCellOwnerID

source§

fn from(owner: &QCellOwnerSeq) -> Self

Converts to this type from the input type.

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for Twhere T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for Twhere U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T, U> TryFrom<U> for Twhere U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.