1 unstable release
0.1.1 | Aug 31, 2024 |
---|---|
0.1.0 |
|
#617 in Rust patterns
64 downloads per month
55KB
1K
SLoC
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<T>
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
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
, ghost-cell
, token-cell
, 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 toqcell
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 requirealloc
crate, and doesn't require allocator at all usingRefToken
for example);- re-borrowing.