@@ -78,9 +78,10 @@ use alloc::sync::Arc;
78
78
79
79
use core:: fmt;
80
80
use core:: future:: Future ;
81
- use core:: mem:: ManuallyDrop ;
81
+ use core:: mem:: { self , ManuallyDrop } ;
82
+ use core:: num:: NonZeroUsize ;
82
83
use core:: pin:: Pin ;
83
- use core:: ptr:: { self , NonNull } ;
84
+ use core:: ptr;
84
85
use core:: sync:: atomic:: { self , AtomicPtr , AtomicUsize , Ordering } ;
85
86
use core:: task:: { Context , Poll , Waker } ;
86
87
use core:: usize;
@@ -92,7 +93,7 @@ use std::time::{Duration, Instant};
92
93
93
94
use inner:: Inner ;
94
95
use list:: { Entry , State } ;
95
- use node:: Node ;
96
+ use node:: { Node , TaskWaiting } ;
96
97
97
98
#[ cfg( feature = "std" ) ]
98
99
use parking:: Unparker ;
@@ -168,9 +169,6 @@ pub struct Event {
168
169
inner : AtomicPtr < Inner > ,
169
170
}
170
171
171
- unsafe impl Send for Event { }
172
- unsafe impl Sync for Event { }
173
-
174
172
#[ cfg( feature = "std" ) ]
175
173
impl UnwindSafe for Event { }
176
174
#[ cfg( feature = "std" ) ]
@@ -210,31 +208,31 @@ impl Event {
210
208
let inner = self . inner ( ) ;
211
209
212
210
// Try to acquire a lock in the inner list.
213
- let entry = unsafe {
214
- if let Some ( mut lock ) = ( * inner) . lock ( ) {
215
- let entry = lock . alloc ( ( * inner) . cache_ptr ( ) ) ;
216
- lock. insert ( entry ) ;
211
+ let state = {
212
+ let inner = unsafe { & * inner } ;
213
+ if let Some ( mut lock ) = inner. lock ( ) {
214
+ let entry = lock. insert ( Entry :: new ( ) ) ;
217
215
218
- entry
216
+ ListenerState :: HasNode ( entry)
219
217
} else {
220
218
// Push entries into the queue indicating that we want to push a listener.
221
219
let ( node, entry) = Node :: listener ( ) ;
222
- ( * inner) . push ( node) ;
220
+ inner. push ( node) ;
223
221
224
222
// Indicate that there are nodes waiting to be notified.
225
- ( * inner)
223
+ inner
226
224
. notified
227
225
. compare_exchange ( usize:: MAX , 0 , Ordering :: AcqRel , Ordering :: Relaxed )
228
226
. ok ( ) ;
229
227
230
- entry
228
+ ListenerState :: Queued ( entry)
231
229
}
232
230
} ;
233
231
234
232
// Register the listener.
235
233
let listener = EventListener {
236
234
inner : unsafe { Arc :: clone ( & ManuallyDrop :: new ( Arc :: from_raw ( inner) ) ) } ,
237
- entry : Some ( entry ) ,
235
+ state ,
238
236
} ;
239
237
240
238
// Make sure the listener is registered before whatever happens next.
@@ -529,12 +527,20 @@ pub struct EventListener {
529
527
/// A reference to [`Event`]'s inner state.
530
528
inner : Arc < Inner > ,
531
529
532
- /// A pointer to this listener's entry in the linked list .
533
- entry : Option < NonNull < Entry > > ,
530
+ /// The current state of the listener .
531
+ state : ListenerState ,
534
532
}
535
533
536
- unsafe impl Send for EventListener { }
537
- unsafe impl Sync for EventListener { }
534
+ enum ListenerState {
535
+ /// The listener has a node inside of the linked list.
536
+ HasNode ( NonZeroUsize ) ,
537
+
538
+ /// The listener has already been notified and has discarded its entry.
539
+ Discarded ,
540
+
541
+ /// The listener has an entry in the queue that may or may not have a task waiting.
542
+ Queued ( Arc < TaskWaiting > ) ,
543
+ }
538
544
539
545
#[ cfg( feature = "std" ) ]
540
546
impl UnwindSafe for EventListener { }
@@ -605,11 +611,26 @@ impl EventListener {
605
611
606
612
fn wait_internal ( mut self , deadline : Option < Instant > ) -> bool {
607
613
// Take out the entry pointer and set it to `None`.
608
- let entry = match self . entry . take ( ) {
609
- None => unreachable ! ( "cannot wait twice on an `EventListener`" ) ,
610
- Some ( entry) => entry,
611
- } ;
612
614
let ( parker, unparker) = parking:: pair ( ) ;
615
+ let entry = match self . state . take ( ) {
616
+ ListenerState :: HasNode ( entry) => entry,
617
+ ListenerState :: Queued ( task_waiting) => {
618
+ // This listener is stuck in the backup queue.
619
+ // Wait for the task to be notified.
620
+ loop {
621
+ match task_waiting. status ( ) {
622
+ Some ( entry_id) => break entry_id,
623
+ None => {
624
+ // Register a task and park until it is notified.
625
+ task_waiting. register ( Task :: Thread ( unparker. clone ( ) ) ) ;
626
+
627
+ parker. park ( ) ;
628
+ }
629
+ }
630
+ }
631
+ }
632
+ ListenerState :: Discarded => panic ! ( "Cannot wait on a discarded listener" ) ,
633
+ } ;
613
634
614
635
// Wait for the lock to be available.
615
636
let lock = || {
@@ -628,22 +649,15 @@ impl EventListener {
628
649
629
650
// Set this listener's state to `Waiting`.
630
651
{
631
- let e = unsafe { entry. as_ref ( ) } ;
632
-
633
- if e. is_queued ( ) {
634
- // Write a task to be woken once the lock is acquired.
635
- e. write_task ( Task :: Thread ( unparker) ) ;
636
- } else {
637
- let mut list = lock ( ) ;
652
+ let mut list = lock ( ) ;
638
653
639
- // If the listener was notified, we're done.
640
- match e. state ( ) . replace ( State :: Notified ( false ) ) {
641
- State :: Notified ( _) => {
642
- list. remove ( entry, self . inner . cache_ptr ( ) ) ;
643
- return true ;
644
- }
645
- _ => e. state ( ) . set ( State :: Task ( Task :: Thread ( unparker) ) ) ,
654
+ // If the listener was notified, we're done.
655
+ match list. state ( entry) . replace ( State :: Notified ( false ) ) {
656
+ State :: Notified ( _) => {
657
+ list. remove ( entry) ;
658
+ return true ;
646
659
}
660
+ _ => list. state ( entry) . set ( State :: Task ( Task :: Thread ( unparker) ) ) ,
647
661
}
648
662
}
649
663
@@ -658,7 +672,7 @@ impl EventListener {
658
672
if now >= deadline {
659
673
// Remove the entry and check if notified.
660
674
let mut list = lock ( ) ;
661
- let state = list. remove ( entry, self . inner . cache_ptr ( ) ) ;
675
+ let state = list. remove ( entry) ;
662
676
return state. is_notified ( ) ;
663
677
}
664
678
@@ -668,17 +682,16 @@ impl EventListener {
668
682
}
669
683
670
684
let mut list = lock ( ) ;
671
- let e = unsafe { entry. as_ref ( ) } ;
672
685
673
686
// Do a dummy replace operation in order to take out the state.
674
- match e . state ( ) . replace ( State :: Notified ( false ) ) {
687
+ match list . state ( entry ) . replace ( State :: Notified ( false ) ) {
675
688
State :: Notified ( _) => {
676
689
// If this listener has been notified, remove it from the list and return.
677
- list. remove ( entry, self . inner . cache_ptr ( ) ) ;
690
+ list. remove ( entry) ;
678
691
return true ;
679
692
}
680
693
// Otherwise, set the state back to `Waiting`.
681
- state => e . state ( ) . set ( state) ,
694
+ state => list . state ( entry ) . set ( state) ,
682
695
}
683
696
}
684
697
}
@@ -706,10 +719,10 @@ impl EventListener {
706
719
/// ```
707
720
pub fn discard ( mut self ) -> bool {
708
721
// If this listener has never picked up a notification...
709
- if let Some ( entry) = self . entry . take ( ) {
722
+ if let ListenerState :: HasNode ( entry) = self . state . take ( ) {
710
723
// Remove the listener from the list and return `true` if it was notified.
711
724
if let Some ( mut lock) = self . inner . lock ( ) {
712
- let state = lock. remove ( entry, self . inner . cache_ptr ( ) ) ;
725
+ let state = lock. remove ( entry) ;
713
726
714
727
if let State :: Notified ( _) = state {
715
728
return true ;
@@ -772,6 +785,30 @@ impl Future for EventListener {
772
785
773
786
#[ allow( unreachable_patterns) ]
774
787
fn poll ( mut self : Pin < & mut Self > , cx : & mut Context < ' _ > ) -> Poll < Self :: Output > {
788
+ let entry = match self . state {
789
+ ListenerState :: Discarded => {
790
+ unreachable ! ( "cannot poll a completed `EventListener` future" )
791
+ }
792
+ ListenerState :: HasNode ( ref entry) => * entry,
793
+ ListenerState :: Queued ( ref task_waiting) => {
794
+ loop {
795
+ // See if the task waiting has been completed.
796
+ match task_waiting. status ( ) {
797
+ Some ( entry_id) => {
798
+ self . state = ListenerState :: HasNode ( entry_id) ;
799
+ break entry_id;
800
+ }
801
+ None => {
802
+ // If not, wait for it to complete.
803
+ task_waiting. register ( Task :: Waker ( cx. waker ( ) . clone ( ) ) ) ;
804
+ if task_waiting. status ( ) . is_none ( ) {
805
+ return Poll :: Pending ;
806
+ }
807
+ }
808
+ }
809
+ }
810
+ }
811
+ } ;
775
812
let mut list = match self . inner . lock ( ) {
776
813
Some ( list) => list,
777
814
None => {
@@ -787,20 +824,15 @@ impl Future for EventListener {
787
824
}
788
825
}
789
826
} ;
790
-
791
- let entry = match self . entry {
792
- None => unreachable ! ( "cannot poll a completed `EventListener` future" ) ,
793
- Some ( entry) => entry,
794
- } ;
795
- let state = unsafe { entry. as_ref ( ) . state ( ) } ;
827
+ let state = list. state ( entry) ;
796
828
797
829
// Do a dummy replace operation in order to take out the state.
798
830
match state. replace ( State :: Notified ( false ) ) {
799
831
State :: Notified ( _) => {
800
832
// If this listener has been notified, remove it from the list and return.
801
- list. remove ( entry, self . inner . cache_ptr ( ) ) ;
833
+ list. remove ( entry) ;
802
834
drop ( list) ;
803
- self . entry = None ;
835
+ self . state = ListenerState :: Discarded ;
804
836
return Poll :: Ready ( ( ) ) ;
805
837
}
806
838
State :: Created => {
@@ -827,12 +859,11 @@ impl Future for EventListener {
827
859
impl Drop for EventListener {
828
860
fn drop ( & mut self ) {
829
861
// If this listener has never picked up a notification...
830
- if let Some ( entry) = self . entry . take ( ) {
862
+ if let ListenerState :: HasNode ( entry) = self . state . take ( ) {
831
863
match self . inner . lock ( ) {
832
864
Some ( mut list) => {
833
865
// But if a notification was delivered to it...
834
- if let State :: Notified ( additional) = list. remove ( entry, self . inner . cache_ptr ( ) )
835
- {
866
+ if let State :: Notified ( additional) = list. remove ( entry) {
836
867
// Then pass it on to another active listener.
837
868
list. notify ( 1 , additional) ;
838
869
}
@@ -849,6 +880,12 @@ impl Drop for EventListener {
849
880
}
850
881
}
851
882
883
+ impl ListenerState {
884
+ fn take ( & mut self ) -> Self {
885
+ mem:: replace ( self , ListenerState :: Discarded )
886
+ }
887
+ }
888
+
852
889
/// Equivalent to `atomic::fence(Ordering::SeqCst)`, but in some cases faster.
853
890
#[ inline]
854
891
fn full_fence ( ) {
@@ -877,17 +914,6 @@ fn full_fence() {
877
914
}
878
915
}
879
916
880
- /// Indicate that we're using spin-based contention and that we should yield the CPU.
881
- #[ inline]
882
- fn yield_now ( ) {
883
- #[ cfg( feature = "std" ) ]
884
- std:: thread:: yield_now ( ) ;
885
-
886
- #[ cfg( not( feature = "std" ) ) ]
887
- #[ allow( deprecated) ]
888
- sync:: atomic:: spin_loop_hint ( ) ;
889
- }
890
-
891
917
#[ cfg( any( feature = "__test" , test) ) ]
892
918
impl Event {
893
919
/// Locks the event.
0 commit comments