async_lock/
once_cell.rs

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