Build Status Crates.io API reference

Overview

once_cell provides two new cell-like types, unsync::OnceCell and sync::OnceCell. OnceCell might store arbitrary non-Copy types, can be assigned to at most once and provide direct access to the stored contents. In a nutshell, API looks roughly like this:

rust,no-run impl OnceCell<T> { fn set(&self, value: T) -> Result<(), T> { ... } fn get(&self) -> Option<&T> { ... } }

Note that, like with RefCell and Mutex, the set method requires only a shared reference. Because of the single assignment restriction get can return an &T instead of ReF<T> or MutexGuard<T>.

Patterns

OnceCell might be useful for a variety of patterns.

Safe Initialization of global data

```rust use std::{env, io}; use once_cell::sync::OnceCell;

[derive(Debug)]

pub struct Logger { // ... } static INSTANCE: OnceCell = OnceCell::INIT;

impl Logger { pub fn global() -> &'static Logger { INSTANCE.get().expect("logger is not initialized") }

fn from_cli(args: env::Args) -> Result<Logger, io::Error> {
   // ...
}

}

fn main() -> Result<(), io::Error> { let logger = Logger::from_cli(env::args())?; INSTANCE.set(logger).unwrap(); // use Logger::global() from now on Ok(()) } ```

Lazy initialized global data

This is essentially lazy_static! macro, but without a macro.

```rust use std::{sync::Mutex, collections::HashMap}; use once_cell::sync::OnceCell;

fn globaldata() -> &'static Mutex> { static INSTANCE: OnceCell>> = OnceCell::INIT; INSTANCE.getorinit(|| { let mut m = HashMap::new(); m.insert(13, "Spica".tostring()); m.insert(74, "Hoyten".to_string()); Mutex::new(m) }) } ```

There are also sync::Lazy and unsync::Lazy convenience types and macros to streamline this pattern:

```rust

[macro_use]

extern crate once_cell;

use std::{sync::Mutex, collections::HashMap}; use once_cell::sync::Lazy;

static GLOBALDATA: Lazy>> = synclazy! { let mut m = HashMap::new(); m.insert(13, "Spica".tostring()); m.insert(74, "Hoyten".tostring()); Mutex::new(m) };

fn main() { println!("{:?}", GLOBAL_DATA.lock().unwrap()); } ```

General purpose lazy evaluation

Unlike lazy_static!, Lazy works with local variables.

```rust use once_cell::unsync::Lazy;

fn main() { let ctx = vec![1, 2, 3]; let thunk = Lazy::new(|| { ctx.iter().sum::() }); assert_eq!(*thunk, 6); } ```

If you need a lazy field in a struct, you probably should use OnceCell directly, because that will allow you to access self during initialization.

```rust use std::{fs, io, path::PathBuf}; use once_cell::unsync::OnceCell;

struct Ctx { config_path: PathBuf, config: OnceCell, }

impl Ctx { pub fn getconfig(&self) -> Result<&str, io::Error> { let cfg = self.config.getortryinit(|| { fs::readtostring(&self.configpath) })?; Ok(cfg.asstr()) } } ```

Implementation details

Implementation is based on lazy_static and lazy_cell crates and in some sense just streamlines and unifies the APIs of those crates.

To implement a sync flavor of OnceCell, this crates uses either ::std::sync::Once or ::parking_lot::Once. This is controlled by the parking_lot feature, which is enabled by default.

When using parking_lot, the crate is compatible with rustc 1.25.0, without parking_lot a minimum of 1.29.0 is required.

This crate uses unsafe.