Crate tagged_cell
source · [−]Expand description
tagged_cell
Fast, initializable, and thread safe static variables
Borrows the excellent ZST based tagging implementation to guarantee cells are initialized exactly once before an access is attempted.
This is implemented via the TaggedCell and a Tag type, which must be unique for each instance of the TaggedCell for safe operation. The TaggedCell must then be set up via init(), which initializes the underlying data using a user provided function or closure, and then returns a special zero-sized Init tag used to access the Cell’s data.
use tagged_cell::TaggedCell;
struct FooTag;
static FOO: TaggedCell<usize, FooTag> = unsafe {TaggedCell::new()};
// Initialize the cell's data and retrieve a tag
let tag = FOO.init(|| 27);
// The tag is required to obtain a shared reference to the data
assert_eq!(*FOO.get(tag), 27);
To ensure unique tag types are used for each cell, and to ‘wrap’ the unsafe call, the tagged_cell! macro is provided. The macro creates a new tag type based on the variable’s name, and applies it in the declaration.
use tagged_cell::tagged_cell;
tagged_cell!{
static BAR: TaggedCell<Vec<usize>, _> = TaggedCell::new();
}
let tag = BAR.init(|| vec![0, 10, 20]);
let vec = BAR.get(tag);
assert_eq!(vec[2], 20);
When unique tag types are used, attempting to access a TaggedCell before it is initialized will cause a compilation error.
use tagged_cell::tagged_cell;
tagged_cell!{
static BAZ: TaggedCell<usize>, _> = TaggedCell::new();
}
tagged_cell!{
static QUX: TaggedCell<usize>, _> = TaggedCell::new();
}
// read before init is not possible
BAZ.get(Init{BAZ::TagType});
let qux_tag = QUX.init(|| 35);
// using the wrong tag throws an error
BAZ.get(qux_tag);
To allow for usage across threads, only the first invocation of init() will initialize the Cell’s data. All future init() calls will just return a new tag. It is undetermined which thread will initialize the Cell’s data.
use std::thread;
use tagged_cell::tagged_cell;
tagged_cell!{
static TABLE: TaggedCell<Vec<usize>, _> = TaggedCell::new();
}
thread::spawn(move || {
let tag = TABLE.init(|| vec![0, 10, 20]);
let table = TABLE.get(tag);
assert_eq!(table[2], 20);
});
thread::spawn(move || {
let tag = TABLE.init(|| vec![0, 10, 20]);
let table = TABLE.get(tag);
assert_eq!(table[1], 10);
});
Macros
Safe macro for creating a TaggedCell
Structs
A marker proving that the unique cell with tag Tag
is initialized.
This cannot be sent across threads, the only way to obtain it is by running
init() in the current thread
Top level structure to support initializable and thread safe static variables. Use tagged_cell! macro to make this struct