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", &notified_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}