@@ -58,21 +58,15 @@ impl<T> BufferedEventManager<T> {
5858 ///
5959 /// When the value given in timeout does not fit within an `i32` e.g.
6060 /// `timeout.map(|u| i32::try_from(u).unwrap())`.
61- pub fn wait ( & mut self , timeout : Option < u32 > ) -> Result < & [ T ] , i32 > {
61+ pub fn wait ( & mut self , timeout : Option < u32 > ) -> Result < Iter < ' _ , T > , i32 > {
6262 // SAFETY: `EventManager::wait` initializes N element from the start of the slice and only
6363 // accesses these, thus it will never access uninitialized memory, making this safe.
6464 unsafe {
6565 self . buffer . set_len ( self . buffer . capacity ( ) ) ;
6666 self . output_buffer . set_len ( self . output_buffer . capacity ( ) ) ;
6767 }
68- let n = self
69- . event_manager
70- . wait ( timeout, & mut self . buffer , & mut self . output_buffer ) ?;
71- unsafe {
72- Ok ( self
73- . output_buffer
74- . get_unchecked ( ..usize:: try_from ( n) . unwrap_unchecked ( ) ) )
75- }
68+ self . event_manager
69+ . wait ( timeout, & mut self . buffer , & mut self . output_buffer )
7670 }
7771
7872 /// Creates new event manager.
@@ -123,6 +117,62 @@ impl<T> std::fmt::Debug for EventManager<T> {
123117 }
124118}
125119
120+ #[ derive( Debug ) ]
121+ pub struct Iter < ' a , T > {
122+ event_manager : & ' a mut EventManager < T > ,
123+ buffer : & ' a [ libc:: epoll_event ] ,
124+ output_buffer : & ' a mut [ T ] ,
125+ index : usize ,
126+ }
127+ impl < ' a , T > Iter < ' a , T > {
128+ /// Returns a mutable slice of all the items previously returned by [`Iter::next`].
129+ pub fn as_mut_slice ( & ' a mut self ) -> & ' a mut [ T ] {
130+ & mut self . output_buffer [ ..self . index ]
131+ }
132+ /// Returns a slice of all the items previously returned by [`Iter::next`].
133+ pub fn as_slice ( & ' a self ) -> & ' a [ T ] {
134+ & self . output_buffer [ ..self . index ]
135+ }
136+ }
137+ impl < ' a , T > Iterator for Iter < ' a , T > {
138+ type Item = & ' a mut T ;
139+ fn next ( & mut self ) -> Option < Self :: Item > {
140+ debug_assert_eq ! ( self . buffer. len( ) , self . output_buffer. len( ) ) ;
141+
142+ if self . index >= self . buffer . len ( ) {
143+ return None ;
144+ }
145+ unsafe {
146+ let event = self . buffer . get_unchecked ( self . index ) ;
147+ // For all events which can fire there exists an entry within `self.events` thus
148+ // it is safe to unwrap here.
149+ let f: * const dyn Fn ( & mut EventManager < T > , EventSet ) -> T = self
150+ . event_manager
151+ . events
152+ . get ( & i32:: try_from ( event. u64 ) . unwrap_unchecked ( ) )
153+ . unwrap_unchecked ( ) ;
154+ self . output_buffer [ self . index ] = ( * f) (
155+ self . event_manager ,
156+ EventSet :: from_bits_unchecked ( event. events ) ,
157+ ) ;
158+
159+ // SAFETY: This is always safe. This is required as the current standard library trait
160+ // doesn't support lending iteraor semantics.
161+ let temp = Some ( std:: mem:: transmute ( & mut self . output_buffer [ self . index ] ) ) ;
162+
163+ self . index += 1 ;
164+
165+ temp
166+ }
167+ }
168+
169+ /// O(1)
170+ fn size_hint ( & self ) -> ( usize , Option < usize > ) {
171+ let n = self . buffer . len ( ) - self . index ;
172+ ( n, Some ( n) )
173+ }
174+ }
175+
126176impl < T > EventManager < T > {
127177 /// Add an entry to the interest list of the epoll file descriptor.
128178 ///
@@ -186,12 +236,12 @@ impl<T> EventManager<T> {
186236 ///
187237 /// When the value given in timeout does not fit within an `i32` e.g.
188238 /// `timeout.map(|u| i32::try_from(u).unwrap())`.
189- pub fn wait (
190- & mut self ,
239+ pub fn wait < ' a > (
240+ & ' a mut self ,
191241 timeout : Option < u32 > ,
192- buffer : & mut [ libc:: epoll_event ] ,
193- output_buffer : & mut [ T ] ,
194- ) -> Result < i32 , i32 > {
242+ buffer : & ' a mut [ libc:: epoll_event ] ,
243+ output_buffer : & ' a mut [ T ] ,
244+ ) -> Result < Iter < ' a , T > , i32 > {
195245 // SAFETY: Always safe.
196246 match unsafe {
197247 libc:: epoll_wait (
@@ -204,18 +254,13 @@ impl<T> EventManager<T> {
204254 -1 => Err ( errno ( ) ) ,
205255 // SAFETY: `x` elements are initialized by `libc::epoll_wait`.
206256 n @ 0 .. => unsafe {
207- #[ allow( clippy:: needless_range_loop) ]
208- for i in 0 ..usize:: try_from ( n) . unwrap_unchecked ( ) {
209- let event = buffer[ i] ;
210- // For all events which can fire there exists an entry within `self.events` thus
211- // it is safe to unwrap here.
212- let f: * const dyn Fn ( & mut EventManager < T > , EventSet ) -> T = self
213- . events
214- . get ( & i32:: try_from ( event. u64 ) . unwrap_unchecked ( ) )
215- . unwrap_unchecked ( ) ;
216- output_buffer[ i] = ( * f) ( self , EventSet :: from_bits_unchecked ( event. events ) ) ;
217- }
218- Ok ( n)
257+ let n = usize:: try_from ( n) . unwrap_unchecked ( ) ;
258+ Ok ( Iter {
259+ event_manager : self ,
260+ buffer : & mut buffer[ ..n] ,
261+ output_buffer : & mut output_buffer[ ..n] ,
262+ index : 0 ,
263+ } )
219264 } ,
220265 _ => unreachable ! ( ) ,
221266 }
@@ -286,17 +331,19 @@ mod tests {
286331
287332 // The file descriptor has been pre-armed, this will immediately call the respective
288333 // closure.
289- let vec = vec ! [ ( ) ] ;
290- assert_eq ! ( manager. wait( Some ( 10 ) ) , Ok ( vec. as_slice( ) ) ) ;
334+ let mut iter = manager. wait ( Some ( 10 ) ) . unwrap ( ) ;
335+ assert_eq ! ( iter. next( ) , Some ( & mut ( ) ) ) ;
336+ assert_eq ! ( iter. next( ) , None ) ;
291337
292338 // As the closure will flip the atomic boolean we assert it has flipped correctly.
293339 assert ! ( COUNT . load( Ordering :: SeqCst ) ) ;
294340
295341 // At this point we have called the closure, since the closure removes the event fd from the
296342 // interest list of the inner epoll, calling this again should timeout as there are no event
297343 // fd in the inner epolls interest list which could trigger.
298- let vec = vec ! [ ] ;
299- assert_eq ! ( manager. wait( Some ( 10 ) ) , Ok ( vec. as_slice( ) ) ) ;
344+ let mut iter = manager. wait ( Some ( 10 ) ) . unwrap ( ) ;
345+ assert_eq ! ( iter. next( ) , None ) ;
346+
300347 // As the `EventManager::wait` should timeout the value of the atomic boolean should not be
301348 // flipped.
302349 assert ! ( COUNT . load( Ordering :: SeqCst ) ) ;
@@ -329,15 +376,18 @@ mod tests {
329376 assert ! ( !COUNT . load( Ordering :: SeqCst ) ) ;
330377
331378 // As the closure will flip the atomic boolean we assert it has flipped correctly.
332- let vec = vec ! [ ( ) ] ;
333- assert_eq ! ( manager. wait( Some ( 10 ) ) , Ok ( vec. as_slice( ) ) ) ;
379+ let mut iter = manager. wait ( Some ( 10 ) ) . unwrap ( ) ;
380+ assert_eq ! ( iter. next( ) , Some ( & mut ( ) ) ) ;
381+ assert_eq ! ( iter. next( ) , None ) ;
382+
334383 // As the closure will flip the atomic boolean we assert it has flipped correctly.
335384 assert ! ( COUNT . load( Ordering :: SeqCst ) ) ;
336385
337386 // The file descriptor has been pre-armed, this will immediately call the respective
338387 // closure.
339- let vec = vec ! [ ( ) ] ;
340- assert_eq ! ( manager. wait( Some ( 10 ) ) , Ok ( vec. as_slice( ) ) ) ;
388+ let mut iter = manager. wait ( Some ( 10 ) ) . unwrap ( ) ;
389+ assert_eq ! ( iter. next( ) , Some ( & mut ( ) ) ) ;
390+ assert_eq ! ( iter. next( ) , None ) ;
341391 // As the closure will flip the atomic boolean we assert it has flipped correctly.
342392 assert ! ( !COUNT . load( Ordering :: SeqCst ) ) ;
343393 }
@@ -394,8 +444,12 @@ mod tests {
394444 }
395445
396446 // Check counter are the correct values
397- let arr = [ 0 ; FIRING ] ;
398- assert_eq ! ( manager. wait( None ) , Ok ( arr. as_slice( ) ) ) ;
447+ let mut iter = manager. wait ( None ) . unwrap ( ) ;
448+ for _ in 0 ..FIRING {
449+ assert_eq ! ( iter. next( ) , Some ( & mut 0 ) ) ;
450+ }
451+ assert_eq ! ( iter. next( ) , None ) ;
452+
399453 for i in set {
400454 assert_eq ! ( subscribers[ i] . 1 . load( Ordering :: SeqCst ) , 1 ) ;
401455 }
@@ -429,7 +483,9 @@ mod tests {
429483 . add ( event_fd, EventSet :: IN , Box :: new ( |_, _| Err ( ( ) ) ) )
430484 . unwrap ( ) ;
431485
432- let arr = [ Ok ( ( ) ) , Err ( ( ) ) ] ;
433- assert_eq ! ( manager. wait( None ) , Ok ( arr. as_slice( ) ) ) ;
486+ let mut iter = manager. wait ( None ) . unwrap ( ) ;
487+ assert_eq ! ( iter. next( ) , Some ( & mut Ok ( ( ) ) ) ) ;
488+ assert_eq ! ( iter. next( ) , Some ( & mut Err ( ( ) ) ) ) ;
489+ assert_eq ! ( iter. next( ) , None ) ;
434490 }
435491}
0 commit comments