@@ -610,15 +610,54 @@ unsafe impl<B: Borrow<Inner> + Unpin + Sync> Sync for Listener<B> {}
610
610
impl < B : Borrow < Inner > + Unpin > Listener < B > {
611
611
/// Wait until the provided deadline.
612
612
#[ cfg( feature = "std" ) ]
613
- fn wait_internal ( mut self , deadline : Option < Instant > ) -> bool {
614
- let ( parker , unparker ) = parking :: pair ( ) ;
613
+ fn wait_internal ( self , deadline : Option < Instant > ) -> bool {
614
+ use std :: cell :: RefCell ;
615
615
616
+ std:: thread_local! {
617
+ /// Cached thread-local parker/unparker pair.
618
+ static PARKER : RefCell <Option <( parking:: Parker , Task ) >> = RefCell :: new( None ) ;
619
+ }
620
+
621
+ // Try to borrow the thread-local parker/unparker pair.
622
+ let mut this = Some ( self ) ;
623
+ PARKER
624
+ . try_with ( {
625
+ |parker| {
626
+ let mut pair = parker
627
+ . try_borrow_mut ( )
628
+ . expect ( "Shouldn't be able to borrow parker reentrantly" ) ;
629
+ let ( parker, unparker) = pair. get_or_insert_with ( || {
630
+ let ( parker, unparker) = parking:: pair ( ) ;
631
+ ( parker, Task :: Unparker ( unparker) )
632
+ } ) ;
633
+
634
+ this. take ( )
635
+ . unwrap ( )
636
+ . wait_with_parker ( deadline, parker, unparker. as_task_ref ( ) )
637
+ }
638
+ } )
639
+ . unwrap_or_else ( |_| {
640
+ // If the pair isn't accessible, we may be being called in a destructor.
641
+ // Just create a new pair.
642
+ let ( parker, unparker) = parking:: pair ( ) ;
643
+ this. take ( ) . unwrap ( ) . wait_with_parker (
644
+ deadline,
645
+ & parker,
646
+ TaskRef :: Unparker ( & unparker) ,
647
+ )
648
+ } )
649
+ }
650
+
651
+ /// Wait until the provided deadline using the specified parker/unparker pair.
652
+ #[ cfg( feature = "std" ) ]
653
+ fn wait_with_parker (
654
+ mut self ,
655
+ deadline : Option < Instant > ,
656
+ parker : & parking:: Parker ,
657
+ unparker : TaskRef < ' _ > ,
658
+ ) -> bool {
616
659
// Set the listener's state to `Task`.
617
- match self
618
- . event
619
- . borrow ( )
620
- . register ( & mut self . listener , TaskRef :: Unparker ( & unparker) )
621
- {
660
+ match self . event . borrow ( ) . register ( & mut self . listener , unparker) {
622
661
Some ( true ) => {
623
662
// We were already notified, so we don't need to park.
624
663
return true ;
@@ -658,7 +697,7 @@ impl<B: Borrow<Inner> + Unpin> Listener<B> {
658
697
if self
659
698
. event
660
699
. borrow ( )
661
- . register ( & mut self . listener , TaskRef :: Unparker ( & unparker) )
700
+ . register ( & mut self . listener , unparker)
662
701
. expect ( "We never removed ourself from the list" )
663
702
{
664
703
return true ;
0 commit comments