1use ::parking_lot::{ Once, OnceState };
2use ::std::cell::UnsafeCell;
3use ::std::mem::ManuallyDrop;
4use ::std::ops::{ Deref, DerefMut };
5use ::std::panic::{ RefUnwindSafe, UnwindSafe };
6use ::std::ptr;
7
8union Data<T, F> {
9 init: ManuallyDrop<F>,
10 value: ManuallyDrop<T>
11}
12
13pub struct LazyWrap<T, F = fn() -> T> {
14 data: UnsafeCell<Data<T, F>>,
15 once: Once
16}
17
18pub enum LazyWrapState<T, F> {
19 Initialised(T),
20 Uninitialised(F)
21}
22
23impl<T, F> LazyWrap<T, F>
24where
25 F: FnOnce() -> T
26{
27 #[inline]
28 pub const fn new(init: F) -> Self {
29 let init = ManuallyDrop::new(init);
30 let data = UnsafeCell::new(Data { init });
31 let once = Once::new();
32 Self { data, once }
33 }
34
35 #[inline]
36 pub fn ensure_initialised(this: &Self) {
37 this.once.call_once(|| {
38 let data = unsafe { &mut (*this.data.get()) };
39 let init = unsafe { ManuallyDrop::take(&mut data.init) };
40 let value = init();
41 data.value = ManuallyDrop::new(value);
42 });
43 }
44
45 #[inline]
46 fn ref_inner(this: &Self) -> &T {
47 Self::ensure_initialised(this);
48 unsafe { &(*this.data.get()).value }
49 }
50
51 #[inline]
52 fn mut_inner(this: &mut Self) -> &mut T {
53 Self::ensure_initialised(this);
54 unsafe { &mut (*this.data.get()).value }
55 }
56
57 #[inline]
58 pub fn is_initialised(this: &Self) -> bool {
59 use OnceState::*;
60 match this.once.state() {
61 New => { false }
62 Poisoned => { panic!("initialiser panicked") }
63 InProgress => {
64 this.once.call_once(|| {});
65 true
66 }
67 Done => { true }
68 }
69 }
70
71 pub fn into_inner(this: Self) -> LazyWrapState<T, F> {
72 let initialised = Self::is_initialised(&this);
73 let this = ManuallyDrop::new(this);
74 let data = unsafe { ptr::read(this.data.get()) };
75
76 if initialised {
77 let value = ManuallyDrop::into_inner(unsafe { data.value });
78 LazyWrapState::Initialised(value)
79 } else {
80 let init = ManuallyDrop::into_inner(unsafe { data.init });
81 LazyWrapState::Uninitialised(init)
82 }
83 }
84
85 pub fn into_inner_initialised(this: Self) -> T {
86 Self::ensure_initialised(&this);
87 let this = ManuallyDrop::new(this);
88 let data = unsafe { ptr::read(this.data.get()) };
89 ManuallyDrop::into_inner(unsafe { data.value })
90 }
91}
92
93impl<T, F> Deref for LazyWrap<T, F>
94where
95 F: FnOnce() -> T
96{
97 type Target = T;
98 #[inline]
99 fn deref(&self) -> &Self::Target {
100 Self::ref_inner(self)
102 }
103}
104
105impl<T, F> DerefMut for LazyWrap<T, F>
106where
107 F: FnOnce() -> T
108{
109 #[inline]
110 fn deref_mut(&mut self) -> &mut Self::Target {
111 Self::mut_inner(self)
113 }
114}
115
116impl<T, U, F> AsRef<U> for LazyWrap<T, F>
117where
118 F: FnOnce() -> T,
119 T: AsRef<U>,
120 U: ?Sized
121{
122 #[inline]
123 fn as_ref(&self) -> &U {
124 (**self).as_ref()
126 }
127}
128
129impl<T, U, F> AsMut<U> for LazyWrap<T, F>
130where
131 F: FnOnce() -> T,
132 T: AsMut<U>,
133 U: ?Sized
134{
135 #[inline]
136 fn as_mut(&mut self) -> &mut U {
137 (**self).as_mut()
139 }
140}
141
142unsafe impl<T, F> Send for LazyWrap<T, F> where T: Send, F: Send {}
143unsafe impl<T, F> Sync for LazyWrap<T, F> where T: Sync, F: Send {}
144impl<T, F> UnwindSafe for LazyWrap<T, F> where T: UnwindSafe, F: UnwindSafe {}
145impl<T, F> RefUnwindSafe for LazyWrap<T, F> where T: RefUnwindSafe, F: UnwindSafe {}
146impl<T, F> Unpin for LazyWrap<T, F> where T: Unpin, F: Unpin {}
147
148impl<T, F> Drop for LazyWrap<T, F> {
149 fn drop(&mut self) {
150 use OnceState::*;
151 match self.once.state() {
152 New => {
153 unsafe { ManuallyDrop::drop(&mut self.data.get_mut().init) }
154 }
155 Poisoned => {}
156 InProgress => {
157 self.once.call_once(|| {});
162 unsafe { ManuallyDrop::drop(&mut self.data.get_mut().value) }
163 }
164 Done => {
165 unsafe { ManuallyDrop::drop(&mut self.data.get_mut().value) }
166 }
167 }
168 }
169}