Skip to content

Commit de1f13a

Browse files
committed
Split the EventListener struct into a sub-listener structure
First part of EventListener reworks. The idea here is that, in the future, we can add an "EventListenerRef" structure that just takes an "&'a Inner" rather than an "Arc<Inner>". This way, you don't need to do an atomic clone for listening.
1 parent 0c76968 commit de1f13a

File tree

1 file changed

+119
-89
lines changed

1 file changed

+119
-89
lines changed

src/lib.rs

Lines changed: 119 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ mod sys;
7373

7474
use alloc::sync::Arc;
7575

76+
use core::borrow::Borrow;
7677
use core::fmt;
7778
use core::future::Future;
7879
use core::mem::ManuallyDrop;
@@ -176,12 +177,12 @@ impl Event {
176177
let inner = self.inner();
177178

178179
// Register the listener.
179-
let mut listener = EventListener {
180-
inner: unsafe { Arc::clone(&ManuallyDrop::new(Arc::from_raw(inner))) },
181-
state: sys::Listener::Discarded,
182-
};
180+
let mut listener = EventListener(Listener {
181+
event: unsafe { Arc::clone(&ManuallyDrop::new(Arc::from_raw(inner))) },
182+
listener: sys::Listener::Discarded,
183+
});
183184

184-
listener.inner.insert(&mut listener.state);
185+
listener.0.event.insert(&mut listener.0.listener);
185186

186187
// Make sure the listener is registered before whatever happens next.
187188
full_fence();
@@ -443,12 +444,12 @@ impl Default for Event {
443444
/// If a notified listener is dropped without receiving a notification, dropping will notify
444445
/// another active listener. Whether one *additional* listener will be notified depends on what
445446
/// kind of notification was delivered.
446-
pub struct EventListener {
447-
/// A reference to [`Event`]'s inner state.
448-
inner: Arc<Inner>,
447+
pub struct EventListener(Listener<Arc<Inner>>);
449448

450-
/// The current state of the listener.
451-
state: sys::Listener,
449+
impl fmt::Debug for EventListener {
450+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
451+
f.write_str("EventListener { .. }")
452+
}
452453
}
453454

454455
#[cfg(feature = "std")]
@@ -475,7 +476,7 @@ impl EventListener {
475476
/// listener.wait();
476477
/// ```
477478
pub fn wait(self) {
478-
self.wait_internal(None);
479+
self.0.wait_internal(None);
479480
}
480481

481482
/// Blocks until a notification is received or a timeout is reached.
@@ -495,7 +496,7 @@ impl EventListener {
495496
/// assert!(!listener.wait_timeout(Duration::from_secs(1)));
496497
/// ```
497498
pub fn wait_timeout(self, timeout: Duration) -> bool {
498-
self.wait_internal(Some(Instant::now() + timeout))
499+
self.0.wait_internal(Instant::now().checked_add(timeout))
499500
}
500501

501502
/// Blocks until a notification is received or a deadline is reached.
@@ -509,69 +510,14 @@ impl EventListener {
509510
/// use event_listener::Event;
510511
///
511512
/// let event = Event::new();
512-
/// let listener = event.listen();
513+
/// let mut listener = event.listen();
513514
///
514515
/// // There are no notification so this times out.
515-
/// assert!(!listener.wait_deadline(Instant::now() + Duration::from_secs(1)));
516+
/// assert!(!listener.as_mut().wait_deadline(Instant::now() + Duration::from_secs(1)));
516517
/// ```
518+
#[cfg(feature = "std")]
517519
pub fn wait_deadline(self, deadline: Instant) -> bool {
518-
self.wait_internal(Some(deadline))
519-
}
520-
521-
fn wait_internal(mut self, deadline: Option<Instant>) -> bool {
522-
let (parker, unparker) = parking::pair();
523-
524-
// Set the listener's state to `Task`.
525-
match self
526-
.inner
527-
.register(&mut self.state, TaskRef::Unparker(&unparker))
528-
{
529-
Some(true) => {
530-
// We were already notified, so we don't need to park.
531-
return true;
532-
}
533-
534-
Some(false) => {
535-
// We're now waiting for a notification.
536-
}
537-
538-
None => {
539-
// We were never inserted into the list.
540-
panic!("listener was never inserted into the list");
541-
}
542-
}
543-
544-
// Wait until a notification is received or the timeout is reached.
545-
loop {
546-
match deadline {
547-
None => parker.park(),
548-
549-
Some(deadline) => {
550-
// Check for timeout.
551-
let now = Instant::now();
552-
if now >= deadline {
553-
// Remove our entry and check if we were notified.
554-
return self
555-
.inner
556-
.remove(&mut self.state, false)
557-
.expect("We never removed ourself from the list")
558-
.is_notified();
559-
}
560-
561-
// Park until the deadline.
562-
parker.park_timeout(deadline - now);
563-
}
564-
}
565-
566-
// See if we were notified.
567-
if self
568-
.inner
569-
.register(&mut self.state, TaskRef::Unparker(&unparker))
570-
.expect("We never removed ourself from the list")
571-
{
572-
return true;
573-
}
574-
}
520+
self.0.wait_internal(Some(deadline))
575521
}
576522
}
577523

@@ -595,10 +541,8 @@ impl EventListener {
595541
/// assert!(listener1.discard());
596542
/// assert!(!listener2.discard());
597543
/// ```
598-
pub fn discard(mut self) -> bool {
599-
self.inner
600-
.remove(&mut self.state, false)
601-
.map_or(false, |state| state.is_notified())
544+
pub fn discard(self) -> bool {
545+
self.0.discard()
602546
}
603547

604548
/// Returns `true` if this listener listens to the given `Event`.
@@ -615,7 +559,7 @@ impl EventListener {
615559
/// ```
616560
#[inline]
617561
pub fn listens_to(&self, event: &Event) -> bool {
618-
ptr::eq::<Inner>(&*self.inner, event.inner.load(Ordering::Acquire))
562+
ptr::eq::<Inner>(&**self.inner(), event.inner.load(Ordering::Acquire))
619563
}
620564

621565
/// Returns `true` if both listeners listen to the same `Event`.
@@ -632,27 +576,112 @@ impl EventListener {
632576
/// assert!(listener1.same_event(&listener2));
633577
/// ```
634578
pub fn same_event(&self, other: &EventListener) -> bool {
635-
ptr::eq::<Inner>(&*self.inner, &*other.inner)
579+
ptr::eq::<Inner>(&**self.inner(), &**other.inner())
636580
}
637-
}
638581

639-
impl fmt::Debug for EventListener {
640-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
641-
f.pad("EventListener { .. }")
582+
fn listener(&mut self) -> &mut Listener<Arc<Inner>> {
583+
&mut self.0
584+
}
585+
586+
fn inner(&self) -> &Arc<Inner> {
587+
&self.0.event
642588
}
643589
}
644590

645591
impl Future for EventListener {
646592
type Output = ();
647593

648-
#[allow(unreachable_patterns)]
649-
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
650-
let this = self.get_mut();
594+
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
595+
self.listener().poll_internal(cx)
596+
}
597+
}
598+
599+
struct Listener<B: Borrow<Inner> + Unpin> {
600+
/// The reference to the original event.
601+
event: B,
602+
603+
/// The inner state of the listener.
604+
listener: sys::Listener,
605+
}
606+
607+
unsafe impl<B: Borrow<Inner> + Unpin + Send> Send for Listener<B> {}
608+
unsafe impl<B: Borrow<Inner> + Unpin + Sync> Sync for Listener<B> {}
609+
610+
impl<B: Borrow<Inner> + Unpin> Listener<B> {
611+
/// Wait until the provided deadline.
612+
#[cfg(feature = "std")]
613+
fn wait_internal(mut self, deadline: Option<Instant>) -> bool {
614+
let (parker, unparker) = parking::pair();
615+
616+
// Set the listener's state to `Task`.
617+
match self
618+
.event
619+
.borrow()
620+
.register(&mut self.listener, TaskRef::Unparker(&unparker))
621+
{
622+
Some(true) => {
623+
// We were already notified, so we don't need to park.
624+
return true;
625+
}
626+
627+
Some(false) => {
628+
// We're now waiting for a notification.
629+
}
651630

631+
None => {
632+
// We were never inserted into the list.
633+
panic!("listener was never inserted into the list");
634+
}
635+
}
636+
637+
// Wait until a notification is received or the timeout is reached.
638+
loop {
639+
match deadline {
640+
None => parker.park(),
641+
642+
Some(deadline) => {
643+
// Make sure we're not timed out already.
644+
let now = Instant::now();
645+
if now >= deadline {
646+
// Remove our entry and check if we were notified.
647+
return self
648+
.event
649+
.borrow()
650+
.remove(&mut self.listener, false)
651+
.expect("We never removed ourself from the list")
652+
.is_notified();
653+
}
654+
}
655+
}
656+
657+
// See if we were notified.
658+
if self
659+
.event
660+
.borrow()
661+
.register(&mut self.listener, TaskRef::Unparker(&unparker))
662+
.expect("We never removed ourself from the list")
663+
{
664+
return true;
665+
}
666+
}
667+
}
668+
669+
/// Drops this listener and discards its notification (if any) without notifying another
670+
/// active listener.
671+
fn discard(mut self) -> bool {
672+
self.event
673+
.borrow()
674+
.remove(&mut self.listener, false)
675+
.map_or(false, |state| state.is_notified())
676+
}
677+
678+
/// Poll this listener for a notification.
679+
fn poll_internal(&mut self, cx: &mut Context<'_>) -> Poll<()> {
652680
// Try to register the listener.
653-
match this
654-
.inner
655-
.register(&mut this.state, TaskRef::Waker(cx.waker()))
681+
match self
682+
.event
683+
.borrow()
684+
.register(&mut self.listener, TaskRef::Waker(cx.waker()))
656685
{
657686
Some(true) => {
658687
// We were already notified, so we don't need to park.
@@ -672,9 +701,10 @@ impl Future for EventListener {
672701
}
673702
}
674703

675-
impl Drop for EventListener {
704+
impl<B: Borrow<Inner> + Unpin> Drop for Listener<B> {
676705
fn drop(&mut self) {
677-
self.inner.remove(&mut self.state, true);
706+
// If we're being dropped, we need to remove ourself from the list.
707+
self.event.borrow().remove(&mut self.listener, true);
678708
}
679709
}
680710

0 commit comments

Comments
 (0)