# `cell-family` Cells inspired by [`qcell::TCell`][__link0] / [`qcell::TLCell`][__link1], with additional features. ## Overview `cell-family` provides the [`define!`][__link2] macro, which defines a new [`Family`][__link3]. For each family, a corresponding [`Cell`][__link4] and [`CellOwner`][__link5] can be created. Only a single [`CellOwner`][__link6] 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: ```rust cell_family::define!(type FooFamily: FooCellOwner for FooCell); ``` This defines `FooFamily` (which implements [`Family`][__link7]) as well as `FooCellOwner` and `FooCell`, aliases for [`CellOwner`][__link8] and [`Cell`][__link9] respectively. One `FooCellOwner` can exist per thread, and thus `FooCellOwner` is **not** `Send`, since sending a `FooCellOwner` to another thread may allow two `FooCellOwner`s to co-exist in a single thread. To allow a single `FooCellOwner` per program (and thus make `FooCellOwner` `Send`), prefix `define!` with `static`: ```rust cell_family::define!(static type FooFamily: FooCellOwner for FooCell); ``` For both thread-local and thread-safe families, the API is the same: ```rust 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)`][__link10] simple wraps `T` in a `#[repr(transparent)]` [`FooCell`][__link11] without performing any checks. - [`FooCell::get(&FooCellOwner)`][__link12] and [`FooCell::get_mut(&mut FooCellOwner)`][__link13] are constant-time operations that return `&T` and `&mut T` respectively without performing any runtime checks. Since a single [`FooCellOwner`][__link14] exists per program (or thread), the aliasing rules of each cell is enforced by Rust through the `FooCellOwner`, which is borrowed as long as each `FooCell` is borrowed. - `FooFamily` ensures that a single `FooCellOwner` exists within a program; if another `FooCellOwner` exists, [`FooCellOwner::new()`][__link15] will panic. A [`try_new()`][__link16] counterpart exists to avoid crashing in such a case. ## Benefits over [`qcell::TCell`][__link17] / [`qcell::TLCell`][__link18] - Unlike [`qcell::TCell`][__link19] (respectively [`qcell::TCell`][__link20]), the `Family` `F` is in charge of ensuring that a single `CellOwner` exists per program (respectively thread). By using macros to generate families, we only need a single [`AtomicBool`][__link21] (respectively [`Cell`][__link22]) for each family, thus requiring no allocations. - A few additional methods are provided; for instance, [`owner.get(c)`][__link23], [`owner.get_mut(c)`][__link24] and [`owner.try_get_mut(c)`][__link25] are provided, where `c` can be: - A tuple of [`Cell`][__link26]s. - An array of [`Cell`][__link27]s. - An array of references to [`Cell`][__link28]s. - A slice of [`Cell`][__link29]s. - Thread-local and thread-safe [`Cell`][__link30]s (and [`CellOwner`][__link31]s) are backed by the same type; whether they are thread-local or thread-safe is determined by their [`Family`][__link32]: if it is thread-safe, it will also implement [`ThreadSafeFamily`][__link33]. This makes it easier to define generic functions over `Cell`s. - `cell-family` fully supports `#[no_std]`, **except** for thread-local families in non-`nightly` builds (since thread-local variables cannot be defined in `#[no_std]` without `#[thread_local]`, which is not stable). - `Cell` is [`Debug`][__link34], and will print a representation of its inner value if no `CellOwner` currently exists. [__cargo_doc2readme_dependencies_info]: ggGkYW0BYXSEGyZKBNWOD3NPG4hWBK_oMjIWG3maRHTpBWgyG_cGPsi3PdHhYXKEG9CfYt4voBe_Gz40t1EfMixKG0c95nDaFBWgG2KZaUhr-pupYWSCg2tjZWxsLWZhbWlseWUwLjEuMGtjZWxsX2ZhbWlseYJmdGxjZWxs9g [__link0]: https://docs.rs/qcell/0.5.2/qcell/struct.TCell.html [__link1]: https://docs.rs/qcell/0.5.2/qcell/struct.TLCell.html [__link10]: https://docs.rs/cell-family/0.1.0/cell_family/?search=Cell::new [__link11]: https://docs.rs/cell-family/0.1.0/cell_family/struct.Cell.html [__link12]: https://docs.rs/cell-family/0.1.0/cell_family/?search=Cell::get [__link13]: https://docs.rs/cell-family/0.1.0/cell_family/?search=Cell::get_mut [__link14]: https://docs.rs/cell-family/0.1.0/cell_family/struct.CellOwner.html [__link15]: https://docs.rs/cell-family/0.1.0/cell_family/?search=CellOwner::new [__link16]: https://docs.rs/cell-family/0.1.0/cell_family/?search=CellOwner::try_new [__link17]: https://docs.rs/qcell/0.5.2/qcell/struct.TCell.html [__link18]: https://docs.rs/qcell/0.5.2/qcell/struct.TLCell.html [__link19]: https://docs.rs/qcell/0.5.2/qcell/struct.TCell.html [__link2]: https://docs.rs/cell-family/0.1.0/cell_family/?search=define [__link20]: https://crates.io/crates/tlcell [__link21]: https://doc.rust-lang.org/stable/std/?search=sync::atomic::AtomicBool [__link22]: https://doc.rust-lang.org/stable/std/?search=cell::Cell [__link23]: https://docs.rs/cell-family/0.1.0/cell_family/?search=CellOwner::get [__link24]: https://docs.rs/cell-family/0.1.0/cell_family/?search=CellOwner::get_mut [__link25]: https://docs.rs/cell-family/0.1.0/cell_family/?search=CellOwner::try_get_mut [__link26]: https://docs.rs/cell-family/0.1.0/cell_family/struct.Cell.html [__link27]: https://docs.rs/cell-family/0.1.0/cell_family/struct.Cell.html [__link28]: https://docs.rs/cell-family/0.1.0/cell_family/struct.Cell.html [__link29]: https://docs.rs/cell-family/0.1.0/cell_family/struct.Cell.html [__link3]: https://docs.rs/cell-family/0.1.0/cell_family/trait.Family.html [__link30]: https://docs.rs/cell-family/0.1.0/cell_family/struct.Cell.html [__link31]: https://docs.rs/cell-family/0.1.0/cell_family/struct.CellOwner.html [__link32]: https://docs.rs/cell-family/0.1.0/cell_family/trait.Family.html [__link33]: https://docs.rs/cell-family/0.1.0/cell_family/trait.ThreadSafeFamily.html [__link34]: https://doc.rust-lang.org/stable/std/?search=fmt::Debug [__link4]: https://docs.rs/cell-family/0.1.0/cell_family/struct.Cell.html [__link5]: https://docs.rs/cell-family/0.1.0/cell_family/struct.CellOwner.html [__link6]: https://docs.rs/cell-family/0.1.0/cell_family/struct.CellOwner.html [__link7]: https://docs.rs/cell-family/0.1.0/cell_family/trait.Family.html [__link8]: https://docs.rs/cell-family/0.1.0/cell_family/struct.CellOwner.html [__link9]: https://docs.rs/cell-family/0.1.0/cell_family/struct.Cell.html