Trait event_listener::IntoNotification
source · pub trait IntoNotification: Sealed {
type Tag;
type Notify: Notification<Tag = Self::Tag>;
// Required method
fn into_notification(self) -> Self::Notify;
// Provided methods
fn additional(self) -> Additional<Self::Notify>
where Self: Sized { ... }
fn relaxed(self) -> Relaxed<Self::Notify>
where Self: Sized { ... }
fn tag<T: Clone>(self, tag: T) -> Tag<Self::Notify, T>
where Self: Sized + IntoNotification<Tag = ()> { ... }
fn tag_with<T, F>(self, tag: F) -> TagWith<Self::Notify, F>
where Self: Sized + IntoNotification<Tag = ()>,
F: FnMut() -> T { ... }
}
Expand description
A value that can be converted into a Notification
.
This trait adds onto the Notification
trait by providing combinators that can be applied to all
notification types as well as numeric literals. This transforms what would normally be:
use event_listener::Event;
let event = Event::new();
// Note that each use case needs its own function, leading to bloat.
event.notify(1);
event.notify_additional(3);
event.notify_relaxed(5);
event.notify_additional_relaxed(2);
into this:
use event_listener::{Event, IntoNotification, Listener};
let event = Event::new();
event.notify(1);
event.notify(3.additional());
event.notify(5.relaxed());
event.notify(2.additional().relaxed());
This trait is implemented for all types that implement Notification
, as well as for non-floating-point
numeric literals (usize
, i32
, etc).
This function can be thought of as being analogous to std::iter::IntoIterator
, but for Notification
.
Required Associated Types§
sourcetype Tag
type Tag
The tag data associated with a notification.
By default, most [Event
]s will use the unit type, ()
. However, this can be used to pass data along to
the listener.
sourcetype Notify: Notification<Tag = Self::Tag>
type Notify: Notification<Tag = Self::Tag>
The notification type.
Tells what kind of underlying type that the Notification
is. You probably don’t need to worry about
this.
Required Methods§
sourcefn into_notification(self) -> Self::Notify
fn into_notification(self) -> Self::Notify
Convert this value into a notification.
This allows the user to convert an IntoNotification
into a Notification
.
Panics
This function panics if the value represents a negative number of notifications.
Examples
use event_listener::IntoNotification;
let _ = 3.into_notification();
Provided Methods§
sourcefn additional(self) -> Additional<Self::Notify>where
Self: Sized,
fn additional(self) -> Additional<Self::Notify>where
Self: Sized,
Convert this value into an additional notification.
By default, notifications ignore listeners that are already notified. Generally, this happens when there
is an [EventListener
] that has been woken up, but hasn’t been polled to completion or waited on yet.
For instance, if you have three notified listeners and you call event.notify(5)
, only two listeners
will be woken up.
This default behavior is generally desired. For instance, if you are writing a Mutex
implementation
powered by an [Event
], you usually only want one consumer to be notified at a time. If you notified
a listener when another listener is already notified, you would have unnecessary contention for your
lock, as both listeners fight over the lock. Therefore, you would call event.notify(1)
to make sure
at least one listener is awake.
Sometimes, this behavior is not desired. For instance, if you are writing an MPMC channel, it is desirable
for multiple listeners to be reading from the underlying queue at once. In this case, you would instead
call event.notify(1.additional())
.
Examples
use event_listener::{Event, IntoNotification, Listener};
let event = Event::new();
let mut l1 = event.listen();
let mut l2 = event.listen();
// This will only wake up the first listener, as the second call observes that there is already a
// notified listener.
event.notify(1);
event.notify(1);
// This call wakes up the other listener.
event.notify(1.additional());
sourcefn relaxed(self) -> Relaxed<Self::Notify>where
Self: Sized,
fn relaxed(self) -> Relaxed<Self::Notify>where
Self: Sized,
Don’t emit a fence for this notification.
Usually, notifications emit a SeqCst
atomic fence before any listeners are woken up. This ensures
that notification state isn’t inconsistent before any wakers are woken up. However, it may be
desirable to omit this fence in certain cases.
- You are running the [
Event
] on a single thread, where no synchronization needs to occur. - You are emitting the
SeqCst
fence yourself.
In these cases, relaxed()
can be used to avoid emitting the SeqCst
fence.
Examples
use event_listener::{Event, IntoNotification, Listener};
use std::sync::atomic::{self, Ordering};
let event = Event::new();
let listener1 = event.listen();
let listener2 = event.listen();
let listener3 = event.listen();
// We should emit a fence manually when using relaxed notifications.
atomic::fence(Ordering::SeqCst);
// Notifies two listeners.
//
// Listener queueing is fair, which means `listener1` and `listener2`
// get notified here since they start listening before `listener3`.
event.notify(1.relaxed());
event.notify(1.relaxed());
sourcefn tag<T: Clone>(self, tag: T) -> Tag<Self::Notify, T>
fn tag<T: Clone>(self, tag: T) -> Tag<Self::Notify, T>
Use a tag with this notification.
In many cases, it is desired to send additional information to the listener of the [Event
]. For instance,
it is possible to optimize a Mutex
implementation by locking directly on the next listener, without
needing to ever unlock the mutex at all.
The tag provided is cloned to provide the tag for all listeners. In cases where this is not flexible
enough, use [IntoNotification::with_tag()
] instead.
Tagging functions cannot be implemented efficiently for no_std
, so this is only available
when the std
feature is enabled.
Examples
use event_listener::{IntoNotification, Listener, Event};
let event = Event::<bool>::with_tag();
let mut listener1 = event.listen();
let mut listener2 = event.listen();
// Notify with `true` then `false`.
event.notify(1.additional().tag(true));
event.notify(1.additional().tag(false));
assert_eq!(listener1.wait(), true);
assert_eq!(listener2.wait(), false);
sourcefn tag_with<T, F>(self, tag: F) -> TagWith<Self::Notify, F>
fn tag_with<T, F>(self, tag: F) -> TagWith<Self::Notify, F>
Use a function to generate a tag with this notification.
In many cases, it is desired to send additional information to the listener of the [Event
]. For instance,
it is possible to optimize a Mutex
implementation by locking directly on the next listener, without
needing to ever unlock the mutex at all.
Tagging functions cannot be implemented efficiently for no_std
, so this is only available
when the std
feature is enabled.
Examples
use event_listener::{IntoNotification, Listener, Event};
let event = Event::<bool>::with_tag();
let mut listener1 = event.listen();
let mut listener2 = event.listen();
// Notify with `true` then `false`.
event.notify(1.additional().tag_with(|| true));
event.notify(1.additional().tag_with(|| false));
assert_eq!(listener1.wait(), true);
assert_eq!(listener2.wait(), false);