Skip to main content

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