@@ -287,7 +287,7 @@ impl<T> Event<T> {
287
287
event : Arc :: clone ( & inner) ,
288
288
listener : None ,
289
289
} ) ;
290
- inner . insert ( listener. as_mut ( ) . project ( ) . listener ) ;
290
+ listener. as_mut ( ) . listen ( ) ;
291
291
292
292
// Return the listener.
293
293
EventListener { listener }
@@ -724,7 +724,7 @@ impl<T> Drop for Event<T> {
724
724
///
725
725
/// This trait represents a type waiting for a notification from an [`Event`]. See the
726
726
/// [`EventListener`] type for more documentation on this trait's usage.
727
- pub trait Listener < T > : Future < Output = T > + __private :: Sealed {
727
+ pub trait Listener < T > : Future < Output = T > + __sealed :: Sealed {
728
728
/// Blocks until a notification is received.
729
729
///
730
730
/// # Examples
@@ -833,6 +833,45 @@ pub trait Listener<T>: Future<Output = T> + __private::Sealed {
833
833
fn same_event ( & self , other : & Self ) -> bool ;
834
834
}
835
835
836
+ macro_rules! forward_impl_to_listener {
837
+ ( $gen: ident => $ty: ty) => {
838
+ impl <$gen> crate :: Listener <$gen> for $ty {
839
+ #[ cfg( all( feature = "std" , not( target_family = "wasm" ) ) ) ]
840
+ fn wait( mut self ) -> $gen {
841
+ self . listener_mut( ) . wait_internal( None ) . unwrap( )
842
+ }
843
+
844
+ #[ cfg( all( feature = "std" , not( target_family = "wasm" ) ) ) ]
845
+ fn wait_timeout( mut self , timeout: std:: time:: Duration ) -> Option <$gen> {
846
+ self . listener_mut( )
847
+ . wait_internal( std:: time:: Instant :: now( ) . checked_add( timeout) )
848
+ }
849
+
850
+ #[ cfg( all( feature = "std" , not( target_family = "wasm" ) ) ) ]
851
+ fn wait_deadline( mut self , deadline: std:: time:: Instant ) -> Option <$gen> {
852
+ self . listener_mut( ) . wait_internal( Some ( deadline) )
853
+ }
854
+
855
+ fn discard( mut self ) -> bool {
856
+ self . listener_mut( ) . discard( )
857
+ }
858
+
859
+ #[ inline]
860
+ fn listens_to( & self , event: & Event <$gen>) -> bool {
861
+ core:: ptr:: eq:: <Inner <$gen>>(
862
+ & * self . listener( ) . event,
863
+ event. inner. load( core:: sync:: atomic:: Ordering :: Acquire ) ,
864
+ )
865
+ }
866
+
867
+ #[ inline]
868
+ fn same_event( & self , other: & $ty) -> bool {
869
+ core:: ptr:: eq:: <Inner <$gen>>( & * self . listener( ) . event, & * other. listener( ) . event)
870
+ }
871
+ }
872
+ } ;
873
+ }
874
+
836
875
/// A guard waiting for a notification from an [`Event`].
837
876
///
838
877
/// There are two ways for a listener to wait for a notification:
@@ -869,39 +908,20 @@ impl<T> fmt::Debug for EventListener<T> {
869
908
}
870
909
}
871
910
872
- impl < T > Listener < T > for EventListener < T > {
873
- #[ cfg( all( feature = "std" , not( target_family = "wasm" ) ) ) ]
874
- fn wait ( mut self ) -> T {
875
- self . listener . as_mut ( ) . wait_internal ( None ) . unwrap ( )
876
- }
877
-
878
- #[ cfg( all( feature = "std" , not( target_family = "wasm" ) ) ) ]
879
- fn wait_timeout ( mut self , timeout : Duration ) -> Option < T > {
880
- self . listener
881
- . as_mut ( )
882
- . wait_internal ( Instant :: now ( ) . checked_add ( timeout) )
883
- }
884
-
885
- #[ cfg( all( feature = "std" , not( target_family = "wasm" ) ) ) ]
886
- fn wait_deadline ( mut self , deadline : Instant ) -> Option < T > {
887
- self . listener . as_mut ( ) . wait_internal ( Some ( deadline) )
888
- }
889
-
890
- fn discard ( mut self ) -> bool {
891
- self . listener . as_mut ( ) . discard ( )
892
- }
893
-
911
+ impl < T > EventListener < T > {
894
912
#[ inline]
895
- fn listens_to ( & self , event : & Event < T > ) -> bool {
896
- ptr :: eq :: < Inner < T > > ( & * self . listener . event , event . inner . load ( Ordering :: Acquire ) )
913
+ fn listener ( & self ) -> & InnerListener < T , Arc < Inner < T > > > {
914
+ & self . listener
897
915
}
898
916
899
917
#[ inline]
900
- fn same_event ( & self , other : & EventListener < T > ) -> bool {
901
- ptr :: eq :: < Inner < T > > ( & * self . listener . event , & * other . listener . event )
918
+ fn listener_mut ( & mut self ) -> Pin < & mut InnerListener < T , Arc < Inner < T > > > > {
919
+ self . listener . as_mut ( )
902
920
}
903
921
}
904
922
923
+ forward_impl_to_listener ! { T => EventListener <T > }
924
+
905
925
impl < T > Future for EventListener < T > {
906
926
type Output = T ;
907
927
@@ -910,6 +930,18 @@ impl<T> Future for EventListener<T> {
910
930
}
911
931
}
912
932
933
+ /// Create a stack-based event listener for an [`Event`].
934
+ #[ macro_export]
935
+ macro_rules! listener {
936
+ ( $event: expr => $listener: ident) => {
937
+ let mut $listener = $crate:: __private:: StackSlot :: new( & $event) ;
938
+ // SAFETY: We shadow $listener so it can't be moved after.
939
+ let mut $listener = unsafe { $crate:: __private:: Pin :: new_unchecked( & mut $listener) } ;
940
+ #[ allow( unused_mut) ]
941
+ let mut $listener = $listener. listen( ) ;
942
+ } ;
943
+ }
944
+
913
945
pin_project_lite:: pin_project! {
914
946
#[ project( !Unpin ) ]
915
947
#[ project = ListenerProject ]
@@ -944,6 +976,13 @@ unsafe impl<T: Send, B: Borrow<Inner<T>> + Unpin + Send> Send for InnerListener<
944
976
unsafe impl < T : Send , B : Borrow < Inner < T > > + Unpin + Sync > Sync for InnerListener < T , B > { }
945
977
946
978
impl < T , B : Borrow < Inner < T > > + Unpin > InnerListener < T , B > {
979
+ /// Insert this listener into the linked list.
980
+ #[ inline]
981
+ fn listen ( self : Pin < & mut Self > ) {
982
+ let this = self . project ( ) ;
983
+ ( * this. event ) . borrow ( ) . insert ( this. listener ) ;
984
+ }
985
+
947
986
/// Wait until the provided deadline.
948
987
#[ cfg( all( feature = "std" , not( target_family = "wasm" ) ) ) ]
949
988
fn wait_internal ( mut self : Pin < & mut Self > , deadline : Option < Instant > ) -> Option < T > {
@@ -1251,9 +1290,99 @@ fn __test_send_and_sync() {
1251
1290
}
1252
1291
1253
1292
#[ doc( hidden) ]
1254
- mod __private {
1255
- use super :: EventListener ;
1293
+ mod __sealed {
1294
+ use super :: { EventListener , __private :: StackListener } ;
1256
1295
1257
1296
pub trait Sealed { }
1258
1297
impl < T > Sealed for EventListener < T > { }
1298
+ impl < T > Sealed for StackListener < ' _ , ' _ , T > { }
1299
+ }
1300
+
1301
+ /// Semver exempt module.
1302
+ #[ doc( hidden) ]
1303
+ pub mod __private {
1304
+ pub use core:: pin:: Pin ;
1305
+
1306
+ use super :: { Event , Inner , InnerListener } ;
1307
+ use core:: fmt;
1308
+ use core:: future:: Future ;
1309
+ use core:: task:: { Context , Poll } ;
1310
+
1311
+ pin_project_lite:: pin_project! {
1312
+ /// Space on the stack where a stack-based listener can be allocated.
1313
+ #[ doc( hidden) ]
1314
+ pub struct StackSlot <' ev, T > {
1315
+ #[ pin]
1316
+ listener: InnerListener <T , & ' ev Inner <T >>
1317
+ }
1318
+ }
1319
+
1320
+ impl < T > fmt:: Debug for StackSlot < ' _ , T > {
1321
+ #[ inline]
1322
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
1323
+ f. debug_struct ( "StackSlot" ) . finish_non_exhaustive ( )
1324
+ }
1325
+ }
1326
+
1327
+ impl < ' ev , T > StackSlot < ' ev , T > {
1328
+ /// Create a new `StackSlot` on the stack.
1329
+ #[ inline]
1330
+ #[ doc( hidden) ]
1331
+ pub fn new ( event : & ' ev Event < T > ) -> Self {
1332
+ let inner = unsafe { & * event. inner ( ) } ;
1333
+ Self {
1334
+ listener : InnerListener {
1335
+ event : inner,
1336
+ listener : None ,
1337
+ } ,
1338
+ }
1339
+ }
1340
+
1341
+ /// Start listening on this `StackSlot`.
1342
+ #[ inline]
1343
+ #[ doc( hidden) ]
1344
+ pub fn listen ( mut self : Pin < & mut Self > ) -> StackListener < ' ev , ' _ , T > {
1345
+ // Insert ourselves into the list.
1346
+ self . as_mut ( ) . project ( ) . listener . listen ( ) ;
1347
+
1348
+ // We are now listening.
1349
+ StackListener { slot : self }
1350
+ }
1351
+ }
1352
+
1353
+ /// A stack-based `EventListener`.
1354
+ #[ doc( hidden) ]
1355
+ pub struct StackListener < ' ev , ' stack , T > {
1356
+ slot : Pin < & ' stack mut StackSlot < ' ev , T > > ,
1357
+ }
1358
+
1359
+ impl < T > fmt:: Debug for StackListener < ' _ , ' _ , T > {
1360
+ #[ inline]
1361
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
1362
+ f. debug_struct ( "StackListener" ) . finish_non_exhaustive ( )
1363
+ }
1364
+ }
1365
+
1366
+ impl < ' ev , T > StackListener < ' ev , ' _ , T > {
1367
+ #[ inline]
1368
+ fn listener ( & self ) -> & InnerListener < T , & ' ev Inner < T > > {
1369
+ & self . slot . listener
1370
+ }
1371
+
1372
+ #[ inline]
1373
+ fn listener_mut ( & mut self ) -> Pin < & mut InnerListener < T , & ' ev Inner < T > > > {
1374
+ self . slot . as_mut ( ) . project ( ) . listener
1375
+ }
1376
+ }
1377
+
1378
+ forward_impl_to_listener ! { T => StackListener <' _, ' _, T > }
1379
+
1380
+ impl < T > Future for StackListener < ' _ , ' _ , T > {
1381
+ type Output = T ;
1382
+
1383
+ #[ inline]
1384
+ fn poll ( mut self : Pin < & mut Self > , cx : & mut Context < ' _ > ) -> Poll < Self :: Output > {
1385
+ self . listener_mut ( ) . poll_internal ( cx)
1386
+ }
1387
+ }
1259
1388
}
0 commit comments