1ef40d7f6Sopenharmony_ci//! # Overview 2ef40d7f6Sopenharmony_ci//! 3ef40d7f6Sopenharmony_ci//! `once_cell` provides two new cell-like types, [`unsync::OnceCell`] and [`sync::OnceCell`]. A `OnceCell` 4ef40d7f6Sopenharmony_ci//! might store arbitrary non-`Copy` types, can be assigned to at most once and provides direct access 5ef40d7f6Sopenharmony_ci//! to the stored contents. The core API looks *roughly* like this (and there's much more inside, read on!): 6ef40d7f6Sopenharmony_ci//! 7ef40d7f6Sopenharmony_ci//! ```rust,ignore 8ef40d7f6Sopenharmony_ci//! impl<T> OnceCell<T> { 9ef40d7f6Sopenharmony_ci//! const fn new() -> OnceCell<T> { ... } 10ef40d7f6Sopenharmony_ci//! fn set(&self, value: T) -> Result<(), T> { ... } 11ef40d7f6Sopenharmony_ci//! fn get(&self) -> Option<&T> { ... } 12ef40d7f6Sopenharmony_ci//! } 13ef40d7f6Sopenharmony_ci//! ``` 14ef40d7f6Sopenharmony_ci//! 15ef40d7f6Sopenharmony_ci//! Note that, like with [`RefCell`] and [`Mutex`], the `set` method requires only a shared reference. 16ef40d7f6Sopenharmony_ci//! Because of the single assignment restriction `get` can return a `&T` instead of `Ref<T>` 17ef40d7f6Sopenharmony_ci//! or `MutexGuard<T>`. 18ef40d7f6Sopenharmony_ci//! 19ef40d7f6Sopenharmony_ci//! The `sync` flavor is thread-safe (that is, implements the [`Sync`] trait), while the `unsync` one is not. 20ef40d7f6Sopenharmony_ci//! 21ef40d7f6Sopenharmony_ci//! [`unsync::OnceCell`]: unsync/struct.OnceCell.html 22ef40d7f6Sopenharmony_ci//! [`sync::OnceCell`]: sync/struct.OnceCell.html 23ef40d7f6Sopenharmony_ci//! [`RefCell`]: https://doc.rust-lang.org/std/cell/struct.RefCell.html 24ef40d7f6Sopenharmony_ci//! [`Mutex`]: https://doc.rust-lang.org/std/sync/struct.Mutex.html 25ef40d7f6Sopenharmony_ci//! [`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html 26ef40d7f6Sopenharmony_ci//! 27ef40d7f6Sopenharmony_ci//! # Recipes 28ef40d7f6Sopenharmony_ci//! 29ef40d7f6Sopenharmony_ci//! `OnceCell` might be useful for a variety of patterns. 30ef40d7f6Sopenharmony_ci//! 31ef40d7f6Sopenharmony_ci//! ## Safe Initialization of Global Data 32ef40d7f6Sopenharmony_ci//! 33ef40d7f6Sopenharmony_ci//! ```rust 34ef40d7f6Sopenharmony_ci//! use std::{env, io}; 35ef40d7f6Sopenharmony_ci//! 36ef40d7f6Sopenharmony_ci//! use once_cell::sync::OnceCell; 37ef40d7f6Sopenharmony_ci//! 38ef40d7f6Sopenharmony_ci//! #[derive(Debug)] 39ef40d7f6Sopenharmony_ci//! pub struct Logger { 40ef40d7f6Sopenharmony_ci//! // ... 41ef40d7f6Sopenharmony_ci//! } 42ef40d7f6Sopenharmony_ci//! static INSTANCE: OnceCell<Logger> = OnceCell::new(); 43ef40d7f6Sopenharmony_ci//! 44ef40d7f6Sopenharmony_ci//! impl Logger { 45ef40d7f6Sopenharmony_ci//! pub fn global() -> &'static Logger { 46ef40d7f6Sopenharmony_ci//! INSTANCE.get().expect("logger is not initialized") 47ef40d7f6Sopenharmony_ci//! } 48ef40d7f6Sopenharmony_ci//! 49ef40d7f6Sopenharmony_ci//! fn from_cli(args: env::Args) -> Result<Logger, std::io::Error> { 50ef40d7f6Sopenharmony_ci//! // ... 51ef40d7f6Sopenharmony_ci//! # Ok(Logger {}) 52ef40d7f6Sopenharmony_ci//! } 53ef40d7f6Sopenharmony_ci//! } 54ef40d7f6Sopenharmony_ci//! 55ef40d7f6Sopenharmony_ci//! fn main() { 56ef40d7f6Sopenharmony_ci//! let logger = Logger::from_cli(env::args()).unwrap(); 57ef40d7f6Sopenharmony_ci//! INSTANCE.set(logger).unwrap(); 58ef40d7f6Sopenharmony_ci//! // use `Logger::global()` from now on 59ef40d7f6Sopenharmony_ci//! } 60ef40d7f6Sopenharmony_ci//! ``` 61ef40d7f6Sopenharmony_ci//! 62ef40d7f6Sopenharmony_ci//! ## Lazy Initialized Global Data 63ef40d7f6Sopenharmony_ci//! 64ef40d7f6Sopenharmony_ci//! This is essentially the `lazy_static!` macro, but without a macro. 65ef40d7f6Sopenharmony_ci//! 66ef40d7f6Sopenharmony_ci//! ```rust 67ef40d7f6Sopenharmony_ci//! use std::{sync::Mutex, collections::HashMap}; 68ef40d7f6Sopenharmony_ci//! 69ef40d7f6Sopenharmony_ci//! use once_cell::sync::OnceCell; 70ef40d7f6Sopenharmony_ci//! 71ef40d7f6Sopenharmony_ci//! fn global_data() -> &'static Mutex<HashMap<i32, String>> { 72ef40d7f6Sopenharmony_ci//! static INSTANCE: OnceCell<Mutex<HashMap<i32, String>>> = OnceCell::new(); 73ef40d7f6Sopenharmony_ci//! INSTANCE.get_or_init(|| { 74ef40d7f6Sopenharmony_ci//! let mut m = HashMap::new(); 75ef40d7f6Sopenharmony_ci//! m.insert(13, "Spica".to_string()); 76ef40d7f6Sopenharmony_ci//! m.insert(74, "Hoyten".to_string()); 77ef40d7f6Sopenharmony_ci//! Mutex::new(m) 78ef40d7f6Sopenharmony_ci//! }) 79ef40d7f6Sopenharmony_ci//! } 80ef40d7f6Sopenharmony_ci//! ``` 81ef40d7f6Sopenharmony_ci//! 82ef40d7f6Sopenharmony_ci//! There are also the [`sync::Lazy`] and [`unsync::Lazy`] convenience types to streamline this pattern: 83ef40d7f6Sopenharmony_ci//! 84ef40d7f6Sopenharmony_ci//! ```rust 85ef40d7f6Sopenharmony_ci//! use std::{sync::Mutex, collections::HashMap}; 86ef40d7f6Sopenharmony_ci//! use once_cell::sync::Lazy; 87ef40d7f6Sopenharmony_ci//! 88ef40d7f6Sopenharmony_ci//! static GLOBAL_DATA: Lazy<Mutex<HashMap<i32, String>>> = Lazy::new(|| { 89ef40d7f6Sopenharmony_ci//! let mut m = HashMap::new(); 90ef40d7f6Sopenharmony_ci//! m.insert(13, "Spica".to_string()); 91ef40d7f6Sopenharmony_ci//! m.insert(74, "Hoyten".to_string()); 92ef40d7f6Sopenharmony_ci//! Mutex::new(m) 93ef40d7f6Sopenharmony_ci//! }); 94ef40d7f6Sopenharmony_ci//! 95ef40d7f6Sopenharmony_ci//! fn main() { 96ef40d7f6Sopenharmony_ci//! println!("{:?}", GLOBAL_DATA.lock().unwrap()); 97ef40d7f6Sopenharmony_ci//! } 98ef40d7f6Sopenharmony_ci//! ``` 99ef40d7f6Sopenharmony_ci//! 100ef40d7f6Sopenharmony_ci//! Note that the variable that holds `Lazy` is declared as `static`, *not* 101ef40d7f6Sopenharmony_ci//! `const`. This is important: using `const` instead compiles, but works wrong. 102ef40d7f6Sopenharmony_ci//! 103ef40d7f6Sopenharmony_ci//! [`sync::Lazy`]: sync/struct.Lazy.html 104ef40d7f6Sopenharmony_ci//! [`unsync::Lazy`]: unsync/struct.Lazy.html 105ef40d7f6Sopenharmony_ci//! 106ef40d7f6Sopenharmony_ci//! ## General purpose lazy evaluation 107ef40d7f6Sopenharmony_ci//! 108ef40d7f6Sopenharmony_ci//! Unlike `lazy_static!`, `Lazy` works with local variables. 109ef40d7f6Sopenharmony_ci//! 110ef40d7f6Sopenharmony_ci//! ```rust 111ef40d7f6Sopenharmony_ci//! use once_cell::unsync::Lazy; 112ef40d7f6Sopenharmony_ci//! 113ef40d7f6Sopenharmony_ci//! fn main() { 114ef40d7f6Sopenharmony_ci//! let ctx = vec![1, 2, 3]; 115ef40d7f6Sopenharmony_ci//! let thunk = Lazy::new(|| { 116ef40d7f6Sopenharmony_ci//! ctx.iter().sum::<i32>() 117ef40d7f6Sopenharmony_ci//! }); 118ef40d7f6Sopenharmony_ci//! assert_eq!(*thunk, 6); 119ef40d7f6Sopenharmony_ci//! } 120ef40d7f6Sopenharmony_ci//! ``` 121ef40d7f6Sopenharmony_ci//! 122ef40d7f6Sopenharmony_ci//! If you need a lazy field in a struct, you probably should use `OnceCell` 123ef40d7f6Sopenharmony_ci//! directly, because that will allow you to access `self` during initialization. 124ef40d7f6Sopenharmony_ci//! 125ef40d7f6Sopenharmony_ci//! ```rust 126ef40d7f6Sopenharmony_ci//! use std::{fs, path::PathBuf}; 127ef40d7f6Sopenharmony_ci//! 128ef40d7f6Sopenharmony_ci//! use once_cell::unsync::OnceCell; 129ef40d7f6Sopenharmony_ci//! 130ef40d7f6Sopenharmony_ci//! struct Ctx { 131ef40d7f6Sopenharmony_ci//! config_path: PathBuf, 132ef40d7f6Sopenharmony_ci//! config: OnceCell<String>, 133ef40d7f6Sopenharmony_ci//! } 134ef40d7f6Sopenharmony_ci//! 135ef40d7f6Sopenharmony_ci//! impl Ctx { 136ef40d7f6Sopenharmony_ci//! pub fn get_config(&self) -> Result<&str, std::io::Error> { 137ef40d7f6Sopenharmony_ci//! let cfg = self.config.get_or_try_init(|| { 138ef40d7f6Sopenharmony_ci//! fs::read_to_string(&self.config_path) 139ef40d7f6Sopenharmony_ci//! })?; 140ef40d7f6Sopenharmony_ci//! Ok(cfg.as_str()) 141ef40d7f6Sopenharmony_ci//! } 142ef40d7f6Sopenharmony_ci//! } 143ef40d7f6Sopenharmony_ci//! ``` 144ef40d7f6Sopenharmony_ci//! 145ef40d7f6Sopenharmony_ci//! ## Lazily Compiled Regex 146ef40d7f6Sopenharmony_ci//! 147ef40d7f6Sopenharmony_ci//! This is a `regex!` macro which takes a string literal and returns an 148ef40d7f6Sopenharmony_ci//! *expression* that evaluates to a `&'static Regex`: 149ef40d7f6Sopenharmony_ci//! 150ef40d7f6Sopenharmony_ci//! ``` 151ef40d7f6Sopenharmony_ci//! macro_rules! regex { 152ef40d7f6Sopenharmony_ci//! ($re:literal $(,)?) => {{ 153ef40d7f6Sopenharmony_ci//! static RE: once_cell::sync::OnceCell<regex::Regex> = once_cell::sync::OnceCell::new(); 154ef40d7f6Sopenharmony_ci//! RE.get_or_init(|| regex::Regex::new($re).unwrap()) 155ef40d7f6Sopenharmony_ci//! }}; 156ef40d7f6Sopenharmony_ci//! } 157ef40d7f6Sopenharmony_ci//! ``` 158ef40d7f6Sopenharmony_ci//! 159ef40d7f6Sopenharmony_ci//! This macro can be useful to avoid the "compile regex on every loop iteration" problem. 160ef40d7f6Sopenharmony_ci//! 161ef40d7f6Sopenharmony_ci//! ## Runtime `include_bytes!` 162ef40d7f6Sopenharmony_ci//! 163ef40d7f6Sopenharmony_ci//! The `include_bytes` macro is useful to include test resources, but it slows 164ef40d7f6Sopenharmony_ci//! down test compilation a lot. An alternative is to load the resources at 165ef40d7f6Sopenharmony_ci//! runtime: 166ef40d7f6Sopenharmony_ci//! 167ef40d7f6Sopenharmony_ci//! ``` 168ef40d7f6Sopenharmony_ci//! use std::path::Path; 169ef40d7f6Sopenharmony_ci//! 170ef40d7f6Sopenharmony_ci//! use once_cell::sync::OnceCell; 171ef40d7f6Sopenharmony_ci//! 172ef40d7f6Sopenharmony_ci//! pub struct TestResource { 173ef40d7f6Sopenharmony_ci//! path: &'static str, 174ef40d7f6Sopenharmony_ci//! cell: OnceCell<Vec<u8>>, 175ef40d7f6Sopenharmony_ci//! } 176ef40d7f6Sopenharmony_ci//! 177ef40d7f6Sopenharmony_ci//! impl TestResource { 178ef40d7f6Sopenharmony_ci//! pub const fn new(path: &'static str) -> TestResource { 179ef40d7f6Sopenharmony_ci//! TestResource { path, cell: OnceCell::new() } 180ef40d7f6Sopenharmony_ci//! } 181ef40d7f6Sopenharmony_ci//! pub fn bytes(&self) -> &[u8] { 182ef40d7f6Sopenharmony_ci//! self.cell.get_or_init(|| { 183ef40d7f6Sopenharmony_ci//! let dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); 184ef40d7f6Sopenharmony_ci//! let path = Path::new(dir.as_str()).join(self.path); 185ef40d7f6Sopenharmony_ci//! std::fs::read(&path).unwrap_or_else(|_err| { 186ef40d7f6Sopenharmony_ci//! panic!("failed to load test resource: {}", path.display()) 187ef40d7f6Sopenharmony_ci//! }) 188ef40d7f6Sopenharmony_ci//! }).as_slice() 189ef40d7f6Sopenharmony_ci//! } 190ef40d7f6Sopenharmony_ci//! } 191ef40d7f6Sopenharmony_ci//! 192ef40d7f6Sopenharmony_ci//! static TEST_IMAGE: TestResource = TestResource::new("test_data/lena.png"); 193ef40d7f6Sopenharmony_ci//! 194ef40d7f6Sopenharmony_ci//! #[test] 195ef40d7f6Sopenharmony_ci//! fn test_sobel_filter() { 196ef40d7f6Sopenharmony_ci//! let rgb: &[u8] = TEST_IMAGE.bytes(); 197ef40d7f6Sopenharmony_ci//! // ... 198ef40d7f6Sopenharmony_ci//! # drop(rgb); 199ef40d7f6Sopenharmony_ci//! } 200ef40d7f6Sopenharmony_ci//! ``` 201ef40d7f6Sopenharmony_ci//! 202ef40d7f6Sopenharmony_ci//! ## `lateinit` 203ef40d7f6Sopenharmony_ci//! 204ef40d7f6Sopenharmony_ci//! `LateInit` type for delayed initialization. It is reminiscent of Kotlin's 205ef40d7f6Sopenharmony_ci//! `lateinit` keyword and allows construction of cyclic data structures: 206ef40d7f6Sopenharmony_ci//! 207ef40d7f6Sopenharmony_ci//! 208ef40d7f6Sopenharmony_ci//! ``` 209ef40d7f6Sopenharmony_ci//! use once_cell::sync::OnceCell; 210ef40d7f6Sopenharmony_ci//! 211ef40d7f6Sopenharmony_ci//! pub struct LateInit<T> { cell: OnceCell<T> } 212ef40d7f6Sopenharmony_ci//! 213ef40d7f6Sopenharmony_ci//! impl<T> LateInit<T> { 214ef40d7f6Sopenharmony_ci//! pub fn init(&self, value: T) { 215ef40d7f6Sopenharmony_ci//! assert!(self.cell.set(value).is_ok()) 216ef40d7f6Sopenharmony_ci//! } 217ef40d7f6Sopenharmony_ci//! } 218ef40d7f6Sopenharmony_ci//! 219ef40d7f6Sopenharmony_ci//! impl<T> Default for LateInit<T> { 220ef40d7f6Sopenharmony_ci//! fn default() -> Self { LateInit { cell: OnceCell::default() } } 221ef40d7f6Sopenharmony_ci//! } 222ef40d7f6Sopenharmony_ci//! 223ef40d7f6Sopenharmony_ci//! impl<T> std::ops::Deref for LateInit<T> { 224ef40d7f6Sopenharmony_ci//! type Target = T; 225ef40d7f6Sopenharmony_ci//! fn deref(&self) -> &T { 226ef40d7f6Sopenharmony_ci//! self.cell.get().unwrap() 227ef40d7f6Sopenharmony_ci//! } 228ef40d7f6Sopenharmony_ci//! } 229ef40d7f6Sopenharmony_ci//! 230ef40d7f6Sopenharmony_ci//! #[derive(Default)] 231ef40d7f6Sopenharmony_ci//! struct A<'a> { 232ef40d7f6Sopenharmony_ci//! b: LateInit<&'a B<'a>>, 233ef40d7f6Sopenharmony_ci//! } 234ef40d7f6Sopenharmony_ci//! 235ef40d7f6Sopenharmony_ci//! #[derive(Default)] 236ef40d7f6Sopenharmony_ci//! struct B<'a> { 237ef40d7f6Sopenharmony_ci//! a: LateInit<&'a A<'a>> 238ef40d7f6Sopenharmony_ci//! } 239ef40d7f6Sopenharmony_ci//! 240ef40d7f6Sopenharmony_ci//! 241ef40d7f6Sopenharmony_ci//! fn build_cycle() { 242ef40d7f6Sopenharmony_ci//! let a = A::default(); 243ef40d7f6Sopenharmony_ci//! let b = B::default(); 244ef40d7f6Sopenharmony_ci//! a.b.init(&b); 245ef40d7f6Sopenharmony_ci//! b.a.init(&a); 246ef40d7f6Sopenharmony_ci//! 247ef40d7f6Sopenharmony_ci//! let _a = &a.b.a.b.a; 248ef40d7f6Sopenharmony_ci//! } 249ef40d7f6Sopenharmony_ci//! ``` 250ef40d7f6Sopenharmony_ci//! 251ef40d7f6Sopenharmony_ci//! # Comparison with std 252ef40d7f6Sopenharmony_ci//! 253ef40d7f6Sopenharmony_ci//! |`!Sync` types | Access Mode | Drawbacks | 254ef40d7f6Sopenharmony_ci//! |----------------------|------------------------|-----------------------------------------------| 255ef40d7f6Sopenharmony_ci//! |`Cell<T>` | `T` | requires `T: Copy` for `get` | 256ef40d7f6Sopenharmony_ci//! |`RefCell<T>` | `RefMut<T>` / `Ref<T>` | may panic at runtime | 257ef40d7f6Sopenharmony_ci//! |`unsync::OnceCell<T>` | `&T` | assignable only once | 258ef40d7f6Sopenharmony_ci//! 259ef40d7f6Sopenharmony_ci//! |`Sync` types | Access Mode | Drawbacks | 260ef40d7f6Sopenharmony_ci//! |----------------------|------------------------|-----------------------------------------------| 261ef40d7f6Sopenharmony_ci//! |`AtomicT` | `T` | works only with certain `Copy` types | 262ef40d7f6Sopenharmony_ci//! |`Mutex<T>` | `MutexGuard<T>` | may deadlock at runtime, may block the thread | 263ef40d7f6Sopenharmony_ci//! |`sync::OnceCell<T>` | `&T` | assignable only once, may block the thread | 264ef40d7f6Sopenharmony_ci//! 265ef40d7f6Sopenharmony_ci//! Technically, calling `get_or_init` will also cause a panic or a deadlock if it recursively calls 266ef40d7f6Sopenharmony_ci//! itself. However, because the assignment can happen only once, such cases should be more rare than 267ef40d7f6Sopenharmony_ci//! equivalents with `RefCell` and `Mutex`. 268ef40d7f6Sopenharmony_ci//! 269ef40d7f6Sopenharmony_ci//! # Minimum Supported `rustc` Version 270ef40d7f6Sopenharmony_ci//! 271ef40d7f6Sopenharmony_ci//! This crate's minimum supported `rustc` version is `1.56.0`. 272ef40d7f6Sopenharmony_ci//! 273ef40d7f6Sopenharmony_ci//! If only the `std` feature is enabled, MSRV will be updated conservatively, supporting at least latest 8 versions of the compiler. 274ef40d7f6Sopenharmony_ci//! When using other features, like `parking_lot`, MSRV might be updated more frequently, up to the latest stable. 275ef40d7f6Sopenharmony_ci//! In both cases, increasing MSRV is *not* considered a semver-breaking change. 276ef40d7f6Sopenharmony_ci//! 277ef40d7f6Sopenharmony_ci//! # Implementation details 278ef40d7f6Sopenharmony_ci//! 279ef40d7f6Sopenharmony_ci//! The implementation is based on the [`lazy_static`](https://github.com/rust-lang-nursery/lazy-static.rs/) 280ef40d7f6Sopenharmony_ci//! and [`lazy_cell`](https://github.com/indiv0/lazycell/) crates and [`std::sync::Once`]. In some sense, 281ef40d7f6Sopenharmony_ci//! `once_cell` just streamlines and unifies those APIs. 282ef40d7f6Sopenharmony_ci//! 283ef40d7f6Sopenharmony_ci//! To implement a sync flavor of `OnceCell`, this crates uses either a custom 284ef40d7f6Sopenharmony_ci//! re-implementation of `std::sync::Once` or `parking_lot::Mutex`. This is 285ef40d7f6Sopenharmony_ci//! controlled by the `parking_lot` feature (disabled by default). Performance 286ef40d7f6Sopenharmony_ci//! is the same for both cases, but the `parking_lot` based `OnceCell<T>` is 287ef40d7f6Sopenharmony_ci//! smaller by up to 16 bytes. 288ef40d7f6Sopenharmony_ci//! 289ef40d7f6Sopenharmony_ci//! This crate uses `unsafe`. 290ef40d7f6Sopenharmony_ci//! 291ef40d7f6Sopenharmony_ci//! [`std::sync::Once`]: https://doc.rust-lang.org/std/sync/struct.Once.html 292ef40d7f6Sopenharmony_ci//! 293ef40d7f6Sopenharmony_ci//! # F.A.Q. 294ef40d7f6Sopenharmony_ci//! 295ef40d7f6Sopenharmony_ci//! **Should I use lazy_static or once_cell?** 296ef40d7f6Sopenharmony_ci//! 297ef40d7f6Sopenharmony_ci//! To the first approximation, `once_cell` is both more flexible and more convenient than `lazy_static` 298ef40d7f6Sopenharmony_ci//! and should be preferred. 299ef40d7f6Sopenharmony_ci//! 300ef40d7f6Sopenharmony_ci//! Unlike `once_cell`, `lazy_static` supports spinlock-based implementation of blocking which works with 301ef40d7f6Sopenharmony_ci//! `#![no_std]`. 302ef40d7f6Sopenharmony_ci//! 303ef40d7f6Sopenharmony_ci//! `lazy_static` has received significantly more real world testing, but `once_cell` is also a widely 304ef40d7f6Sopenharmony_ci//! used crate. 305ef40d7f6Sopenharmony_ci//! 306ef40d7f6Sopenharmony_ci//! **Should I use the sync or unsync flavor?** 307ef40d7f6Sopenharmony_ci//! 308ef40d7f6Sopenharmony_ci//! Because Rust compiler checks thread safety for you, it's impossible to accidentally use `unsync` where 309ef40d7f6Sopenharmony_ci//! `sync` is required. So, use `unsync` in single-threaded code and `sync` in multi-threaded. It's easy 310ef40d7f6Sopenharmony_ci//! to switch between the two if code becomes multi-threaded later. 311ef40d7f6Sopenharmony_ci//! 312ef40d7f6Sopenharmony_ci//! At the moment, `unsync` has an additional benefit that reentrant initialization causes a panic, which 313ef40d7f6Sopenharmony_ci//! might be easier to debug than a deadlock. 314ef40d7f6Sopenharmony_ci//! 315ef40d7f6Sopenharmony_ci//! **Does this crate support async?** 316ef40d7f6Sopenharmony_ci//! 317ef40d7f6Sopenharmony_ci//! No, but you can use [`async_once_cell`](https://crates.io/crates/async_once_cell) instead. 318ef40d7f6Sopenharmony_ci//! 319ef40d7f6Sopenharmony_ci//! **Can I bring my own mutex?** 320ef40d7f6Sopenharmony_ci//! 321ef40d7f6Sopenharmony_ci//! There is [generic_once_cell](https://crates.io/crates/generic_once_cell) to allow just that. 322ef40d7f6Sopenharmony_ci//! 323ef40d7f6Sopenharmony_ci//! # Related crates 324ef40d7f6Sopenharmony_ci//! 325ef40d7f6Sopenharmony_ci//! * [double-checked-cell](https://github.com/niklasf/double-checked-cell) 326ef40d7f6Sopenharmony_ci//! * [lazy-init](https://crates.io/crates/lazy-init) 327ef40d7f6Sopenharmony_ci//! * [lazycell](https://crates.io/crates/lazycell) 328ef40d7f6Sopenharmony_ci//! * [mitochondria](https://crates.io/crates/mitochondria) 329ef40d7f6Sopenharmony_ci//! * [lazy_static](https://crates.io/crates/lazy_static) 330ef40d7f6Sopenharmony_ci//! * [async_once_cell](https://crates.io/crates/async_once_cell) 331ef40d7f6Sopenharmony_ci//! * [generic_once_cell](https://crates.io/crates/generic_once_cell) (bring your own mutex) 332ef40d7f6Sopenharmony_ci//! 333ef40d7f6Sopenharmony_ci//! Most of this crate's functionality is available in `std` in nightly Rust. 334ef40d7f6Sopenharmony_ci//! See the [tracking issue](https://github.com/rust-lang/rust/issues/74465). 335ef40d7f6Sopenharmony_ci 336ef40d7f6Sopenharmony_ci#![cfg_attr(not(feature = "std"), no_std)] 337ef40d7f6Sopenharmony_ci 338ef40d7f6Sopenharmony_ci#[cfg(feature = "alloc")] 339ef40d7f6Sopenharmony_ciextern crate alloc; 340ef40d7f6Sopenharmony_ci 341ef40d7f6Sopenharmony_ci#[cfg(all(feature = "critical-section", not(feature = "std")))] 342ef40d7f6Sopenharmony_ci#[path = "imp_cs.rs"] 343ef40d7f6Sopenharmony_cimod imp; 344ef40d7f6Sopenharmony_ci 345ef40d7f6Sopenharmony_ci#[cfg(all(feature = "std", feature = "parking_lot"))] 346ef40d7f6Sopenharmony_ci#[path = "imp_pl.rs"] 347ef40d7f6Sopenharmony_cimod imp; 348ef40d7f6Sopenharmony_ci 349ef40d7f6Sopenharmony_ci#[cfg(all(feature = "std", not(feature = "parking_lot")))] 350ef40d7f6Sopenharmony_ci#[path = "imp_std.rs"] 351ef40d7f6Sopenharmony_cimod imp; 352ef40d7f6Sopenharmony_ci 353ef40d7f6Sopenharmony_ci/// Single-threaded version of `OnceCell`. 354ef40d7f6Sopenharmony_cipub mod unsync { 355ef40d7f6Sopenharmony_ci use core::{ 356ef40d7f6Sopenharmony_ci cell::{Cell, UnsafeCell}, 357ef40d7f6Sopenharmony_ci fmt, mem, 358ef40d7f6Sopenharmony_ci ops::{Deref, DerefMut}, 359ef40d7f6Sopenharmony_ci panic::{RefUnwindSafe, UnwindSafe}, 360ef40d7f6Sopenharmony_ci }; 361ef40d7f6Sopenharmony_ci 362ef40d7f6Sopenharmony_ci use super::unwrap_unchecked; 363ef40d7f6Sopenharmony_ci 364ef40d7f6Sopenharmony_ci /// A cell which can be written to only once. It is not thread safe. 365ef40d7f6Sopenharmony_ci /// 366ef40d7f6Sopenharmony_ci /// Unlike [`std::cell::RefCell`], a `OnceCell` provides simple `&` 367ef40d7f6Sopenharmony_ci /// references to the contents. 368ef40d7f6Sopenharmony_ci /// 369ef40d7f6Sopenharmony_ci /// [`std::cell::RefCell`]: https://doc.rust-lang.org/std/cell/struct.RefCell.html 370ef40d7f6Sopenharmony_ci /// 371ef40d7f6Sopenharmony_ci /// # Example 372ef40d7f6Sopenharmony_ci /// ``` 373ef40d7f6Sopenharmony_ci /// use once_cell::unsync::OnceCell; 374ef40d7f6Sopenharmony_ci /// 375ef40d7f6Sopenharmony_ci /// let cell = OnceCell::new(); 376ef40d7f6Sopenharmony_ci /// assert!(cell.get().is_none()); 377ef40d7f6Sopenharmony_ci /// 378ef40d7f6Sopenharmony_ci /// let value: &String = cell.get_or_init(|| { 379ef40d7f6Sopenharmony_ci /// "Hello, World!".to_string() 380ef40d7f6Sopenharmony_ci /// }); 381ef40d7f6Sopenharmony_ci /// assert_eq!(value, "Hello, World!"); 382ef40d7f6Sopenharmony_ci /// assert!(cell.get().is_some()); 383ef40d7f6Sopenharmony_ci /// ``` 384ef40d7f6Sopenharmony_ci pub struct OnceCell<T> { 385ef40d7f6Sopenharmony_ci // Invariant: written to at most once. 386ef40d7f6Sopenharmony_ci inner: UnsafeCell<Option<T>>, 387ef40d7f6Sopenharmony_ci } 388ef40d7f6Sopenharmony_ci 389ef40d7f6Sopenharmony_ci // Similarly to a `Sync` bound on `sync::OnceCell`, we can use 390ef40d7f6Sopenharmony_ci // `&unsync::OnceCell` to sneak a `T` through `catch_unwind`, 391ef40d7f6Sopenharmony_ci // by initializing the cell in closure and extracting the value in the 392ef40d7f6Sopenharmony_ci // `Drop`. 393ef40d7f6Sopenharmony_ci impl<T: RefUnwindSafe + UnwindSafe> RefUnwindSafe for OnceCell<T> {} 394ef40d7f6Sopenharmony_ci impl<T: UnwindSafe> UnwindSafe for OnceCell<T> {} 395ef40d7f6Sopenharmony_ci 396ef40d7f6Sopenharmony_ci impl<T> Default for OnceCell<T> { 397ef40d7f6Sopenharmony_ci fn default() -> Self { 398ef40d7f6Sopenharmony_ci Self::new() 399ef40d7f6Sopenharmony_ci } 400ef40d7f6Sopenharmony_ci } 401ef40d7f6Sopenharmony_ci 402ef40d7f6Sopenharmony_ci impl<T: fmt::Debug> fmt::Debug for OnceCell<T> { 403ef40d7f6Sopenharmony_ci fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 404ef40d7f6Sopenharmony_ci match self.get() { 405ef40d7f6Sopenharmony_ci Some(v) => f.debug_tuple("OnceCell").field(v).finish(), 406ef40d7f6Sopenharmony_ci None => f.write_str("OnceCell(Uninit)"), 407ef40d7f6Sopenharmony_ci } 408ef40d7f6Sopenharmony_ci } 409ef40d7f6Sopenharmony_ci } 410ef40d7f6Sopenharmony_ci 411ef40d7f6Sopenharmony_ci impl<T: Clone> Clone for OnceCell<T> { 412ef40d7f6Sopenharmony_ci fn clone(&self) -> OnceCell<T> { 413ef40d7f6Sopenharmony_ci match self.get() { 414ef40d7f6Sopenharmony_ci Some(value) => OnceCell::with_value(value.clone()), 415ef40d7f6Sopenharmony_ci None => OnceCell::new(), 416ef40d7f6Sopenharmony_ci } 417ef40d7f6Sopenharmony_ci } 418ef40d7f6Sopenharmony_ci 419ef40d7f6Sopenharmony_ci fn clone_from(&mut self, source: &Self) { 420ef40d7f6Sopenharmony_ci match (self.get_mut(), source.get()) { 421ef40d7f6Sopenharmony_ci (Some(this), Some(source)) => this.clone_from(source), 422ef40d7f6Sopenharmony_ci _ => *self = source.clone(), 423ef40d7f6Sopenharmony_ci } 424ef40d7f6Sopenharmony_ci } 425ef40d7f6Sopenharmony_ci } 426ef40d7f6Sopenharmony_ci 427ef40d7f6Sopenharmony_ci impl<T: PartialEq> PartialEq for OnceCell<T> { 428ef40d7f6Sopenharmony_ci fn eq(&self, other: &Self) -> bool { 429ef40d7f6Sopenharmony_ci self.get() == other.get() 430ef40d7f6Sopenharmony_ci } 431ef40d7f6Sopenharmony_ci } 432ef40d7f6Sopenharmony_ci 433ef40d7f6Sopenharmony_ci impl<T: Eq> Eq for OnceCell<T> {} 434ef40d7f6Sopenharmony_ci 435ef40d7f6Sopenharmony_ci impl<T> From<T> for OnceCell<T> { 436ef40d7f6Sopenharmony_ci fn from(value: T) -> Self { 437ef40d7f6Sopenharmony_ci OnceCell::with_value(value) 438ef40d7f6Sopenharmony_ci } 439ef40d7f6Sopenharmony_ci } 440ef40d7f6Sopenharmony_ci 441ef40d7f6Sopenharmony_ci impl<T> OnceCell<T> { 442ef40d7f6Sopenharmony_ci /// Creates a new empty cell. 443ef40d7f6Sopenharmony_ci pub const fn new() -> OnceCell<T> { 444ef40d7f6Sopenharmony_ci OnceCell { inner: UnsafeCell::new(None) } 445ef40d7f6Sopenharmony_ci } 446ef40d7f6Sopenharmony_ci 447ef40d7f6Sopenharmony_ci /// Creates a new initialized cell. 448ef40d7f6Sopenharmony_ci pub const fn with_value(value: T) -> OnceCell<T> { 449ef40d7f6Sopenharmony_ci OnceCell { inner: UnsafeCell::new(Some(value)) } 450ef40d7f6Sopenharmony_ci } 451ef40d7f6Sopenharmony_ci 452ef40d7f6Sopenharmony_ci /// Gets a reference to the underlying value. 453ef40d7f6Sopenharmony_ci /// 454ef40d7f6Sopenharmony_ci /// Returns `None` if the cell is empty. 455ef40d7f6Sopenharmony_ci #[inline] 456ef40d7f6Sopenharmony_ci pub fn get(&self) -> Option<&T> { 457ef40d7f6Sopenharmony_ci // Safe due to `inner`'s invariant 458ef40d7f6Sopenharmony_ci unsafe { &*self.inner.get() }.as_ref() 459ef40d7f6Sopenharmony_ci } 460ef40d7f6Sopenharmony_ci 461ef40d7f6Sopenharmony_ci /// Gets a mutable reference to the underlying value. 462ef40d7f6Sopenharmony_ci /// 463ef40d7f6Sopenharmony_ci /// Returns `None` if the cell is empty. 464ef40d7f6Sopenharmony_ci /// 465ef40d7f6Sopenharmony_ci /// This method is allowed to violate the invariant of writing to a `OnceCell` 466ef40d7f6Sopenharmony_ci /// at most once because it requires `&mut` access to `self`. As with all 467ef40d7f6Sopenharmony_ci /// interior mutability, `&mut` access permits arbitrary modification: 468ef40d7f6Sopenharmony_ci /// 469ef40d7f6Sopenharmony_ci /// ``` 470ef40d7f6Sopenharmony_ci /// use once_cell::unsync::OnceCell; 471ef40d7f6Sopenharmony_ci /// 472ef40d7f6Sopenharmony_ci /// let mut cell: OnceCell<u32> = OnceCell::new(); 473ef40d7f6Sopenharmony_ci /// cell.set(92).unwrap(); 474ef40d7f6Sopenharmony_ci /// *cell.get_mut().unwrap() = 93; 475ef40d7f6Sopenharmony_ci /// assert_eq!(cell.get(), Some(&93)); 476ef40d7f6Sopenharmony_ci /// ``` 477ef40d7f6Sopenharmony_ci #[inline] 478ef40d7f6Sopenharmony_ci pub fn get_mut(&mut self) -> Option<&mut T> { 479ef40d7f6Sopenharmony_ci // Safe because we have unique access 480ef40d7f6Sopenharmony_ci unsafe { &mut *self.inner.get() }.as_mut() 481ef40d7f6Sopenharmony_ci } 482ef40d7f6Sopenharmony_ci 483ef40d7f6Sopenharmony_ci /// Sets the contents of this cell to `value`. 484ef40d7f6Sopenharmony_ci /// 485ef40d7f6Sopenharmony_ci /// Returns `Ok(())` if the cell was empty and `Err(value)` if it was 486ef40d7f6Sopenharmony_ci /// full. 487ef40d7f6Sopenharmony_ci /// 488ef40d7f6Sopenharmony_ci /// # Example 489ef40d7f6Sopenharmony_ci /// ``` 490ef40d7f6Sopenharmony_ci /// use once_cell::unsync::OnceCell; 491ef40d7f6Sopenharmony_ci /// 492ef40d7f6Sopenharmony_ci /// let cell = OnceCell::new(); 493ef40d7f6Sopenharmony_ci /// assert!(cell.get().is_none()); 494ef40d7f6Sopenharmony_ci /// 495ef40d7f6Sopenharmony_ci /// assert_eq!(cell.set(92), Ok(())); 496ef40d7f6Sopenharmony_ci /// assert_eq!(cell.set(62), Err(62)); 497ef40d7f6Sopenharmony_ci /// 498ef40d7f6Sopenharmony_ci /// assert!(cell.get().is_some()); 499ef40d7f6Sopenharmony_ci /// ``` 500ef40d7f6Sopenharmony_ci pub fn set(&self, value: T) -> Result<(), T> { 501ef40d7f6Sopenharmony_ci match self.try_insert(value) { 502ef40d7f6Sopenharmony_ci Ok(_) => Ok(()), 503ef40d7f6Sopenharmony_ci Err((_, value)) => Err(value), 504ef40d7f6Sopenharmony_ci } 505ef40d7f6Sopenharmony_ci } 506ef40d7f6Sopenharmony_ci 507ef40d7f6Sopenharmony_ci /// Like [`set`](Self::set), but also returns a reference to the final cell value. 508ef40d7f6Sopenharmony_ci /// 509ef40d7f6Sopenharmony_ci /// # Example 510ef40d7f6Sopenharmony_ci /// ``` 511ef40d7f6Sopenharmony_ci /// use once_cell::unsync::OnceCell; 512ef40d7f6Sopenharmony_ci /// 513ef40d7f6Sopenharmony_ci /// let cell = OnceCell::new(); 514ef40d7f6Sopenharmony_ci /// assert!(cell.get().is_none()); 515ef40d7f6Sopenharmony_ci /// 516ef40d7f6Sopenharmony_ci /// assert_eq!(cell.try_insert(92), Ok(&92)); 517ef40d7f6Sopenharmony_ci /// assert_eq!(cell.try_insert(62), Err((&92, 62))); 518ef40d7f6Sopenharmony_ci /// 519ef40d7f6Sopenharmony_ci /// assert!(cell.get().is_some()); 520ef40d7f6Sopenharmony_ci /// ``` 521ef40d7f6Sopenharmony_ci pub fn try_insert(&self, value: T) -> Result<&T, (&T, T)> { 522ef40d7f6Sopenharmony_ci if let Some(old) = self.get() { 523ef40d7f6Sopenharmony_ci return Err((old, value)); 524ef40d7f6Sopenharmony_ci } 525ef40d7f6Sopenharmony_ci 526ef40d7f6Sopenharmony_ci let slot = unsafe { &mut *self.inner.get() }; 527ef40d7f6Sopenharmony_ci // This is the only place where we set the slot, no races 528ef40d7f6Sopenharmony_ci // due to reentrancy/concurrency are possible, and we've 529ef40d7f6Sopenharmony_ci // checked that slot is currently `None`, so this write 530ef40d7f6Sopenharmony_ci // maintains the `inner`'s invariant. 531ef40d7f6Sopenharmony_ci *slot = Some(value); 532ef40d7f6Sopenharmony_ci Ok(unsafe { unwrap_unchecked(slot.as_ref()) }) 533ef40d7f6Sopenharmony_ci } 534ef40d7f6Sopenharmony_ci 535ef40d7f6Sopenharmony_ci /// Gets the contents of the cell, initializing it with `f` 536ef40d7f6Sopenharmony_ci /// if the cell was empty. 537ef40d7f6Sopenharmony_ci /// 538ef40d7f6Sopenharmony_ci /// # Panics 539ef40d7f6Sopenharmony_ci /// 540ef40d7f6Sopenharmony_ci /// If `f` panics, the panic is propagated to the caller, and the cell 541ef40d7f6Sopenharmony_ci /// remains uninitialized. 542ef40d7f6Sopenharmony_ci /// 543ef40d7f6Sopenharmony_ci /// It is an error to reentrantly initialize the cell from `f`. Doing 544ef40d7f6Sopenharmony_ci /// so results in a panic. 545ef40d7f6Sopenharmony_ci /// 546ef40d7f6Sopenharmony_ci /// # Example 547ef40d7f6Sopenharmony_ci /// ``` 548ef40d7f6Sopenharmony_ci /// use once_cell::unsync::OnceCell; 549ef40d7f6Sopenharmony_ci /// 550ef40d7f6Sopenharmony_ci /// let cell = OnceCell::new(); 551ef40d7f6Sopenharmony_ci /// let value = cell.get_or_init(|| 92); 552ef40d7f6Sopenharmony_ci /// assert_eq!(value, &92); 553ef40d7f6Sopenharmony_ci /// let value = cell.get_or_init(|| unreachable!()); 554ef40d7f6Sopenharmony_ci /// assert_eq!(value, &92); 555ef40d7f6Sopenharmony_ci /// ``` 556ef40d7f6Sopenharmony_ci pub fn get_or_init<F>(&self, f: F) -> &T 557ef40d7f6Sopenharmony_ci where 558ef40d7f6Sopenharmony_ci F: FnOnce() -> T, 559ef40d7f6Sopenharmony_ci { 560ef40d7f6Sopenharmony_ci enum Void {} 561ef40d7f6Sopenharmony_ci match self.get_or_try_init(|| Ok::<T, Void>(f())) { 562ef40d7f6Sopenharmony_ci Ok(val) => val, 563ef40d7f6Sopenharmony_ci Err(void) => match void {}, 564ef40d7f6Sopenharmony_ci } 565ef40d7f6Sopenharmony_ci } 566ef40d7f6Sopenharmony_ci 567ef40d7f6Sopenharmony_ci /// Gets the contents of the cell, initializing it with `f` if 568ef40d7f6Sopenharmony_ci /// the cell was empty. If the cell was empty and `f` failed, an 569ef40d7f6Sopenharmony_ci /// error is returned. 570ef40d7f6Sopenharmony_ci /// 571ef40d7f6Sopenharmony_ci /// # Panics 572ef40d7f6Sopenharmony_ci /// 573ef40d7f6Sopenharmony_ci /// If `f` panics, the panic is propagated to the caller, and the cell 574ef40d7f6Sopenharmony_ci /// remains uninitialized. 575ef40d7f6Sopenharmony_ci /// 576ef40d7f6Sopenharmony_ci /// It is an error to reentrantly initialize the cell from `f`. Doing 577ef40d7f6Sopenharmony_ci /// so results in a panic. 578ef40d7f6Sopenharmony_ci /// 579ef40d7f6Sopenharmony_ci /// # Example 580ef40d7f6Sopenharmony_ci /// ``` 581ef40d7f6Sopenharmony_ci /// use once_cell::unsync::OnceCell; 582ef40d7f6Sopenharmony_ci /// 583ef40d7f6Sopenharmony_ci /// let cell = OnceCell::new(); 584ef40d7f6Sopenharmony_ci /// assert_eq!(cell.get_or_try_init(|| Err(())), Err(())); 585ef40d7f6Sopenharmony_ci /// assert!(cell.get().is_none()); 586ef40d7f6Sopenharmony_ci /// let value = cell.get_or_try_init(|| -> Result<i32, ()> { 587ef40d7f6Sopenharmony_ci /// Ok(92) 588ef40d7f6Sopenharmony_ci /// }); 589ef40d7f6Sopenharmony_ci /// assert_eq!(value, Ok(&92)); 590ef40d7f6Sopenharmony_ci /// assert_eq!(cell.get(), Some(&92)) 591ef40d7f6Sopenharmony_ci /// ``` 592ef40d7f6Sopenharmony_ci pub fn get_or_try_init<F, E>(&self, f: F) -> Result<&T, E> 593ef40d7f6Sopenharmony_ci where 594ef40d7f6Sopenharmony_ci F: FnOnce() -> Result<T, E>, 595ef40d7f6Sopenharmony_ci { 596ef40d7f6Sopenharmony_ci if let Some(val) = self.get() { 597ef40d7f6Sopenharmony_ci return Ok(val); 598ef40d7f6Sopenharmony_ci } 599ef40d7f6Sopenharmony_ci let val = f()?; 600ef40d7f6Sopenharmony_ci // Note that *some* forms of reentrant initialization might lead to 601ef40d7f6Sopenharmony_ci // UB (see `reentrant_init` test). I believe that just removing this 602ef40d7f6Sopenharmony_ci // `assert`, while keeping `set/get` would be sound, but it seems 603ef40d7f6Sopenharmony_ci // better to panic, rather than to silently use an old value. 604ef40d7f6Sopenharmony_ci assert!(self.set(val).is_ok(), "reentrant init"); 605ef40d7f6Sopenharmony_ci Ok(unsafe { unwrap_unchecked(self.get()) }) 606ef40d7f6Sopenharmony_ci } 607ef40d7f6Sopenharmony_ci 608ef40d7f6Sopenharmony_ci /// Takes the value out of this `OnceCell`, moving it back to an uninitialized state. 609ef40d7f6Sopenharmony_ci /// 610ef40d7f6Sopenharmony_ci /// Has no effect and returns `None` if the `OnceCell` hasn't been initialized. 611ef40d7f6Sopenharmony_ci /// 612ef40d7f6Sopenharmony_ci /// # Examples 613ef40d7f6Sopenharmony_ci /// 614ef40d7f6Sopenharmony_ci /// ``` 615ef40d7f6Sopenharmony_ci /// use once_cell::unsync::OnceCell; 616ef40d7f6Sopenharmony_ci /// 617ef40d7f6Sopenharmony_ci /// let mut cell: OnceCell<String> = OnceCell::new(); 618ef40d7f6Sopenharmony_ci /// assert_eq!(cell.take(), None); 619ef40d7f6Sopenharmony_ci /// 620ef40d7f6Sopenharmony_ci /// let mut cell = OnceCell::new(); 621ef40d7f6Sopenharmony_ci /// cell.set("hello".to_string()).unwrap(); 622ef40d7f6Sopenharmony_ci /// assert_eq!(cell.take(), Some("hello".to_string())); 623ef40d7f6Sopenharmony_ci /// assert_eq!(cell.get(), None); 624ef40d7f6Sopenharmony_ci /// ``` 625ef40d7f6Sopenharmony_ci /// 626ef40d7f6Sopenharmony_ci /// This method is allowed to violate the invariant of writing to a `OnceCell` 627ef40d7f6Sopenharmony_ci /// at most once because it requires `&mut` access to `self`. As with all 628ef40d7f6Sopenharmony_ci /// interior mutability, `&mut` access permits arbitrary modification: 629ef40d7f6Sopenharmony_ci /// 630ef40d7f6Sopenharmony_ci /// ``` 631ef40d7f6Sopenharmony_ci /// use once_cell::unsync::OnceCell; 632ef40d7f6Sopenharmony_ci /// 633ef40d7f6Sopenharmony_ci /// let mut cell: OnceCell<u32> = OnceCell::new(); 634ef40d7f6Sopenharmony_ci /// cell.set(92).unwrap(); 635ef40d7f6Sopenharmony_ci /// cell = OnceCell::new(); 636ef40d7f6Sopenharmony_ci /// ``` 637ef40d7f6Sopenharmony_ci pub fn take(&mut self) -> Option<T> { 638ef40d7f6Sopenharmony_ci mem::replace(self, Self::default()).into_inner() 639ef40d7f6Sopenharmony_ci } 640ef40d7f6Sopenharmony_ci 641ef40d7f6Sopenharmony_ci /// Consumes the `OnceCell`, returning the wrapped value. 642ef40d7f6Sopenharmony_ci /// 643ef40d7f6Sopenharmony_ci /// Returns `None` if the cell was empty. 644ef40d7f6Sopenharmony_ci /// 645ef40d7f6Sopenharmony_ci /// # Examples 646ef40d7f6Sopenharmony_ci /// 647ef40d7f6Sopenharmony_ci /// ``` 648ef40d7f6Sopenharmony_ci /// use once_cell::unsync::OnceCell; 649ef40d7f6Sopenharmony_ci /// 650ef40d7f6Sopenharmony_ci /// let cell: OnceCell<String> = OnceCell::new(); 651ef40d7f6Sopenharmony_ci /// assert_eq!(cell.into_inner(), None); 652ef40d7f6Sopenharmony_ci /// 653ef40d7f6Sopenharmony_ci /// let cell = OnceCell::new(); 654ef40d7f6Sopenharmony_ci /// cell.set("hello".to_string()).unwrap(); 655ef40d7f6Sopenharmony_ci /// assert_eq!(cell.into_inner(), Some("hello".to_string())); 656ef40d7f6Sopenharmony_ci /// ``` 657ef40d7f6Sopenharmony_ci pub fn into_inner(self) -> Option<T> { 658ef40d7f6Sopenharmony_ci // Because `into_inner` takes `self` by value, the compiler statically verifies 659ef40d7f6Sopenharmony_ci // that it is not currently borrowed. So it is safe to move out `Option<T>`. 660ef40d7f6Sopenharmony_ci self.inner.into_inner() 661ef40d7f6Sopenharmony_ci } 662ef40d7f6Sopenharmony_ci } 663ef40d7f6Sopenharmony_ci 664ef40d7f6Sopenharmony_ci /// A value which is initialized on the first access. 665ef40d7f6Sopenharmony_ci /// 666ef40d7f6Sopenharmony_ci /// # Example 667ef40d7f6Sopenharmony_ci /// ``` 668ef40d7f6Sopenharmony_ci /// use once_cell::unsync::Lazy; 669ef40d7f6Sopenharmony_ci /// 670ef40d7f6Sopenharmony_ci /// let lazy: Lazy<i32> = Lazy::new(|| { 671ef40d7f6Sopenharmony_ci /// println!("initializing"); 672ef40d7f6Sopenharmony_ci /// 92 673ef40d7f6Sopenharmony_ci /// }); 674ef40d7f6Sopenharmony_ci /// println!("ready"); 675ef40d7f6Sopenharmony_ci /// println!("{}", *lazy); 676ef40d7f6Sopenharmony_ci /// println!("{}", *lazy); 677ef40d7f6Sopenharmony_ci /// 678ef40d7f6Sopenharmony_ci /// // Prints: 679ef40d7f6Sopenharmony_ci /// // ready 680ef40d7f6Sopenharmony_ci /// // initializing 681ef40d7f6Sopenharmony_ci /// // 92 682ef40d7f6Sopenharmony_ci /// // 92 683ef40d7f6Sopenharmony_ci /// ``` 684ef40d7f6Sopenharmony_ci pub struct Lazy<T, F = fn() -> T> { 685ef40d7f6Sopenharmony_ci cell: OnceCell<T>, 686ef40d7f6Sopenharmony_ci init: Cell<Option<F>>, 687ef40d7f6Sopenharmony_ci } 688ef40d7f6Sopenharmony_ci 689ef40d7f6Sopenharmony_ci impl<T, F: RefUnwindSafe> RefUnwindSafe for Lazy<T, F> where OnceCell<T>: RefUnwindSafe {} 690ef40d7f6Sopenharmony_ci 691ef40d7f6Sopenharmony_ci impl<T: fmt::Debug, F> fmt::Debug for Lazy<T, F> { 692ef40d7f6Sopenharmony_ci fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 693ef40d7f6Sopenharmony_ci f.debug_struct("Lazy").field("cell", &self.cell).field("init", &"..").finish() 694ef40d7f6Sopenharmony_ci } 695ef40d7f6Sopenharmony_ci } 696ef40d7f6Sopenharmony_ci 697ef40d7f6Sopenharmony_ci impl<T, F> Lazy<T, F> { 698ef40d7f6Sopenharmony_ci /// Creates a new lazy value with the given initializing function. 699ef40d7f6Sopenharmony_ci /// 700ef40d7f6Sopenharmony_ci /// # Example 701ef40d7f6Sopenharmony_ci /// ``` 702ef40d7f6Sopenharmony_ci /// # fn main() { 703ef40d7f6Sopenharmony_ci /// use once_cell::unsync::Lazy; 704ef40d7f6Sopenharmony_ci /// 705ef40d7f6Sopenharmony_ci /// let hello = "Hello, World!".to_string(); 706ef40d7f6Sopenharmony_ci /// 707ef40d7f6Sopenharmony_ci /// let lazy = Lazy::new(|| hello.to_uppercase()); 708ef40d7f6Sopenharmony_ci /// 709ef40d7f6Sopenharmony_ci /// assert_eq!(&*lazy, "HELLO, WORLD!"); 710ef40d7f6Sopenharmony_ci /// # } 711ef40d7f6Sopenharmony_ci /// ``` 712ef40d7f6Sopenharmony_ci pub const fn new(init: F) -> Lazy<T, F> { 713ef40d7f6Sopenharmony_ci Lazy { cell: OnceCell::new(), init: Cell::new(Some(init)) } 714ef40d7f6Sopenharmony_ci } 715ef40d7f6Sopenharmony_ci 716ef40d7f6Sopenharmony_ci /// Consumes this `Lazy` returning the stored value. 717ef40d7f6Sopenharmony_ci /// 718ef40d7f6Sopenharmony_ci /// Returns `Ok(value)` if `Lazy` is initialized and `Err(f)` otherwise. 719ef40d7f6Sopenharmony_ci pub fn into_value(this: Lazy<T, F>) -> Result<T, F> { 720ef40d7f6Sopenharmony_ci let cell = this.cell; 721ef40d7f6Sopenharmony_ci let init = this.init; 722ef40d7f6Sopenharmony_ci cell.into_inner().ok_or_else(|| { 723ef40d7f6Sopenharmony_ci init.take().unwrap_or_else(|| panic!("Lazy instance has previously been poisoned")) 724ef40d7f6Sopenharmony_ci }) 725ef40d7f6Sopenharmony_ci } 726ef40d7f6Sopenharmony_ci } 727ef40d7f6Sopenharmony_ci 728ef40d7f6Sopenharmony_ci impl<T, F: FnOnce() -> T> Lazy<T, F> { 729ef40d7f6Sopenharmony_ci /// Forces the evaluation of this lazy value and returns a reference to 730ef40d7f6Sopenharmony_ci /// the result. 731ef40d7f6Sopenharmony_ci /// 732ef40d7f6Sopenharmony_ci /// This is equivalent to the `Deref` impl, but is explicit. 733ef40d7f6Sopenharmony_ci /// 734ef40d7f6Sopenharmony_ci /// # Example 735ef40d7f6Sopenharmony_ci /// ``` 736ef40d7f6Sopenharmony_ci /// use once_cell::unsync::Lazy; 737ef40d7f6Sopenharmony_ci /// 738ef40d7f6Sopenharmony_ci /// let lazy = Lazy::new(|| 92); 739ef40d7f6Sopenharmony_ci /// 740ef40d7f6Sopenharmony_ci /// assert_eq!(Lazy::force(&lazy), &92); 741ef40d7f6Sopenharmony_ci /// assert_eq!(&*lazy, &92); 742ef40d7f6Sopenharmony_ci /// ``` 743ef40d7f6Sopenharmony_ci pub fn force(this: &Lazy<T, F>) -> &T { 744ef40d7f6Sopenharmony_ci this.cell.get_or_init(|| match this.init.take() { 745ef40d7f6Sopenharmony_ci Some(f) => f(), 746ef40d7f6Sopenharmony_ci None => panic!("Lazy instance has previously been poisoned"), 747ef40d7f6Sopenharmony_ci }) 748ef40d7f6Sopenharmony_ci } 749ef40d7f6Sopenharmony_ci 750ef40d7f6Sopenharmony_ci /// Forces the evaluation of this lazy value and returns a mutable reference to 751ef40d7f6Sopenharmony_ci /// the result. 752ef40d7f6Sopenharmony_ci /// 753ef40d7f6Sopenharmony_ci /// This is equivalent to the `DerefMut` impl, but is explicit. 754ef40d7f6Sopenharmony_ci /// 755ef40d7f6Sopenharmony_ci /// # Example 756ef40d7f6Sopenharmony_ci /// ``` 757ef40d7f6Sopenharmony_ci /// use once_cell::unsync::Lazy; 758ef40d7f6Sopenharmony_ci /// 759ef40d7f6Sopenharmony_ci /// let mut lazy = Lazy::new(|| 92); 760ef40d7f6Sopenharmony_ci /// 761ef40d7f6Sopenharmony_ci /// assert_eq!(Lazy::force_mut(&mut lazy), &92); 762ef40d7f6Sopenharmony_ci /// assert_eq!(*lazy, 92); 763ef40d7f6Sopenharmony_ci /// ``` 764ef40d7f6Sopenharmony_ci pub fn force_mut(this: &mut Lazy<T, F>) -> &mut T { 765ef40d7f6Sopenharmony_ci Self::force(this); 766ef40d7f6Sopenharmony_ci Self::get_mut(this).unwrap_or_else(|| unreachable!()) 767ef40d7f6Sopenharmony_ci } 768ef40d7f6Sopenharmony_ci 769ef40d7f6Sopenharmony_ci /// Gets the reference to the result of this lazy value if 770ef40d7f6Sopenharmony_ci /// it was initialized, otherwise returns `None`. 771ef40d7f6Sopenharmony_ci /// 772ef40d7f6Sopenharmony_ci /// # Example 773ef40d7f6Sopenharmony_ci /// ``` 774ef40d7f6Sopenharmony_ci /// use once_cell::unsync::Lazy; 775ef40d7f6Sopenharmony_ci /// 776ef40d7f6Sopenharmony_ci /// let lazy = Lazy::new(|| 92); 777ef40d7f6Sopenharmony_ci /// 778ef40d7f6Sopenharmony_ci /// assert_eq!(Lazy::get(&lazy), None); 779ef40d7f6Sopenharmony_ci /// assert_eq!(&*lazy, &92); 780ef40d7f6Sopenharmony_ci /// assert_eq!(Lazy::get(&lazy), Some(&92)); 781ef40d7f6Sopenharmony_ci /// ``` 782ef40d7f6Sopenharmony_ci pub fn get(this: &Lazy<T, F>) -> Option<&T> { 783ef40d7f6Sopenharmony_ci this.cell.get() 784ef40d7f6Sopenharmony_ci } 785ef40d7f6Sopenharmony_ci 786ef40d7f6Sopenharmony_ci /// Gets the mutable reference to the result of this lazy value if 787ef40d7f6Sopenharmony_ci /// it was initialized, otherwise returns `None`. 788ef40d7f6Sopenharmony_ci /// 789ef40d7f6Sopenharmony_ci /// # Example 790ef40d7f6Sopenharmony_ci /// ``` 791ef40d7f6Sopenharmony_ci /// use once_cell::unsync::Lazy; 792ef40d7f6Sopenharmony_ci /// 793ef40d7f6Sopenharmony_ci /// let mut lazy = Lazy::new(|| 92); 794ef40d7f6Sopenharmony_ci /// 795ef40d7f6Sopenharmony_ci /// assert_eq!(Lazy::get_mut(&mut lazy), None); 796ef40d7f6Sopenharmony_ci /// assert_eq!(*lazy, 92); 797ef40d7f6Sopenharmony_ci /// assert_eq!(Lazy::get_mut(&mut lazy), Some(&mut 92)); 798ef40d7f6Sopenharmony_ci /// ``` 799ef40d7f6Sopenharmony_ci pub fn get_mut(this: &mut Lazy<T, F>) -> Option<&mut T> { 800ef40d7f6Sopenharmony_ci this.cell.get_mut() 801ef40d7f6Sopenharmony_ci } 802ef40d7f6Sopenharmony_ci } 803ef40d7f6Sopenharmony_ci 804ef40d7f6Sopenharmony_ci impl<T, F: FnOnce() -> T> Deref for Lazy<T, F> { 805ef40d7f6Sopenharmony_ci type Target = T; 806ef40d7f6Sopenharmony_ci fn deref(&self) -> &T { 807ef40d7f6Sopenharmony_ci Lazy::force(self) 808ef40d7f6Sopenharmony_ci } 809ef40d7f6Sopenharmony_ci } 810ef40d7f6Sopenharmony_ci 811ef40d7f6Sopenharmony_ci impl<T, F: FnOnce() -> T> DerefMut for Lazy<T, F> { 812ef40d7f6Sopenharmony_ci fn deref_mut(&mut self) -> &mut T { 813ef40d7f6Sopenharmony_ci Lazy::force(self); 814ef40d7f6Sopenharmony_ci self.cell.get_mut().unwrap_or_else(|| unreachable!()) 815ef40d7f6Sopenharmony_ci } 816ef40d7f6Sopenharmony_ci } 817ef40d7f6Sopenharmony_ci 818ef40d7f6Sopenharmony_ci impl<T: Default> Default for Lazy<T> { 819ef40d7f6Sopenharmony_ci /// Creates a new lazy value using `Default` as the initializing function. 820ef40d7f6Sopenharmony_ci fn default() -> Lazy<T> { 821ef40d7f6Sopenharmony_ci Lazy::new(T::default) 822ef40d7f6Sopenharmony_ci } 823ef40d7f6Sopenharmony_ci } 824ef40d7f6Sopenharmony_ci} 825ef40d7f6Sopenharmony_ci 826ef40d7f6Sopenharmony_ci/// Thread-safe, blocking version of `OnceCell`. 827ef40d7f6Sopenharmony_ci#[cfg(any(feature = "std", feature = "critical-section"))] 828ef40d7f6Sopenharmony_cipub mod sync { 829ef40d7f6Sopenharmony_ci use core::{ 830ef40d7f6Sopenharmony_ci cell::Cell, 831ef40d7f6Sopenharmony_ci fmt, mem, 832ef40d7f6Sopenharmony_ci ops::{Deref, DerefMut}, 833ef40d7f6Sopenharmony_ci panic::RefUnwindSafe, 834ef40d7f6Sopenharmony_ci }; 835ef40d7f6Sopenharmony_ci 836ef40d7f6Sopenharmony_ci use super::{imp::OnceCell as Imp, unwrap_unchecked}; 837ef40d7f6Sopenharmony_ci 838ef40d7f6Sopenharmony_ci /// A thread-safe cell which can be written to only once. 839ef40d7f6Sopenharmony_ci /// 840ef40d7f6Sopenharmony_ci /// `OnceCell` provides `&` references to the contents without RAII guards. 841ef40d7f6Sopenharmony_ci /// 842ef40d7f6Sopenharmony_ci /// Reading a non-`None` value out of `OnceCell` establishes a 843ef40d7f6Sopenharmony_ci /// happens-before relationship with a corresponding write. For example, if 844ef40d7f6Sopenharmony_ci /// thread A initializes the cell with `get_or_init(f)`, and thread B 845ef40d7f6Sopenharmony_ci /// subsequently reads the result of this call, B also observes all the side 846ef40d7f6Sopenharmony_ci /// effects of `f`. 847ef40d7f6Sopenharmony_ci /// 848ef40d7f6Sopenharmony_ci /// # Example 849ef40d7f6Sopenharmony_ci /// ``` 850ef40d7f6Sopenharmony_ci /// use once_cell::sync::OnceCell; 851ef40d7f6Sopenharmony_ci /// 852ef40d7f6Sopenharmony_ci /// static CELL: OnceCell<String> = OnceCell::new(); 853ef40d7f6Sopenharmony_ci /// assert!(CELL.get().is_none()); 854ef40d7f6Sopenharmony_ci /// 855ef40d7f6Sopenharmony_ci /// std::thread::spawn(|| { 856ef40d7f6Sopenharmony_ci /// let value: &String = CELL.get_or_init(|| { 857ef40d7f6Sopenharmony_ci /// "Hello, World!".to_string() 858ef40d7f6Sopenharmony_ci /// }); 859ef40d7f6Sopenharmony_ci /// assert_eq!(value, "Hello, World!"); 860ef40d7f6Sopenharmony_ci /// }).join().unwrap(); 861ef40d7f6Sopenharmony_ci /// 862ef40d7f6Sopenharmony_ci /// let value: Option<&String> = CELL.get(); 863ef40d7f6Sopenharmony_ci /// assert!(value.is_some()); 864ef40d7f6Sopenharmony_ci /// assert_eq!(value.unwrap().as_str(), "Hello, World!"); 865ef40d7f6Sopenharmony_ci /// ``` 866ef40d7f6Sopenharmony_ci pub struct OnceCell<T>(Imp<T>); 867ef40d7f6Sopenharmony_ci 868ef40d7f6Sopenharmony_ci impl<T> Default for OnceCell<T> { 869ef40d7f6Sopenharmony_ci fn default() -> OnceCell<T> { 870ef40d7f6Sopenharmony_ci OnceCell::new() 871ef40d7f6Sopenharmony_ci } 872ef40d7f6Sopenharmony_ci } 873ef40d7f6Sopenharmony_ci 874ef40d7f6Sopenharmony_ci impl<T: fmt::Debug> fmt::Debug for OnceCell<T> { 875ef40d7f6Sopenharmony_ci fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 876ef40d7f6Sopenharmony_ci match self.get() { 877ef40d7f6Sopenharmony_ci Some(v) => f.debug_tuple("OnceCell").field(v).finish(), 878ef40d7f6Sopenharmony_ci None => f.write_str("OnceCell(Uninit)"), 879ef40d7f6Sopenharmony_ci } 880ef40d7f6Sopenharmony_ci } 881ef40d7f6Sopenharmony_ci } 882ef40d7f6Sopenharmony_ci 883ef40d7f6Sopenharmony_ci impl<T: Clone> Clone for OnceCell<T> { 884ef40d7f6Sopenharmony_ci fn clone(&self) -> OnceCell<T> { 885ef40d7f6Sopenharmony_ci match self.get() { 886ef40d7f6Sopenharmony_ci Some(value) => Self::with_value(value.clone()), 887ef40d7f6Sopenharmony_ci None => Self::new(), 888ef40d7f6Sopenharmony_ci } 889ef40d7f6Sopenharmony_ci } 890ef40d7f6Sopenharmony_ci 891ef40d7f6Sopenharmony_ci fn clone_from(&mut self, source: &Self) { 892ef40d7f6Sopenharmony_ci match (self.get_mut(), source.get()) { 893ef40d7f6Sopenharmony_ci (Some(this), Some(source)) => this.clone_from(source), 894ef40d7f6Sopenharmony_ci _ => *self = source.clone(), 895ef40d7f6Sopenharmony_ci } 896ef40d7f6Sopenharmony_ci } 897ef40d7f6Sopenharmony_ci } 898ef40d7f6Sopenharmony_ci 899ef40d7f6Sopenharmony_ci impl<T> From<T> for OnceCell<T> { 900ef40d7f6Sopenharmony_ci fn from(value: T) -> Self { 901ef40d7f6Sopenharmony_ci Self::with_value(value) 902ef40d7f6Sopenharmony_ci } 903ef40d7f6Sopenharmony_ci } 904ef40d7f6Sopenharmony_ci 905ef40d7f6Sopenharmony_ci impl<T: PartialEq> PartialEq for OnceCell<T> { 906ef40d7f6Sopenharmony_ci fn eq(&self, other: &OnceCell<T>) -> bool { 907ef40d7f6Sopenharmony_ci self.get() == other.get() 908ef40d7f6Sopenharmony_ci } 909ef40d7f6Sopenharmony_ci } 910ef40d7f6Sopenharmony_ci 911ef40d7f6Sopenharmony_ci impl<T: Eq> Eq for OnceCell<T> {} 912ef40d7f6Sopenharmony_ci 913ef40d7f6Sopenharmony_ci impl<T> OnceCell<T> { 914ef40d7f6Sopenharmony_ci /// Creates a new empty cell. 915ef40d7f6Sopenharmony_ci pub const fn new() -> OnceCell<T> { 916ef40d7f6Sopenharmony_ci OnceCell(Imp::new()) 917ef40d7f6Sopenharmony_ci } 918ef40d7f6Sopenharmony_ci 919ef40d7f6Sopenharmony_ci /// Creates a new initialized cell. 920ef40d7f6Sopenharmony_ci pub const fn with_value(value: T) -> OnceCell<T> { 921ef40d7f6Sopenharmony_ci OnceCell(Imp::with_value(value)) 922ef40d7f6Sopenharmony_ci } 923ef40d7f6Sopenharmony_ci 924ef40d7f6Sopenharmony_ci /// Gets the reference to the underlying value. 925ef40d7f6Sopenharmony_ci /// 926ef40d7f6Sopenharmony_ci /// Returns `None` if the cell is empty, or being initialized. This 927ef40d7f6Sopenharmony_ci /// method never blocks. 928ef40d7f6Sopenharmony_ci pub fn get(&self) -> Option<&T> { 929ef40d7f6Sopenharmony_ci if self.0.is_initialized() { 930ef40d7f6Sopenharmony_ci // Safe b/c value is initialized. 931ef40d7f6Sopenharmony_ci Some(unsafe { self.get_unchecked() }) 932ef40d7f6Sopenharmony_ci } else { 933ef40d7f6Sopenharmony_ci None 934ef40d7f6Sopenharmony_ci } 935ef40d7f6Sopenharmony_ci } 936ef40d7f6Sopenharmony_ci 937ef40d7f6Sopenharmony_ci /// Gets the reference to the underlying value, blocking the current 938ef40d7f6Sopenharmony_ci /// thread until it is set. 939ef40d7f6Sopenharmony_ci /// 940ef40d7f6Sopenharmony_ci /// ``` 941ef40d7f6Sopenharmony_ci /// use once_cell::sync::OnceCell; 942ef40d7f6Sopenharmony_ci /// 943ef40d7f6Sopenharmony_ci /// let mut cell = std::sync::Arc::new(OnceCell::new()); 944ef40d7f6Sopenharmony_ci /// let t = std::thread::spawn({ 945ef40d7f6Sopenharmony_ci /// let cell = std::sync::Arc::clone(&cell); 946ef40d7f6Sopenharmony_ci /// move || cell.set(92).unwrap() 947ef40d7f6Sopenharmony_ci /// }); 948ef40d7f6Sopenharmony_ci /// 949ef40d7f6Sopenharmony_ci /// // Returns immediately, but might return None. 950ef40d7f6Sopenharmony_ci /// let _value_or_none = cell.get(); 951ef40d7f6Sopenharmony_ci /// 952ef40d7f6Sopenharmony_ci /// // Will return 92, but might block until the other thread does `.set`. 953ef40d7f6Sopenharmony_ci /// let value: &u32 = cell.wait(); 954ef40d7f6Sopenharmony_ci /// assert_eq!(*value, 92); 955ef40d7f6Sopenharmony_ci /// t.join().unwrap(); 956ef40d7f6Sopenharmony_ci /// ``` 957ef40d7f6Sopenharmony_ci #[cfg(feature = "std")] 958ef40d7f6Sopenharmony_ci pub fn wait(&self) -> &T { 959ef40d7f6Sopenharmony_ci if !self.0.is_initialized() { 960ef40d7f6Sopenharmony_ci self.0.wait() 961ef40d7f6Sopenharmony_ci } 962ef40d7f6Sopenharmony_ci debug_assert!(self.0.is_initialized()); 963ef40d7f6Sopenharmony_ci // Safe b/c of the wait call above and the fact that we didn't 964ef40d7f6Sopenharmony_ci // relinquish our borrow. 965ef40d7f6Sopenharmony_ci unsafe { self.get_unchecked() } 966ef40d7f6Sopenharmony_ci } 967ef40d7f6Sopenharmony_ci 968ef40d7f6Sopenharmony_ci /// Gets the mutable reference to the underlying value. 969ef40d7f6Sopenharmony_ci /// 970ef40d7f6Sopenharmony_ci /// Returns `None` if the cell is empty. 971ef40d7f6Sopenharmony_ci /// 972ef40d7f6Sopenharmony_ci /// This method is allowed to violate the invariant of writing to a `OnceCell` 973ef40d7f6Sopenharmony_ci /// at most once because it requires `&mut` access to `self`. As with all 974ef40d7f6Sopenharmony_ci /// interior mutability, `&mut` access permits arbitrary modification: 975ef40d7f6Sopenharmony_ci /// 976ef40d7f6Sopenharmony_ci /// ``` 977ef40d7f6Sopenharmony_ci /// use once_cell::sync::OnceCell; 978ef40d7f6Sopenharmony_ci /// 979ef40d7f6Sopenharmony_ci /// let mut cell: OnceCell<u32> = OnceCell::new(); 980ef40d7f6Sopenharmony_ci /// cell.set(92).unwrap(); 981ef40d7f6Sopenharmony_ci /// cell = OnceCell::new(); 982ef40d7f6Sopenharmony_ci /// ``` 983ef40d7f6Sopenharmony_ci #[inline] 984ef40d7f6Sopenharmony_ci pub fn get_mut(&mut self) -> Option<&mut T> { 985ef40d7f6Sopenharmony_ci self.0.get_mut() 986ef40d7f6Sopenharmony_ci } 987ef40d7f6Sopenharmony_ci 988ef40d7f6Sopenharmony_ci /// Get the reference to the underlying value, without checking if the 989ef40d7f6Sopenharmony_ci /// cell is initialized. 990ef40d7f6Sopenharmony_ci /// 991ef40d7f6Sopenharmony_ci /// # Safety 992ef40d7f6Sopenharmony_ci /// 993ef40d7f6Sopenharmony_ci /// Caller must ensure that the cell is in initialized state, and that 994ef40d7f6Sopenharmony_ci /// the contents are acquired by (synchronized to) this thread. 995ef40d7f6Sopenharmony_ci #[inline] 996ef40d7f6Sopenharmony_ci pub unsafe fn get_unchecked(&self) -> &T { 997ef40d7f6Sopenharmony_ci self.0.get_unchecked() 998ef40d7f6Sopenharmony_ci } 999ef40d7f6Sopenharmony_ci 1000ef40d7f6Sopenharmony_ci /// Sets the contents of this cell to `value`. 1001ef40d7f6Sopenharmony_ci /// 1002ef40d7f6Sopenharmony_ci /// Returns `Ok(())` if the cell was empty and `Err(value)` if it was 1003ef40d7f6Sopenharmony_ci /// full. 1004ef40d7f6Sopenharmony_ci /// 1005ef40d7f6Sopenharmony_ci /// # Example 1006ef40d7f6Sopenharmony_ci /// 1007ef40d7f6Sopenharmony_ci /// ``` 1008ef40d7f6Sopenharmony_ci /// use once_cell::sync::OnceCell; 1009ef40d7f6Sopenharmony_ci /// 1010ef40d7f6Sopenharmony_ci /// static CELL: OnceCell<i32> = OnceCell::new(); 1011ef40d7f6Sopenharmony_ci /// 1012ef40d7f6Sopenharmony_ci /// fn main() { 1013ef40d7f6Sopenharmony_ci /// assert!(CELL.get().is_none()); 1014ef40d7f6Sopenharmony_ci /// 1015ef40d7f6Sopenharmony_ci /// std::thread::spawn(|| { 1016ef40d7f6Sopenharmony_ci /// assert_eq!(CELL.set(92), Ok(())); 1017ef40d7f6Sopenharmony_ci /// }).join().unwrap(); 1018ef40d7f6Sopenharmony_ci /// 1019ef40d7f6Sopenharmony_ci /// assert_eq!(CELL.set(62), Err(62)); 1020ef40d7f6Sopenharmony_ci /// assert_eq!(CELL.get(), Some(&92)); 1021ef40d7f6Sopenharmony_ci /// } 1022ef40d7f6Sopenharmony_ci /// ``` 1023ef40d7f6Sopenharmony_ci pub fn set(&self, value: T) -> Result<(), T> { 1024ef40d7f6Sopenharmony_ci match self.try_insert(value) { 1025ef40d7f6Sopenharmony_ci Ok(_) => Ok(()), 1026ef40d7f6Sopenharmony_ci Err((_, value)) => Err(value), 1027ef40d7f6Sopenharmony_ci } 1028ef40d7f6Sopenharmony_ci } 1029ef40d7f6Sopenharmony_ci 1030ef40d7f6Sopenharmony_ci /// Like [`set`](Self::set), but also returns a reference to the final cell value. 1031ef40d7f6Sopenharmony_ci /// 1032ef40d7f6Sopenharmony_ci /// # Example 1033ef40d7f6Sopenharmony_ci /// 1034ef40d7f6Sopenharmony_ci /// ``` 1035ef40d7f6Sopenharmony_ci /// use once_cell::unsync::OnceCell; 1036ef40d7f6Sopenharmony_ci /// 1037ef40d7f6Sopenharmony_ci /// let cell = OnceCell::new(); 1038ef40d7f6Sopenharmony_ci /// assert!(cell.get().is_none()); 1039ef40d7f6Sopenharmony_ci /// 1040ef40d7f6Sopenharmony_ci /// assert_eq!(cell.try_insert(92), Ok(&92)); 1041ef40d7f6Sopenharmony_ci /// assert_eq!(cell.try_insert(62), Err((&92, 62))); 1042ef40d7f6Sopenharmony_ci /// 1043ef40d7f6Sopenharmony_ci /// assert!(cell.get().is_some()); 1044ef40d7f6Sopenharmony_ci /// ``` 1045ef40d7f6Sopenharmony_ci pub fn try_insert(&self, value: T) -> Result<&T, (&T, T)> { 1046ef40d7f6Sopenharmony_ci let mut value = Some(value); 1047ef40d7f6Sopenharmony_ci let res = self.get_or_init(|| unsafe { unwrap_unchecked(value.take()) }); 1048ef40d7f6Sopenharmony_ci match value { 1049ef40d7f6Sopenharmony_ci None => Ok(res), 1050ef40d7f6Sopenharmony_ci Some(value) => Err((res, value)), 1051ef40d7f6Sopenharmony_ci } 1052ef40d7f6Sopenharmony_ci } 1053ef40d7f6Sopenharmony_ci 1054ef40d7f6Sopenharmony_ci /// Gets the contents of the cell, initializing it with `f` if the cell 1055ef40d7f6Sopenharmony_ci /// was empty. 1056ef40d7f6Sopenharmony_ci /// 1057ef40d7f6Sopenharmony_ci /// Many threads may call `get_or_init` concurrently with different 1058ef40d7f6Sopenharmony_ci /// initializing functions, but it is guaranteed that only one function 1059ef40d7f6Sopenharmony_ci /// will be executed. 1060ef40d7f6Sopenharmony_ci /// 1061ef40d7f6Sopenharmony_ci /// # Panics 1062ef40d7f6Sopenharmony_ci /// 1063ef40d7f6Sopenharmony_ci /// If `f` panics, the panic is propagated to the caller, and the cell 1064ef40d7f6Sopenharmony_ci /// remains uninitialized. 1065ef40d7f6Sopenharmony_ci /// 1066ef40d7f6Sopenharmony_ci /// It is an error to reentrantly initialize the cell from `f`. The 1067ef40d7f6Sopenharmony_ci /// exact outcome is unspecified. Current implementation deadlocks, but 1068ef40d7f6Sopenharmony_ci /// this may be changed to a panic in the future. 1069ef40d7f6Sopenharmony_ci /// 1070ef40d7f6Sopenharmony_ci /// # Example 1071ef40d7f6Sopenharmony_ci /// ``` 1072ef40d7f6Sopenharmony_ci /// use once_cell::sync::OnceCell; 1073ef40d7f6Sopenharmony_ci /// 1074ef40d7f6Sopenharmony_ci /// let cell = OnceCell::new(); 1075ef40d7f6Sopenharmony_ci /// let value = cell.get_or_init(|| 92); 1076ef40d7f6Sopenharmony_ci /// assert_eq!(value, &92); 1077ef40d7f6Sopenharmony_ci /// let value = cell.get_or_init(|| unreachable!()); 1078ef40d7f6Sopenharmony_ci /// assert_eq!(value, &92); 1079ef40d7f6Sopenharmony_ci /// ``` 1080ef40d7f6Sopenharmony_ci pub fn get_or_init<F>(&self, f: F) -> &T 1081ef40d7f6Sopenharmony_ci where 1082ef40d7f6Sopenharmony_ci F: FnOnce() -> T, 1083ef40d7f6Sopenharmony_ci { 1084ef40d7f6Sopenharmony_ci enum Void {} 1085ef40d7f6Sopenharmony_ci match self.get_or_try_init(|| Ok::<T, Void>(f())) { 1086ef40d7f6Sopenharmony_ci Ok(val) => val, 1087ef40d7f6Sopenharmony_ci Err(void) => match void {}, 1088ef40d7f6Sopenharmony_ci } 1089ef40d7f6Sopenharmony_ci } 1090ef40d7f6Sopenharmony_ci 1091ef40d7f6Sopenharmony_ci /// Gets the contents of the cell, initializing it with `f` if 1092ef40d7f6Sopenharmony_ci /// the cell was empty. If the cell was empty and `f` failed, an 1093ef40d7f6Sopenharmony_ci /// error is returned. 1094ef40d7f6Sopenharmony_ci /// 1095ef40d7f6Sopenharmony_ci /// # Panics 1096ef40d7f6Sopenharmony_ci /// 1097ef40d7f6Sopenharmony_ci /// If `f` panics, the panic is propagated to the caller, and 1098ef40d7f6Sopenharmony_ci /// the cell remains uninitialized. 1099ef40d7f6Sopenharmony_ci /// 1100ef40d7f6Sopenharmony_ci /// It is an error to reentrantly initialize the cell from `f`. 1101ef40d7f6Sopenharmony_ci /// The exact outcome is unspecified. Current implementation 1102ef40d7f6Sopenharmony_ci /// deadlocks, but this may be changed to a panic in the future. 1103ef40d7f6Sopenharmony_ci /// 1104ef40d7f6Sopenharmony_ci /// # Example 1105ef40d7f6Sopenharmony_ci /// ``` 1106ef40d7f6Sopenharmony_ci /// use once_cell::sync::OnceCell; 1107ef40d7f6Sopenharmony_ci /// 1108ef40d7f6Sopenharmony_ci /// let cell = OnceCell::new(); 1109ef40d7f6Sopenharmony_ci /// assert_eq!(cell.get_or_try_init(|| Err(())), Err(())); 1110ef40d7f6Sopenharmony_ci /// assert!(cell.get().is_none()); 1111ef40d7f6Sopenharmony_ci /// let value = cell.get_or_try_init(|| -> Result<i32, ()> { 1112ef40d7f6Sopenharmony_ci /// Ok(92) 1113ef40d7f6Sopenharmony_ci /// }); 1114ef40d7f6Sopenharmony_ci /// assert_eq!(value, Ok(&92)); 1115ef40d7f6Sopenharmony_ci /// assert_eq!(cell.get(), Some(&92)) 1116ef40d7f6Sopenharmony_ci /// ``` 1117ef40d7f6Sopenharmony_ci pub fn get_or_try_init<F, E>(&self, f: F) -> Result<&T, E> 1118ef40d7f6Sopenharmony_ci where 1119ef40d7f6Sopenharmony_ci F: FnOnce() -> Result<T, E>, 1120ef40d7f6Sopenharmony_ci { 1121ef40d7f6Sopenharmony_ci // Fast path check 1122ef40d7f6Sopenharmony_ci if let Some(value) = self.get() { 1123ef40d7f6Sopenharmony_ci return Ok(value); 1124ef40d7f6Sopenharmony_ci } 1125ef40d7f6Sopenharmony_ci 1126ef40d7f6Sopenharmony_ci self.0.initialize(f)?; 1127ef40d7f6Sopenharmony_ci 1128ef40d7f6Sopenharmony_ci // Safe b/c value is initialized. 1129ef40d7f6Sopenharmony_ci debug_assert!(self.0.is_initialized()); 1130ef40d7f6Sopenharmony_ci Ok(unsafe { self.get_unchecked() }) 1131ef40d7f6Sopenharmony_ci } 1132ef40d7f6Sopenharmony_ci 1133ef40d7f6Sopenharmony_ci /// Takes the value out of this `OnceCell`, moving it back to an uninitialized state. 1134ef40d7f6Sopenharmony_ci /// 1135ef40d7f6Sopenharmony_ci /// Has no effect and returns `None` if the `OnceCell` hasn't been initialized. 1136ef40d7f6Sopenharmony_ci /// 1137ef40d7f6Sopenharmony_ci /// # Examples 1138ef40d7f6Sopenharmony_ci /// 1139ef40d7f6Sopenharmony_ci /// ``` 1140ef40d7f6Sopenharmony_ci /// use once_cell::sync::OnceCell; 1141ef40d7f6Sopenharmony_ci /// 1142ef40d7f6Sopenharmony_ci /// let mut cell: OnceCell<String> = OnceCell::new(); 1143ef40d7f6Sopenharmony_ci /// assert_eq!(cell.take(), None); 1144ef40d7f6Sopenharmony_ci /// 1145ef40d7f6Sopenharmony_ci /// let mut cell = OnceCell::new(); 1146ef40d7f6Sopenharmony_ci /// cell.set("hello".to_string()).unwrap(); 1147ef40d7f6Sopenharmony_ci /// assert_eq!(cell.take(), Some("hello".to_string())); 1148ef40d7f6Sopenharmony_ci /// assert_eq!(cell.get(), None); 1149ef40d7f6Sopenharmony_ci /// ``` 1150ef40d7f6Sopenharmony_ci /// 1151ef40d7f6Sopenharmony_ci /// This method is allowed to violate the invariant of writing to a `OnceCell` 1152ef40d7f6Sopenharmony_ci /// at most once because it requires `&mut` access to `self`. As with all 1153ef40d7f6Sopenharmony_ci /// interior mutability, `&mut` access permits arbitrary modification: 1154ef40d7f6Sopenharmony_ci /// 1155ef40d7f6Sopenharmony_ci /// ``` 1156ef40d7f6Sopenharmony_ci /// use once_cell::sync::OnceCell; 1157ef40d7f6Sopenharmony_ci /// 1158ef40d7f6Sopenharmony_ci /// let mut cell: OnceCell<u32> = OnceCell::new(); 1159ef40d7f6Sopenharmony_ci /// cell.set(92).unwrap(); 1160ef40d7f6Sopenharmony_ci /// cell = OnceCell::new(); 1161ef40d7f6Sopenharmony_ci /// ``` 1162ef40d7f6Sopenharmony_ci pub fn take(&mut self) -> Option<T> { 1163ef40d7f6Sopenharmony_ci mem::replace(self, Self::default()).into_inner() 1164ef40d7f6Sopenharmony_ci } 1165ef40d7f6Sopenharmony_ci 1166ef40d7f6Sopenharmony_ci /// Consumes the `OnceCell`, returning the wrapped value. Returns 1167ef40d7f6Sopenharmony_ci /// `None` if the cell was empty. 1168ef40d7f6Sopenharmony_ci /// 1169ef40d7f6Sopenharmony_ci /// # Examples 1170ef40d7f6Sopenharmony_ci /// 1171ef40d7f6Sopenharmony_ci /// ``` 1172ef40d7f6Sopenharmony_ci /// use once_cell::sync::OnceCell; 1173ef40d7f6Sopenharmony_ci /// 1174ef40d7f6Sopenharmony_ci /// let cell: OnceCell<String> = OnceCell::new(); 1175ef40d7f6Sopenharmony_ci /// assert_eq!(cell.into_inner(), None); 1176ef40d7f6Sopenharmony_ci /// 1177ef40d7f6Sopenharmony_ci /// let cell = OnceCell::new(); 1178ef40d7f6Sopenharmony_ci /// cell.set("hello".to_string()).unwrap(); 1179ef40d7f6Sopenharmony_ci /// assert_eq!(cell.into_inner(), Some("hello".to_string())); 1180ef40d7f6Sopenharmony_ci /// ``` 1181ef40d7f6Sopenharmony_ci #[inline] 1182ef40d7f6Sopenharmony_ci pub fn into_inner(self) -> Option<T> { 1183ef40d7f6Sopenharmony_ci self.0.into_inner() 1184ef40d7f6Sopenharmony_ci } 1185ef40d7f6Sopenharmony_ci } 1186ef40d7f6Sopenharmony_ci 1187ef40d7f6Sopenharmony_ci /// A value which is initialized on the first access. 1188ef40d7f6Sopenharmony_ci /// 1189ef40d7f6Sopenharmony_ci /// This type is thread-safe and can be used in statics. 1190ef40d7f6Sopenharmony_ci /// 1191ef40d7f6Sopenharmony_ci /// # Example 1192ef40d7f6Sopenharmony_ci /// 1193ef40d7f6Sopenharmony_ci /// ``` 1194ef40d7f6Sopenharmony_ci /// use std::collections::HashMap; 1195ef40d7f6Sopenharmony_ci /// 1196ef40d7f6Sopenharmony_ci /// use once_cell::sync::Lazy; 1197ef40d7f6Sopenharmony_ci /// 1198ef40d7f6Sopenharmony_ci /// static HASHMAP: Lazy<HashMap<i32, String>> = Lazy::new(|| { 1199ef40d7f6Sopenharmony_ci /// println!("initializing"); 1200ef40d7f6Sopenharmony_ci /// let mut m = HashMap::new(); 1201ef40d7f6Sopenharmony_ci /// m.insert(13, "Spica".to_string()); 1202ef40d7f6Sopenharmony_ci /// m.insert(74, "Hoyten".to_string()); 1203ef40d7f6Sopenharmony_ci /// m 1204ef40d7f6Sopenharmony_ci /// }); 1205ef40d7f6Sopenharmony_ci /// 1206ef40d7f6Sopenharmony_ci /// fn main() { 1207ef40d7f6Sopenharmony_ci /// println!("ready"); 1208ef40d7f6Sopenharmony_ci /// std::thread::spawn(|| { 1209ef40d7f6Sopenharmony_ci /// println!("{:?}", HASHMAP.get(&13)); 1210ef40d7f6Sopenharmony_ci /// }).join().unwrap(); 1211ef40d7f6Sopenharmony_ci /// println!("{:?}", HASHMAP.get(&74)); 1212ef40d7f6Sopenharmony_ci /// 1213ef40d7f6Sopenharmony_ci /// // Prints: 1214ef40d7f6Sopenharmony_ci /// // ready 1215ef40d7f6Sopenharmony_ci /// // initializing 1216ef40d7f6Sopenharmony_ci /// // Some("Spica") 1217ef40d7f6Sopenharmony_ci /// // Some("Hoyten") 1218ef40d7f6Sopenharmony_ci /// } 1219ef40d7f6Sopenharmony_ci /// ``` 1220ef40d7f6Sopenharmony_ci pub struct Lazy<T, F = fn() -> T> { 1221ef40d7f6Sopenharmony_ci cell: OnceCell<T>, 1222ef40d7f6Sopenharmony_ci init: Cell<Option<F>>, 1223ef40d7f6Sopenharmony_ci } 1224ef40d7f6Sopenharmony_ci 1225ef40d7f6Sopenharmony_ci impl<T: fmt::Debug, F> fmt::Debug for Lazy<T, F> { 1226ef40d7f6Sopenharmony_ci fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 1227ef40d7f6Sopenharmony_ci f.debug_struct("Lazy").field("cell", &self.cell).field("init", &"..").finish() 1228ef40d7f6Sopenharmony_ci } 1229ef40d7f6Sopenharmony_ci } 1230ef40d7f6Sopenharmony_ci 1231ef40d7f6Sopenharmony_ci // We never create a `&F` from a `&Lazy<T, F>` so it is fine to not impl 1232ef40d7f6Sopenharmony_ci // `Sync` for `F`. We do create a `&mut Option<F>` in `force`, but this is 1233ef40d7f6Sopenharmony_ci // properly synchronized, so it only happens once so it also does not 1234ef40d7f6Sopenharmony_ci // contribute to this impl. 1235ef40d7f6Sopenharmony_ci unsafe impl<T, F: Send> Sync for Lazy<T, F> where OnceCell<T>: Sync {} 1236ef40d7f6Sopenharmony_ci // auto-derived `Send` impl is OK. 1237ef40d7f6Sopenharmony_ci 1238ef40d7f6Sopenharmony_ci impl<T, F: RefUnwindSafe> RefUnwindSafe for Lazy<T, F> where OnceCell<T>: RefUnwindSafe {} 1239ef40d7f6Sopenharmony_ci 1240ef40d7f6Sopenharmony_ci impl<T, F> Lazy<T, F> { 1241ef40d7f6Sopenharmony_ci /// Creates a new lazy value with the given initializing 1242ef40d7f6Sopenharmony_ci /// function. 1243ef40d7f6Sopenharmony_ci pub const fn new(f: F) -> Lazy<T, F> { 1244ef40d7f6Sopenharmony_ci Lazy { cell: OnceCell::new(), init: Cell::new(Some(f)) } 1245ef40d7f6Sopenharmony_ci } 1246ef40d7f6Sopenharmony_ci 1247ef40d7f6Sopenharmony_ci /// Consumes this `Lazy` returning the stored value. 1248ef40d7f6Sopenharmony_ci /// 1249ef40d7f6Sopenharmony_ci /// Returns `Ok(value)` if `Lazy` is initialized and `Err(f)` otherwise. 1250ef40d7f6Sopenharmony_ci pub fn into_value(this: Lazy<T, F>) -> Result<T, F> { 1251ef40d7f6Sopenharmony_ci let cell = this.cell; 1252ef40d7f6Sopenharmony_ci let init = this.init; 1253ef40d7f6Sopenharmony_ci cell.into_inner().ok_or_else(|| { 1254ef40d7f6Sopenharmony_ci init.take().unwrap_or_else(|| panic!("Lazy instance has previously been poisoned")) 1255ef40d7f6Sopenharmony_ci }) 1256ef40d7f6Sopenharmony_ci } 1257ef40d7f6Sopenharmony_ci } 1258ef40d7f6Sopenharmony_ci 1259ef40d7f6Sopenharmony_ci impl<T, F: FnOnce() -> T> Lazy<T, F> { 1260ef40d7f6Sopenharmony_ci /// Forces the evaluation of this lazy value and 1261ef40d7f6Sopenharmony_ci /// returns a reference to the result. This is equivalent 1262ef40d7f6Sopenharmony_ci /// to the `Deref` impl, but is explicit. 1263ef40d7f6Sopenharmony_ci /// 1264ef40d7f6Sopenharmony_ci /// # Example 1265ef40d7f6Sopenharmony_ci /// ``` 1266ef40d7f6Sopenharmony_ci /// use once_cell::sync::Lazy; 1267ef40d7f6Sopenharmony_ci /// 1268ef40d7f6Sopenharmony_ci /// let lazy = Lazy::new(|| 92); 1269ef40d7f6Sopenharmony_ci /// 1270ef40d7f6Sopenharmony_ci /// assert_eq!(Lazy::force(&lazy), &92); 1271ef40d7f6Sopenharmony_ci /// assert_eq!(&*lazy, &92); 1272ef40d7f6Sopenharmony_ci /// ``` 1273ef40d7f6Sopenharmony_ci pub fn force(this: &Lazy<T, F>) -> &T { 1274ef40d7f6Sopenharmony_ci this.cell.get_or_init(|| match this.init.take() { 1275ef40d7f6Sopenharmony_ci Some(f) => f(), 1276ef40d7f6Sopenharmony_ci None => panic!("Lazy instance has previously been poisoned"), 1277ef40d7f6Sopenharmony_ci }) 1278ef40d7f6Sopenharmony_ci } 1279ef40d7f6Sopenharmony_ci 1280ef40d7f6Sopenharmony_ci /// Forces the evaluation of this lazy value and 1281ef40d7f6Sopenharmony_ci /// returns a mutable reference to the result. This is equivalent 1282ef40d7f6Sopenharmony_ci /// to the `Deref` impl, but is explicit. 1283ef40d7f6Sopenharmony_ci /// 1284ef40d7f6Sopenharmony_ci /// # Example 1285ef40d7f6Sopenharmony_ci /// ``` 1286ef40d7f6Sopenharmony_ci /// use once_cell::sync::Lazy; 1287ef40d7f6Sopenharmony_ci /// 1288ef40d7f6Sopenharmony_ci /// let mut lazy = Lazy::new(|| 92); 1289ef40d7f6Sopenharmony_ci /// 1290ef40d7f6Sopenharmony_ci /// assert_eq!(Lazy::force_mut(&mut lazy), &mut 92); 1291ef40d7f6Sopenharmony_ci /// ``` 1292ef40d7f6Sopenharmony_ci pub fn force_mut(this: &mut Lazy<T, F>) -> &mut T { 1293ef40d7f6Sopenharmony_ci Self::force(this); 1294ef40d7f6Sopenharmony_ci Self::get_mut(this).unwrap_or_else(|| unreachable!()) 1295ef40d7f6Sopenharmony_ci } 1296ef40d7f6Sopenharmony_ci 1297ef40d7f6Sopenharmony_ci /// Gets the reference to the result of this lazy value if 1298ef40d7f6Sopenharmony_ci /// it was initialized, otherwise returns `None`. 1299ef40d7f6Sopenharmony_ci /// 1300ef40d7f6Sopenharmony_ci /// # Example 1301ef40d7f6Sopenharmony_ci /// ``` 1302ef40d7f6Sopenharmony_ci /// use once_cell::sync::Lazy; 1303ef40d7f6Sopenharmony_ci /// 1304ef40d7f6Sopenharmony_ci /// let lazy = Lazy::new(|| 92); 1305ef40d7f6Sopenharmony_ci /// 1306ef40d7f6Sopenharmony_ci /// assert_eq!(Lazy::get(&lazy), None); 1307ef40d7f6Sopenharmony_ci /// assert_eq!(&*lazy, &92); 1308ef40d7f6Sopenharmony_ci /// assert_eq!(Lazy::get(&lazy), Some(&92)); 1309ef40d7f6Sopenharmony_ci /// ``` 1310ef40d7f6Sopenharmony_ci pub fn get(this: &Lazy<T, F>) -> Option<&T> { 1311ef40d7f6Sopenharmony_ci this.cell.get() 1312ef40d7f6Sopenharmony_ci } 1313ef40d7f6Sopenharmony_ci 1314ef40d7f6Sopenharmony_ci /// Gets the reference to the result of this lazy value if 1315ef40d7f6Sopenharmony_ci /// it was initialized, otherwise returns `None`. 1316ef40d7f6Sopenharmony_ci /// 1317ef40d7f6Sopenharmony_ci /// # Example 1318ef40d7f6Sopenharmony_ci /// ``` 1319ef40d7f6Sopenharmony_ci /// use once_cell::sync::Lazy; 1320ef40d7f6Sopenharmony_ci /// 1321ef40d7f6Sopenharmony_ci /// let mut lazy = Lazy::new(|| 92); 1322ef40d7f6Sopenharmony_ci /// 1323ef40d7f6Sopenharmony_ci /// assert_eq!(Lazy::get_mut(&mut lazy), None); 1324ef40d7f6Sopenharmony_ci /// assert_eq!(&*lazy, &92); 1325ef40d7f6Sopenharmony_ci /// assert_eq!(Lazy::get_mut(&mut lazy), Some(&mut 92)); 1326ef40d7f6Sopenharmony_ci /// ``` 1327ef40d7f6Sopenharmony_ci pub fn get_mut(this: &mut Lazy<T, F>) -> Option<&mut T> { 1328ef40d7f6Sopenharmony_ci this.cell.get_mut() 1329ef40d7f6Sopenharmony_ci } 1330ef40d7f6Sopenharmony_ci } 1331ef40d7f6Sopenharmony_ci 1332ef40d7f6Sopenharmony_ci impl<T, F: FnOnce() -> T> Deref for Lazy<T, F> { 1333ef40d7f6Sopenharmony_ci type Target = T; 1334ef40d7f6Sopenharmony_ci fn deref(&self) -> &T { 1335ef40d7f6Sopenharmony_ci Lazy::force(self) 1336ef40d7f6Sopenharmony_ci } 1337ef40d7f6Sopenharmony_ci } 1338ef40d7f6Sopenharmony_ci 1339ef40d7f6Sopenharmony_ci impl<T, F: FnOnce() -> T> DerefMut for Lazy<T, F> { 1340ef40d7f6Sopenharmony_ci fn deref_mut(&mut self) -> &mut T { 1341ef40d7f6Sopenharmony_ci Lazy::force(self); 1342ef40d7f6Sopenharmony_ci self.cell.get_mut().unwrap_or_else(|| unreachable!()) 1343ef40d7f6Sopenharmony_ci } 1344ef40d7f6Sopenharmony_ci } 1345ef40d7f6Sopenharmony_ci 1346ef40d7f6Sopenharmony_ci impl<T: Default> Default for Lazy<T> { 1347ef40d7f6Sopenharmony_ci /// Creates a new lazy value using `Default` as the initializing function. 1348ef40d7f6Sopenharmony_ci fn default() -> Lazy<T> { 1349ef40d7f6Sopenharmony_ci Lazy::new(T::default) 1350ef40d7f6Sopenharmony_ci } 1351ef40d7f6Sopenharmony_ci } 1352ef40d7f6Sopenharmony_ci 1353ef40d7f6Sopenharmony_ci /// ```compile_fail 1354ef40d7f6Sopenharmony_ci /// struct S(*mut ()); 1355ef40d7f6Sopenharmony_ci /// unsafe impl Sync for S {} 1356ef40d7f6Sopenharmony_ci /// 1357ef40d7f6Sopenharmony_ci /// fn share<T: Sync>(_: &T) {} 1358ef40d7f6Sopenharmony_ci /// share(&once_cell::sync::OnceCell::<S>::new()); 1359ef40d7f6Sopenharmony_ci /// ``` 1360ef40d7f6Sopenharmony_ci /// 1361ef40d7f6Sopenharmony_ci /// ```compile_fail 1362ef40d7f6Sopenharmony_ci /// struct S(*mut ()); 1363ef40d7f6Sopenharmony_ci /// unsafe impl Sync for S {} 1364ef40d7f6Sopenharmony_ci /// 1365ef40d7f6Sopenharmony_ci /// fn share<T: Sync>(_: &T) {} 1366ef40d7f6Sopenharmony_ci /// share(&once_cell::sync::Lazy::<S>::new(|| unimplemented!())); 1367ef40d7f6Sopenharmony_ci /// ``` 1368ef40d7f6Sopenharmony_ci fn _dummy() {} 1369ef40d7f6Sopenharmony_ci} 1370ef40d7f6Sopenharmony_ci 1371ef40d7f6Sopenharmony_ci#[cfg(feature = "race")] 1372ef40d7f6Sopenharmony_cipub mod race; 1373ef40d7f6Sopenharmony_ci 1374ef40d7f6Sopenharmony_ci// Remove once MSRV is at least 1.58. 1375ef40d7f6Sopenharmony_ci#[inline] 1376ef40d7f6Sopenharmony_ciunsafe fn unwrap_unchecked<T>(val: Option<T>) -> T { 1377ef40d7f6Sopenharmony_ci match val { 1378ef40d7f6Sopenharmony_ci Some(value) => value, 1379ef40d7f6Sopenharmony_ci None => { 1380ef40d7f6Sopenharmony_ci debug_assert!(false); 1381ef40d7f6Sopenharmony_ci core::hint::unreachable_unchecked() 1382ef40d7f6Sopenharmony_ci } 1383ef40d7f6Sopenharmony_ci } 1384ef40d7f6Sopenharmony_ci} 1385