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