Expand description
Cells inspired by qcell::TCell / qcell::TLCell, with
additional features.
§Overview
cell-family provides the define! macro, which defines a
new Family. For each family, a corresponding Cell and CellOwner
can be created. Only a single CellOwner per family can exist at once,
but multiple cells can exist at the same time.
For instance, you may define a family FooFamily as below:
cell_family::define!(type FooFamily: FooCellOwner for FooCell<T>);This defines FooFamily (which implements Family) as well as
FooCellOwner and FooCell, aliases for CellOwner<FooFamily> and
Cell<FooFamily> respectively.
One FooCellOwner can exist per thread, and thus FooCellOwner is not
Send, since sending a FooCellOwner to another thread may allow two
FooCellOwners to co-exist in a single thread. To allow a single
FooCellOwner per program (and thus make FooCellOwner Send),
prefix define! with static:
cell_family::define!(static type FooFamily: FooCellOwner for FooCell<T>);For both thread-local and thread-safe families, the API is the same:
let mut owner = FooCellOwner::new();
let a = FooCell::new(1);
let b = FooCell::new("bar");
assert_eq!(*a.get(&owner), 1);
assert_eq!(*b.get(&owner), "bar");
*a.get_mut(&mut owner) += 1;
*b.get_mut(&mut owner) = "baz";
assert_eq!(*a.get(&owner), 2);
assert_eq!(*b.get(&owner), "baz");FooCell::new(T)simple wrapsTin a#[repr(transparent)]FooCellwithout performing any checks.FooCell::get(&FooCellOwner)andFooCell::get_mut(&mut FooCellOwner)are constant-time operations that return&Tand&mut Trespectively without performing any runtime checks. Since a singleFooCellOwnerexists per program (or thread), the aliasing rules of each cell is enforced by Rust through theFooCellOwner, which is borrowed as long as eachFooCellis borrowed.FooFamilyensures that a singleFooCellOwnerexists within a program; if anotherFooCellOwnerexists,FooCellOwner::new()will panic. Atry_new()counterpart exists to avoid crashing in such a case.
§Benefits over qcell::TCell / qcell::TLCell
- Unlike
qcell::TCell(respectivelyqcell::TCell), theFamilyFis in charge of ensuring that a singleCellOwner<F>exists per program (respectively thread). By using macros to generate families, we only need a singleAtomicBool(respectivelyCell<bool>) for each family, thus requiring no allocations. - A few additional methods are provided; for instance,
owner.get(c),owner.get_mut(c)andowner.try_get_mut(c)are provided, whereccan be: - Thread-local and thread-safe
Cells (andCellOwners) are backed by the same type; whether they are thread-local or thread-safe is determined by theirFamily: if it is thread-safe, it will also implementThreadSafeFamily. This makes it easier to define generic functions overCells. cell-familyfully supports#[no_std], except for thread-local families in non-nightlybuilds (since thread-local variables cannot be defined in#[no_std]without#[thread_local], which is not stable).CellisDebug, and will print a representation of its inner value if noCellOwnercurrently exists.
Modules§
Macros§
Structs§
Traits§
- Trait implemented by values that can be given to
CellOwner::get_mut(). - Trait implemented by values that can be given to
CellOwner::get(). - An extension of
Familyto defineCellOwners that can be shared between different threads, at the cost of slighly more expensive costs to create or drop aCellOwner.