# token-ref-cell This library provides `TokenRefCell`, an interior mutability cell which uses an external `Token` reference to synchronize its accesses. Contrary to other standard cells like `RefCell`, `TokenRefCell` is `Sync` as long as its token is `Send + Sync`; it can thus be used in multithreaded programs. Multiple token implementations are provided, the easiest to use being the smart-pointer-based ones: every `Box` can indeed be used as a token (as long as `T` is not a ZST). The recommended token implementation is `BoxToken`, and it's the default value of the generic parameter of `TokenRefCell`. The runtime cost is very lightweight: only one pointer comparison for `TokenRefCell::borrow`/`TokenRefCell::borrow_mut` when using `BoxToken` (and zero-cost when using `singleton_token!`).
Because one token can be used with multiple cells, it's possible for example to use a single rwlock wrapping a token to synchronize mutable access to multiple `Arc` data. ## Examples ```rust use std::sync::{Arc, RwLock}; use token_ref_cell::{TokenRefCell, BoxToken}; let mut token = RwLock::new(BoxToken::new()); // Initialize a vector of arcs let token_ref = token.read().unwrap(); let arc_vec = vec![Arc::new(TokenRefCell::new(0, &*token_ref)); 42]; drop(token_ref); // Use only one rwlock to write to all the arcs let mut token_mut = token.write().unwrap(); for cell in &arc_vec { *cell.borrow_mut(&mut *token_mut) += 1; } drop(token_mut) ``` ## Why another crate? Many crates based on the same principle exists: [`qcell`](https://crates.io/crates/qcell), [`ghost-cell`](https://crates.io/crates/ghost-cell), [`token-cell`](https://crates.io/crates/token-cell), [`singleton-cell`](https://crates.io/crates/singleton-cell), etc. When I started writing `token-ref-cell`, I only knew `token-cell` one, as it was written by a guy previously working in the same company as me. But I wanted to take a new approach, notably designing an API closer than standard `RefCell` one, hence the name `TokenRefCell`. In fact, my goal was simple: to make the graph example compile, and for that I needed to enable "re-borrowing", i.e. reusing the token used in a mutable borrow to mutably borrow a "sub-cell". When I was satisfied with the result, before publishing it, I search for other similar crates, and I found the list above, and realized I'd reimplemented the same concept as a bunch of people, especially `qcell` which uses a `Box` for its cell token/owner. However, this fresh implementation still has a few specificities which makes it relevant: - a familiar API close to `RefCell` one; - a unified API with a single `Token` trait, contrary to `qcell` which provides four different cell types; - a larger choice of token implementations, thanks to the simplicity of the `Token` trait: singleton types, smart-pointers, pinned/unpinned references, etc.; - `no_std` implementation, compatible with custom allocators (doesn't require `alloc` crate, and doesn't require allocator at all using `RefToken` for example); - re-borrowing.