1 | use core::cell::UnsafeCell; |
2 | use core::convert::Infallible; |
3 | use core::fmt; |
4 | use core::future::Future; |
5 | use core::mem::{forget, MaybeUninit}; |
6 | use core::ptr; |
7 | |
8 | use crate::sync::atomic::{AtomicUsize, Ordering}; |
9 | |
10 | #[cfg (not(loom))] |
11 | use crate::sync::WithMut; |
12 | |
13 | #[cfg (all(feature = "std" , not(target_family = "wasm" )))] |
14 | use core::task::{Context, Poll, RawWaker, RawWakerVTable, Waker}; |
15 | |
16 | use event_listener::Event; |
17 | use event_listener_strategy::{NonBlocking, Strategy}; |
18 | |
19 | #[cfg (all(feature = "std" , not(target_family = "wasm" )))] |
20 | use event_listener::Listener; |
21 | |
22 | /// The current state of the `OnceCell`. |
23 | #[derive (Copy, Clone, PartialEq, Eq)] |
24 | #[repr (usize)] |
25 | enum State { |
26 | /// The `OnceCell` is uninitialized. |
27 | Uninitialized = 0, |
28 | /// The `OnceCell` is being initialized. |
29 | Initializing = 1, |
30 | /// The `OnceCell` is initialized. |
31 | Initialized = 2, |
32 | } |
33 | |
34 | impl From<usize> for State { |
35 | fn from(val: usize) -> Self { |
36 | match val { |
37 | 0 => State::Uninitialized, |
38 | 1 => State::Initializing, |
39 | 2 => State::Initialized, |
40 | _ => unreachable!("Invalid state" ), |
41 | } |
42 | } |
43 | } |
44 | |
45 | impl From<State> for usize { |
46 | fn from(val: State) -> Self { |
47 | val as usize |
48 | } |
49 | } |
50 | |
51 | /// A memory location that can be written to at most once. |
52 | /// |
53 | /// A `OnceCell` can be used to store a single value, and only once. However, |
54 | /// once the value is stored, it can be accessed directly through a reference |
55 | /// instead of needing an RAII guard like `Mutex` or `RwLock`. |
56 | /// |
57 | /// # Examples |
58 | /// |
59 | /// This structure is useful for a variety of patterns, most notably for one-time |
60 | /// initialization. |
61 | /// |
62 | /// ```rust |
63 | /// use async_lock::OnceCell; |
64 | /// |
65 | /// # struct Foobar; |
66 | /// |
67 | /// async fn very_expensive_initialization() -> Foobar { |
68 | /// // Imagine this is very expensive to initialize, |
69 | /// // for instance, it requires a network request or |
70 | /// // a database call. |
71 | /// # Foobar |
72 | /// } |
73 | /// |
74 | /// struct LazyFoobar { |
75 | /// inner: OnceCell<Foobar>, |
76 | /// } |
77 | /// |
78 | /// impl LazyFoobar { |
79 | /// fn new() -> Self { |
80 | /// Self { |
81 | /// inner: OnceCell::new(), |
82 | /// } |
83 | /// } |
84 | /// |
85 | /// async fn load(&self) -> &Foobar { |
86 | /// self.inner.get_or_init(|| async { |
87 | /// very_expensive_initialization().await |
88 | /// }).await |
89 | /// } |
90 | /// } |
91 | /// ``` |
92 | pub struct OnceCell<T> { |
93 | /// Listeners waiting for a chance to initialize the cell. |
94 | /// |
95 | /// These are the users of get_or_init() and similar functions. |
96 | active_initializers: Event, |
97 | |
98 | /// Listeners waiting for the cell to be initialized. |
99 | /// |
100 | /// These are the users of wait(). |
101 | passive_waiters: Event, |
102 | |
103 | /// State associated with the cell. |
104 | state: AtomicUsize, |
105 | |
106 | /// The value of the cell. |
107 | value: UnsafeCell<MaybeUninit<T>>, |
108 | } |
109 | |
110 | unsafe impl<T: Send> Send for OnceCell<T> {} |
111 | unsafe impl<T: Send + Sync> Sync for OnceCell<T> {} |
112 | |
113 | impl<T> OnceCell<T> { |
114 | const_fn! { |
115 | const_if: #[cfg(not(loom))]; |
116 | /// Create a new, uninitialized `OnceCell`. |
117 | /// |
118 | /// # Example |
119 | /// |
120 | /// ```rust |
121 | /// use async_lock::OnceCell; |
122 | /// |
123 | /// let cell = OnceCell::new(); |
124 | /// # cell.set_blocking(1); |
125 | /// ``` |
126 | pub const fn new() -> Self { |
127 | Self { |
128 | active_initializers: Event::new(), |
129 | passive_waiters: Event::new(), |
130 | state: AtomicUsize::new(State::Uninitialized as _), |
131 | value: UnsafeCell::new(MaybeUninit::uninit()), |
132 | } |
133 | } |
134 | } |
135 | |
136 | /// Tell whether or not the cell is initialized. |
137 | /// |
138 | /// This may not always be accurate. For instance, it is possible for |
139 | /// another thread to initialize the cell between the time when this |
140 | /// function is called and the time when the result is actually used. |
141 | /// |
142 | /// # Example |
143 | /// |
144 | /// ```rust |
145 | /// use async_lock::OnceCell; |
146 | /// |
147 | /// # futures_lite::future::block_on(async { |
148 | /// let cell = OnceCell::new(); |
149 | /// assert!(!cell.is_initialized()); |
150 | /// cell.set(1).await; |
151 | /// assert!(cell.is_initialized()); |
152 | /// # }); |
153 | /// ``` |
154 | pub fn is_initialized(&self) -> bool { |
155 | State::from(self.state.load(Ordering::Acquire)) == State::Initialized |
156 | } |
157 | |
158 | /// Get a reference to the inner value, or `None` if the value |
159 | /// is not yet initialized. |
160 | /// |
161 | /// # Example |
162 | /// |
163 | /// ```rust |
164 | /// use async_lock::OnceCell; |
165 | /// |
166 | /// # futures_lite::future::block_on(async { |
167 | /// let cell = OnceCell::new(); |
168 | /// assert!(cell.get().is_none()); |
169 | /// cell.set(1).await; |
170 | /// assert_eq!(cell.get(), Some(&1)); |
171 | /// # }); |
172 | /// ``` |
173 | pub fn get(&self) -> Option<&T> { |
174 | if self.is_initialized() { |
175 | // SAFETY: We know that the value is initialized, so it is safe to |
176 | // read it. |
177 | Some(unsafe { self.get_unchecked() }) |
178 | } else { |
179 | None |
180 | } |
181 | } |
182 | |
183 | /// Get a mutable reference to the inner value, or `None` if the value |
184 | /// is not yet initialized. |
185 | /// |
186 | /// This function is useful for initializing the value inside the cell |
187 | /// when we still have a mutable reference to the cell. |
188 | /// |
189 | /// # Example |
190 | /// |
191 | /// ```rust |
192 | /// use async_lock::OnceCell; |
193 | /// |
194 | /// # futures_lite::future::block_on(async { |
195 | /// let mut cell = OnceCell::new(); |
196 | /// assert!(cell.get_mut().is_none()); |
197 | /// cell.set(1).await; |
198 | /// assert_eq!(cell.get_mut(), Some(&mut 1)); |
199 | /// *cell.get_mut().unwrap() = 2; |
200 | /// assert_eq!(cell.get(), Some(&2)); |
201 | /// # }); |
202 | /// ``` |
203 | pub fn get_mut(&mut self) -> Option<&mut T> { |
204 | self.state.with_mut(|state| { |
205 | if State::from(*state) == State::Initialized { |
206 | // SAFETY: We know that the value is initialized, so it is safe to |
207 | // read it. |
208 | Some(unsafe { &mut *self.value.get().cast() }) |
209 | } else { |
210 | None |
211 | } |
212 | }) |
213 | } |
214 | |
215 | /// Take the value out of this `OnceCell`, moving it back to the uninitialized |
216 | /// state. |
217 | /// |
218 | /// # Example |
219 | /// |
220 | /// ```rust |
221 | /// use async_lock::OnceCell; |
222 | /// |
223 | /// # futures_lite::future::block_on(async { |
224 | /// let mut cell = OnceCell::new(); |
225 | /// cell.set(1).await; |
226 | /// assert_eq!(cell.take(), Some(1)); |
227 | /// assert!(!cell.is_initialized()); |
228 | /// # }); |
229 | /// ``` |
230 | pub fn take(&mut self) -> Option<T> { |
231 | self.state.with_mut(|state| { |
232 | if State::from(*state) == State::Initialized { |
233 | // SAFETY: We know that the value is initialized, so it is safe to |
234 | // read it. |
235 | let value = unsafe { ptr::read(self.value.get().cast()) }; |
236 | *state = State::Uninitialized.into(); |
237 | Some(value) |
238 | } else { |
239 | None |
240 | } |
241 | }) |
242 | } |
243 | |
244 | /// Convert this `OnceCell` into the inner value, if it is initialized. |
245 | /// |
246 | /// # Example |
247 | /// |
248 | /// ```rust |
249 | /// use async_lock::OnceCell; |
250 | /// |
251 | /// # futures_lite::future::block_on(async { |
252 | /// let cell = OnceCell::new(); |
253 | /// cell.set(1).await; |
254 | /// assert_eq!(cell.into_inner(), Some(1)); |
255 | /// # }); |
256 | /// ``` |
257 | pub fn into_inner(mut self) -> Option<T> { |
258 | self.take() |
259 | } |
260 | |
261 | /// Wait for the cell to be initialized, and then return a reference to the |
262 | /// inner value. |
263 | /// |
264 | /// # Example |
265 | /// |
266 | /// ```rust |
267 | /// use async_lock::OnceCell; |
268 | /// use std::sync::Arc; |
269 | /// use std::time::Duration; |
270 | /// use std::thread::{sleep, spawn}; |
271 | /// |
272 | /// let cell = Arc::new(OnceCell::new()); |
273 | /// let cell2 = cell.clone(); |
274 | /// |
275 | /// spawn(move || { |
276 | /// sleep(Duration::from_millis(5)); |
277 | /// cell2.set_blocking(1); |
278 | /// }); |
279 | /// |
280 | /// # futures_lite::future::block_on(async { |
281 | /// assert_eq!(cell.wait().await, &1); |
282 | /// # }); |
283 | /// ``` |
284 | pub async fn wait(&self) -> &T { |
285 | // Fast path: see if the value is already initialized. |
286 | if let Some(value) = self.get() { |
287 | return value; |
288 | } |
289 | |
290 | // Slow path: wait for the value to be initialized. |
291 | event_listener::listener!(self.passive_waiters => listener); |
292 | |
293 | // Try again. |
294 | if let Some(value) = self.get() { |
295 | return value; |
296 | } |
297 | |
298 | listener.await; |
299 | debug_assert!(self.is_initialized()); |
300 | |
301 | // SAFETY: We know that the value is initialized, so it is safe to |
302 | // read it. |
303 | unsafe { self.get_unchecked() } |
304 | } |
305 | |
306 | /// Wait for the cell to be initialized, and then return a reference to the |
307 | /// inner value. |
308 | /// |
309 | /// # Blocking |
310 | /// |
311 | /// In contrast to the `wait` method, this method blocks the current thread of |
312 | /// execution instead of awaiting. |
313 | /// |
314 | /// This method should not be used in an asynchronous context. It is intended |
315 | /// to be used such that a `OnceCell` can be used in both asynchronous and synchronous contexts. |
316 | /// Calling this method in an asynchronous context may result in deadlocks. |
317 | /// |
318 | /// # Example |
319 | /// |
320 | /// ```rust |
321 | /// use async_lock::OnceCell; |
322 | /// use std::sync::Arc; |
323 | /// use std::time::Duration; |
324 | /// use std::thread::{sleep, spawn}; |
325 | /// |
326 | /// let cell = Arc::new(OnceCell::new()); |
327 | /// let cell2 = cell.clone(); |
328 | /// |
329 | /// spawn(move || { |
330 | /// sleep(Duration::from_millis(5)); |
331 | /// cell2.set_blocking(1); |
332 | /// }); |
333 | /// |
334 | /// assert_eq!(cell.wait_blocking(), &1); |
335 | /// ``` |
336 | #[cfg (all(feature = "std" , not(target_family = "wasm" )))] |
337 | pub fn wait_blocking(&self) -> &T { |
338 | // Fast path: see if the value is already initialized. |
339 | if let Some(value) = self.get() { |
340 | return value; |
341 | } |
342 | |
343 | // Slow path: wait for the value to be initialized. |
344 | event_listener::listener!(self.passive_waiters => listener); |
345 | |
346 | // Try again. |
347 | if let Some(value) = self.get() { |
348 | return value; |
349 | } |
350 | |
351 | listener.wait(); |
352 | debug_assert!(self.is_initialized()); |
353 | |
354 | // SAFETY: We know that the value is initialized, so it is safe to |
355 | // read it. |
356 | unsafe { self.get_unchecked() } |
357 | } |
358 | |
359 | /// Either get the value or initialize it with the given closure. |
360 | /// |
361 | /// The cell will not be initialized if the closure returns an error. |
362 | /// |
363 | /// # Example |
364 | /// |
365 | /// ```rust |
366 | /// use async_lock::OnceCell; |
367 | /// # |
368 | /// # // Prevent explicit value errors. |
369 | /// # fn _explicit(_: &Result<&i32, ()>) {} |
370 | /// |
371 | /// # futures_lite::future::block_on(async { |
372 | /// let cell = OnceCell::new(); |
373 | /// |
374 | /// let result = cell.get_or_try_init(|| async { Err(()) }).await; |
375 | /// assert!(result.is_err()); |
376 | /// |
377 | /// let result = cell.get_or_try_init(|| async { Ok(1) }).await; |
378 | /// # _explicit(&result); |
379 | /// assert_eq!(result.unwrap(), &1); |
380 | /// |
381 | /// let result = cell.get_or_try_init(|| async { Err(()) }).await; |
382 | /// |
383 | /// assert_eq!(result.unwrap(), &1); |
384 | /// # }); |
385 | /// ``` |
386 | pub async fn get_or_try_init<E, Fut: Future<Output = Result<T, E>>>( |
387 | &self, |
388 | closure: impl FnOnce() -> Fut, |
389 | ) -> Result<&T, E> { |
390 | // Fast path: see if the value is already initialized. |
391 | if let Some(value) = self.get() { |
392 | return Ok(value); |
393 | } |
394 | |
395 | // Slow path: initialize the value. |
396 | self.initialize_or_wait(closure, &mut NonBlocking::default()) |
397 | .await?; |
398 | debug_assert!(self.is_initialized()); |
399 | |
400 | // SAFETY: We know that the value is initialized, so it is safe to |
401 | // read it. |
402 | Ok(unsafe { self.get_unchecked() }) |
403 | } |
404 | |
405 | /// Either get the value or initialize it with the given closure. |
406 | /// |
407 | /// The cell will not be initialized if the closure returns an error. |
408 | /// |
409 | /// # Blocking |
410 | /// |
411 | /// In contrast to the `get_or_try_init` method, this method blocks the current thread of |
412 | /// execution instead of awaiting. |
413 | /// |
414 | /// This method should not be used in an asynchronous context. It is intended |
415 | /// to be used such that a `OnceCell` can be used in both asynchronous and synchronous contexts. |
416 | /// Calling this method in an asynchronous context may result in deadlocks. |
417 | /// |
418 | /// # Example |
419 | /// |
420 | /// ```rust |
421 | /// use async_lock::OnceCell; |
422 | /// # |
423 | /// # // Prevent explicit type errors. |
424 | /// # fn _explicit(_: &Result<&i32, ()>) {} |
425 | /// |
426 | /// let cell = OnceCell::new(); |
427 | /// |
428 | /// let result = cell.get_or_try_init_blocking(|| Err(())); |
429 | /// assert!(result.is_err()); |
430 | /// |
431 | /// let result = cell.get_or_try_init_blocking(|| Ok(1)); |
432 | /// # _explicit(&result); |
433 | /// assert_eq!(result.unwrap(), &1); |
434 | /// |
435 | /// let result = cell.get_or_try_init_blocking(|| Err(())); |
436 | /// |
437 | /// assert_eq!(result.unwrap(), &1); |
438 | /// ``` |
439 | #[cfg (all(feature = "std" , not(target_family = "wasm" )))] |
440 | pub fn get_or_try_init_blocking<E>( |
441 | &self, |
442 | closure: impl FnOnce() -> Result<T, E>, |
443 | ) -> Result<&T, E> { |
444 | // Fast path: see if the value is already initialized. |
445 | if let Some(value) = self.get() { |
446 | return Ok(value); |
447 | } |
448 | |
449 | // Slow path: initialize the value. |
450 | // The futures provided should never block, so we can use `now_or_never`. |
451 | now_or_never(self.initialize_or_wait( |
452 | move || core::future::ready(closure()), |
453 | &mut event_listener_strategy::Blocking::default(), |
454 | ))?; |
455 | debug_assert!(self.is_initialized()); |
456 | |
457 | // SAFETY: We know that the value is initialized, so it is safe to |
458 | // read it. |
459 | Ok(unsafe { self.get_unchecked() }) |
460 | } |
461 | |
462 | /// Either get the value or initialize it with the given closure. |
463 | /// |
464 | /// Many tasks may call this function, but the value will only be set once |
465 | /// and only one closure will be invoked. |
466 | /// |
467 | /// # Example |
468 | /// |
469 | /// ```rust |
470 | /// use async_lock::OnceCell; |
471 | /// |
472 | /// # futures_lite::future::block_on(async { |
473 | /// let cell = OnceCell::new(); |
474 | /// assert_eq!(cell.get_or_init(|| async { 1 }).await, &1); |
475 | /// assert_eq!(cell.get_or_init(|| async { 2 }).await, &1); |
476 | /// # }); |
477 | /// ``` |
478 | pub async fn get_or_init<Fut: Future<Output = T>>(&self, closure: impl FnOnce() -> Fut) -> &T { |
479 | match self |
480 | .get_or_try_init(move || async move { |
481 | let result: Result<T, Infallible> = Ok(closure().await); |
482 | result |
483 | }) |
484 | .await |
485 | { |
486 | Ok(value) => value, |
487 | Err(infallible) => match infallible {}, |
488 | } |
489 | } |
490 | |
491 | /// Either get the value or initialize it with the given closure. |
492 | /// |
493 | /// Many tasks may call this function, but the value will only be set once |
494 | /// and only one closure will be invoked. |
495 | /// |
496 | /// # Blocking |
497 | /// |
498 | /// In contrast to the `get_or_init` method, this method blocks the current thread of |
499 | /// execution instead of awaiting. |
500 | /// |
501 | /// This method should not be used in an asynchronous context. It is intended |
502 | /// to be used such that a `OnceCell` can be used in both asynchronous and synchronous contexts. |
503 | /// Calling this method in an asynchronous context may result in deadlocks. |
504 | /// |
505 | /// # Example |
506 | /// |
507 | /// ```rust |
508 | /// use async_lock::OnceCell; |
509 | /// |
510 | /// let cell = OnceCell::new(); |
511 | /// assert_eq!(cell.get_or_init_blocking(|| 1), &1); |
512 | /// assert_eq!(cell.get_or_init_blocking(|| 2), &1); |
513 | /// ``` |
514 | #[cfg (all(feature = "std" , not(target_family = "wasm" )))] |
515 | pub fn get_or_init_blocking(&self, closure: impl FnOnce() -> T + Unpin) -> &T { |
516 | let result = self.get_or_try_init_blocking(move || { |
517 | let result: Result<T, Infallible> = Ok(closure()); |
518 | result |
519 | }); |
520 | match result { |
521 | Ok(value) => value, |
522 | Err(infallible) => match infallible {}, |
523 | } |
524 | } |
525 | |
526 | /// Try to set the value of the cell. |
527 | /// |
528 | /// If the cell is already initialized, this method returns the original |
529 | /// value back. |
530 | /// |
531 | /// # Example |
532 | /// |
533 | /// ```rust |
534 | /// use async_lock::OnceCell; |
535 | /// |
536 | /// # futures_lite::future::block_on(async { |
537 | /// let cell = OnceCell::new(); |
538 | /// |
539 | /// assert_eq!(cell.set(1).await, Ok(&1)); |
540 | /// assert_eq!(cell.get(), Some(&1)); |
541 | /// assert_eq!(cell.set(2).await, Err(2)); |
542 | /// # }); |
543 | /// ``` |
544 | pub async fn set(&self, value: T) -> Result<&T, T> { |
545 | let mut value = Some(value); |
546 | self.get_or_init(|| async { value.take().unwrap() }).await; |
547 | |
548 | match value { |
549 | Some(value) => Err(value), |
550 | None => { |
551 | // SAFETY: value was taken, so we are initialized |
552 | Ok(unsafe { self.get_unchecked() }) |
553 | } |
554 | } |
555 | } |
556 | |
557 | /// Try to set the value of the cell. |
558 | /// |
559 | /// If the cell is already initialized, this method returns the original |
560 | /// value back. |
561 | /// |
562 | /// # Blocking |
563 | /// |
564 | /// In contrast to the `set` method, this method blocks the current thread of |
565 | /// execution instead of awaiting. |
566 | /// |
567 | /// This method should not be used in an asynchronous context. It is intended |
568 | /// to be used such that a `OnceCell` can be used in both asynchronous and synchronous contexts. |
569 | /// Calling this method in an asynchronous context may result in deadlocks. |
570 | /// |
571 | /// # Example |
572 | /// |
573 | /// ```rust |
574 | /// use async_lock::OnceCell; |
575 | /// |
576 | /// let cell = OnceCell::new(); |
577 | /// |
578 | /// assert_eq!(cell.set_blocking(1), Ok(&1)); |
579 | /// assert_eq!(cell.get(), Some(&1)); |
580 | /// assert_eq!(cell.set_blocking(2), Err(2)); |
581 | /// ``` |
582 | #[cfg (all(feature = "std" , not(target_family = "wasm" )))] |
583 | pub fn set_blocking(&self, value: T) -> Result<&T, T> { |
584 | let mut value = Some(value); |
585 | self.get_or_init_blocking(|| value.take().unwrap()); |
586 | |
587 | match value { |
588 | Some(value) => Err(value), |
589 | None => { |
590 | // SAFETY: value was taken, so we are initialized |
591 | Ok(unsafe { self.get_unchecked() }) |
592 | } |
593 | } |
594 | } |
595 | |
596 | /// Wait for the cell to be initialized, optionally using a closure |
597 | /// to initialize the cell if it is not initialized yet. |
598 | #[cold ] |
599 | async fn initialize_or_wait<E, Fut: Future<Output = Result<T, E>>, F: FnOnce() -> Fut>( |
600 | &self, |
601 | closure: F, |
602 | strategy: &mut impl for<'a> Strategy<'a>, |
603 | ) -> Result<(), E> { |
604 | // The event listener we're currently waiting on. |
605 | let mut event_listener = None; |
606 | |
607 | let mut closure = Some(closure); |
608 | |
609 | loop { |
610 | // Check the current state of the cell. |
611 | let state = self.state.load(Ordering::Acquire); |
612 | |
613 | // Determine what we should do based on our state. |
614 | match state.into() { |
615 | State::Initialized => { |
616 | // The cell is initialized now, so we can return. |
617 | return Ok(()); |
618 | } |
619 | State::Initializing => { |
620 | // The cell is currently initializing, or the cell is uninitialized |
621 | // but we do not have the ability to initialize it. |
622 | // |
623 | // We need to wait the initialization to complete. |
624 | if let Some(listener) = event_listener.take() { |
625 | strategy.wait(listener).await; |
626 | } else { |
627 | event_listener = Some(self.active_initializers.listen()); |
628 | } |
629 | } |
630 | State::Uninitialized => { |
631 | // Try to move the cell into the initializing state. |
632 | if self |
633 | .state |
634 | .compare_exchange( |
635 | State::Uninitialized.into(), |
636 | State::Initializing.into(), |
637 | Ordering::AcqRel, |
638 | Ordering::Acquire, |
639 | ) |
640 | .is_err() |
641 | { |
642 | // The cell was initialized while we were trying to |
643 | // initialize it. |
644 | continue; |
645 | } |
646 | |
647 | // Now that we have an exclusive lock on the cell's value, |
648 | // we can try to initialize it. |
649 | let _guard = Guard(self); |
650 | let initializer = closure.take().unwrap(); |
651 | match (initializer)().await { |
652 | Ok(value) => { |
653 | // Write the value into the cell and update the state. |
654 | unsafe { |
655 | ptr::write(self.value.get().cast(), value); |
656 | } |
657 | forget(_guard); |
658 | self.state |
659 | .store(State::Initialized.into(), Ordering::Release); |
660 | |
661 | // Notify the listeners that the value is initialized. |
662 | self.active_initializers.notify_additional(core::usize::MAX); |
663 | self.passive_waiters.notify_additional(core::usize::MAX); |
664 | |
665 | return Ok(()); |
666 | } |
667 | Err(err) => { |
668 | // Update the state to indicate that the value is |
669 | // uninitialized. |
670 | drop(_guard); |
671 | |
672 | return Err(err); |
673 | } |
674 | } |
675 | } |
676 | } |
677 | } |
678 | |
679 | /// Set the cell's state back to `UNINITIALIZED on drop. |
680 | /// |
681 | /// If the closure panics, this ensures that the cell's state is set back to |
682 | /// `UNINITIALIZED` and that the next listener is notified. |
683 | struct Guard<'a, T>(&'a OnceCell<T>); |
684 | |
685 | impl<'a, T> Drop for Guard<'a, T> { |
686 | fn drop(&mut self) { |
687 | self.0 |
688 | .state |
689 | .store(State::Uninitialized.into(), Ordering::Release); |
690 | |
691 | // Notify the next initializer that it's their turn. |
692 | self.0.active_initializers.notify(1); |
693 | } |
694 | } |
695 | } |
696 | |
697 | /// Get a reference to the inner value. |
698 | /// |
699 | /// # Safety |
700 | /// |
701 | /// The caller must ensure that the cell is initialized. |
702 | /// |
703 | /// # Example |
704 | /// |
705 | /// ```rust |
706 | /// use async_lock::OnceCell; |
707 | /// |
708 | /// # futures_lite::future::block_on(async { |
709 | /// let cell = OnceCell::new(); |
710 | /// cell.set(1).await; |
711 | /// |
712 | /// // SAFETY: We know that the value is initialized, so it is safe to |
713 | /// // read it. |
714 | /// assert_eq!(unsafe { cell.get_unchecked() }, &1); |
715 | /// # }); |
716 | /// ``` |
717 | pub unsafe fn get_unchecked(&self) -> &T { |
718 | // SAFETY: The caller asserts that the value is initialized |
719 | &*self.value.get().cast() |
720 | } |
721 | } |
722 | |
723 | impl<T> From<T> for OnceCell<T> { |
724 | /// Create a new, initialized `OnceCell` from an existing value. |
725 | /// |
726 | /// # Example |
727 | /// |
728 | /// ```rust |
729 | /// use async_lock::OnceCell; |
730 | /// |
731 | /// let cell = OnceCell::from(42); |
732 | /// assert_eq!(cell.get(), Some(&42)); |
733 | /// ``` |
734 | fn from(value: T) -> Self { |
735 | Self { |
736 | active_initializers: Event::new(), |
737 | passive_waiters: Event::new(), |
738 | state: AtomicUsize::new(State::Initialized.into()), |
739 | value: UnsafeCell::new(MaybeUninit::new(val:value)), |
740 | } |
741 | } |
742 | } |
743 | |
744 | impl<T: fmt::Debug> fmt::Debug for OnceCell<T> { |
745 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
746 | struct Inner<'a, T>(&'a OnceCell<T>); |
747 | |
748 | impl<T: fmt::Debug> fmt::Debug for Inner<'_, T> { |
749 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
750 | match self.0.state.load(order:Ordering::Acquire).into() { |
751 | State::Uninitialized => f.write_str(data:"<uninitialized>" ), |
752 | State::Initializing => f.write_str(data:"<initializing>" ), |
753 | State::Initialized => { |
754 | // SAFETY: "value" is initialized. |
755 | let value: &T = unsafe { self.0.get_unchecked() }; |
756 | fmt::Debug::fmt(self:value, f) |
757 | } |
758 | } |
759 | } |
760 | } |
761 | |
762 | f.debug_tuple(name:"OnceCell" ).field(&Inner(self)).finish() |
763 | } |
764 | } |
765 | |
766 | impl<T> Drop for OnceCell<T> { |
767 | fn drop(&mut self) { |
768 | self.state.with_mut(|state: &mut usize| { |
769 | if State::from(*state) == State::Initialized { |
770 | // SAFETY: We know that the value is initialized, so it is safe to |
771 | // drop it. |
772 | unsafe { self.value.get().cast::<T>().drop_in_place() } |
773 | } |
774 | }); |
775 | } |
776 | } |
777 | |
778 | impl<T> Default for OnceCell<T> { |
779 | // Calls `OnceCell::new`. |
780 | #[inline ] |
781 | fn default() -> Self { |
782 | Self::new() |
783 | } |
784 | } |
785 | |
786 | /// Either return the result of a future now, or panic. |
787 | #[cfg (all(feature = "std" , not(target_family = "wasm" )))] |
788 | fn now_or_never<T>(f: impl Future<Output = T>) -> T { |
789 | const NOOP_WAKER: RawWakerVTable = RawWakerVTable::new(clone, wake, wake_by_ref, drop); |
790 | |
791 | unsafe fn wake(_: *const ()) {} |
792 | unsafe fn wake_by_ref(_: *const ()) {} |
793 | unsafe fn clone(_: *const ()) -> RawWaker { |
794 | RawWaker::new(data:ptr::null(), &NOOP_WAKER) |
795 | } |
796 | unsafe fn drop(_: *const ()) {} |
797 | |
798 | pin!(f); |
799 | |
800 | let waker: Waker = unsafe { Waker::from_raw(waker:RawWaker::new(data:ptr::null(), &NOOP_WAKER)) }; |
801 | |
802 | // Poll the future exactly once. |
803 | let mut cx: Context<'_> = Context::from_waker(&waker); |
804 | |
805 | match f.poll(&mut cx) { |
806 | Poll::Ready(value: T) => value, |
807 | Poll::Pending => unreachable!("future not ready" ), |
808 | } |
809 | } |
810 | |