@@ -237,6 +237,25 @@ impl<T> Event<T> {
237
237
/// let event = Event::new();
238
238
/// let listener = event.listen();
239
239
/// ```
240
+ ///
241
+ /// # Caveats
242
+ ///
243
+ /// The above example is equivalent to this code:
244
+ ///
245
+ /// ```
246
+ /// use event_listener::{Event, EventListener};
247
+ ///
248
+ /// let event = Event::new();
249
+ /// let mut listener = Box::pin(EventListener::new(&event));
250
+ /// listener.as_mut().listen();
251
+ /// ```
252
+ ///
253
+ /// It creates a new listener, pins it to the heap, and inserts it into the linked list
254
+ /// of listeners. While this type of usage is simple, it may be desired to eliminate this
255
+ /// heap allocation. In this case, consider using the [`EventListener::new`] constructor
256
+ /// directly, which allows for greater control over where the [`EventListener`] is
257
+ /// allocated. However, users of this `new` method must be careful to ensure that the
258
+ /// [`EventListener`] is `listen`ing before waiting on it; panics may occur otherwise.
240
259
#[ cold]
241
260
pub fn listen ( & self ) -> Pin < Box < EventListener < T > > > {
242
261
let mut listener = Box :: pin ( EventListener :: new ( self ) ) ;
@@ -638,6 +657,77 @@ pin_project_lite::pin_project! {
638
657
/// If a notified listener is dropped without receiving a notification, dropping will notify
639
658
/// another active listener. Whether one *additional* listener will be notified depends on what
640
659
/// kind of notification was delivered.
660
+ ///
661
+ /// The listener is not registered into the linked list inside of the [`Event`] by default. It
662
+ /// needs to be pinned first before being inserted using the `listen()` method. After the
663
+ /// listener has begun `listen`ing, the user can `await` it like a future or call `wait()`
664
+ /// to block the current thread until it is notified.
665
+ ///
666
+ /// ## Examples
667
+ ///
668
+ /// ```
669
+ /// use event_listener::{Event, EventListener};
670
+ /// use std::sync::{Arc, atomic::{AtomicBool, Ordering}};
671
+ /// use std::thread;
672
+ /// use std::time::Duration;
673
+ ///
674
+ /// // Some flag to wait on.
675
+ /// let flag = Arc::new(AtomicBool::new(false));
676
+ ///
677
+ /// // Create an event to wait on.
678
+ /// let event = Event::new();
679
+ ///
680
+ /// thread::spawn({
681
+ /// let flag = flag.clone();
682
+ /// move || {
683
+ /// thread::sleep(Duration::from_secs(2));
684
+ /// flag.store(true, Ordering::SeqCst);
685
+ ///
686
+ /// // Wake up the listener.
687
+ /// event.notify_additional(std::usize::MAX);
688
+ /// }
689
+ /// });
690
+ ///
691
+ /// let listener = EventListener::new(&event);
692
+ ///
693
+ /// // Make sure that the event listener is pinned before doing anything else.
694
+ /// //
695
+ /// // We pin the listener to the stack here, as it lets us avoid a heap allocation.
696
+ /// futures_lite::pin!(listener);
697
+ ///
698
+ /// // Wait for the flag to become ready.
699
+ /// loop {
700
+ /// if flag.load(Ordering::Acquire) {
701
+ /// // We are done.
702
+ /// break;
703
+ /// }
704
+ ///
705
+ /// if listener.is_listening() {
706
+ /// // We are inserted into the linked list and we can now wait.
707
+ /// listener.as_mut().wait();
708
+ /// } else {
709
+ /// // We need to insert ourselves into the list. Since this insertion is an atomic
710
+ /// // operation, we should check the flag again before waiting.
711
+ /// listener.as_mut().listen();
712
+ /// }
713
+ /// }
714
+ /// ```
715
+ ///
716
+ /// The above example is equivalent to the one provided in the crate level example. However,
717
+ /// it has some advantages. By directly creating the listener with `EventListener::new()`,
718
+ /// we have control over how the listener is handled in memory. We take advantage of this by
719
+ /// pinning the `listener` variable to the stack using the [`futures_lite::pin`] macro. In
720
+ /// contrast, `Event::listen` binds the listener to the heap.
721
+ ///
722
+ /// However, this additional power comes with additional responsibility. By default, the
723
+ /// event listener is created in an "uninserted" state. This property means that any
724
+ /// notifications delivered to the [`Event`] by default will not wake up this listener.
725
+ /// Before any notifications can be received, the `listen()` method must be called on
726
+ /// `EventListener` to insert it into the list of listeners. After a `.await` or a `wait()`
727
+ /// call has completed, `listen()` must be called again if the user is still interested in
728
+ /// any events.
729
+ ///
730
+ /// [`futures_lite::pin`]: https://docs.rs/futures-lite/latest/futures_lite/macro.pin.html
641
731
#[ project( !Unpin ) ] // implied by Listener, but can generate better docs
642
732
pub struct EventListener <T = ( ) > {
643
733
#[ pin]
@@ -656,6 +746,23 @@ impl<T> fmt::Debug for EventListener<T> {
656
746
657
747
impl < T > EventListener < T > {
658
748
/// Create a new `EventListener` that will wait for a notification from the given [`Event`].
749
+ ///
750
+ /// This function does not register the `EventListener` into the linked list of listeners
751
+ /// contained within the [`Event`]. Make sure to call `listen` before `await`ing on
752
+ /// this future or calling `wait()`.
753
+ ///
754
+ /// ## Examples
755
+ ///
756
+ /// ```
757
+ /// use event_listener::{Event, EventListener};
758
+ ///
759
+ /// let event = Event::new();
760
+ /// let listener = EventListener::new(&event);
761
+ ///
762
+ /// // Make sure that the listener is pinned and listening before doing anything else.
763
+ /// let mut listener = Box::pin(listener);
764
+ /// listener.as_mut().listen();
765
+ /// ```
659
766
pub fn new ( event : & Event < T > ) -> Self {
660
767
let inner = event. inner ( ) ;
661
768
0 commit comments