Things on this page are fragmentary and immature notes/thoughts of the author. Please read with your own judgement!
Tips and Traps¶
std::cell::OnceCell is a partial implementation of
once_cell
in the Rust standard library.There are 2 Rust crates lazy_static and once_cell for (lazy) once assignment (which can be used to create singletons). once_cell is preferred to lazy_static for a few reasons .
once_cell is both more flexible and more convenient than lazy_static .
Unlike once_cell , lazy_static supports spinlock-based implementation of blocking which works with
#![no_std]
.once_cell will likely be part of the Rust standard library in future.
Once assignment means that you can only assign value to such a variable once. However, it is still possible to mutate the variable after initialization.
When defining a static variable which implements Copy, you can define it as a static reference. This helps avoiding accidental implicity copies. The more idiomatic way is to define a wrapper non-Copy struct so that you can be sure that the underlying data won't get copied.
:timing
:sccache 1
:dep once_cell = "1.13.0"
use std::{sync::Mutex, collections::HashMap};
use once_cell::sync::Lazy;
Create a Mutable Static Variable (Singleton)¶
static GLOBAL_DATA_1: Lazy<Mutex<HashMap<i32, String>>> = Lazy::new(|| {
let mut m = HashMap::new();
m.insert(13, "Spica".to_string());
m.insert(74, "Hoyten".to_string());
Mutex::new(m)
});
GLOBAL_DATA_1.lock().unwrap().insert(1, "New change".to_string());
GLOBAL_DATA_1.lock().unwrap().get(&1)
Create a Immutable Static Variable (Singleton)¶
Mutex allows threads to mutate the static variable after initialization. It is not necessary if you just need a readable static variable (after initialization).
static GLOBAL_DATA_2: Lazy<HashMap<i32, String>> = Lazy::new(|| {
let mut m = HashMap::new();
m.insert(13, "Spica".to_string());
m.insert(74, "Hoyten".to_string());
m
});
GLOBAL_DATA_2.insert(1, "New change".to_string());
GLOBAL_DATA_2.get(&1)
GLOBAL_DATA_2.get(&13)
Lazy Referencing Lazy¶
static GLOBAL_DATA_3: Lazy<[Lazy<&[usize]>; 2]> = Lazy::new(|| {
let mut arr: [Lazy<&[usize]>; 2] = [
Lazy::new(|| &[]),
Lazy::new(|| &[]),
];
arr[0] = Lazy::new(|| &[1, 2, 3]);
arr[1] = Lazy::new(|| &[4, 5, 6, 7]);
arr
});
GLOBAL_DATA_3
let x1: &[usize] = &GLOBAL_DATA_3[0];
x1
let x2: &[usize] = &GLOBAL_DATA_3[1];
x2