1 | use core::cell::UnsafeCell; |
2 | |
3 | pub struct LazyCell<T> { |
4 | contents: UnsafeCell<Option<T>>, |
5 | } |
6 | impl<T> LazyCell<T> { |
7 | pub fn new() -> LazyCell<T> { |
8 | LazyCell { |
9 | contents: UnsafeCell::new(None), |
10 | } |
11 | } |
12 | |
13 | pub fn borrow(&self) -> Option<&T> { |
14 | unsafe { &*self.contents.get() }.as_ref() |
15 | } |
16 | |
17 | pub fn borrow_with(&self, closure: impl FnOnce() -> T) -> &T { |
18 | // First check if we're already initialized... |
19 | let ptr = self.contents.get(); |
20 | if let Some(val) = unsafe { &*ptr } { |
21 | return val; |
22 | } |
23 | // Note that while we're executing `closure` our `borrow_with` may |
24 | // be called recursively. This means we need to check again after |
25 | // the closure has executed. For that we use the `get_or_insert` |
26 | // method which will only perform mutation if we aren't already |
27 | // `Some`. |
28 | let val = closure(); |
29 | unsafe { (*ptr).get_or_insert(val) } |
30 | } |
31 | } |
32 | |