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