Crate double_checked_cell [−] [src]
A thread-safe lazily initialized cell using double-checked locking.
Provides a memory location that can be safely shared between threads and initialized at most once. Once the cell is initialized it becomes immutable.
If you do not need to change the value after initialization
DoubleCheckedCell<T>
is more efficient than a Mutex<Option<T>>
.
Examples
use double_checked_cell::DoubleCheckedCell; let cell = DoubleCheckedCell::new(); // The cell starts uninitialized. assert_eq!(cell.get(), None); // Perform potentially expensive initialization. let value = cell.get_or_init(|| 21 + 21); assert_eq!(*value, 42); assert_eq!(cell.get(), Some(&42)); // The cell is already initialized. let value = cell.get_or_init(|| { panic!("initilization does not run again") }); assert_eq!(*value, 42); assert_eq!(cell.get(), Some(&42));
Errors
DoubleCheckedCell
supports fallible initialization.
use std::fs::File; use std::io; use std::io::prelude::*; use double_checked_cell::DoubleCheckedCell; let cell = DoubleCheckedCell::new(); let contents: io::Result<&String> = cell.get_or_try_init(|| { let mut file = File::open("not-found.txt")?; let mut contents = String::new(); file.read_to_string(&mut contents)?; Ok(contents) }); // File not found. assert!(contents.is_err()); // Cell remains uninitialized for now. assert_eq!(cell.get(), None);
Poisoning
DoubleCheckedCell
achieves unwind safety by implementing "poisoning".
If an initilization closure is executed and panics, the DoubleCheckedCell
becomes poisoned. Any subsequent reads will then also panic.
use std::panic; use double_checked_cell::DoubleCheckedCell; let cell = DoubleCheckedCell::new(); // Cell gets poisoned. assert!(panic::catch_unwind(|| { cell.get_or_init(|| panic!("oh no!")); }).is_err()); // Now it is poisoned forever. assert!(panic::catch_unwind(|| { cell.get_or_init(|| true); }).is_err());
Structs
DoubleCheckedCell |
A thread-safe lazily initialized cell. |