/rust/registry/src/index.crates.io-1949cf8c6b5b557f/conquer-once-0.3.2/src/cell.rs
Line | Count | Source |
1 | | //! Generic definition and implementation of the [`OnceCell`] type. |
2 | | |
3 | | use core::cell::UnsafeCell; |
4 | | use core::fmt; |
5 | | use core::marker::PhantomData; |
6 | | use core::mem::{self, MaybeUninit}; |
7 | | use core::ptr; |
8 | | use core::sync::atomic::Ordering; |
9 | | |
10 | | use crate::state::{AtomicOnceState, BlockedState, OnceState, SwapState, TryBlockError}; |
11 | | use crate::POISON_PANIC_MSG; |
12 | | |
13 | | //////////////////////////////////////////////////////////////////////////////////////////////////// |
14 | | // Unblock (trait) |
15 | | //////////////////////////////////////////////////////////////////////////////////////////////////// |
16 | | |
17 | | /// An internal (sealed) trait specifying the unblocking mechanism of a cell |
18 | | /// locking strategy. |
19 | | pub unsafe trait Unblock { |
20 | | /// Unblocks all waiting threads after setting the cell state to `READY`. |
21 | | /// |
22 | | /// # Safety |
23 | | /// |
24 | | /// Must only be called after swapping the cell with `READY` with the state |
25 | | /// returned by the swap operation. |
26 | | unsafe fn on_unblock(state: BlockedState); |
27 | | } |
28 | | |
29 | | //////////////////////////////////////////////////////////////////////////////////////////////////// |
30 | | // Block (trait) |
31 | | //////////////////////////////////////////////////////////////////////////////////////////////////// |
32 | | |
33 | | /// An internal (sealed) trait specifying the blocking mechanism of a cell |
34 | | /// locking strategy. |
35 | | pub unsafe trait Block: Unblock { |
36 | | /// Blocks the current thread until `state` is either `READY` or `POISONED`. |
37 | | fn block(state: &AtomicOnceState); |
38 | | } |
39 | | |
40 | | //////////////////////////////////////////////////////////////////////////////////////////////////// |
41 | | // OnceCell |
42 | | //////////////////////////////////////////////////////////////////////////////////////////////////// |
43 | | |
44 | | /// An interior mutability cell type which allows synchronized one-time |
45 | | /// initialization and read-only access exclusively after initialization. |
46 | | /// |
47 | | /// # Poisoning |
48 | | /// |
49 | | /// A thread that panics in the course of executing its `init` function or |
50 | | /// closure **poisons** the cell. |
51 | | /// All subsequent accesses to a poisoned cell will propagate this and panic |
52 | | /// themselves. |
53 | | pub struct OnceCell<T, B> { |
54 | | /// The current initialization status. |
55 | | state: AtomicOnceState, |
56 | | /// The internal and potentially uninitialized value. |
57 | | inner: UnsafeCell<MaybeUninit<T>>, |
58 | | /// A marker for the blocking strategy (i.e. OS-level block or spin-lock) |
59 | | _marker: PhantomData<B>, |
60 | | } |
61 | | |
62 | | /********** impl Send + Sync **********************************************************************/ |
63 | | |
64 | | unsafe impl<T, B> Send for OnceCell<T, B> where T: Send {} |
65 | | unsafe impl<T, B> Sync for OnceCell<T, B> where T: Send + Sync {} |
66 | | |
67 | | /********** impl inherent *************************************************************************/ |
68 | | |
69 | | impl<T, B> OnceCell<T, B> { |
70 | | /// Creates a new uninitialized [`OnceCell`]. |
71 | | #[inline] |
72 | | pub const fn uninit() -> Self { |
73 | | Self { |
74 | | state: AtomicOnceState::new(), |
75 | | inner: UnsafeCell::new(MaybeUninit::uninit()), |
76 | | _marker: PhantomData, |
77 | | } |
78 | | } |
79 | | |
80 | | /// Creates a new [`OnceCell`] pre-initialized with `value`. |
81 | | #[inline] |
82 | | pub const fn new(value: T) -> Self { |
83 | | Self { |
84 | | state: AtomicOnceState::ready(), |
85 | | inner: UnsafeCell::new(MaybeUninit::new(value)), |
86 | | _marker: PhantomData, |
87 | | } |
88 | | } |
89 | | |
90 | | /// Consumes `self` and returns a [`Some(T)`](Some) if the [`OnceCell`] has |
91 | | /// previously been successfully initialized or [`None`] otherwise. |
92 | | /// |
93 | | /// # Panics |
94 | | /// |
95 | | /// This method panics if the [`OnceCell`] has been poisoned. |
96 | | /// |
97 | | /// # Examples |
98 | | /// |
99 | | /// ``` |
100 | | /// # use conquer_once::spin::OnceCell; |
101 | | /// |
102 | | /// let uninit: OnceCell<i32> = OnceCell::uninit(); |
103 | | /// assert!(uninit.into_inner().is_none()); |
104 | | /// |
105 | | /// let once = OnceCell::uninit(); |
106 | | /// once.init_once(|| "initialized"); |
107 | | /// assert_eq!(once.into_inner(), Some("initialized")); |
108 | | /// ``` |
109 | | #[inline] |
110 | | pub fn into_inner(mut self) -> Option<T> { |
111 | | let res = self.take_inner(false); |
112 | | mem::forget(self); |
113 | | res |
114 | | } |
115 | | |
116 | | /// Returns true if the [`OnceCell`] has been successfully initialized. |
117 | | /// |
118 | | /// This method does not panic if the [`OnceCell`] is poisoned and |
119 | | /// never blocks. |
120 | | #[inline] |
121 | | pub fn is_initialized(&self) -> bool { |
122 | | // (cell:1) this acquire load syncs-with the acq-rel swap (guard:2) |
123 | | self.state.load(Ordering::Acquire) == Ok(OnceState::Ready) |
124 | | } |
125 | | |
126 | | /// Returns true if the [`OnceCell`] has been poisoned during |
127 | | /// initialization. |
128 | | /// |
129 | | /// This method does not panic if the [`OnceCell`] is poisoned and |
130 | | /// never blocks. |
131 | | /// Once this method has returned `true` all other means of accessing the |
132 | | /// [`OnceCell`] except for further calls to |
133 | | /// [`is_initialized`][OnceCell::is_initialized] or |
134 | | /// [`is_poisoned`][OnceCell::is_poisoned] will lead to a panic |
135 | | #[inline] |
136 | | pub fn is_poisoned(&self) -> bool { |
137 | | self.state.load(Ordering::Relaxed).is_err() |
138 | | } |
139 | | |
140 | | /// Returns a reference to the [`OnceCell`]'s initialized inner state or |
141 | | /// an [`Err`]. |
142 | | /// |
143 | | /// This method never blocks. |
144 | | /// |
145 | | /// When this function returns with an [`Ok`] result, it is guaranteed that |
146 | | /// some initialization closure has run and completed. |
147 | | /// It is also guaranteed that any memory writes performed by the executed |
148 | | /// closure can be reliably observed by other threads at this point (there |
149 | | /// is a happens-before relation between the closure and code executing |
150 | | /// after the return). |
151 | | /// |
152 | | /// # Errors |
153 | | /// |
154 | | /// This method fails if the [`OnceCell`] is either not initialized |
155 | | /// ([`Uninit`][TryGetError::Uninit]) or is currently being |
156 | | /// initialized by some other thread |
157 | | /// ([`WouldBlock`][TryGetError::WouldBlock]). |
158 | | /// |
159 | | /// # Panics |
160 | | /// |
161 | | /// This method panics if the [`OnceCell`] has been poisoned. |
162 | | #[inline] |
163 | 0 | pub fn try_get(&self) -> Result<&T, TryGetError> { |
164 | | // (cell:2) this acquire load syncs-with the acq-rel swap (guard:2) |
165 | 0 | match self.state.load(Ordering::Acquire).expect(POISON_PANIC_MSG) { |
166 | 0 | OnceState::Ready => Ok(unsafe { self.get_unchecked() }), |
167 | 0 | OnceState::Uninit => Err(TryGetError::Uninit), |
168 | 0 | OnceState::WouldBlock(_) => Err(TryGetError::WouldBlock), |
169 | | } |
170 | 0 | } Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::time::time_callbacks::SpdmTime, conquer_once::spin::internal::Spin>>::try_get Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmKemDecap, conquer_once::spin::internal::Spin>>::try_get Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmKemEncap, conquer_once::spin::internal::Spin>>::try_get Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmAsymVerify, conquer_once::spin::internal::Spin>>::try_get Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmCryptoRandom, conquer_once::spin::internal::Spin>>::try_get Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmCertOperation, conquer_once::spin::internal::Spin>>::try_get Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmPqcAsymVerify, conquer_once::spin::internal::Spin>>::try_get Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmDhe, conquer_once::spin::internal::Spin>>::try_get Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmAead, conquer_once::spin::internal::Spin>>::try_get Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmHash, conquer_once::spin::internal::Spin>>::try_get Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmHkdf, conquer_once::spin::internal::Spin>>::try_get Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmHmac, conquer_once::spin::internal::Spin>>::try_get Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::secret::secret_callback::SpdmSecretPsk, conquer_once::spin::internal::Spin>>::try_get Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::secret::secret_callback::SpdmSecretAsymSign, conquer_once::spin::internal::Spin>>::try_get Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::secret::secret_callback::SpdmSecretMeasurement, conquer_once::spin::internal::Spin>>::try_get Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::secret::secret_callback::SpdmSecretPqcAsymSign, conquer_once::spin::internal::Spin>>::try_get Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::message::vendor::VendorDefinedStruct, conquer_once::spin::internal::Spin>>::try_get Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::message::vendor::VendorDefinedStructEx, conquer_once::spin::internal::Spin>>::try_get Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::watchdog::watchdog_callbacks::SpdmWatchDog, conquer_once::spin::internal::Spin>>::try_get Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::responder::app_message_handler::SpdmAppMessageHandler, conquer_once::spin::internal::Spin>>::try_get |
171 | | |
172 | | /// Returns a reference to the inner value without checking whether the |
173 | | /// [`OnceCell`] is actually initialized. |
174 | | /// |
175 | | /// # Safety |
176 | | /// |
177 | | /// The caller has to ensure that the cell has been successfully |
178 | | /// initialized, otherwise uninitialized memory will be read. |
179 | | /// |
180 | | /// # Examples |
181 | | /// |
182 | | /// This is one safe way to use this method, although |
183 | | /// [`try_get`][OnceCell::try_get] is the better alternative: |
184 | | /// |
185 | | /// ``` |
186 | | /// # #[cfg(feature = "std")] |
187 | | /// use conquer_once::OnceCell; |
188 | | /// # #[cfg(not(feature = "std"))] |
189 | | /// # use conquer_once::spin::OnceCell; |
190 | | /// |
191 | | /// // let cell = ... |
192 | | /// # let cell = OnceCell::uninit(); |
193 | | /// # cell.init_once(|| 0); |
194 | | /// |
195 | | /// let res = if cell.is_initialized() { |
196 | | /// Some(unsafe { cell.get_unchecked() }) |
197 | | /// } else { |
198 | | /// None |
199 | | /// }; |
200 | | /// |
201 | | /// # assert_eq!(res, Some(&0)); |
202 | | /// ``` |
203 | | #[inline] |
204 | 0 | pub unsafe fn get_unchecked(&self) -> &T { |
205 | 0 | let inner = &*self.inner.get(); |
206 | 0 | &*inner.as_ptr() |
207 | 0 | } Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::time::time_callbacks::SpdmTime, conquer_once::spin::internal::Spin>>::get_unchecked Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmKemDecap, conquer_once::spin::internal::Spin>>::get_unchecked Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmKemEncap, conquer_once::spin::internal::Spin>>::get_unchecked Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmAsymVerify, conquer_once::spin::internal::Spin>>::get_unchecked Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmCryptoRandom, conquer_once::spin::internal::Spin>>::get_unchecked Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmCertOperation, conquer_once::spin::internal::Spin>>::get_unchecked Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmPqcAsymVerify, conquer_once::spin::internal::Spin>>::get_unchecked Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmDhe, conquer_once::spin::internal::Spin>>::get_unchecked Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmAead, conquer_once::spin::internal::Spin>>::get_unchecked Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmHash, conquer_once::spin::internal::Spin>>::get_unchecked Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmHkdf, conquer_once::spin::internal::Spin>>::get_unchecked Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmHmac, conquer_once::spin::internal::Spin>>::get_unchecked Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::secret::secret_callback::SpdmSecretPsk, conquer_once::spin::internal::Spin>>::get_unchecked Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::secret::secret_callback::SpdmSecretAsymSign, conquer_once::spin::internal::Spin>>::get_unchecked Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::secret::secret_callback::SpdmSecretMeasurement, conquer_once::spin::internal::Spin>>::get_unchecked Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::secret::secret_callback::SpdmSecretPqcAsymSign, conquer_once::spin::internal::Spin>>::get_unchecked Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::message::vendor::VendorDefinedStruct, conquer_once::spin::internal::Spin>>::get_unchecked Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::message::vendor::VendorDefinedStructEx, conquer_once::spin::internal::Spin>>::get_unchecked Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::watchdog::watchdog_callbacks::SpdmWatchDog, conquer_once::spin::internal::Spin>>::get_unchecked Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::responder::app_message_handler::SpdmAppMessageHandler, conquer_once::spin::internal::Spin>>::get_unchecked |
208 | | |
209 | | /// Moves the inner cell value out of the [`OnceCell`] and returns it |
210 | | /// wrapped in [`Some`], if it has been successfully initialized. |
211 | | /// |
212 | | /// # Panics |
213 | | /// |
214 | | /// If `ignore_panic` is `false`, this method will panic if the [`OnceCell`] |
215 | | /// has been poisoned, otherwise it will simply return [`None`]. |
216 | | #[inline] |
217 | 0 | fn take_inner(&mut self, ignore_panic: bool) -> Option<T> { |
218 | | #[allow(clippy::match_wild_err_arm)] |
219 | 0 | match self.state.load(Ordering::Relaxed) { |
220 | 0 | Err(_) if !ignore_panic => panic!(POISON_PANIC_MSG), |
221 | 0 | Ok(OnceState::Ready) => Some(unsafe { ptr::read(self.get_unchecked()) }), |
222 | 0 | _ => None, |
223 | | } |
224 | 0 | } Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::time::time_callbacks::SpdmTime, conquer_once::spin::internal::Spin>>::take_inner Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmKemDecap, conquer_once::spin::internal::Spin>>::take_inner Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmKemEncap, conquer_once::spin::internal::Spin>>::take_inner Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmAsymVerify, conquer_once::spin::internal::Spin>>::take_inner Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmCryptoRandom, conquer_once::spin::internal::Spin>>::take_inner Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmCertOperation, conquer_once::spin::internal::Spin>>::take_inner Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmPqcAsymVerify, conquer_once::spin::internal::Spin>>::take_inner Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmDhe, conquer_once::spin::internal::Spin>>::take_inner Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmAead, conquer_once::spin::internal::Spin>>::take_inner Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmHash, conquer_once::spin::internal::Spin>>::take_inner Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmHkdf, conquer_once::spin::internal::Spin>>::take_inner Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmHmac, conquer_once::spin::internal::Spin>>::take_inner Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::secret::secret_callback::SpdmSecretPsk, conquer_once::spin::internal::Spin>>::take_inner Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::secret::secret_callback::SpdmSecretAsymSign, conquer_once::spin::internal::Spin>>::take_inner Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::secret::secret_callback::SpdmSecretMeasurement, conquer_once::spin::internal::Spin>>::take_inner Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::secret::secret_callback::SpdmSecretPqcAsymSign, conquer_once::spin::internal::Spin>>::take_inner Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::message::vendor::VendorDefinedStruct, conquer_once::spin::internal::Spin>>::take_inner Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::message::vendor::VendorDefinedStructEx, conquer_once::spin::internal::Spin>>::take_inner Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::watchdog::watchdog_callbacks::SpdmWatchDog, conquer_once::spin::internal::Spin>>::take_inner Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::responder::app_message_handler::SpdmAppMessageHandler, conquer_once::spin::internal::Spin>>::take_inner |
225 | | } |
226 | | |
227 | | impl<T, B: Unblock> OnceCell<T, B> { |
228 | | /// Attempts to initialize the [`OnceCell`] with `func` if is is |
229 | | /// uninitialized and returns [`Ok(())`](Ok) only if `func` is successfully |
230 | | /// executed. |
231 | | /// |
232 | | /// This method never blocks. |
233 | | /// |
234 | | /// When this function returns with an [`Ok`] or |
235 | | /// [`AlreadyInit`][TryInitError::AlreadyInit] result, it is guaranteed that |
236 | | /// some initialization closure has run and completed (it may not be the |
237 | | /// closure specified). |
238 | | /// It is also guaranteed that any memory writes performed by the executed |
239 | | /// closure can be reliably observed by other threads at this point (there |
240 | | /// is a happens-before relation between the closure and code executing |
241 | | /// after the return). |
242 | | /// |
243 | | /// # Errors |
244 | | /// |
245 | | /// This method fails if the initialization of [`OnceCell`] has already been |
246 | | /// completed previously, in which case an |
247 | | /// [`AlreadyInit`][TryInitError::AlreadyInit] error is returned. |
248 | | /// If another thread is concurrently in the process of initializing it and |
249 | | /// this thread would have to block, a |
250 | | /// [`WouldBlock`][TryInitError::WouldBlock] error is returned. |
251 | | /// |
252 | | /// # Panics |
253 | | /// |
254 | | /// This method panics if the [`OnceCell`] has been poisoned. |
255 | | /// |
256 | | /// # Examples |
257 | | /// |
258 | | /// ``` |
259 | | /// # #[cfg(feature = "std")] |
260 | | /// use conquer_once::{OnceCell, TryInitError}; |
261 | | /// # #[cfg(not(feature = "std"))] |
262 | | /// # use conquer_once::{spin::OnceCell, TryInitError}; |
263 | | /// |
264 | | /// let cell = OnceCell::uninit(); |
265 | | /// |
266 | | /// // .. in thread 1 |
267 | | /// let res = cell.try_init_once(|| { |
268 | | /// 1 |
269 | | /// }); |
270 | | /// assert!(res.is_ok()); |
271 | | /// |
272 | | /// // .. in thread 2 |
273 | | /// let res = cell.try_init_once(|| { |
274 | | /// 2 |
275 | | /// }); |
276 | | /// assert_eq!(res, Err(TryInitError::AlreadyInit)); |
277 | | /// |
278 | | /// # assert_eq!(cell.get().copied(), Some(1)); |
279 | | /// ``` |
280 | | #[inline] |
281 | 0 | pub fn try_init_once(&self, func: impl FnOnce() -> T) -> Result<(), TryInitError> { |
282 | | // (cell:3) this acq load syncs-with the acq-rel swap (guard:2) |
283 | 0 | match self.state.load(Ordering::Acquire).expect(POISON_PANIC_MSG) { |
284 | 0 | OnceState::Ready => Err(TryInitError::AlreadyInit), |
285 | 0 | OnceState::WouldBlock(_) => Err(TryInitError::WouldBlock), |
286 | | OnceState::Uninit => { |
287 | 0 | let mut func = Some(func); |
288 | 0 | self.try_init_inner(&mut || func.take().unwrap()())?; Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::time::time_callbacks::SpdmTime, conquer_once::spin::internal::Spin>>::try_init_once::<spdmlib::time::register::{closure#0}>::{closure#0}Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmKemDecap, conquer_once::spin::internal::Spin>>::try_init_once::<spdmlib::crypto::kem_decap::register::{closure#0}>::{closure#0}Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmKemEncap, conquer_once::spin::internal::Spin>>::try_init_once::<spdmlib::crypto::kem_encap::register::{closure#0}>::{closure#0}Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmCryptoRandom, conquer_once::spin::internal::Spin>>::try_init_once::<spdmlib::crypto::rand::register::{closure#0}>::{closure#0}Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmCertOperation, conquer_once::spin::internal::Spin>>::try_init_once::<spdmlib::crypto::cert_operation::register::{closure#0}>::{closure#0}Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmDhe, conquer_once::spin::internal::Spin>>::try_init_once::<spdmlib::crypto::dhe::register::{closure#0}>::{closure#0}Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmAead, conquer_once::spin::internal::Spin>>::try_init_once::<spdmlib::crypto::aead::register::{closure#0}>::{closure#0}Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmHash, conquer_once::spin::internal::Spin>>::try_init_once::<spdmlib::crypto::hash::register::{closure#0}>::{closure#0}Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmHkdf, conquer_once::spin::internal::Spin>>::try_init_once::<spdmlib::crypto::hkdf::register::{closure#0}>::{closure#0}Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmHmac, conquer_once::spin::internal::Spin>>::try_init_once::<spdmlib::crypto::hmac::register::{closure#0}>::{closure#0}Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::secret::secret_callback::SpdmSecretPsk, conquer_once::spin::internal::Spin>>::try_init_once::<spdmlib::secret::psk::register::{closure#0}>::{closure#0}Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::secret::secret_callback::SpdmSecretAsymSign, conquer_once::spin::internal::Spin>>::try_init_once::<spdmlib::secret::asym_sign::register::{closure#0}>::{closure#0}Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::secret::secret_callback::SpdmSecretMeasurement, conquer_once::spin::internal::Spin>>::try_init_once::<spdmlib::secret::measurement::register::{closure#0}>::{closure#0}Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::secret::secret_callback::SpdmSecretPqcAsymSign, conquer_once::spin::internal::Spin>>::try_init_once::<spdmlib::secret::pqc_asym_sign::register::{closure#0}>::{closure#0}Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::message::vendor::VendorDefinedStruct, conquer_once::spin::internal::Spin>>::try_init_once::<spdmlib::message::vendor::register_vendor_defined_struct::{closure#0}>::{closure#0}Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::message::vendor::VendorDefinedStructEx, conquer_once::spin::internal::Spin>>::try_init_once::<spdmlib::message::vendor::register_vendor_defined_struct_ex::{closure#0}>::{closure#0}Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::watchdog::watchdog_callbacks::SpdmWatchDog, conquer_once::spin::internal::Spin>>::try_init_once::<spdmlib::watchdog::register::{closure#0}>::{closure#0}Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::responder::app_message_handler::SpdmAppMessageHandler, conquer_once::spin::internal::Spin>>::try_init_once::<spdmlib::responder::app_message_handler::register::{closure#0}>::{closure#0} |
289 | 0 | Ok(()) |
290 | | } |
291 | | } |
292 | 0 | } Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::time::time_callbacks::SpdmTime, conquer_once::spin::internal::Spin>>::try_init_once::<spdmlib::time::register::{closure#0}>Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmKemDecap, conquer_once::spin::internal::Spin>>::try_init_once::<spdmlib::crypto::kem_decap::register::{closure#0}>Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmKemEncap, conquer_once::spin::internal::Spin>>::try_init_once::<spdmlib::crypto::kem_encap::register::{closure#0}>Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmCryptoRandom, conquer_once::spin::internal::Spin>>::try_init_once::<spdmlib::crypto::rand::register::{closure#0}>Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmCertOperation, conquer_once::spin::internal::Spin>>::try_init_once::<spdmlib::crypto::cert_operation::register::{closure#0}>Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmDhe, conquer_once::spin::internal::Spin>>::try_init_once::<spdmlib::crypto::dhe::register::{closure#0}>Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmAead, conquer_once::spin::internal::Spin>>::try_init_once::<spdmlib::crypto::aead::register::{closure#0}>Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmHash, conquer_once::spin::internal::Spin>>::try_init_once::<spdmlib::crypto::hash::register::{closure#0}>Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmHkdf, conquer_once::spin::internal::Spin>>::try_init_once::<spdmlib::crypto::hkdf::register::{closure#0}>Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmHmac, conquer_once::spin::internal::Spin>>::try_init_once::<spdmlib::crypto::hmac::register::{closure#0}>Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::secret::secret_callback::SpdmSecretPsk, conquer_once::spin::internal::Spin>>::try_init_once::<spdmlib::secret::psk::register::{closure#0}>Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::secret::secret_callback::SpdmSecretAsymSign, conquer_once::spin::internal::Spin>>::try_init_once::<spdmlib::secret::asym_sign::register::{closure#0}>Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::secret::secret_callback::SpdmSecretMeasurement, conquer_once::spin::internal::Spin>>::try_init_once::<spdmlib::secret::measurement::register::{closure#0}>Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::secret::secret_callback::SpdmSecretPqcAsymSign, conquer_once::spin::internal::Spin>>::try_init_once::<spdmlib::secret::pqc_asym_sign::register::{closure#0}>Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::message::vendor::VendorDefinedStruct, conquer_once::spin::internal::Spin>>::try_init_once::<spdmlib::message::vendor::register_vendor_defined_struct::{closure#0}>Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::message::vendor::VendorDefinedStructEx, conquer_once::spin::internal::Spin>>::try_init_once::<spdmlib::message::vendor::register_vendor_defined_struct_ex::{closure#0}>Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::watchdog::watchdog_callbacks::SpdmWatchDog, conquer_once::spin::internal::Spin>>::try_init_once::<spdmlib::watchdog::register::{closure#0}>Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::responder::app_message_handler::SpdmAppMessageHandler, conquer_once::spin::internal::Spin>>::try_init_once::<spdmlib::responder::app_message_handler::register::{closure#0}> |
293 | | |
294 | | /// This method is annotated with `#[cold]` in order to keep it out of the |
295 | | /// fast path. |
296 | | #[inline(never)] |
297 | | #[cold] |
298 | 0 | fn try_init_inner(&self, func: &mut dyn FnMut() -> T) -> Result<&T, TryBlockError> { |
299 | | // sets the state to blocked (i.e. guarantees mutual exclusion) or |
300 | | // returns with an error. |
301 | 0 | let guard = PanicGuard::<B>::try_block(&self.state)?; |
302 | 0 | unsafe { |
303 | 0 | let inner = &mut *self.inner.get(); |
304 | 0 | inner.as_mut_ptr().write(func()); |
305 | 0 | } |
306 | 0 | guard.disarm(); |
307 | | |
308 | 0 | Ok(unsafe { self.get_unchecked() }) |
309 | 0 | } Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::time::time_callbacks::SpdmTime, conquer_once::spin::internal::Spin>>::try_init_inner Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmKemDecap, conquer_once::spin::internal::Spin>>::try_init_inner Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmKemEncap, conquer_once::spin::internal::Spin>>::try_init_inner Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmAsymVerify, conquer_once::spin::internal::Spin>>::try_init_inner Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmCryptoRandom, conquer_once::spin::internal::Spin>>::try_init_inner Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmCertOperation, conquer_once::spin::internal::Spin>>::try_init_inner Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmPqcAsymVerify, conquer_once::spin::internal::Spin>>::try_init_inner Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmDhe, conquer_once::spin::internal::Spin>>::try_init_inner Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmAead, conquer_once::spin::internal::Spin>>::try_init_inner Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmHash, conquer_once::spin::internal::Spin>>::try_init_inner Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmHkdf, conquer_once::spin::internal::Spin>>::try_init_inner Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmHmac, conquer_once::spin::internal::Spin>>::try_init_inner Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::secret::secret_callback::SpdmSecretPsk, conquer_once::spin::internal::Spin>>::try_init_inner Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::secret::secret_callback::SpdmSecretAsymSign, conquer_once::spin::internal::Spin>>::try_init_inner Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::secret::secret_callback::SpdmSecretMeasurement, conquer_once::spin::internal::Spin>>::try_init_inner Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::secret::secret_callback::SpdmSecretPqcAsymSign, conquer_once::spin::internal::Spin>>::try_init_inner Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::message::vendor::VendorDefinedStruct, conquer_once::spin::internal::Spin>>::try_init_inner Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::message::vendor::VendorDefinedStructEx, conquer_once::spin::internal::Spin>>::try_init_inner Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::watchdog::watchdog_callbacks::SpdmWatchDog, conquer_once::spin::internal::Spin>>::try_init_inner Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::responder::app_message_handler::SpdmAppMessageHandler, conquer_once::spin::internal::Spin>>::try_init_inner |
310 | | |
311 | | /// Returns a reference to the [`OnceCell`]'s initialized inner state or |
312 | | /// otherwise attempts to initialize it with `func` and return the result. |
313 | | /// |
314 | | /// This method never blocks. |
315 | | /// |
316 | | /// When this function returns with an [`Ok`] result, it is guaranteed that |
317 | | /// some initialization closure has run and completed (it may not be the |
318 | | /// closure specified). |
319 | | /// It is also guaranteed that any memory writes performed by the executed |
320 | | /// closure can be reliably observed by other threads at this point (there |
321 | | /// is a happens-before relation between the closure and code executing |
322 | | /// after the return). |
323 | | /// |
324 | | /// # Errors |
325 | | /// |
326 | | /// This method only fails if the calling thread would have to block in case |
327 | | /// another thread is concurrently initializing the [`OnceCell`]. |
328 | | /// |
329 | | /// # Panics |
330 | | /// |
331 | | /// This method panics if the [`OnceCell`] has been poisoned. |
332 | | #[inline] |
333 | 0 | pub fn try_get_or_init(&self, func: impl FnOnce() -> T) -> Result<&T, WouldBlockError> { |
334 | 0 | match self.try_get() { |
335 | 0 | Ok(res) => Ok(res), |
336 | 0 | Err(TryGetError::WouldBlock) => Err(WouldBlockError(())), |
337 | | Err(TryGetError::Uninit) => { |
338 | 0 | let mut func = Some(func); |
339 | 0 | let res = self.try_init_inner(&mut || func.take().unwrap()())?; Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::time::time_callbacks::SpdmTime, conquer_once::spin::internal::Spin>>::try_get_or_init::<spdmlib::time::sleep::{closure#0}>::{closure#0}Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmKemDecap, conquer_once::spin::internal::Spin>>::try_get_or_init::<spdmlib::crypto::kem_decap::generate_key_pair::{closure#0}>::{closure#0}Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmKemEncap, conquer_once::spin::internal::Spin>>::try_get_or_init::<spdmlib::crypto::kem_encap::new_key::{closure#0}>::{closure#0}Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmAsymVerify, conquer_once::spin::internal::Spin>>::try_get_or_init::<spdmlib::crypto::asym_verify::verify::{closure#0}>::{closure#0}Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmAsymVerify, conquer_once::spin::internal::Spin>>::try_get_or_init::<spdmlib::crypto::asym_verify::register::{closure#0}>::{closure#0}Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmCryptoRandom, conquer_once::spin::internal::Spin>>::try_get_or_init::<spdmlib::crypto::rand::get_random::{closure#0}>::{closure#0}Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmCertOperation, conquer_once::spin::internal::Spin>>::try_get_or_init::<spdmlib::crypto::cert_operation::verify_cert_chain::{closure#0}>::{closure#0}Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmCertOperation, conquer_once::spin::internal::Spin>>::try_get_or_init::<spdmlib::crypto::cert_operation::get_cert_from_cert_chain::{closure#0}>::{closure#0}Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmPqcAsymVerify, conquer_once::spin::internal::Spin>>::try_get_or_init::<spdmlib::crypto::pqc_asym_verify::verify::{closure#0}>::{closure#0}Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmPqcAsymVerify, conquer_once::spin::internal::Spin>>::try_get_or_init::<spdmlib::crypto::pqc_asym_verify::register::{closure#0}>::{closure#0}Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmDhe, conquer_once::spin::internal::Spin>>::try_get_or_init::<spdmlib::crypto::dhe::generate_key_pair::{closure#0}>::{closure#0}Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmAead, conquer_once::spin::internal::Spin>>::try_get_or_init::<spdmlib::crypto::aead::decrypt::{closure#0}>::{closure#0}Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmAead, conquer_once::spin::internal::Spin>>::try_get_or_init::<spdmlib::crypto::aead::encrypt::{closure#0}>::{closure#0}Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmHash, conquer_once::spin::internal::Spin>>::try_get_or_init::<spdmlib::crypto::hash::hash_all::{closure#0}>::{closure#0}Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmHash, conquer_once::spin::internal::Spin>>::try_get_or_init::<spdmlib::crypto::hash::hash_ext::hash_ctx_dup::{closure#0}>::{closure#0}Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmHash, conquer_once::spin::internal::Spin>>::try_get_or_init::<spdmlib::crypto::hash::hash_ext::hash_ctx_init::{closure#0}>::{closure#0}Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmHash, conquer_once::spin::internal::Spin>>::try_get_or_init::<spdmlib::crypto::hash::hash_ext::hash_ctx_update::{closure#0}>::{closure#0}Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmHash, conquer_once::spin::internal::Spin>>::try_get_or_init::<spdmlib::crypto::hash::hash_ext::hash_ctx_finalize::{closure#0}>::{closure#0}Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmHkdf, conquer_once::spin::internal::Spin>>::try_get_or_init::<spdmlib::crypto::hkdf::hkdf_expand::{closure#0}>::{closure#0}Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmHkdf, conquer_once::spin::internal::Spin>>::try_get_or_init::<spdmlib::crypto::hkdf::hkdf_extract::{closure#0}>::{closure#0}Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmHmac, conquer_once::spin::internal::Spin>>::try_get_or_init::<spdmlib::crypto::hmac::hmac_verify::{closure#0}>::{closure#0}Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmHmac, conquer_once::spin::internal::Spin>>::try_get_or_init::<spdmlib::crypto::hmac::hmac::{closure#0}>::{closure#0}Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::secret::secret_callback::SpdmSecretPsk, conquer_once::spin::internal::Spin>>::try_get_or_init::<spdmlib::secret::psk::master_secret_hkdf_expand::{closure#0}>::{closure#0}Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::secret::secret_callback::SpdmSecretPsk, conquer_once::spin::internal::Spin>>::try_get_or_init::<spdmlib::secret::psk::handshake_secret_hkdf_expand::{closure#0}>::{closure#0}Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::secret::secret_callback::SpdmSecretAsymSign, conquer_once::spin::internal::Spin>>::try_get_or_init::<spdmlib::secret::asym_sign::sign::{closure#0}>::{closure#0}Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::secret::secret_callback::SpdmSecretMeasurement, conquer_once::spin::internal::Spin>>::try_get_or_init::<spdmlib::secret::measurement::measurement_collection::{closure#0}>::{closure#0}Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::secret::secret_callback::SpdmSecretMeasurement, conquer_once::spin::internal::Spin>>::try_get_or_init::<spdmlib::secret::measurement::generate_measurement_summary_hash::{closure#0}>::{closure#0}Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::secret::secret_callback::SpdmSecretPqcAsymSign, conquer_once::spin::internal::Spin>>::try_get_or_init::<spdmlib::secret::pqc_asym_sign::sign::{closure#0}>::{closure#0}Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::message::vendor::VendorDefinedStruct, conquer_once::spin::internal::Spin>>::try_get_or_init::<spdmlib::message::vendor::vendor_defined_request_handler::{closure#0}>::{closure#0}Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::message::vendor::VendorDefinedStructEx, conquer_once::spin::internal::Spin>>::try_get_or_init::<spdmlib::message::vendor::vendor_defined_request_handler_ex::{closure#0}>::{closure#0}Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::watchdog::watchdog_callbacks::SpdmWatchDog, conquer_once::spin::internal::Spin>>::try_get_or_init::<spdmlib::watchdog::stop_watchdog::{closure#0}>::{closure#0}Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::watchdog::watchdog_callbacks::SpdmWatchDog, conquer_once::spin::internal::Spin>>::try_get_or_init::<spdmlib::watchdog::reset_watchdog::{closure#0}>::{closure#0}Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::watchdog::watchdog_callbacks::SpdmWatchDog, conquer_once::spin::internal::Spin>>::try_get_or_init::<spdmlib::watchdog::start_watchdog::{closure#0}>::{closure#0}Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::responder::app_message_handler::SpdmAppMessageHandler, conquer_once::spin::internal::Spin>>::try_get_or_init::<spdmlib::responder::app_message_handler::dispatch_secured_app_message_cb::{closure#0}>::{closure#0} |
340 | 0 | Ok(res) |
341 | | } |
342 | | } |
343 | 0 | } Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::time::time_callbacks::SpdmTime, conquer_once::spin::internal::Spin>>::try_get_or_init::<spdmlib::time::sleep::{closure#0}>Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmKemDecap, conquer_once::spin::internal::Spin>>::try_get_or_init::<spdmlib::crypto::kem_decap::generate_key_pair::{closure#0}>Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmKemEncap, conquer_once::spin::internal::Spin>>::try_get_or_init::<spdmlib::crypto::kem_encap::new_key::{closure#0}>Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmAsymVerify, conquer_once::spin::internal::Spin>>::try_get_or_init::<spdmlib::crypto::asym_verify::verify::{closure#0}>Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmAsymVerify, conquer_once::spin::internal::Spin>>::try_get_or_init::<spdmlib::crypto::asym_verify::register::{closure#0}>Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmCryptoRandom, conquer_once::spin::internal::Spin>>::try_get_or_init::<spdmlib::crypto::rand::get_random::{closure#0}>Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmCertOperation, conquer_once::spin::internal::Spin>>::try_get_or_init::<spdmlib::crypto::cert_operation::verify_cert_chain::{closure#0}>Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmCertOperation, conquer_once::spin::internal::Spin>>::try_get_or_init::<spdmlib::crypto::cert_operation::get_cert_from_cert_chain::{closure#0}>Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmPqcAsymVerify, conquer_once::spin::internal::Spin>>::try_get_or_init::<spdmlib::crypto::pqc_asym_verify::verify::{closure#0}>Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmPqcAsymVerify, conquer_once::spin::internal::Spin>>::try_get_or_init::<spdmlib::crypto::pqc_asym_verify::register::{closure#0}>Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmDhe, conquer_once::spin::internal::Spin>>::try_get_or_init::<spdmlib::crypto::dhe::generate_key_pair::{closure#0}>Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmAead, conquer_once::spin::internal::Spin>>::try_get_or_init::<spdmlib::crypto::aead::decrypt::{closure#0}>Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmAead, conquer_once::spin::internal::Spin>>::try_get_or_init::<spdmlib::crypto::aead::encrypt::{closure#0}>Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmHash, conquer_once::spin::internal::Spin>>::try_get_or_init::<spdmlib::crypto::hash::hash_all::{closure#0}>Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmHash, conquer_once::spin::internal::Spin>>::try_get_or_init::<spdmlib::crypto::hash::hash_ext::hash_ctx_dup::{closure#0}>Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmHash, conquer_once::spin::internal::Spin>>::try_get_or_init::<spdmlib::crypto::hash::hash_ext::hash_ctx_init::{closure#0}>Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmHash, conquer_once::spin::internal::Spin>>::try_get_or_init::<spdmlib::crypto::hash::hash_ext::hash_ctx_update::{closure#0}>Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmHash, conquer_once::spin::internal::Spin>>::try_get_or_init::<spdmlib::crypto::hash::hash_ext::hash_ctx_finalize::{closure#0}>Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmHkdf, conquer_once::spin::internal::Spin>>::try_get_or_init::<spdmlib::crypto::hkdf::hkdf_expand::{closure#0}>Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmHkdf, conquer_once::spin::internal::Spin>>::try_get_or_init::<spdmlib::crypto::hkdf::hkdf_extract::{closure#0}>Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmHmac, conquer_once::spin::internal::Spin>>::try_get_or_init::<spdmlib::crypto::hmac::hmac_verify::{closure#0}>Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmHmac, conquer_once::spin::internal::Spin>>::try_get_or_init::<spdmlib::crypto::hmac::hmac::{closure#0}>Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::secret::secret_callback::SpdmSecretPsk, conquer_once::spin::internal::Spin>>::try_get_or_init::<spdmlib::secret::psk::master_secret_hkdf_expand::{closure#0}>Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::secret::secret_callback::SpdmSecretPsk, conquer_once::spin::internal::Spin>>::try_get_or_init::<spdmlib::secret::psk::handshake_secret_hkdf_expand::{closure#0}>Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::secret::secret_callback::SpdmSecretAsymSign, conquer_once::spin::internal::Spin>>::try_get_or_init::<spdmlib::secret::asym_sign::sign::{closure#0}>Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::secret::secret_callback::SpdmSecretMeasurement, conquer_once::spin::internal::Spin>>::try_get_or_init::<spdmlib::secret::measurement::measurement_collection::{closure#0}>Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::secret::secret_callback::SpdmSecretMeasurement, conquer_once::spin::internal::Spin>>::try_get_or_init::<spdmlib::secret::measurement::generate_measurement_summary_hash::{closure#0}>Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::secret::secret_callback::SpdmSecretPqcAsymSign, conquer_once::spin::internal::Spin>>::try_get_or_init::<spdmlib::secret::pqc_asym_sign::sign::{closure#0}>Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::message::vendor::VendorDefinedStruct, conquer_once::spin::internal::Spin>>::try_get_or_init::<spdmlib::message::vendor::vendor_defined_request_handler::{closure#0}>Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::message::vendor::VendorDefinedStructEx, conquer_once::spin::internal::Spin>>::try_get_or_init::<spdmlib::message::vendor::vendor_defined_request_handler_ex::{closure#0}>Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::watchdog::watchdog_callbacks::SpdmWatchDog, conquer_once::spin::internal::Spin>>::try_get_or_init::<spdmlib::watchdog::stop_watchdog::{closure#0}>Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::watchdog::watchdog_callbacks::SpdmWatchDog, conquer_once::spin::internal::Spin>>::try_get_or_init::<spdmlib::watchdog::reset_watchdog::{closure#0}>Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::watchdog::watchdog_callbacks::SpdmWatchDog, conquer_once::spin::internal::Spin>>::try_get_or_init::<spdmlib::watchdog::start_watchdog::{closure#0}>Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::responder::app_message_handler::SpdmAppMessageHandler, conquer_once::spin::internal::Spin>>::try_get_or_init::<spdmlib::responder::app_message_handler::dispatch_secured_app_message_cb::{closure#0}> |
344 | | } |
345 | | |
346 | | impl<T, B: Block> OnceCell<T, B> { |
347 | | /// Returns a reference to the [`OnceCell`]'s initialized inner state or |
348 | | /// [`None`]. |
349 | | /// |
350 | | /// This method **blocks** if another thread has already begun initializing |
351 | | /// the [`OnceCell`] concurrently. |
352 | | /// See [`try_get`][OnceCell::try_get] for a non-blocking alternative. |
353 | | /// |
354 | | /// When this function returns with [`Some`], it is guaranteed that some |
355 | | /// initialization closure has run and completed. |
356 | | /// It is also guaranteed that any memory writes performed by the executed |
357 | | /// closure can be reliably observed by other threads at this point (there |
358 | | /// is a happens-before relation between the closure and code executing |
359 | | /// after the return). |
360 | | /// |
361 | | /// # Panics |
362 | | /// |
363 | | /// This method panics if the [`OnceCell`] has been poisoned. |
364 | | /// |
365 | | /// # Examples |
366 | | /// |
367 | | /// ``` |
368 | | /// # #[cfg(feature = "std")] |
369 | | /// use conquer_once::OnceCell; |
370 | | /// # #[cfg(not(feature = "std"))] |
371 | | /// # use conquer_once::spin::OnceCell; |
372 | | /// |
373 | | /// let cell = OnceCell::uninit(); |
374 | | /// assert_eq!(cell.get(), None); |
375 | | /// cell.init_once(|| { |
376 | | /// 1 |
377 | | /// }); |
378 | | /// assert_eq!(cell.get(), Some(&1)); |
379 | | /// ``` |
380 | | #[inline] |
381 | | pub fn get(&self) -> Option<&T> { |
382 | | match self.try_get() { |
383 | | Ok(res) => Some(res), |
384 | | Err(TryGetError::WouldBlock) => { |
385 | | B::block(&self.state); |
386 | | Some(unsafe { self.get_unchecked() }) |
387 | | } |
388 | | Err(TryGetError::Uninit) => None, |
389 | | } |
390 | | } |
391 | | |
392 | | /// Attempts to initialize the [`OnceCell`] with `func` if it is |
393 | | /// uninitialized. |
394 | | /// |
395 | | /// This method **blocks** if another thread has already begun initializing |
396 | | /// the [`OnceCell`] concurrently. |
397 | | /// |
398 | | /// If the initialization of the [`OnceCell`] has already been |
399 | | /// completed previously, this method returns early with minimal |
400 | | /// overhead. |
401 | | /// |
402 | | /// When this function returns, it is guaranteed that some initialization |
403 | | /// closure has run and completed (it may not be the closure specified). |
404 | | /// It is also guaranteed that any memory writes performed by the executed |
405 | | /// closure can be reliably observed by other threads at this point (there |
406 | | /// is a happens-before relation between the closure and code executing |
407 | | /// after the return). |
408 | | /// |
409 | | /// # Panics |
410 | | /// |
411 | | /// This method panics if the [`OnceCell`] has been poisoned. |
412 | | /// |
413 | | /// # Examples |
414 | | /// |
415 | | /// ``` |
416 | | /// # #[cfg(feature = "std")] |
417 | | /// use conquer_once::OnceCell; |
418 | | /// # #[cfg(not(feature = "std"))] |
419 | | /// # use conquer_once::spin::OnceCell; |
420 | | /// |
421 | | /// let cell = OnceCell::uninit(); |
422 | | /// cell.init_once(|| { |
423 | | /// // expensive calculation |
424 | | /// (0..1_000).map(|i| i * i).sum::<usize>() |
425 | | /// }); |
426 | | /// |
427 | | /// cell.init_once(|| { |
428 | | /// // any further or concurrent calls to `init_once` will do |
429 | | /// // nothing and return immediately with almost no overhead. |
430 | | /// # 0 |
431 | | /// }); |
432 | | /// |
433 | | /// # let exp = (0..1_000).map(|i| i * i).sum::<usize>(); |
434 | | /// # assert_eq!(cell.get().copied(), Some(exp)); |
435 | | /// ``` |
436 | | #[inline] |
437 | | pub fn init_once(&self, func: impl FnOnce() -> T) { |
438 | | if let Err(TryInitError::WouldBlock) = self.try_init_once(func) { |
439 | | B::block(&self.state); |
440 | | } |
441 | | } |
442 | | |
443 | | /// Returns a reference to the [`OnceCell`]'s initialized inner state or |
444 | | /// otherwise attempts to initialize it with `func` and return the result. |
445 | | /// |
446 | | /// This method **blocks** if another thread has already begun |
447 | | /// initializing the [`OnceCell`] concurrently. |
448 | | /// See [`try_get_or_init`][OnceCell::try_get_or_init] for a non-blocking |
449 | | /// alternative. |
450 | | /// |
451 | | /// When this function returns, it is guaranteed that some initialization |
452 | | /// closure has run and completed (it may not be the closure specified). |
453 | | /// It is also guaranteed that any memory writes performed by the executed |
454 | | /// closure can be reliably observed by other threads at this point (there |
455 | | /// is a happens-before relation between the closure and code executing |
456 | | /// after the return). |
457 | | /// |
458 | | /// # Panics |
459 | | /// |
460 | | /// This method panics if the [`OnceCell`] has been poisoned. |
461 | | #[inline] |
462 | | pub fn get_or_init(&self, func: impl FnOnce() -> T) -> &T { |
463 | | match self.try_get_or_init(func) { |
464 | | Ok(res) => res, |
465 | | Err(_) => { |
466 | | B::block(&self.state); |
467 | | // `block` only returns when the state is set to initialized and |
468 | | // acts as an acquire barrier |
469 | | unsafe { self.get_unchecked() } |
470 | | } |
471 | | } |
472 | | } |
473 | | } |
474 | | |
475 | | /********** impl Debug ****************************************************************************/ |
476 | | |
477 | | impl<T: fmt::Debug, B> fmt::Debug for OnceCell<T, B> { |
478 | | #[inline] |
479 | | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
480 | | f.debug_struct("OnceCell").field("inner", &self.try_get().ok()).finish() |
481 | | } |
482 | | } |
483 | | |
484 | | /********** impl Drop *****************************************************************************/ |
485 | | |
486 | | impl<T, B> Drop for OnceCell<T, B> { |
487 | | #[inline] |
488 | 0 | fn drop(&mut self) { |
489 | | // drop must never panic |
490 | 0 | mem::drop(self.take_inner(true)) |
491 | 0 | } Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::time::time_callbacks::SpdmTime, conquer_once::spin::internal::Spin> as core::ops::drop::Drop>::drop Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmKemDecap, conquer_once::spin::internal::Spin> as core::ops::drop::Drop>::drop Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmKemEncap, conquer_once::spin::internal::Spin> as core::ops::drop::Drop>::drop Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmAsymVerify, conquer_once::spin::internal::Spin> as core::ops::drop::Drop>::drop Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmCryptoRandom, conquer_once::spin::internal::Spin> as core::ops::drop::Drop>::drop Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmCertOperation, conquer_once::spin::internal::Spin> as core::ops::drop::Drop>::drop Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmPqcAsymVerify, conquer_once::spin::internal::Spin> as core::ops::drop::Drop>::drop Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmDhe, conquer_once::spin::internal::Spin> as core::ops::drop::Drop>::drop Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmAead, conquer_once::spin::internal::Spin> as core::ops::drop::Drop>::drop Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmHash, conquer_once::spin::internal::Spin> as core::ops::drop::Drop>::drop Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmHkdf, conquer_once::spin::internal::Spin> as core::ops::drop::Drop>::drop Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::crypto::crypto_callbacks::SpdmHmac, conquer_once::spin::internal::Spin> as core::ops::drop::Drop>::drop Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::secret::secret_callback::SpdmSecretPsk, conquer_once::spin::internal::Spin> as core::ops::drop::Drop>::drop Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::secret::secret_callback::SpdmSecretAsymSign, conquer_once::spin::internal::Spin> as core::ops::drop::Drop>::drop Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::secret::secret_callback::SpdmSecretMeasurement, conquer_once::spin::internal::Spin> as core::ops::drop::Drop>::drop Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::secret::secret_callback::SpdmSecretPqcAsymSign, conquer_once::spin::internal::Spin> as core::ops::drop::Drop>::drop Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::message::vendor::VendorDefinedStruct, conquer_once::spin::internal::Spin> as core::ops::drop::Drop>::drop Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::message::vendor::VendorDefinedStructEx, conquer_once::spin::internal::Spin> as core::ops::drop::Drop>::drop Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::watchdog::watchdog_callbacks::SpdmWatchDog, conquer_once::spin::internal::Spin> as core::ops::drop::Drop>::drop Unexecuted instantiation: <conquer_once::cell::OnceCell<spdmlib::responder::app_message_handler::SpdmAppMessageHandler, conquer_once::spin::internal::Spin> as core::ops::drop::Drop>::drop |
492 | | } |
493 | | |
494 | | //////////////////////////////////////////////////////////////////////////////////////////////////// |
495 | | // TryInitError |
496 | | //////////////////////////////////////////////////////////////////////////////////////////////////// |
497 | | |
498 | | const UNINIT_MSG: &str = "the `OnceCell` is uninitialized"; |
499 | | const ALREADY_INIT_MSG: &str = "the `OnceCell` has already been initialized"; |
500 | | const WOULD_BLOCK_MSG: &str = "the `OnceCell` is currently being initialized"; |
501 | | |
502 | | /// Possible error variants of non-blocking initialization calls. |
503 | | #[derive(Copy, Clone, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)] |
504 | | pub enum TryInitError { |
505 | | /// The [`OnceCell`] is already initialized and the initialization procedure |
506 | | /// was not called. |
507 | | AlreadyInit, |
508 | | /// The [`OnceCell`] is currently being initialized by another thread and |
509 | | /// the current thread would have to block. |
510 | | WouldBlock, |
511 | | } |
512 | | |
513 | | /*********** impl Display *************************************************************************/ |
514 | | |
515 | | impl fmt::Display for TryInitError { |
516 | | #[inline] |
517 | | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
518 | | match self { |
519 | | TryInitError::AlreadyInit => write!(f, "{}", ALREADY_INIT_MSG), |
520 | | TryInitError::WouldBlock => write!(f, "{}", WOULD_BLOCK_MSG), |
521 | | } |
522 | | } |
523 | | } |
524 | | |
525 | | /*********** impl From ****************************************************************************/ |
526 | | |
527 | | impl From<TryBlockError> for TryInitError { |
528 | | #[inline] |
529 | 0 | fn from(err: TryBlockError) -> Self { |
530 | 0 | match err { |
531 | 0 | TryBlockError::AlreadyInit => TryInitError::AlreadyInit, |
532 | 0 | TryBlockError::WouldBlock(_) => TryInitError::WouldBlock, |
533 | | } |
534 | 0 | } |
535 | | } |
536 | | |
537 | | /*********** impl Error ***************************************************************************/ |
538 | | |
539 | | #[cfg(feature = "std")] |
540 | | impl std::error::Error for TryInitError {} |
541 | | |
542 | | //////////////////////////////////////////////////////////////////////////////////////////////////// |
543 | | // TryGetError |
544 | | //////////////////////////////////////////////////////////////////////////////////////////////////// |
545 | | |
546 | | /// Possible error variants of non-blocking fallible get calls. |
547 | | #[derive(Copy, Clone, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)] |
548 | | pub enum TryGetError { |
549 | | /// The [`OnceCell`] is currently not initialized. |
550 | | Uninit, |
551 | | /// The [`OnceCell`] is currently being initialized by another thread and |
552 | | /// the current thread would have to block. |
553 | | WouldBlock, |
554 | | } |
555 | | |
556 | | /*********** impl Display *************************************************************************/ |
557 | | |
558 | | impl fmt::Display for TryGetError { |
559 | | #[inline] |
560 | | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
561 | | match self { |
562 | | TryGetError::Uninit => write!(f, "{}", UNINIT_MSG), |
563 | | TryGetError::WouldBlock => write!(f, "{}", WOULD_BLOCK_MSG), |
564 | | } |
565 | | } |
566 | | } |
567 | | |
568 | | /*********** impl Error ***************************************************************************/ |
569 | | |
570 | | #[cfg(feature = "std")] |
571 | | impl std::error::Error for TryGetError {} |
572 | | |
573 | | //////////////////////////////////////////////////////////////////////////////////////////////////// |
574 | | // WouldBlockError |
575 | | //////////////////////////////////////////////////////////////////////////////////////////////////// |
576 | | |
577 | | /// An error indicating that a [`OnceCell`] would have to block. |
578 | | #[derive(Copy, Clone, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)] |
579 | | pub struct WouldBlockError(()); |
580 | | |
581 | | /*********** impl Display *************************************************************************/ |
582 | | |
583 | | impl fmt::Display for WouldBlockError { |
584 | | #[inline] |
585 | | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
586 | | write!(f, "{}", WOULD_BLOCK_MSG) |
587 | | } |
588 | | } |
589 | | |
590 | | /*********** impl From ****************************************************************************/ |
591 | | |
592 | | impl From<TryBlockError> for WouldBlockError { |
593 | | #[inline] |
594 | 0 | fn from(err: TryBlockError) -> Self { |
595 | 0 | match err { |
596 | 0 | TryBlockError::AlreadyInit => unreachable!(), |
597 | 0 | TryBlockError::WouldBlock(_) => Self(()), |
598 | | } |
599 | 0 | } |
600 | | } |
601 | | |
602 | | /*********** impl Error ***************************************************************************/ |
603 | | |
604 | | #[cfg(feature = "std")] |
605 | | impl std::error::Error for WouldBlockError {} |
606 | | |
607 | | //////////////////////////////////////////////////////////////////////////////////////////////////// |
608 | | // PanicGuard |
609 | | //////////////////////////////////////////////////////////////////////////////////////////////////// |
610 | | |
611 | | /// A guard for catching panics during the execution of the initialization |
612 | | /// closure. |
613 | | #[derive(Debug)] |
614 | | struct PanicGuard<'a, B: Unblock> { |
615 | | /// The state of the associated [`OnceCell`]. |
616 | | state: &'a AtomicOnceState, |
617 | | /// Flag for indicating if a panic has occurred during the caller supplied |
618 | | /// arbitrary closure. |
619 | | poison: bool, |
620 | | /// A marker for the [`OnceCell`]'s blocking strategy. |
621 | | _marker: PhantomData<B>, |
622 | | } |
623 | | |
624 | | impl<'a, B: Unblock> PanicGuard<'a, B> { |
625 | | /// Attempts to block the [`OnceCell`] and return a guard on success. |
626 | | #[inline] |
627 | 0 | fn try_block(state: &'a AtomicOnceState) -> Result<Self, TryBlockError> { |
628 | | // (guard:1) this acquire CAS syncs-with the acq-rel swap (guard:2) and the acq-rel CAS |
629 | | // (wait:2) |
630 | 0 | state.try_block(Ordering::Acquire)?; |
631 | 0 | Ok(Self { state, poison: true, _marker: PhantomData }) |
632 | 0 | } |
633 | | |
634 | | /// Consumes the guard and assures that no panic has occurred. |
635 | | #[inline] |
636 | 0 | fn disarm(mut self) { |
637 | 0 | self.poison = false; |
638 | 0 | mem::drop(self); |
639 | 0 | } |
640 | | } |
641 | | |
642 | | /********** impl Drop *****************************************************************************/ |
643 | | |
644 | | impl<B: Unblock> Drop for PanicGuard<'_, B> { |
645 | | #[inline] |
646 | 0 | fn drop(&mut self) { |
647 | 0 | let swap = if self.poison { SwapState::Poisoned } else { SwapState::Ready }; |
648 | 0 | unsafe { |
649 | 0 | // (guard:2) this acq-rel swap syncs-with the acq-rel CAS (wait:2) |
650 | 0 | // and the acquire loads (cell:1), (cell:2), (wait:1) and the |
651 | 0 | // acquire CAS (guard:1) |
652 | 0 | let prev = self.state.unblock(swap, Ordering::AcqRel); |
653 | 0 | B::on_unblock(prev); |
654 | 0 | } |
655 | 0 | } |
656 | | } |