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}