]>
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> { | |
9 | //! fn new() -> OnceCell<T> { ... } | |
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 | //! | |
27 | //! # Patterns | |
28 | //! | |
29 | //! `OnceCell` might be useful for a variety of patterns. | |
30 | //! | |
31 | //! ## Safe Initialization of global data | |
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 | //! | |
62 | //! ## Lazy initialized global data | |
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 | //! | |
100 | //! [`sync::Lazy`]: sync/struct.Lazy.html | |
101 | //! [`unsync::Lazy`]: unsync/struct.Lazy.html | |
102 | //! | |
103 | //! ## General purpose lazy evaluation | |
104 | //! | |
105 | //! Unlike `lazy_static!`, `Lazy` works with local variables. | |
106 | //! | |
107 | //! ```rust | |
108 | //! use once_cell::unsync::Lazy; | |
109 | //! | |
110 | //! fn main() { | |
111 | //! let ctx = vec![1, 2, 3]; | |
112 | //! let thunk = Lazy::new(|| { | |
113 | //! ctx.iter().sum::<i32>() | |
114 | //! }); | |
115 | //! assert_eq!(*thunk, 6); | |
116 | //! } | |
117 | //! ``` | |
118 | //! | |
119 | //! If you need a lazy field in a struct, you probably should use `OnceCell` | |
120 | //! directly, because that will allow you to access `self` during initialization. | |
121 | //! | |
122 | //! ```rust | |
123 | //! use std::{fs, path::PathBuf}; | |
124 | //! | |
125 | //! use once_cell::unsync::OnceCell; | |
126 | //! | |
127 | //! struct Ctx { | |
128 | //! config_path: PathBuf, | |
129 | //! config: OnceCell<String>, | |
130 | //! } | |
131 | //! | |
132 | //! impl Ctx { | |
133 | //! pub fn get_config(&self) -> Result<&str, std::io::Error> { | |
134 | //! let cfg = self.config.get_or_try_init(|| { | |
135 | //! fs::read_to_string(&self.config_path) | |
136 | //! })?; | |
137 | //! Ok(cfg.as_str()) | |
138 | //! } | |
139 | //! } | |
140 | //! ``` | |
141 | //! | |
142 | //! ## Building block | |
143 | //! | |
144 | //! Naturally, it is possible to build other abstractions on top of `OnceCell`. | |
145 | //! For example, this is a `regex!` macro which takes a string literal and returns an | |
146 | //! *expression* that evaluates to a `&'static Regex`: | |
147 | //! | |
148 | //! ``` | |
149 | //! macro_rules! regex { | |
150 | //! ($re:literal $(,)?) => {{ | |
151 | //! static RE: once_cell::sync::OnceCell<regex::Regex> = once_cell::sync::OnceCell::new(); | |
152 | //! RE.get_or_init(|| regex::Regex::new($re).unwrap()) | |
153 | //! }}; | |
154 | //! } | |
155 | //! ``` | |
156 | //! | |
157 | //! This macro can be useful to avoid the "compile regex on every loop iteration" problem. | |
158 | //! | |
159 | //! Another pattern would be a `LateInit` type for delayed initialization: | |
160 | //! | |
161 | //! | |
162 | //! ``` | |
163 | //! use once_cell::sync::OnceCell; | |
164 | //! | |
165 | //! #[derive(Debug)] | |
166 | //! pub struct LateInit<T> { cell: OnceCell<T> } | |
167 | //! | |
168 | //! impl<T> LateInit<T> { | |
169 | //! pub fn init(&self, value: T) { | |
170 | //! assert!(self.cell.set(value).is_ok()) | |
171 | //! } | |
172 | //! } | |
173 | //! | |
174 | //! impl<T> Default for LateInit<T> { | |
175 | //! fn default() -> Self { LateInit { cell: OnceCell::default() } } | |
176 | //! } | |
177 | //! | |
178 | //! impl<T> std::ops::Deref for LateInit<T> { | |
179 | //! type Target = T; | |
180 | //! fn deref(&self) -> &T { | |
181 | //! self.cell.get().unwrap() | |
182 | //! } | |
183 | //! } | |
184 | //! | |
185 | //! #[derive(Default, Debug)] | |
186 | //! struct A<'a> { | |
187 | //! b: LateInit<&'a B<'a>>, | |
188 | //! } | |
189 | //! | |
190 | //! #[derive(Default, Debug)] | |
191 | //! struct B<'a> { | |
192 | //! a: LateInit<&'a A<'a>> | |
193 | //! } | |
194 | //! | |
195 | //! fn build_cycle() { | |
196 | //! let a = A::default(); | |
197 | //! let b = B::default(); | |
198 | //! a.b.init(&b); | |
199 | //! b.a.init(&a); | |
200 | //! println!("{:?}", a.b.a.b.a); | |
201 | //! } | |
202 | //! ``` | |
203 | //! | |
204 | //! # Comparison with std | |
205 | //! | |
206 | //! |`!Sync` types | Access Mode | Drawbacks | | |
207 | //! |----------------------|------------------------|-----------------------------------------------| | |
208 | //! |`Cell<T>` | `T` | requires `T: Copy` for `get` | | |
209 | //! |`RefCell<T>` | `RefMut<T>` / `Ref<T>` | may panic at runtime | | |
210 | //! |`unsync::OnceCell<T>` | `&T` | assignable only once | | |
211 | //! | |
212 | //! |`Sync` types | Access Mode | Drawbacks | | |
213 | //! |----------------------|------------------------|-----------------------------------------------| | |
214 | //! |`AtomicT` | `T` | works only with certain `Copy` types | | |
215 | //! |`Mutex<T>` | `MutexGuard<T>` | may deadlock at runtime, may block the thread | | |
216 | //! |`sync::OnceCell<T>` | `&T` | assignable only once, may block the thread | | |
217 | //! | |
218 | //! Technically, calling `get_or_init` will also cause a panic or a deadlock if it recursively calls | |
219 | //! itself. However, because the assignment can happen only once, such cases should be more rare than | |
220 | //! equivalents with `RefCell` and `Mutex`. | |
221 | //! | |
222 | //! # Minimum Supported `rustc` Version | |
223 | //! | |
224 | //! This crate's minimum supported `rustc` version is `1.36.0`. | |
225 | //! | |
226 | //! If only the `std` feature is enabled, MSRV will be updated conservatively. | |
227 | //! When using other features, like `parking_lot`, MSRV might be updated more frequently, up to the latest stable. | |
228 | //! In both cases, increasing MSRV is *not* considered a semver-breaking change. | |
229 | //! | |
230 | //! # Implementation details | |
231 | //! | |
232 | //! The implementation is based on the [`lazy_static`](https://github.com/rust-lang-nursery/lazy-static.rs/) | |
233 | //! and [`lazy_cell`](https://github.com/indiv0/lazycell/) crates and [`std::sync::Once`]. In some sense, | |
234 | //! `once_cell` just streamlines and unifies those APIs. | |
235 | //! | |
6a06907d XL |
236 | //! To implement a sync flavor of `OnceCell`, this crates uses either a custom |
237 | //! re-implementation of `std::sync::Once` or `parking_lot::Mutex`. This is | |
238 | //! controlled by the `parking_lot` feature (disabled by default). Performance | |
239 | //! is the same for both cases, but the `parking_lot` based `OnceCell<T>` is | |
240 | //! smaller by up to 16 bytes. | |
5869c6ff XL |
241 | //! |
242 | //! This crate uses `unsafe`. | |
243 | //! | |
244 | //! [`std::sync::Once`]: https://doc.rust-lang.org/std/sync/struct.Once.html | |
245 | //! | |
246 | //! # F.A.Q. | |
247 | //! | |
248 | //! **Should I use lazy_static or once_cell?** | |
249 | //! | |
250 | //! To the first approximation, `once_cell` is both more flexible and more convenient than `lazy_static` | |
251 | //! and should be preferred. | |
252 | //! | |
253 | //! Unlike `once_cell`, `lazy_static` supports spinlock-based implementation of blocking which works with | |
254 | //! `#![no_std]`. | |
255 | //! | |
256 | //! `lazy_static` has received significantly more real world testing, but `once_cell` is also a widely | |
257 | //! used crate. | |
258 | //! | |
259 | //! **Should I use the sync or unsync flavor?** | |
260 | //! | |
261 | //! Because Rust compiler checks thread safety for you, it's impossible to accidentally use `unsync` where | |
262 | //! `sync` is required. So, use `unsync` in single-threaded code and `sync` in multi-threaded. It's easy | |
263 | //! to switch between the two if code becomes multi-threaded later. | |
264 | //! | |
265 | //! At the moment, `unsync` has an additional benefit that reentrant initialization causes a panic, which | |
266 | //! might be easier to debug than a deadlock. | |
267 | //! | |
268 | //! # Related crates | |
269 | //! | |
270 | //! * [double-checked-cell](https://github.com/niklasf/double-checked-cell) | |
271 | //! * [lazy-init](https://crates.io/crates/lazy-init) | |
272 | //! * [lazycell](https://crates.io/crates/lazycell) | |
273 | //! * [mitochondria](https://crates.io/crates/mitochondria) | |
274 | //! * [lazy_static](https://crates.io/crates/lazy_static) | |
275 | //! | |
276 | //! Most of this crate's functionality is available in `std` in nightly Rust. | |
277 | //! See the [tracking issue](https://github.com/rust-lang/rust/issues/74465). | |
e1599b0c XL |
278 | |
279 | #![cfg_attr(not(feature = "std"), no_std)] | |
280 | ||
5869c6ff XL |
281 | #[cfg(feature = "alloc")] |
282 | extern crate alloc; | |
283 | ||
e1599b0c XL |
284 | #[cfg(feature = "std")] |
285 | #[cfg(feature = "parking_lot")] | |
286 | #[path = "imp_pl.rs"] | |
287 | mod imp; | |
288 | ||
289 | #[cfg(feature = "std")] | |
290 | #[cfg(not(feature = "parking_lot"))] | |
291 | #[path = "imp_std.rs"] | |
292 | mod imp; | |
293 | ||
294 | pub mod unsync { | |
295 | use core::{ | |
296 | cell::{Cell, UnsafeCell}, | |
f035d41b XL |
297 | fmt, mem, |
298 | ops::{Deref, DerefMut}, | |
e1599b0c XL |
299 | }; |
300 | ||
301 | #[cfg(feature = "std")] | |
302 | use std::panic::{RefUnwindSafe, UnwindSafe}; | |
303 | ||
f035d41b | 304 | /// A cell which can be written to only once. It is not thread safe. |
e1599b0c | 305 | /// |
f035d41b | 306 | /// Unlike [`std::cell::RefCell`], a `OnceCell` provides simple `&` |
e1599b0c XL |
307 | /// references to the contents. |
308 | /// | |
f035d41b XL |
309 | /// [`std::cell::RefCell`]: https://doc.rust-lang.org/std/cell/struct.RefCell.html |
310 | /// | |
e1599b0c XL |
311 | /// # Example |
312 | /// ``` | |
313 | /// use once_cell::unsync::OnceCell; | |
314 | /// | |
315 | /// let cell = OnceCell::new(); | |
316 | /// assert!(cell.get().is_none()); | |
317 | /// | |
318 | /// let value: &String = cell.get_or_init(|| { | |
319 | /// "Hello, World!".to_string() | |
320 | /// }); | |
321 | /// assert_eq!(value, "Hello, World!"); | |
322 | /// assert!(cell.get().is_some()); | |
323 | /// ``` | |
324 | pub struct OnceCell<T> { | |
325 | // Invariant: written to at most once. | |
326 | inner: UnsafeCell<Option<T>>, | |
327 | } | |
328 | ||
329 | // Similarly to a `Sync` bound on `sync::OnceCell`, we can use | |
330 | // `&unsync::OnceCell` to sneak a `T` through `catch_unwind`, | |
331 | // by initializing the cell in closure and extracting the value in the | |
332 | // `Drop`. | |
333 | #[cfg(feature = "std")] | |
334 | impl<T: RefUnwindSafe + UnwindSafe> RefUnwindSafe for OnceCell<T> {} | |
335 | #[cfg(feature = "std")] | |
336 | impl<T: UnwindSafe> UnwindSafe for OnceCell<T> {} | |
337 | ||
338 | impl<T> Default for OnceCell<T> { | |
339 | fn default() -> Self { | |
340 | Self::new() | |
341 | } | |
342 | } | |
343 | ||
344 | impl<T: fmt::Debug> fmt::Debug for OnceCell<T> { | |
345 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
346 | match self.get() { | |
347 | Some(v) => f.debug_tuple("OnceCell").field(v).finish(), | |
348 | None => f.write_str("OnceCell(Uninit)"), | |
349 | } | |
350 | } | |
351 | } | |
352 | ||
353 | impl<T: Clone> Clone for OnceCell<T> { | |
354 | fn clone(&self) -> OnceCell<T> { | |
355 | let res = OnceCell::new(); | |
356 | if let Some(value) = self.get() { | |
357 | match res.set(value.clone()) { | |
358 | Ok(()) => (), | |
359 | Err(_) => unreachable!(), | |
360 | } | |
361 | } | |
362 | res | |
363 | } | |
364 | } | |
365 | ||
366 | impl<T: PartialEq> PartialEq for OnceCell<T> { | |
367 | fn eq(&self, other: &Self) -> bool { | |
368 | self.get() == other.get() | |
369 | } | |
370 | } | |
371 | ||
372 | impl<T: Eq> Eq for OnceCell<T> {} | |
373 | ||
374 | impl<T> From<T> for OnceCell<T> { | |
375 | fn from(value: T) -> Self { | |
376 | OnceCell { inner: UnsafeCell::new(Some(value)) } | |
377 | } | |
378 | } | |
379 | ||
380 | impl<T> OnceCell<T> { | |
381 | /// Creates a new empty cell. | |
382 | pub const fn new() -> OnceCell<T> { | |
383 | OnceCell { inner: UnsafeCell::new(None) } | |
384 | } | |
385 | ||
f035d41b | 386 | /// Gets a reference to the underlying value. |
e1599b0c XL |
387 | /// |
388 | /// Returns `None` if the cell is empty. | |
389 | pub fn get(&self) -> Option<&T> { | |
390 | // Safe due to `inner`'s invariant | |
391 | unsafe { &*self.inner.get() }.as_ref() | |
392 | } | |
393 | ||
f035d41b | 394 | /// Gets a mutable reference to the underlying value. |
e1599b0c XL |
395 | /// |
396 | /// Returns `None` if the cell is empty. | |
397 | pub fn get_mut(&mut self) -> Option<&mut T> { | |
398 | // Safe because we have unique access | |
399 | unsafe { &mut *self.inner.get() }.as_mut() | |
400 | } | |
401 | ||
402 | /// Sets the contents of this cell to `value`. | |
403 | /// | |
404 | /// Returns `Ok(())` if the cell was empty and `Err(value)` if it was | |
405 | /// full. | |
406 | /// | |
407 | /// # Example | |
408 | /// ``` | |
409 | /// use once_cell::unsync::OnceCell; | |
410 | /// | |
411 | /// let cell = OnceCell::new(); | |
412 | /// assert!(cell.get().is_none()); | |
413 | /// | |
414 | /// assert_eq!(cell.set(92), Ok(())); | |
415 | /// assert_eq!(cell.set(62), Err(62)); | |
416 | /// | |
417 | /// assert!(cell.get().is_some()); | |
418 | /// ``` | |
419 | pub fn set(&self, value: T) -> Result<(), T> { | |
420 | let slot = unsafe { &*self.inner.get() }; | |
421 | if slot.is_some() { | |
422 | return Err(value); | |
423 | } | |
424 | let slot = unsafe { &mut *self.inner.get() }; | |
425 | // This is the only place where we set the slot, no races | |
426 | // due to reentrancy/concurrency are possible, and we've | |
427 | // checked that slot is currently `None`, so this write | |
428 | // maintains the `inner`'s invariant. | |
429 | *slot = Some(value); | |
430 | Ok(()) | |
431 | } | |
432 | ||
433 | /// Gets the contents of the cell, initializing it with `f` | |
434 | /// if the cell was empty. | |
435 | /// | |
436 | /// # Panics | |
437 | /// | |
438 | /// If `f` panics, the panic is propagated to the caller, and the cell | |
439 | /// remains uninitialized. | |
440 | /// | |
441 | /// It is an error to reentrantly initialize the cell from `f`. Doing | |
442 | /// so results in a panic. | |
443 | /// | |
444 | /// # Example | |
445 | /// ``` | |
446 | /// use once_cell::unsync::OnceCell; | |
447 | /// | |
448 | /// let cell = OnceCell::new(); | |
449 | /// let value = cell.get_or_init(|| 92); | |
450 | /// assert_eq!(value, &92); | |
451 | /// let value = cell.get_or_init(|| unreachable!()); | |
452 | /// assert_eq!(value, &92); | |
453 | /// ``` | |
454 | pub fn get_or_init<F>(&self, f: F) -> &T | |
455 | where | |
456 | F: FnOnce() -> T, | |
457 | { | |
458 | enum Void {} | |
459 | match self.get_or_try_init(|| Ok::<T, Void>(f())) { | |
460 | Ok(val) => val, | |
461 | Err(void) => match void {}, | |
462 | } | |
463 | } | |
464 | ||
465 | /// Gets the contents of the cell, initializing it with `f` if | |
466 | /// the cell was empty. If the cell was empty and `f` failed, an | |
467 | /// error is returned. | |
468 | /// | |
469 | /// # Panics | |
470 | /// | |
471 | /// If `f` panics, the panic is propagated to the caller, and the cell | |
472 | /// remains uninitialized. | |
473 | /// | |
474 | /// It is an error to reentrantly initialize the cell from `f`. Doing | |
475 | /// so results in a panic. | |
476 | /// | |
477 | /// # Example | |
478 | /// ``` | |
479 | /// use once_cell::unsync::OnceCell; | |
480 | /// | |
481 | /// let cell = OnceCell::new(); | |
482 | /// assert_eq!(cell.get_or_try_init(|| Err(())), Err(())); | |
483 | /// assert!(cell.get().is_none()); | |
484 | /// let value = cell.get_or_try_init(|| -> Result<i32, ()> { | |
485 | /// Ok(92) | |
486 | /// }); | |
487 | /// assert_eq!(value, Ok(&92)); | |
488 | /// assert_eq!(cell.get(), Some(&92)) | |
489 | /// ``` | |
490 | pub fn get_or_try_init<F, E>(&self, f: F) -> Result<&T, E> | |
491 | where | |
492 | F: FnOnce() -> Result<T, E>, | |
493 | { | |
494 | if let Some(val) = self.get() { | |
495 | return Ok(val); | |
496 | } | |
497 | let val = f()?; | |
f035d41b XL |
498 | // Note that *some* forms of reentrant initialization might lead to |
499 | // UB (see `reentrant_init` test). I believe that just removing this | |
500 | // `assert`, while keeping `set/get` would be sound, but it seems | |
501 | // better to panic, rather than to silently use an old value. | |
e1599b0c XL |
502 | assert!(self.set(val).is_ok(), "reentrant init"); |
503 | Ok(self.get().unwrap()) | |
504 | } | |
505 | ||
f035d41b XL |
506 | /// Takes the value out of this `OnceCell`, moving it back to an uninitialized state. |
507 | /// | |
508 | /// Has no effect and returns `None` if the `OnceCell` hasn't been initialized. | |
509 | /// | |
510 | /// # Examples | |
511 | /// | |
512 | /// ``` | |
513 | /// use once_cell::unsync::OnceCell; | |
514 | /// | |
515 | /// let mut cell: OnceCell<String> = OnceCell::new(); | |
516 | /// assert_eq!(cell.take(), None); | |
517 | /// | |
518 | /// let mut cell = OnceCell::new(); | |
519 | /// cell.set("hello".to_string()).unwrap(); | |
520 | /// assert_eq!(cell.take(), Some("hello".to_string())); | |
521 | /// assert_eq!(cell.get(), None); | |
522 | /// ``` | |
523 | pub fn take(&mut self) -> Option<T> { | |
524 | mem::replace(self, Self::default()).into_inner() | |
525 | } | |
526 | ||
e1599b0c XL |
527 | /// Consumes the `OnceCell`, returning the wrapped value. |
528 | /// | |
529 | /// Returns `None` if the cell was empty. | |
530 | /// | |
531 | /// # Examples | |
532 | /// | |
533 | /// ``` | |
534 | /// use once_cell::unsync::OnceCell; | |
535 | /// | |
536 | /// let cell: OnceCell<String> = OnceCell::new(); | |
537 | /// assert_eq!(cell.into_inner(), None); | |
538 | /// | |
539 | /// let cell = OnceCell::new(); | |
540 | /// cell.set("hello".to_string()).unwrap(); | |
541 | /// assert_eq!(cell.into_inner(), Some("hello".to_string())); | |
542 | /// ``` | |
543 | pub fn into_inner(self) -> Option<T> { | |
544 | // Because `into_inner` takes `self` by value, the compiler statically verifies | |
545 | // that it is not currently borrowed. So it is safe to move out `Option<T>`. | |
546 | self.inner.into_inner() | |
547 | } | |
548 | } | |
549 | ||
550 | /// A value which is initialized on the first access. | |
551 | /// | |
552 | /// # Example | |
553 | /// ``` | |
554 | /// use once_cell::unsync::Lazy; | |
555 | /// | |
556 | /// let lazy: Lazy<i32> = Lazy::new(|| { | |
557 | /// println!("initializing"); | |
558 | /// 92 | |
559 | /// }); | |
560 | /// println!("ready"); | |
561 | /// println!("{}", *lazy); | |
562 | /// println!("{}", *lazy); | |
563 | /// | |
564 | /// // Prints: | |
565 | /// // ready | |
566 | /// // initializing | |
567 | /// // 92 | |
568 | /// // 92 | |
569 | /// ``` | |
570 | pub struct Lazy<T, F = fn() -> T> { | |
571 | cell: OnceCell<T>, | |
572 | init: Cell<Option<F>>, | |
573 | } | |
574 | ||
575 | #[cfg(feature = "std")] | |
576 | impl<T, F: RefUnwindSafe> RefUnwindSafe for Lazy<T, F> where OnceCell<T>: RefUnwindSafe {} | |
577 | ||
f035d41b | 578 | impl<T: fmt::Debug, F> fmt::Debug for Lazy<T, F> { |
e1599b0c XL |
579 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
580 | f.debug_struct("Lazy").field("cell", &self.cell).field("init", &"..").finish() | |
581 | } | |
582 | } | |
583 | ||
584 | impl<T, F> Lazy<T, F> { | |
585 | /// Creates a new lazy value with the given initializing function. | |
586 | /// | |
587 | /// # Example | |
588 | /// ``` | |
589 | /// # fn main() { | |
590 | /// use once_cell::unsync::Lazy; | |
591 | /// | |
592 | /// let hello = "Hello, World!".to_string(); | |
593 | /// | |
594 | /// let lazy = Lazy::new(|| hello.to_uppercase()); | |
595 | /// | |
596 | /// assert_eq!(&*lazy, "HELLO, WORLD!"); | |
597 | /// # } | |
598 | /// ``` | |
599 | pub const fn new(init: F) -> Lazy<T, F> { | |
600 | Lazy { cell: OnceCell::new(), init: Cell::new(Some(init)) } | |
601 | } | |
6a06907d XL |
602 | |
603 | /// Consumes this `Lazy` returning the stored value. | |
604 | /// | |
605 | /// Returns `Ok(value)` if `Lazy` is initialized and `Err(f)` otherwise. | |
606 | pub fn into_value(this: Lazy<T, F>) -> Result<T, F> { | |
607 | let cell = this.cell; | |
608 | let init = this.init; | |
609 | cell.into_inner().ok_or_else(|| { | |
610 | init.take().unwrap_or_else(|| panic!("Lazy instance has previously been poisoned")) | |
611 | }) | |
612 | } | |
e1599b0c XL |
613 | } |
614 | ||
615 | impl<T, F: FnOnce() -> T> Lazy<T, F> { | |
616 | /// Forces the evaluation of this lazy value and returns a reference to | |
617 | /// the result. | |
618 | /// | |
619 | /// This is equivalent to the `Deref` impl, but is explicit. | |
620 | /// | |
621 | /// # Example | |
622 | /// ``` | |
623 | /// use once_cell::unsync::Lazy; | |
624 | /// | |
625 | /// let lazy = Lazy::new(|| 92); | |
626 | /// | |
627 | /// assert_eq!(Lazy::force(&lazy), &92); | |
628 | /// assert_eq!(&*lazy, &92); | |
629 | /// ``` | |
630 | pub fn force(this: &Lazy<T, F>) -> &T { | |
631 | this.cell.get_or_init(|| match this.init.take() { | |
632 | Some(f) => f(), | |
633 | None => panic!("Lazy instance has previously been poisoned"), | |
634 | }) | |
635 | } | |
636 | } | |
637 | ||
638 | impl<T, F: FnOnce() -> T> Deref for Lazy<T, F> { | |
639 | type Target = T; | |
640 | fn deref(&self) -> &T { | |
641 | Lazy::force(self) | |
642 | } | |
643 | } | |
644 | ||
f035d41b XL |
645 | impl<T, F: FnOnce() -> T> DerefMut for Lazy<T, F> { |
646 | fn deref_mut(&mut self) -> &mut T { | |
647 | Lazy::force(self); | |
648 | self.cell.get_mut().unwrap_or_else(|| unreachable!()) | |
649 | } | |
650 | } | |
651 | ||
e1599b0c XL |
652 | impl<T: Default> Default for Lazy<T> { |
653 | /// Creates a new lazy value using `Default` as the initializing function. | |
654 | fn default() -> Lazy<T> { | |
655 | Lazy::new(T::default) | |
656 | } | |
657 | } | |
658 | } | |
659 | ||
660 | #[cfg(feature = "std")] | |
661 | pub mod sync { | |
f035d41b XL |
662 | use std::{ |
663 | cell::Cell, | |
664 | fmt, mem, | |
665 | ops::{Deref, DerefMut}, | |
666 | panic::RefUnwindSafe, | |
667 | }; | |
e1599b0c XL |
668 | |
669 | use crate::imp::OnceCell as Imp; | |
670 | ||
671 | /// A thread-safe cell which can be written to only once. | |
672 | /// | |
f035d41b XL |
673 | /// `OnceCell` provides `&` references to the contents without RAII guards. |
674 | /// | |
675 | /// Reading a non-`None` value out of `OnceCell` establishes a | |
676 | /// happens-before relationship with a corresponding write. For example, if | |
677 | /// thread A initializes the cell with `get_or_init(f)`, and thread B | |
678 | /// subsequently reads the result of this call, B also observes all the side | |
679 | /// effects of `f`. | |
e1599b0c XL |
680 | /// |
681 | /// # Example | |
682 | /// ``` | |
683 | /// use once_cell::sync::OnceCell; | |
684 | /// | |
685 | /// static CELL: OnceCell<String> = OnceCell::new(); | |
686 | /// assert!(CELL.get().is_none()); | |
687 | /// | |
688 | /// std::thread::spawn(|| { | |
689 | /// let value: &String = CELL.get_or_init(|| { | |
690 | /// "Hello, World!".to_string() | |
691 | /// }); | |
692 | /// assert_eq!(value, "Hello, World!"); | |
693 | /// }).join().unwrap(); | |
694 | /// | |
695 | /// let value: Option<&String> = CELL.get(); | |
696 | /// assert!(value.is_some()); | |
697 | /// assert_eq!(value.unwrap().as_str(), "Hello, World!"); | |
698 | /// ``` | |
699 | pub struct OnceCell<T>(Imp<T>); | |
700 | ||
701 | impl<T> Default for OnceCell<T> { | |
702 | fn default() -> OnceCell<T> { | |
703 | OnceCell::new() | |
704 | } | |
705 | } | |
706 | ||
707 | impl<T: fmt::Debug> fmt::Debug for OnceCell<T> { | |
708 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
709 | match self.get() { | |
710 | Some(v) => f.debug_tuple("OnceCell").field(v).finish(), | |
711 | None => f.write_str("OnceCell(Uninit)"), | |
712 | } | |
713 | } | |
714 | } | |
715 | ||
716 | impl<T: Clone> Clone for OnceCell<T> { | |
717 | fn clone(&self) -> OnceCell<T> { | |
718 | let res = OnceCell::new(); | |
719 | if let Some(value) = self.get() { | |
720 | match res.set(value.clone()) { | |
721 | Ok(()) => (), | |
722 | Err(_) => unreachable!(), | |
723 | } | |
724 | } | |
725 | res | |
726 | } | |
727 | } | |
728 | ||
729 | impl<T> From<T> for OnceCell<T> { | |
730 | fn from(value: T) -> Self { | |
731 | let cell = Self::new(); | |
732 | cell.get_or_init(|| value); | |
733 | cell | |
734 | } | |
735 | } | |
736 | ||
737 | impl<T: PartialEq> PartialEq for OnceCell<T> { | |
738 | fn eq(&self, other: &OnceCell<T>) -> bool { | |
739 | self.get() == other.get() | |
740 | } | |
741 | } | |
742 | ||
743 | impl<T: Eq> Eq for OnceCell<T> {} | |
744 | ||
745 | impl<T> OnceCell<T> { | |
746 | /// Creates a new empty cell. | |
747 | pub const fn new() -> OnceCell<T> { | |
748 | OnceCell(Imp::new()) | |
749 | } | |
750 | ||
751 | /// Gets the reference to the underlying value. | |
752 | /// | |
753 | /// Returns `None` if the cell is empty, or being initialized. This | |
754 | /// method never blocks. | |
755 | pub fn get(&self) -> Option<&T> { | |
756 | if self.0.is_initialized() { | |
f035d41b | 757 | // Safe b/c value is initialized. |
e1599b0c XL |
758 | Some(unsafe { self.get_unchecked() }) |
759 | } else { | |
760 | None | |
761 | } | |
762 | } | |
763 | ||
764 | /// Gets the mutable reference to the underlying value. | |
765 | /// | |
766 | /// Returns `None` if the cell is empty. | |
767 | pub fn get_mut(&mut self) -> Option<&mut T> { | |
f035d41b XL |
768 | self.0.get_mut() |
769 | } | |
770 | ||
771 | /// Get the reference to the underlying value, without checking if the | |
772 | /// cell is initialized. | |
773 | /// | |
774 | /// # Safety | |
775 | /// | |
776 | /// Caller must ensure that the cell is in initialized state, and that | |
777 | /// the contents are acquired by (synchronized to) this thread. | |
778 | pub unsafe fn get_unchecked(&self) -> &T { | |
779 | self.0.get_unchecked() | |
e1599b0c XL |
780 | } |
781 | ||
782 | /// Sets the contents of this cell to `value`. | |
783 | /// | |
784 | /// Returns `Ok(())` if the cell was empty and `Err(value)` if it was | |
785 | /// full. | |
786 | /// | |
787 | /// # Example | |
f035d41b | 788 | /// |
e1599b0c XL |
789 | /// ``` |
790 | /// use once_cell::sync::OnceCell; | |
791 | /// | |
792 | /// static CELL: OnceCell<i32> = OnceCell::new(); | |
793 | /// | |
794 | /// fn main() { | |
795 | /// assert!(CELL.get().is_none()); | |
796 | /// | |
797 | /// std::thread::spawn(|| { | |
798 | /// assert_eq!(CELL.set(92), Ok(())); | |
799 | /// }).join().unwrap(); | |
800 | /// | |
801 | /// assert_eq!(CELL.set(62), Err(62)); | |
802 | /// assert_eq!(CELL.get(), Some(&92)); | |
803 | /// } | |
804 | /// ``` | |
805 | pub fn set(&self, value: T) -> Result<(), T> { | |
806 | let mut value = Some(value); | |
807 | self.get_or_init(|| value.take().unwrap()); | |
808 | match value { | |
809 | None => Ok(()), | |
810 | Some(value) => Err(value), | |
811 | } | |
812 | } | |
813 | ||
814 | /// Gets the contents of the cell, initializing it with `f` if the cell | |
815 | /// was empty. | |
816 | /// | |
817 | /// Many threads may call `get_or_init` concurrently with different | |
818 | /// initializing functions, but it is guaranteed that only one function | |
819 | /// will be executed. | |
820 | /// | |
821 | /// # Panics | |
822 | /// | |
823 | /// If `f` panics, the panic is propagated to the caller, and the cell | |
824 | /// remains uninitialized. | |
825 | /// | |
826 | /// It is an error to reentrantly initialize the cell from `f`. The | |
827 | /// exact outcome is unspecified. Current implementation deadlocks, but | |
828 | /// this may be changed to a panic in the future. | |
829 | /// | |
830 | /// # Example | |
831 | /// ``` | |
832 | /// use once_cell::sync::OnceCell; | |
833 | /// | |
834 | /// let cell = OnceCell::new(); | |
835 | /// let value = cell.get_or_init(|| 92); | |
836 | /// assert_eq!(value, &92); | |
837 | /// let value = cell.get_or_init(|| unreachable!()); | |
838 | /// assert_eq!(value, &92); | |
839 | /// ``` | |
840 | pub fn get_or_init<F>(&self, f: F) -> &T | |
841 | where | |
842 | F: FnOnce() -> T, | |
843 | { | |
844 | enum Void {} | |
845 | match self.get_or_try_init(|| Ok::<T, Void>(f())) { | |
846 | Ok(val) => val, | |
847 | Err(void) => match void {}, | |
848 | } | |
849 | } | |
850 | ||
851 | /// Gets the contents of the cell, initializing it with `f` if | |
852 | /// the cell was empty. If the cell was empty and `f` failed, an | |
853 | /// error is returned. | |
854 | /// | |
855 | /// # Panics | |
856 | /// | |
857 | /// If `f` panics, the panic is propagated to the caller, and | |
858 | /// the cell remains uninitialized. | |
859 | /// | |
860 | /// It is an error to reentrantly initialize the cell from `f`. | |
861 | /// The exact outcome is unspecified. Current implementation | |
862 | /// deadlocks, but this may be changed to a panic in the future. | |
863 | /// | |
864 | /// # Example | |
865 | /// ``` | |
866 | /// use once_cell::sync::OnceCell; | |
867 | /// | |
868 | /// let cell = OnceCell::new(); | |
869 | /// assert_eq!(cell.get_or_try_init(|| Err(())), Err(())); | |
870 | /// assert!(cell.get().is_none()); | |
871 | /// let value = cell.get_or_try_init(|| -> Result<i32, ()> { | |
872 | /// Ok(92) | |
873 | /// }); | |
874 | /// assert_eq!(value, Ok(&92)); | |
875 | /// assert_eq!(cell.get(), Some(&92)) | |
876 | /// ``` | |
877 | pub fn get_or_try_init<F, E>(&self, f: F) -> Result<&T, E> | |
878 | where | |
879 | F: FnOnce() -> Result<T, E>, | |
880 | { | |
881 | // Fast path check | |
882 | if let Some(value) = self.get() { | |
883 | return Ok(value); | |
884 | } | |
885 | self.0.initialize(f)?; | |
886 | ||
f035d41b | 887 | // Safe b/c value is initialized. |
e1599b0c XL |
888 | debug_assert!(self.0.is_initialized()); |
889 | Ok(unsafe { self.get_unchecked() }) | |
890 | } | |
891 | ||
f035d41b XL |
892 | /// Takes the value out of this `OnceCell`, moving it back to an uninitialized state. |
893 | /// | |
894 | /// Has no effect and returns `None` if the `OnceCell` hasn't been initialized. | |
895 | /// | |
896 | /// # Examples | |
897 | /// | |
898 | /// ``` | |
899 | /// use once_cell::sync::OnceCell; | |
900 | /// | |
901 | /// let mut cell: OnceCell<String> = OnceCell::new(); | |
902 | /// assert_eq!(cell.take(), None); | |
903 | /// | |
904 | /// let mut cell = OnceCell::new(); | |
905 | /// cell.set("hello".to_string()).unwrap(); | |
906 | /// assert_eq!(cell.take(), Some("hello".to_string())); | |
907 | /// assert_eq!(cell.get(), None); | |
908 | /// ``` | |
909 | pub fn take(&mut self) -> Option<T> { | |
910 | mem::replace(self, Self::default()).into_inner() | |
911 | } | |
912 | ||
e1599b0c XL |
913 | /// Consumes the `OnceCell`, returning the wrapped value. Returns |
914 | /// `None` if the cell was empty. | |
915 | /// | |
916 | /// # Examples | |
917 | /// | |
918 | /// ``` | |
919 | /// use once_cell::sync::OnceCell; | |
920 | /// | |
921 | /// let cell: OnceCell<String> = OnceCell::new(); | |
922 | /// assert_eq!(cell.into_inner(), None); | |
923 | /// | |
924 | /// let cell = OnceCell::new(); | |
925 | /// cell.set("hello".to_string()).unwrap(); | |
926 | /// assert_eq!(cell.into_inner(), Some("hello".to_string())); | |
927 | /// ``` | |
928 | pub fn into_inner(self) -> Option<T> { | |
f035d41b | 929 | self.0.into_inner() |
e1599b0c XL |
930 | } |
931 | } | |
932 | ||
933 | /// A value which is initialized on the first access. | |
934 | /// | |
f035d41b | 935 | /// This type is thread-safe and can be used in statics. |
e1599b0c XL |
936 | /// |
937 | /// # Example | |
f035d41b | 938 | /// |
e1599b0c XL |
939 | /// ``` |
940 | /// use std::collections::HashMap; | |
941 | /// | |
942 | /// use once_cell::sync::Lazy; | |
943 | /// | |
944 | /// static HASHMAP: Lazy<HashMap<i32, String>> = Lazy::new(|| { | |
945 | /// println!("initializing"); | |
946 | /// let mut m = HashMap::new(); | |
947 | /// m.insert(13, "Spica".to_string()); | |
948 | /// m.insert(74, "Hoyten".to_string()); | |
949 | /// m | |
950 | /// }); | |
951 | /// | |
952 | /// fn main() { | |
953 | /// println!("ready"); | |
954 | /// std::thread::spawn(|| { | |
955 | /// println!("{:?}", HASHMAP.get(&13)); | |
956 | /// }).join().unwrap(); | |
957 | /// println!("{:?}", HASHMAP.get(&74)); | |
958 | /// | |
959 | /// // Prints: | |
960 | /// // ready | |
961 | /// // initializing | |
962 | /// // Some("Spica") | |
963 | /// // Some("Hoyten") | |
964 | /// } | |
965 | /// ``` | |
966 | pub struct Lazy<T, F = fn() -> T> { | |
967 | cell: OnceCell<T>, | |
968 | init: Cell<Option<F>>, | |
969 | } | |
970 | ||
f035d41b | 971 | impl<T: fmt::Debug, F> fmt::Debug for Lazy<T, F> { |
e1599b0c XL |
972 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
973 | f.debug_struct("Lazy").field("cell", &self.cell).field("init", &"..").finish() | |
974 | } | |
975 | } | |
976 | ||
977 | // We never create a `&F` from a `&Lazy<T, F>` so it is fine | |
978 | // to not impl `Sync` for `F` | |
979 | // we do create a `&mut Option<F>` in `force`, but this is | |
980 | // properly synchronized, so it only happens once | |
981 | // so it also does not contribute to this impl. | |
982 | unsafe impl<T, F: Send> Sync for Lazy<T, F> where OnceCell<T>: Sync {} | |
983 | // auto-derived `Send` impl is OK. | |
984 | ||
985 | #[cfg(feature = "std")] | |
986 | impl<T, F: RefUnwindSafe> RefUnwindSafe for Lazy<T, F> where OnceCell<T>: RefUnwindSafe {} | |
987 | ||
988 | impl<T, F> Lazy<T, F> { | |
989 | /// Creates a new lazy value with the given initializing | |
990 | /// function. | |
991 | pub const fn new(f: F) -> Lazy<T, F> { | |
992 | Lazy { cell: OnceCell::new(), init: Cell::new(Some(f)) } | |
993 | } | |
6a06907d XL |
994 | |
995 | /// Consumes this `Lazy` returning the stored value. | |
996 | /// | |
997 | /// Returns `Ok(value)` if `Lazy` is initialized and `Err(f)` otherwise. | |
998 | pub fn into_value(this: Lazy<T, F>) -> Result<T, F> { | |
999 | let cell = this.cell; | |
1000 | let init = this.init; | |
1001 | cell.into_inner().ok_or_else(|| { | |
1002 | init.take().unwrap_or_else(|| panic!("Lazy instance has previously been poisoned")) | |
1003 | }) | |
1004 | } | |
e1599b0c XL |
1005 | } |
1006 | ||
1007 | impl<T, F: FnOnce() -> T> Lazy<T, F> { | |
1008 | /// Forces the evaluation of this lazy value and | |
f035d41b | 1009 | /// returns a reference to the result. This is equivalent |
e1599b0c XL |
1010 | /// to the `Deref` impl, but is explicit. |
1011 | /// | |
1012 | /// # Example | |
1013 | /// ``` | |
1014 | /// use once_cell::sync::Lazy; | |
1015 | /// | |
1016 | /// let lazy = Lazy::new(|| 92); | |
1017 | /// | |
1018 | /// assert_eq!(Lazy::force(&lazy), &92); | |
1019 | /// assert_eq!(&*lazy, &92); | |
1020 | /// ``` | |
1021 | pub fn force(this: &Lazy<T, F>) -> &T { | |
1022 | this.cell.get_or_init(|| match this.init.take() { | |
1023 | Some(f) => f(), | |
1024 | None => panic!("Lazy instance has previously been poisoned"), | |
1025 | }) | |
1026 | } | |
1027 | } | |
1028 | ||
f035d41b | 1029 | impl<T, F: FnOnce() -> T> Deref for Lazy<T, F> { |
e1599b0c XL |
1030 | type Target = T; |
1031 | fn deref(&self) -> &T { | |
1032 | Lazy::force(self) | |
1033 | } | |
1034 | } | |
1035 | ||
f035d41b XL |
1036 | impl<T, F: FnOnce() -> T> DerefMut for Lazy<T, F> { |
1037 | fn deref_mut(&mut self) -> &mut T { | |
1038 | Lazy::force(self); | |
1039 | self.cell.get_mut().unwrap_or_else(|| unreachable!()) | |
1040 | } | |
1041 | } | |
1042 | ||
e1599b0c XL |
1043 | impl<T: Default> Default for Lazy<T> { |
1044 | /// Creates a new lazy value using `Default` as the initializing function. | |
1045 | fn default() -> Lazy<T> { | |
1046 | Lazy::new(T::default) | |
1047 | } | |
1048 | } | |
1049 | ||
1050 | /// ```compile_fail | |
1051 | /// struct S(*mut ()); | |
1052 | /// unsafe impl Sync for S {} | |
1053 | /// | |
1054 | /// fn share<T: Sync>(_: &T) {} | |
1055 | /// share(&once_cell::sync::OnceCell::<S>::new()); | |
1056 | /// ``` | |
1057 | /// | |
1058 | /// ```compile_fail | |
1059 | /// struct S(*mut ()); | |
1060 | /// unsafe impl Sync for S {} | |
1061 | /// | |
1062 | /// fn share<T: Sync>(_: &T) {} | |
1063 | /// share(&once_cell::sync::Lazy::<S>::new(|| unimplemented!())); | |
1064 | /// ``` | |
1065 | fn _dummy() {} | |
1066 | } | |
5869c6ff | 1067 | |
6a06907d | 1068 | #[cfg(feature = "race")] |
5869c6ff | 1069 | pub mod race; |
6a06907d XL |
1070 | |
1071 | #[cfg(feature = "std")] | |
1072 | unsafe fn take_unchecked<T>(val: &mut Option<T>) -> T { | |
1073 | match val.take() { | |
1074 | Some(it) => it, | |
1075 | None => { | |
1076 | debug_assert!(false); | |
1077 | std::hint::unreachable_unchecked() | |
1078 | } | |
1079 | } | |
1080 | } |