event_listener/lib.rs
1//! Notify async tasks or threads.
2//!
3//! This is a synchronization primitive similar to [eventcounts] invented by Dmitry Vyukov.
4//!
5//! You can use this crate to turn non-blocking data structures into async or blocking data
6//! structures. See a [simple mutex] implementation that exposes an async and a blocking interface
7//! for acquiring locks.
8//!
9//! [eventcounts]: https://www.1024cores.net/home/lock-free-algorithms/eventcounts
10//! [simple mutex]: https://github.com/smol-rs/event-listener/blob/master/examples/mutex.rs
11//!
12//! # Examples
13//!
14//! Wait until another thread sets a boolean flag:
15//!
16//! ```
17//! # #[cfg(not(target_family = "wasm"))] { // Listener::wait is unavailable on WASM
18//! use std::sync::atomic::{AtomicBool, Ordering};
19//! use std::sync::Arc;
20//! use std::thread;
21//! use std::time::Duration;
22//! use std::usize;
23//! use event_listener::{Event, Listener};
24//!
25//! let flag = Arc::new(AtomicBool::new(false));
26//! let event = Arc::new(Event::new());
27//!
28//! // Spawn a thread that will set the flag after 1 second.
29//! thread::spawn({
30//! let flag = flag.clone();
31//! let event = event.clone();
32//! move || {
33//! // Wait for a second.
34//! thread::sleep(Duration::from_secs(1));
35//!
36//! // Set the flag.
37//! flag.store(true, Ordering::SeqCst);
38//!
39//! // Notify all listeners that the flag has been set.
40//! event.notify(usize::MAX);
41//! }
42//! });
43//!
44//! // Wait until the flag is set.
45//! loop {
46//! // Check the flag.
47//! if flag.load(Ordering::SeqCst) {
48//! break;
49//! }
50//!
51//! // Start listening for events.
52//! let mut listener = event.listen();
53//!
54//! // Check the flag again after creating the listener.
55//! if flag.load(Ordering::SeqCst) {
56//! break;
57//! }
58//!
59//! // Wait for a notification and continue the loop.
60//! listener.wait();
61//! }
62//! # }
63//! ```
64//!
65//! # Features
66//!
67//! - The `std` feature (enabled by default) enables the use of the Rust standard library. Disable it for `no_std`
68//! support.
69//!
70//! - The `critical-section` feature enables usage of the [`critical-section`] crate to enable a
71//! more efficient implementation of `event-listener` for `no_std` platforms.
72//!
73//! - The `portable-atomic` feature enables the use of the [`portable-atomic`] crate to provide
74//! atomic operations on platforms that don't support them.
75//!
76//! [`critical-section`]: https://crates.io/crates/critical-section
77//! [`portable-atomic`]: https://crates.io/crates/portable-atomic
78
79#![cfg_attr(not(feature = "std"), no_std)]
80#![allow(clippy::multiple_bound_locations)] // This is a WONTFIX issue with pin-project-lite
81#![warn(missing_docs, missing_debug_implementations, rust_2018_idioms)]
82#![doc(
83 html_favicon_url = "https://raw.githubusercontent.com/smol-rs/smol/master/assets/images/logo_fullsize_transparent.png"
84)]
85#![doc(
86 html_logo_url = "https://raw.githubusercontent.com/smol-rs/smol/master/assets/images/logo_fullsize_transparent.png"
87)]
88
89#[cfg(not(feature = "std"))]
90extern crate alloc;
91#[cfg(feature = "std")]
92extern crate std as alloc;
93
94#[cfg_attr(
95 any(feature = "std", feature = "critical-section"),
96 path = "intrusive.rs"
97)]
98#[cfg_attr(
99 not(any(feature = "std", feature = "critical-section")),
100 path = "slab.rs"
101)]
102mod sys;
103
104mod notify;
105
106#[cfg(not(feature = "std"))]
107use alloc::boxed::Box;
108
109use core::borrow::Borrow;
110use core::fmt;
111use core::future::Future;
112use core::mem::ManuallyDrop;
113use core::pin::Pin;
114use core::ptr;
115use core::task::{Context, Poll, Waker};
116
117#[cfg(all(feature = "std", not(target_family = "wasm")))]
118use {
119 parking::{Parker, Unparker},
120 std::time::{Duration, Instant},
121};
122
123use sync::atomic::{AtomicPtr, AtomicUsize, Ordering};
124use sync::Arc;
125
126#[cfg(not(loom))]
127use sync::WithMut;
128
129use notify::NotificationPrivate;
130pub use notify::{IntoNotification, Notification};
131
132/// Inner state of [`Event`].
133struct Inner<T> {
134 /// The number of notified entries, or `usize::MAX` if all of them have been notified.
135 ///
136 /// If there are no entries, this value is set to `usize::MAX`.
137 notified: AtomicUsize,
138
139 /// Inner queue of event listeners.
140 ///
141 /// On `std` platforms, this is an intrusive linked list. On `no_std` platforms, this is a
142 /// more traditional `Vec` of listeners, with an atomic queue used as a backup for high
143 /// contention.
144 list: sys::List<T>,
145}
146
147impl<T> Inner<T> {
148 fn new() -> Self {
149 Self {
150 notified: AtomicUsize::new(usize::MAX),
151 list: sys::List::new(),
152 }
153 }
154}
155
156/// A synchronization primitive for notifying async tasks and threads.
157///
158/// Listeners can be registered using [`Event::listen()`]. There are two ways to notify listeners:
159///
160/// 1. [`Event::notify()`] notifies a number of listeners.
161/// 2. [`Event::notify_additional()`] notifies a number of previously unnotified listeners.
162///
163/// If there are no active listeners at the time a notification is sent, it simply gets lost.
164///
165/// There are two ways for a listener to wait for a notification:
166///
167/// 1. In an asynchronous manner using `.await`.
168/// 2. In a blocking manner by calling [`EventListener::wait()`] on it.
169///
170/// If a notified listener is dropped without receiving a notification, dropping will notify
171/// another active listener. Whether one *additional* listener will be notified depends on what
172/// kind of notification was delivered.
173///
174/// Listeners are registered and notified in the first-in first-out fashion, ensuring fairness.
175pub struct Event<T = ()> {
176 /// A pointer to heap-allocated inner state.
177 ///
178 /// This pointer is initially null and gets lazily initialized on first use. Semantically, it
179 /// is an `Arc<Inner>` so it's important to keep in mind that it contributes to the [`Arc`]'s
180 /// reference count.
181 inner: AtomicPtr<Inner<T>>,
182}
183
184unsafe impl<T: Send> Send for Event<T> {}
185unsafe impl<T: Send> Sync for Event<T> {}
186
187impl<T> core::panic::UnwindSafe for Event<T> {}
188impl<T> core::panic::RefUnwindSafe for Event<T> {}
189
190impl<T> fmt::Debug for Event<T> {
191 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
192 match self.try_inner() {
193 Some(inner) => {
194 let notified_count = inner.notified.load(Ordering::Relaxed);
195 let total_count = match inner.list.try_total_listeners() {
196 Some(total_count) => total_count,
197 None => {
198 return f
199 .debug_tuple("Event")
200 .field(&format_args!("<locked>"))
201 .finish()
202 }
203 };
204
205 f.debug_struct("Event")
206 .field("listeners_notified", ¬ified_count)
207 .field("listeners_total", &total_count)
208 .finish()
209 }
210 None => f
211 .debug_tuple("Event")
212 .field(&format_args!("<uninitialized>"))
213 .finish(),
214 }
215 }
216}
217
218impl Default for Event {
219 #[inline]
220 fn default() -> Self {
221 Self::new()
222 }
223}
224
225impl<T> Event<T> {
226 /// Creates a new `Event` with a tag type.
227 ///
228 /// Tagging cannot be implemented efficiently on `no_std`, so this is only available when the
229 /// `std` feature is enabled.
230 ///
231 /// # Examples
232 ///
233 /// ```
234 /// use event_listener::Event;
235 ///
236 /// let event = Event::<usize>::with_tag();
237 /// ```
238 #[cfg(all(feature = "std", not(loom)))]
239 #[inline]
240 pub const fn with_tag() -> Self {
241 Self {
242 inner: AtomicPtr::new(ptr::null_mut()),
243 }
244 }
245 #[cfg(all(feature = "std", loom))]
246 #[inline]
247 pub fn with_tag() -> Self {
248 Self {
249 inner: AtomicPtr::new(ptr::null_mut()),
250 }
251 }
252
253 /// Tell whether any listeners are currently notified.
254 ///
255 /// # Examples
256 ///
257 /// ```
258 /// use event_listener::{Event, Listener};
259 ///
260 /// let event = Event::new();
261 /// let listener = event.listen();
262 /// assert!(!event.is_notified());
263 ///
264 /// event.notify(1);
265 /// assert!(event.is_notified());
266 /// ```
267 #[inline]
268 pub fn is_notified(&self) -> bool {
269 self.try_inner()
270 .map_or(false, |inner| inner.notified.load(Ordering::Acquire) > 0)
271 }
272
273 /// Returns a guard listening for a notification.
274 ///
275 /// This method emits a `SeqCst` fence after registering a listener. For now, this method
276 /// is an alias for calling [`EventListener::new()`], pinning it to the heap, and then
277 /// inserting it into a list.
278 ///
279 /// # Examples
280 ///
281 /// ```
282 /// use event_listener::Event;
283 ///
284 /// let event = Event::new();
285 /// let listener = event.listen();
286 /// ```
287 ///
288 /// # Caveats
289 ///
290 /// The above example is equivalent to this code:
291 ///
292 /// ```no_compile
293 /// use event_listener::{Event, EventListener};
294 ///
295 /// let event = Event::new();
296 /// let mut listener = Box::pin(EventListener::new());
297 /// listener.listen(&event);
298 /// ```
299 ///
300 /// It creates a new listener, pins it to the heap, and inserts it into the linked list
301 /// of listeners. While this type of usage is simple, it may be desired to eliminate this
302 /// heap allocation. In this case, consider using the [`EventListener::new`] constructor
303 /// directly, which allows for greater control over where the [`EventListener`] is
304 /// allocated. However, users of this `new` method must be careful to ensure that the
305 /// [`EventListener`] is `listen`ing before waiting on it; panics may occur otherwise.
306 #[cold]
307 pub fn listen(&self) -> EventListener<T> {
308 let inner = ManuallyDrop::new(unsafe { Arc::from_raw(self.inner()) });
309
310 // Allocate the listener on the heap and insert it.
311 let mut listener = Box::pin(InnerListener {
312 event: Arc::clone(&inner),
313 listener: None,
314 });
315 listener.as_mut().listen();
316
317 // Return the listener.
318 EventListener { listener }
319 }
320
321 /// Notifies a number of active listeners.
322 ///
323 /// The number is allowed to be zero or exceed the current number of listeners.
324 ///
325 /// The [`Notification`] trait is used to define what kind of notification is delivered.
326 /// The default implementation (implemented on `usize`) is a notification that only notifies
327 /// *at least* the specified number of listeners.
328 ///
329 /// In certain cases, this function emits a `SeqCst` fence before notifying listeners.
330 ///
331 /// This function returns the number of [`EventListener`]s that were notified by this call.
332 ///
333 /// # Caveats
334 ///
335 /// If the `std` feature is disabled, the notification will be delayed under high contention,
336 /// such as when another thread is taking a while to `notify` the event. In this circumstance,
337 /// this function will return `0` instead of the number of listeners actually notified. Therefore
338 /// if the `std` feature is disabled the return value of this function should not be relied upon
339 /// for soundness and should be used only as a hint.
340 ///
341 /// If the `std` feature is enabled, no spurious returns are possible, since the `std`
342 /// implementation uses system locking primitives to ensure there is no unavoidable
343 /// contention.
344 ///
345 /// # Examples
346 ///
347 /// Use the default notification strategy:
348 ///
349 /// ```
350 /// use event_listener::Event;
351 ///
352 /// let event = Event::new();
353 ///
354 /// // This notification gets lost because there are no listeners.
355 /// event.notify(1);
356 ///
357 /// let listener1 = event.listen();
358 /// let listener2 = event.listen();
359 /// let listener3 = event.listen();
360 ///
361 /// // Notifies two listeners.
362 /// //
363 /// // Listener queueing is fair, which means `listener1` and `listener2`
364 /// // get notified here since they start listening before `listener3`.
365 /// event.notify(2);
366 /// ```
367 ///
368 /// Notify without emitting a `SeqCst` fence. This uses the [`relaxed`] notification strategy.
369 /// This is equivalent to calling [`Event::notify_relaxed()`].
370 ///
371 /// [`relaxed`]: IntoNotification::relaxed
372 ///
373 /// ```
374 /// use event_listener::{IntoNotification, Event};
375 /// use std::sync::atomic::{self, Ordering};
376 ///
377 /// let event = Event::new();
378 ///
379 /// // This notification gets lost because there are no listeners.
380 /// event.notify(1.relaxed());
381 ///
382 /// let listener1 = event.listen();
383 /// let listener2 = event.listen();
384 /// let listener3 = event.listen();
385 ///
386 /// // We should emit a fence manually when using relaxed notifications.
387 /// atomic::fence(Ordering::SeqCst);
388 ///
389 /// // Notifies two listeners.
390 /// //
391 /// // Listener queueing is fair, which means `listener1` and `listener2`
392 /// // get notified here since they start listening before `listener3`.
393 /// event.notify(2.relaxed());
394 /// ```
395 ///
396 /// Notify additional listeners. In contrast to [`Event::notify()`], this method will notify `n`
397 /// *additional* listeners that were previously unnotified. This uses the [`additional`]
398 /// notification strategy. This is equivalent to calling [`Event::notify_additional()`].
399 ///
400 /// [`additional`]: IntoNotification::additional
401 ///
402 /// ```
403 /// use event_listener::{IntoNotification, Event};
404 ///
405 /// let event = Event::new();
406 ///
407 /// // This notification gets lost because there are no listeners.
408 /// event.notify(1.additional());
409 ///
410 /// let listener1 = event.listen();
411 /// let listener2 = event.listen();
412 /// let listener3 = event.listen();
413 ///
414 /// // Notifies two listeners.
415 /// //
416 /// // Listener queueing is fair, which means `listener1` and `listener2`
417 /// // get notified here since they start listening before `listener3`.
418 /// event.notify(1.additional());
419 /// event.notify(1.additional());
420 /// ```
421 ///
422 /// Notifies with the [`additional`] and [`relaxed`] strategies at the same time. This is
423 /// equivalent to calling [`Event::notify_additional_relaxed()`].
424 ///
425 /// ```
426 /// use event_listener::{IntoNotification, Event};
427 /// use std::sync::atomic::{self, Ordering};
428 ///
429 /// let event = Event::new();
430 ///
431 /// // This notification gets lost because there are no listeners.
432 /// event.notify(1.additional().relaxed());
433 ///
434 /// let listener1 = event.listen();
435 /// let listener2 = event.listen();
436 /// let listener3 = event.listen();
437 ///
438 /// // We should emit a fence manually when using relaxed notifications.
439 /// atomic::fence(Ordering::SeqCst);
440 ///
441 /// // Notifies two listeners.
442 /// //
443 /// // Listener queueing is fair, which means `listener1` and `listener2`
444 /// // get notified here since they start listening before `listener3`.
445 /// event.notify(1.additional().relaxed());
446 /// event.notify(1.additional().relaxed());
447 /// ```
448 #[inline]
449 pub fn notify(&self, notify: impl IntoNotification<Tag = T>) -> usize {
450 let notify = notify.into_notification();
451
452 // Make sure the notification comes after whatever triggered it.
453 notify.fence(notify::Internal::new());
454
455 let inner = unsafe { &*self.inner() };
456 inner.notify(notify)
457 }
458
459 /// Return a reference to the inner state if it has been initialized.
460 #[inline]
461 fn try_inner(&self) -> Option<&Inner<T>> {
462 let inner = self.inner.load(Ordering::Acquire);
463 unsafe { inner.as_ref() }
464 }
465
466 /// Returns a raw, initialized pointer to the inner state.
467 ///
468 /// This returns a raw pointer instead of reference because `from_raw`
469 /// requires raw/mut provenance: <https://github.com/rust-lang/rust/pull/67339>.
470 fn inner(&self) -> *const Inner<T> {
471 let mut inner = self.inner.load(Ordering::Acquire);
472
473 // If this is the first use, initialize the state.
474 if inner.is_null() {
475 // Allocate the state on the heap.
476 let new = Arc::new(Inner::<T>::new());
477
478 // Convert the state to a raw pointer.
479 let new = Arc::into_raw(new) as *mut Inner<T>;
480
481 // Replace the null pointer with the new state pointer.
482 inner = self
483 .inner
484 .compare_exchange(inner, new, Ordering::AcqRel, Ordering::Acquire)
485 .unwrap_or_else(|x| x);
486
487 // Check if the old pointer value was indeed null.
488 if inner.is_null() {
489 // If yes, then use the new state pointer.
490 inner = new;
491 } else {
492 // If not, that means a concurrent operation has initialized the state.
493 // In that case, use the old pointer and deallocate the new one.
494 unsafe {
495 drop(Arc::from_raw(new));
496 }
497 }
498 }
499
500 inner
501 }
502
503 /// Get the number of listeners currently listening to this [`Event`].
504 ///
505 /// This call returns the number of [`EventListener`]s that are currently listening to
506 /// this event. It does this by acquiring the internal event lock and reading the listener
507 /// count. Therefore it is only available for `std`-enabled platforms.
508 ///
509 /// # Caveats
510 ///
511 /// This function returns just a snapshot of the number of listeners at this point in time.
512 /// Due to the nature of multi-threaded CPUs, it is possible that this number will be
513 /// inaccurate by the time that this function returns.
514 ///
515 /// It is possible for the actual number to change at any point. Therefore, the number should
516 /// only ever be used as a hint.
517 ///
518 /// # Examples
519 ///
520 /// ```
521 /// use event_listener::Event;
522 ///
523 /// let event = Event::new();
524 ///
525 /// assert_eq!(event.total_listeners(), 0);
526 ///
527 /// let listener1 = event.listen();
528 /// assert_eq!(event.total_listeners(), 1);
529 ///
530 /// let listener2 = event.listen();
531 /// assert_eq!(event.total_listeners(), 2);
532 ///
533 /// drop(listener1);
534 /// drop(listener2);
535 /// assert_eq!(event.total_listeners(), 0);
536 /// ```
537 #[cfg(feature = "std")]
538 #[inline]
539 pub fn total_listeners(&self) -> usize {
540 if let Some(inner) = self.try_inner() {
541 inner.list.total_listeners()
542 } else {
543 0
544 }
545 }
546}
547
548impl Event<()> {
549 /// Creates a new [`Event`].
550 ///
551 /// # Examples
552 ///
553 /// ```
554 /// use event_listener::Event;
555 ///
556 /// let event = Event::new();
557 /// ```
558 #[inline]
559 #[cfg(not(loom))]
560 pub const fn new() -> Self {
561 Self {
562 inner: AtomicPtr::new(ptr::null_mut()),
563 }
564 }
565
566 #[inline]
567 #[cfg(loom)]
568 pub fn new() -> Self {
569 Self {
570 inner: AtomicPtr::new(ptr::null_mut()),
571 }
572 }
573
574 /// Notifies a number of active listeners without emitting a `SeqCst` fence.
575 ///
576 /// The number is allowed to be zero or exceed the current number of listeners.
577 ///
578 /// In contrast to [`Event::notify_additional()`], this method only makes sure *at least* `n`
579 /// listeners among the active ones are notified.
580 ///
581 /// Unlike [`Event::notify()`], this method does not emit a `SeqCst` fence.
582 ///
583 /// This method only works for untagged events. In other cases, it is recommended to instead
584 /// use [`Event::notify()`] like so:
585 ///
586 /// ```
587 /// use event_listener::{IntoNotification, Event};
588 /// let event = Event::new();
589 ///
590 /// // Old way:
591 /// event.notify_relaxed(1);
592 ///
593 /// // New way:
594 /// event.notify(1.relaxed());
595 /// ```
596 ///
597 /// # Examples
598 ///
599 /// ```
600 /// use event_listener::{Event, IntoNotification};
601 /// use std::sync::atomic::{self, Ordering};
602 ///
603 /// let event = Event::new();
604 ///
605 /// // This notification gets lost because there are no listeners.
606 /// event.notify_relaxed(1);
607 ///
608 /// let listener1 = event.listen();
609 /// let listener2 = event.listen();
610 /// let listener3 = event.listen();
611 ///
612 /// // We should emit a fence manually when using relaxed notifications.
613 /// atomic::fence(Ordering::SeqCst);
614 ///
615 /// // Notifies two listeners.
616 /// //
617 /// // Listener queueing is fair, which means `listener1` and `listener2`
618 /// // get notified here since they start listening before `listener3`.
619 /// event.notify_relaxed(2);
620 /// ```
621 #[inline]
622 pub fn notify_relaxed(&self, n: usize) -> usize {
623 self.notify(n.relaxed())
624 }
625
626 /// Notifies a number of active and still unnotified listeners.
627 ///
628 /// The number is allowed to be zero or exceed the current number of listeners.
629 ///
630 /// In contrast to [`Event::notify()`], this method will notify `n` *additional* listeners that
631 /// were previously unnotified.
632 ///
633 /// This method emits a `SeqCst` fence before notifying listeners.
634 ///
635 /// This method only works for untagged events. In other cases, it is recommended to instead
636 /// use [`Event::notify()`] like so:
637 ///
638 /// ```
639 /// use event_listener::{IntoNotification, Event};
640 /// let event = Event::new();
641 ///
642 /// // Old way:
643 /// event.notify_additional(1);
644 ///
645 /// // New way:
646 /// event.notify(1.additional());
647 /// ```
648 ///
649 /// # Examples
650 ///
651 /// ```
652 /// use event_listener::Event;
653 ///
654 /// let event = Event::new();
655 ///
656 /// // This notification gets lost because there are no listeners.
657 /// event.notify_additional(1);
658 ///
659 /// let listener1 = event.listen();
660 /// let listener2 = event.listen();
661 /// let listener3 = event.listen();
662 ///
663 /// // Notifies two listeners.
664 /// //
665 /// // Listener queueing is fair, which means `listener1` and `listener2`
666 /// // get notified here since they start listening before `listener3`.
667 /// event.notify_additional(1);
668 /// event.notify_additional(1);
669 /// ```
670 #[inline]
671 pub fn notify_additional(&self, n: usize) -> usize {
672 self.notify(n.additional())
673 }
674
675 /// Notifies a number of active and still unnotified listeners without emitting a `SeqCst`
676 /// fence.
677 ///
678 /// The number is allowed to be zero or exceed the current number of listeners.
679 ///
680 /// In contrast to [`Event::notify()`], this method will notify `n` *additional* listeners that
681 /// were previously unnotified.
682 ///
683 /// Unlike [`Event::notify_additional()`], this method does not emit a `SeqCst` fence.
684 ///
685 /// This method only works for untagged events. In other cases, it is recommended to instead
686 /// use [`Event::notify()`] like so:
687 ///
688 /// ```
689 /// use event_listener::{IntoNotification, Event};
690 /// let event = Event::new();
691 ///
692 /// // Old way:
693 /// event.notify_additional_relaxed(1);
694 ///
695 /// // New way:
696 /// event.notify(1.additional().relaxed());
697 /// ```
698 ///
699 /// # Examples
700 ///
701 /// ```
702 /// use event_listener::Event;
703 /// use std::sync::atomic::{self, Ordering};
704 ///
705 /// let event = Event::new();
706 ///
707 /// // This notification gets lost because there are no listeners.
708 /// event.notify(1);
709 ///
710 /// let listener1 = event.listen();
711 /// let listener2 = event.listen();
712 /// let listener3 = event.listen();
713 ///
714 /// // We should emit a fence manually when using relaxed notifications.
715 /// atomic::fence(Ordering::SeqCst);
716 ///
717 /// // Notifies two listeners.
718 /// //
719 /// // Listener queueing is fair, which means `listener1` and `listener2`
720 /// // get notified here since they start listening before `listener3`.
721 /// event.notify_additional_relaxed(1);
722 /// event.notify_additional_relaxed(1);
723 /// ```
724 #[inline]
725 pub fn notify_additional_relaxed(&self, n: usize) -> usize {
726 self.notify(n.additional().relaxed())
727 }
728}
729
730impl<T> Drop for Event<T> {
731 #[inline]
732 fn drop(&mut self) {
733 self.inner.with_mut(|&mut inner| {
734 // If the state pointer has been initialized, drop it.
735 if !inner.is_null() {
736 unsafe {
737 drop(Arc::from_raw(inner));
738 }
739 }
740 })
741 }
742}
743
744/// A handle that is listening to an [`Event`].
745///
746/// This trait represents a type waiting for a notification from an [`Event`]. See the
747/// [`EventListener`] type for more documentation on this trait's usage.
748pub trait Listener<T = ()>: Future<Output = T> + __sealed::Sealed {
749 /// Blocks until a notification is received.
750 ///
751 /// # Examples
752 ///
753 /// ```
754 /// use event_listener::{Event, Listener};
755 ///
756 /// let event = Event::new();
757 /// let mut listener = event.listen();
758 ///
759 /// // Notify `listener`.
760 /// event.notify(1);
761 ///
762 /// // Receive the notification.
763 /// listener.wait();
764 /// ```
765 #[cfg(all(feature = "std", not(target_family = "wasm")))]
766 fn wait(self) -> T;
767
768 /// Blocks until a notification is received or a timeout is reached.
769 ///
770 /// Returns `Some` if a notification was received.
771 ///
772 /// # Examples
773 ///
774 /// ```
775 /// use std::time::Duration;
776 /// use event_listener::{Event, Listener};
777 ///
778 /// let event = Event::new();
779 /// let mut listener = event.listen();
780 ///
781 /// // There are no notification so this times out.
782 /// assert!(listener.wait_timeout(Duration::from_secs(1)).is_none());
783 /// ```
784 #[cfg(all(feature = "std", not(target_family = "wasm")))]
785 fn wait_timeout(self, timeout: Duration) -> Option<T>;
786
787 /// Blocks until a notification is received or a deadline is reached.
788 ///
789 /// Returns `true` if a notification was received.
790 ///
791 /// # Examples
792 ///
793 /// ```
794 /// use std::time::{Duration, Instant};
795 /// use event_listener::{Event, Listener};
796 ///
797 /// let event = Event::new();
798 /// let mut listener = event.listen();
799 ///
800 /// // There are no notification so this times out.
801 /// assert!(listener.wait_deadline(Instant::now() + Duration::from_secs(1)).is_none());
802 /// ```
803 #[cfg(all(feature = "std", not(target_family = "wasm")))]
804 fn wait_deadline(self, deadline: Instant) -> Option<T>;
805
806 /// Drops this listener and discards its notification (if any) without notifying another
807 /// active listener.
808 ///
809 /// Returns `true` if a notification was discarded.
810 ///
811 /// # Examples
812 ///
813 /// ```
814 /// use event_listener::{Event, Listener};
815 ///
816 /// let event = Event::new();
817 /// let mut listener1 = event.listen();
818 /// let mut listener2 = event.listen();
819 ///
820 /// event.notify(1);
821 ///
822 /// assert!(listener1.discard());
823 /// assert!(!listener2.discard());
824 /// ```
825 fn discard(self) -> bool;
826
827 /// Returns `true` if this listener listens to the given `Event`.
828 ///
829 /// # Examples
830 ///
831 /// ```
832 /// use event_listener::{Event, Listener};
833 ///
834 /// let event = Event::new();
835 /// let listener = event.listen();
836 ///
837 /// assert!(listener.listens_to(&event));
838 /// ```
839 fn listens_to(&self, event: &Event<T>) -> bool;
840
841 /// Returns `true` if both listeners listen to the same `Event`.
842 ///
843 /// # Examples
844 ///
845 /// ```
846 /// use event_listener::{Event, Listener};
847 ///
848 /// let event = Event::new();
849 /// let listener1 = event.listen();
850 /// let listener2 = event.listen();
851 ///
852 /// assert!(listener1.same_event(&listener2));
853 /// ```
854 fn same_event(&self, other: &Self) -> bool;
855}
856
857/// Implement the `Listener` trait using the underlying `InnerListener`.
858macro_rules! forward_impl_to_listener {
859 ($gen:ident => $ty:ty) => {
860 impl<$gen> crate::Listener<$gen> for $ty {
861 #[cfg(all(feature = "std", not(target_family = "wasm")))]
862 fn wait(mut self) -> $gen {
863 self.listener_mut().wait_internal(None).unwrap()
864 }
865
866 #[cfg(all(feature = "std", not(target_family = "wasm")))]
867 fn wait_timeout(mut self, timeout: std::time::Duration) -> Option<$gen> {
868 self.listener_mut()
869 .wait_internal(std::time::Instant::now().checked_add(timeout))
870 }
871
872 #[cfg(all(feature = "std", not(target_family = "wasm")))]
873 fn wait_deadline(mut self, deadline: std::time::Instant) -> Option<$gen> {
874 self.listener_mut().wait_internal(Some(deadline))
875 }
876
877 fn discard(mut self) -> bool {
878 self.listener_mut().discard()
879 }
880
881 #[inline]
882 fn listens_to(&self, event: &Event<$gen>) -> bool {
883 core::ptr::eq::<Inner<$gen>>(
884 &*self.listener().event,
885 event.inner.load(core::sync::atomic::Ordering::Acquire),
886 )
887 }
888
889 #[inline]
890 fn same_event(&self, other: &$ty) -> bool {
891 core::ptr::eq::<Inner<$gen>>(&*self.listener().event, &*other.listener().event)
892 }
893 }
894
895 impl<$gen> Future for $ty {
896 type Output = $gen;
897
898 #[inline]
899 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<$gen> {
900 self.listener_mut().poll_internal(cx)
901 }
902 }
903 };
904}
905
906/// A guard waiting for a notification from an [`Event`].
907///
908/// There are two ways for a listener to wait for a notification:
909///
910/// 1. In an asynchronous manner using `.await`.
911/// 2. In a blocking manner by calling [`EventListener::wait()`] on it.
912///
913/// If a notified listener is dropped without receiving a notification, dropping will notify
914/// another active listener. Whether one *additional* listener will be notified depends on what
915/// kind of notification was delivered.
916///
917/// See the [`Listener`] trait for the functionality exposed by this type.
918///
919/// This structure allocates the listener on the heap.
920pub struct EventListener<T = ()> {
921 listener: Pin<Box<InnerListener<T, Arc<Inner<T>>>>>,
922}
923
924unsafe impl<T: Send> Send for EventListener<T> {}
925unsafe impl<T: Send> Sync for EventListener<T> {}
926
927impl<T> core::panic::UnwindSafe for EventListener<T> {}
928impl<T> core::panic::RefUnwindSafe for EventListener<T> {}
929impl<T> Unpin for EventListener<T> {}
930
931impl<T> fmt::Debug for EventListener<T> {
932 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
933 f.debug_struct("EventListener").finish_non_exhaustive()
934 }
935}
936
937impl<T> EventListener<T> {
938 #[inline]
939 fn listener(&self) -> &InnerListener<T, Arc<Inner<T>>> {
940 &self.listener
941 }
942
943 #[inline]
944 fn listener_mut(&mut self) -> Pin<&mut InnerListener<T, Arc<Inner<T>>>> {
945 self.listener.as_mut()
946 }
947}
948
949forward_impl_to_listener! { T => EventListener<T> }
950
951/// Create a stack-based event listener for an [`Event`].
952///
953/// [`EventListener`] allocates the listener on the heap. While this works for most use cases, in
954/// practice this heap allocation can be expensive for repeated uses. This method allows for
955/// allocating the listener on the stack instead.
956///
957/// There are limitations to using this macro instead of the [`EventListener`] type, however.
958/// Firstly, it is significantly less flexible. The listener is locked to the current stack
959/// frame, meaning that it can't be returned or put into a place where it would go out of
960/// scope. For instance, this will not work:
961///
962/// ```compile_fail
963/// use event_listener::{Event, Listener, listener};
964///
965/// fn get_listener(event: &Event) -> impl Listener {
966/// listener!(event => cant_return_this);
967/// cant_return_this
968/// }
969/// ```
970///
971/// In addition, the types involved in creating this listener are not able to be named. Therefore
972/// it cannot be used in hand-rolled futures or similar structures.
973///
974/// The type created by this macro implements [`Listener`], allowing it to be used in cases where
975/// [`EventListener`] would normally be used.
976///
977/// ## Example
978///
979/// To use this macro, replace cases where you would normally use this...
980///
981/// ```no_compile
982/// let listener = event.listen();
983/// ```
984///
985/// ...with this:
986///
987/// ```no_compile
988/// listener!(event => listener);
989/// ```
990///
991/// Here is the top level example from this crate's documentation, but using [`listener`] instead
992/// of [`EventListener`].
993///
994/// ```
995/// # #[cfg(not(target_family = "wasm"))] { // Listener::wait is unavailable on WASM
996/// use std::sync::atomic::{AtomicBool, Ordering};
997/// use std::sync::Arc;
998/// use std::thread;
999/// use std::time::Duration;
1000/// use std::usize;
1001/// use event_listener::{Event, listener, IntoNotification, Listener};
1002///
1003/// let flag = Arc::new(AtomicBool::new(false));
1004/// let event = Arc::new(Event::new());
1005///
1006/// // Spawn a thread that will set the flag after 1 second.
1007/// thread::spawn({
1008/// let flag = flag.clone();
1009/// let event = event.clone();
1010/// move || {
1011/// // Wait for a second.
1012/// thread::sleep(Duration::from_secs(1));
1013///
1014/// // Set the flag.
1015/// flag.store(true, Ordering::SeqCst);
1016///
1017/// // Notify all listeners that the flag has been set.
1018/// event.notify(usize::MAX);
1019/// }
1020/// });
1021///
1022/// // Wait until the flag is set.
1023/// loop {
1024/// // Check the flag.
1025/// if flag.load(Ordering::SeqCst) {
1026/// break;
1027/// }
1028///
1029/// // Start listening for events.
1030/// // NEW: Changed to a stack-based listener.
1031/// listener!(event => listener);
1032///
1033/// // Check the flag again after creating the listener.
1034/// if flag.load(Ordering::SeqCst) {
1035/// break;
1036/// }
1037///
1038/// // Wait for a notification and continue the loop.
1039/// listener.wait();
1040/// }
1041/// # }
1042/// ```
1043#[macro_export]
1044macro_rules! listener {
1045 ($event:expr => $listener:ident) => {
1046 let mut $listener = $crate::__private::StackSlot::new(&$event);
1047 // SAFETY: We shadow $listener so it can't be moved after.
1048 let mut $listener = unsafe { $crate::__private::Pin::new_unchecked(&mut $listener) };
1049 #[allow(unused_mut)]
1050 let mut $listener = $listener.listen();
1051 };
1052}
1053
1054pin_project_lite::pin_project! {
1055 #[project(!Unpin)]
1056 #[project = ListenerProject]
1057 struct InnerListener<T, B: Borrow<Inner<T>>>
1058 where
1059 B: Unpin,
1060 {
1061 // The reference to the original event.
1062 event: B,
1063
1064 // The inner state of the listener.
1065 //
1066 // This is only ever `None` during initialization. After `listen()` has completed, this
1067 // should be `Some`.
1068 #[pin]
1069 listener: Option<sys::Listener<T>>,
1070 }
1071
1072 impl<T, B: Borrow<Inner<T>>> PinnedDrop for InnerListener<T, B>
1073 where
1074 B: Unpin,
1075 {
1076 fn drop(mut this: Pin<&mut Self>) {
1077 // If we're being dropped, we need to remove ourself from the list.
1078 let this = this.project();
1079 (*this.event).borrow().remove(this.listener, true);
1080 }
1081 }
1082}
1083
1084unsafe impl<T: Send, B: Borrow<Inner<T>> + Unpin + Send> Send for InnerListener<T, B> {}
1085unsafe impl<T: Send, B: Borrow<Inner<T>> + Unpin + Sync> Sync for InnerListener<T, B> {}
1086
1087impl<T, B: Borrow<Inner<T>> + Unpin> InnerListener<T, B> {
1088 /// Insert this listener into the linked list.
1089 #[inline]
1090 fn listen(self: Pin<&mut Self>) {
1091 let this = self.project();
1092 (*this.event).borrow().insert(this.listener);
1093 }
1094
1095 /// Wait until the provided deadline.
1096 #[cfg(all(feature = "std", not(target_family = "wasm")))]
1097 fn wait_internal(mut self: Pin<&mut Self>, deadline: Option<Instant>) -> Option<T> {
1098 fn parker_and_task() -> (Parker, Task) {
1099 let parker = Parker::new();
1100 let unparker = parker.unparker();
1101 (parker, Task::Unparker(unparker))
1102 }
1103
1104 crate::sync::thread_local! {
1105 /// Cached thread-local parker/unparker pair.
1106 static PARKER: (Parker, Task) = parker_and_task();
1107 }
1108
1109 // Try to borrow the thread-local parker/unparker pair.
1110 PARKER
1111 .try_with({
1112 let this = self.as_mut();
1113 |(parker, unparker)| this.wait_with_parker(deadline, parker, unparker.as_task_ref())
1114 })
1115 .unwrap_or_else(|_| {
1116 // If the pair isn't accessible, we may be being called in a destructor.
1117 // Just create a new pair.
1118 let (parker, unparker) = parking::pair();
1119 self.as_mut()
1120 .wait_with_parker(deadline, &parker, TaskRef::Unparker(&unparker))
1121 })
1122 }
1123
1124 /// Wait until the provided deadline using the specified parker/unparker pair.
1125 #[cfg(all(feature = "std", not(target_family = "wasm")))]
1126 fn wait_with_parker(
1127 self: Pin<&mut Self>,
1128 deadline: Option<Instant>,
1129 parker: &Parker,
1130 unparker: TaskRef<'_>,
1131 ) -> Option<T> {
1132 let mut this = self.project();
1133 let inner = (*this.event).borrow();
1134
1135 // Set the listener's state to `Task`.
1136 if let Some(tag) = inner.register(this.listener.as_mut(), unparker).notified() {
1137 // We were already notified, so we don't need to park.
1138 return Some(tag);
1139 }
1140
1141 // Wait until a notification is received or the timeout is reached.
1142 loop {
1143 match deadline {
1144 None => parker.park(),
1145
1146 #[cfg(loom)]
1147 Some(_deadline) => {
1148 panic!("parking does not support timeouts under loom");
1149 }
1150
1151 #[cfg(not(loom))]
1152 Some(deadline) => {
1153 // Make sure we're not timed out already.
1154 let now = Instant::now();
1155 if now >= deadline {
1156 // Remove our entry and check if we were notified.
1157 return inner
1158 .remove(this.listener.as_mut(), false)
1159 .expect("We never removed ourself from the list")
1160 .notified();
1161 }
1162 parker.park_deadline(deadline);
1163 }
1164 }
1165
1166 // See if we were notified.
1167 if let Some(tag) = inner.register(this.listener.as_mut(), unparker).notified() {
1168 return Some(tag);
1169 }
1170 }
1171 }
1172
1173 /// Drops this listener and discards its notification (if any) without notifying another
1174 /// active listener.
1175 fn discard(self: Pin<&mut Self>) -> bool {
1176 let this = self.project();
1177 (*this.event)
1178 .borrow()
1179 .remove(this.listener, false)
1180 .map_or(false, |state| state.is_notified())
1181 }
1182
1183 /// Poll this listener for a notification.
1184 fn poll_internal(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<T> {
1185 let this = self.project();
1186 let inner = (*this.event).borrow();
1187
1188 // Try to register the listener.
1189 match inner
1190 .register(this.listener, TaskRef::Waker(cx.waker()))
1191 .notified()
1192 {
1193 Some(tag) => {
1194 // We were already notified, so we don't need to park.
1195 Poll::Ready(tag)
1196 }
1197
1198 None => {
1199 // We're now waiting for a notification.
1200 Poll::Pending
1201 }
1202 }
1203 }
1204}
1205
1206/// The state of a listener.
1207#[derive(PartialEq)]
1208enum State<T> {
1209 /// The listener was just created.
1210 Created,
1211
1212 /// The listener has received a notification.
1213 ///
1214 /// The `bool` is `true` if this was an "additional" notification.
1215 Notified {
1216 /// Whether or not this is an "additional" notification.
1217 additional: bool,
1218
1219 /// The tag associated with the notification.
1220 tag: T,
1221 },
1222
1223 /// A task is waiting for a notification.
1224 Task(Task),
1225
1226 /// Empty hole used to replace a notified listener.
1227 NotifiedTaken,
1228}
1229
1230impl<T> fmt::Debug for State<T> {
1231 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1232 match self {
1233 Self::Created => f.write_str("Created"),
1234 Self::Notified { additional, .. } => f
1235 .debug_struct("Notified")
1236 .field("additional", additional)
1237 .finish(),
1238 Self::Task(_) => f.write_str("Task(_)"),
1239 Self::NotifiedTaken => f.write_str("NotifiedTaken"),
1240 }
1241 }
1242}
1243
1244impl<T> State<T> {
1245 fn is_notified(&self) -> bool {
1246 matches!(self, Self::Notified { .. } | Self::NotifiedTaken)
1247 }
1248
1249 /// If this state was notified, return the tag associated with the notification.
1250 #[allow(unused)]
1251 fn notified(self) -> Option<T> {
1252 match self {
1253 Self::Notified { tag, .. } => Some(tag),
1254 Self::NotifiedTaken => panic!("listener was already notified but taken"),
1255 _ => None,
1256 }
1257 }
1258}
1259
1260/// The result of registering a listener.
1261#[derive(Debug, PartialEq)]
1262enum RegisterResult<T> {
1263 /// The listener was already notified.
1264 Notified(T),
1265
1266 /// The listener has been registered.
1267 Registered,
1268
1269 /// The listener was never inserted into the list.
1270 NeverInserted,
1271}
1272
1273impl<T> RegisterResult<T> {
1274 /// Whether or not the listener was notified.
1275 ///
1276 /// Panics if the listener was never inserted into the list.
1277 fn notified(self) -> Option<T> {
1278 match self {
1279 Self::Notified(tag) => Some(tag),
1280 Self::Registered => None,
1281 Self::NeverInserted => panic!("{}", NEVER_INSERTED_PANIC),
1282 }
1283 }
1284}
1285
1286/// A task that can be woken up.
1287#[derive(Debug, Clone)]
1288enum Task {
1289 /// A waker that wakes up a future.
1290 Waker(Waker),
1291
1292 /// An unparker that wakes up a thread.
1293 #[cfg(all(feature = "std", not(target_family = "wasm")))]
1294 Unparker(Unparker),
1295}
1296
1297impl Task {
1298 fn as_task_ref(&self) -> TaskRef<'_> {
1299 match self {
1300 Self::Waker(waker) => TaskRef::Waker(waker),
1301 #[cfg(all(feature = "std", not(target_family = "wasm")))]
1302 Self::Unparker(unparker) => TaskRef::Unparker(unparker),
1303 }
1304 }
1305
1306 fn wake(self) {
1307 match self {
1308 Self::Waker(waker) => waker.wake(),
1309 #[cfg(all(feature = "std", not(target_family = "wasm")))]
1310 Self::Unparker(unparker) => {
1311 unparker.unpark();
1312 }
1313 }
1314 }
1315}
1316
1317impl PartialEq for Task {
1318 fn eq(&self, other: &Self) -> bool {
1319 self.as_task_ref().will_wake(other.as_task_ref())
1320 }
1321}
1322
1323/// A reference to a task.
1324#[derive(Clone, Copy)]
1325enum TaskRef<'a> {
1326 /// A waker that wakes up a future.
1327 Waker(&'a Waker),
1328
1329 /// An unparker that wakes up a thread.
1330 #[cfg(all(feature = "std", not(target_family = "wasm")))]
1331 Unparker(&'a Unparker),
1332}
1333
1334impl TaskRef<'_> {
1335 /// Tells if this task will wake up the other task.
1336 #[allow(unreachable_patterns)]
1337 fn will_wake(self, other: Self) -> bool {
1338 match (self, other) {
1339 (Self::Waker(a), Self::Waker(b)) => a.will_wake(b),
1340 #[cfg(all(feature = "std", not(target_family = "wasm")))]
1341 (Self::Unparker(_), Self::Unparker(_)) => {
1342 // TODO: Use unreleased will_unpark API.
1343 false
1344 }
1345 _ => false,
1346 }
1347 }
1348
1349 /// Converts this task reference to a task by cloning.
1350 fn into_task(self) -> Task {
1351 match self {
1352 Self::Waker(waker) => Task::Waker(waker.clone()),
1353 #[cfg(all(feature = "std", not(target_family = "wasm")))]
1354 Self::Unparker(unparker) => Task::Unparker(unparker.clone()),
1355 }
1356 }
1357}
1358
1359const NEVER_INSERTED_PANIC: &str = "\
1360EventListener was not inserted into the linked list, make sure you're not polling \
1361EventListener/listener! after it has finished";
1362
1363#[cfg(not(loom))]
1364/// Synchronization primitive implementation.
1365mod sync {
1366 #[cfg(not(feature = "portable-atomic"))]
1367 pub(super) use alloc::sync::Arc;
1368 #[cfg(not(feature = "portable-atomic"))]
1369 pub(super) use core::sync::atomic;
1370
1371 #[cfg(feature = "portable-atomic")]
1372 pub(super) use portable_atomic_crate as atomic;
1373 #[cfg(feature = "portable-atomic")]
1374 pub(super) use portable_atomic_util::Arc;
1375
1376 #[allow(unused)]
1377 #[cfg(all(feature = "std", not(feature = "critical-section"), not(loom)))]
1378 pub(super) use std::sync::{Mutex, MutexGuard};
1379 #[cfg(all(feature = "std", not(target_family = "wasm"), not(loom)))]
1380 pub(super) use std::thread_local;
1381
1382 pub(super) trait WithMut {
1383 type Output;
1384
1385 fn with_mut<F, R>(&mut self, f: F) -> R
1386 where
1387 F: FnOnce(&mut Self::Output) -> R;
1388 }
1389
1390 impl<T> WithMut for atomic::AtomicPtr<T> {
1391 type Output = *mut T;
1392
1393 #[inline]
1394 fn with_mut<F, R>(&mut self, f: F) -> R
1395 where
1396 F: FnOnce(&mut Self::Output) -> R,
1397 {
1398 f(self.get_mut())
1399 }
1400 }
1401
1402 pub(crate) mod cell {
1403 pub(crate) use core::cell::Cell;
1404
1405 /// This newtype around *mut T exists for interoperability with loom::cell::ConstPtr,
1406 /// which works as a guard and performs additional logic to track access scope.
1407 pub(crate) struct ConstPtr<T>(*mut T);
1408 impl<T> ConstPtr<T> {
1409 pub(crate) unsafe fn deref(&self) -> &T {
1410 &*self.0
1411 }
1412
1413 #[allow(unused)] // std code does not need this
1414 pub(crate) unsafe fn deref_mut(&mut self) -> &mut T {
1415 &mut *self.0
1416 }
1417 }
1418
1419 /// This UnsafeCell wrapper exists for interoperability with loom::cell::UnsafeCell, and
1420 /// only contains the interface that is needed for this crate.
1421 #[derive(Debug, Default)]
1422 pub(crate) struct UnsafeCell<T>(core::cell::UnsafeCell<T>);
1423
1424 impl<T> UnsafeCell<T> {
1425 pub(crate) fn new(data: T) -> UnsafeCell<T> {
1426 UnsafeCell(core::cell::UnsafeCell::new(data))
1427 }
1428
1429 pub(crate) fn get(&self) -> ConstPtr<T> {
1430 ConstPtr(self.0.get())
1431 }
1432
1433 #[allow(dead_code)] // no_std does not need this
1434 pub(crate) fn into_inner(self) -> T {
1435 self.0.into_inner()
1436 }
1437 }
1438 }
1439}
1440
1441#[cfg(loom)]
1442/// Synchronization primitive implementation.
1443mod sync {
1444 pub(super) use loom::sync::{atomic, Arc, Mutex, MutexGuard};
1445 pub(super) use loom::{cell, thread_local};
1446}
1447
1448fn __test_send_and_sync() {
1449 fn _assert_send<T: Send>() {}
1450 fn _assert_sync<T: Sync>() {}
1451
1452 _assert_send::<crate::__private::StackSlot<'_, ()>>();
1453 _assert_sync::<crate::__private::StackSlot<'_, ()>>();
1454 _assert_send::<crate::__private::StackListener<'_, '_, ()>>();
1455 _assert_sync::<crate::__private::StackListener<'_, '_, ()>>();
1456 _assert_send::<Event<()>>();
1457 _assert_sync::<Event<()>>();
1458 _assert_send::<EventListener<()>>();
1459 _assert_sync::<EventListener<()>>();
1460}
1461
1462#[doc(hidden)]
1463mod __sealed {
1464 use super::{EventListener, __private::StackListener};
1465
1466 pub trait Sealed {}
1467 impl<T> Sealed for EventListener<T> {}
1468 impl<T> Sealed for StackListener<'_, '_, T> {}
1469}
1470
1471/// Semver exempt module.
1472#[doc(hidden)]
1473pub mod __private {
1474 pub use core::pin::Pin;
1475
1476 use super::{Event, Inner, InnerListener};
1477 use core::fmt;
1478 use core::future::Future;
1479 use core::task::{Context, Poll};
1480
1481 pin_project_lite::pin_project! {
1482 /// Space on the stack where a stack-based listener can be allocated.
1483 #[doc(hidden)]
1484 #[project(!Unpin)]
1485 pub struct StackSlot<'ev, T> {
1486 #[pin]
1487 listener: InnerListener<T, &'ev Inner<T>>
1488 }
1489 }
1490
1491 impl<T> fmt::Debug for StackSlot<'_, T> {
1492 #[inline]
1493 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1494 f.debug_struct("StackSlot").finish_non_exhaustive()
1495 }
1496 }
1497
1498 impl<T> core::panic::UnwindSafe for StackSlot<'_, T> {}
1499 impl<T> core::panic::RefUnwindSafe for StackSlot<'_, T> {}
1500 unsafe impl<T> Send for StackSlot<'_, T> {}
1501 unsafe impl<T> Sync for StackSlot<'_, T> {}
1502
1503 impl<'ev, T> StackSlot<'ev, T> {
1504 /// Create a new `StackSlot` on the stack.
1505 #[inline]
1506 #[doc(hidden)]
1507 pub fn new(event: &'ev Event<T>) -> Self {
1508 let inner = unsafe { &*event.inner() };
1509 Self {
1510 listener: InnerListener {
1511 event: inner,
1512 listener: None,
1513 },
1514 }
1515 }
1516
1517 /// Start listening on this `StackSlot`.
1518 #[inline]
1519 #[doc(hidden)]
1520 pub fn listen(mut self: Pin<&mut Self>) -> StackListener<'ev, '_, T> {
1521 // Insert ourselves into the list.
1522 self.as_mut().project().listener.listen();
1523
1524 // We are now listening.
1525 StackListener { slot: self }
1526 }
1527 }
1528
1529 /// A stack-based `EventListener`.
1530 #[doc(hidden)]
1531 pub struct StackListener<'ev, 'stack, T> {
1532 slot: Pin<&'stack mut StackSlot<'ev, T>>,
1533 }
1534
1535 impl<T> core::panic::UnwindSafe for StackListener<'_, '_, T> {}
1536 impl<T> core::panic::RefUnwindSafe for StackListener<'_, '_, T> {}
1537 impl<T> Unpin for StackListener<'_, '_, T> {}
1538
1539 impl<T> fmt::Debug for StackListener<'_, '_, T> {
1540 #[inline]
1541 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1542 f.debug_struct("StackListener").finish_non_exhaustive()
1543 }
1544 }
1545
1546 impl<'ev, T> StackListener<'ev, '_, T> {
1547 #[inline]
1548 fn listener(&self) -> &InnerListener<T, &'ev Inner<T>> {
1549 &self.slot.listener
1550 }
1551
1552 #[inline]
1553 fn listener_mut(&mut self) -> Pin<&mut InnerListener<T, &'ev Inner<T>>> {
1554 self.slot.as_mut().project().listener
1555 }
1556 }
1557
1558 forward_impl_to_listener! { T => StackListener<'_, '_, T> }
1559}