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()][TaggedCell::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
// 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 [taggedcell!] macro is provided. The
macro creates a new tag type based on the variable's name, and applies it in the declaration.
```
use taggedcell::taggedcell;
taggedcell!{
static BAR: TaggedCell
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. ```compilefail use taggedcell::tagged_cell;
taggedcell!{
static BAZ: TaggedCell
// 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()][TaggedCell::init] will initialize the Cell's data. All future [init()][TaggedCell::init] calls will just return a new tag. It is undetermined which thread will initialize the Cell's data. ``` use std::thread; use taggedcell::taggedcell;
tagged_cell!{
static TABLE: TaggedCell
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); });
```