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", ¬ified_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}