11use std:: fmt;
2- use std:: io:: { Read as _, Write as _} ;
3- use std:: pin:: Pin ;
4- use std:: sync:: atomic:: { AtomicUsize , Ordering } ;
52use std:: sync:: { Arc , Mutex } ;
63
7- use futures_io:: { AsyncRead , AsyncWrite } ;
84use lazy_static:: lazy_static;
95use mio:: { self , Evented } ;
106use slab:: Slab ;
@@ -19,9 +15,6 @@ struct Entry {
1915 /// A unique identifier.
2016 token : mio:: Token ,
2117
22- /// Indicates whether this I/O handle is ready for reading, writing, or if it is disconnected.
23- readiness : AtomicUsize ,
24-
2518 /// Tasks that are blocked on reading from this I/O handle.
2619 readers : Mutex < Vec < Waker > > ,
2720
@@ -75,7 +68,6 @@ impl Reactor {
7568 // Allocate an entry and insert it into the slab.
7669 let entry = Arc :: new ( Entry {
7770 token,
78- readiness : AtomicUsize :: new ( mio:: Ready :: empty ( ) . as_usize ( ) ) ,
7971 readers : Mutex :: new ( Vec :: new ( ) ) ,
8072 writers : Mutex :: new ( Vec :: new ( ) ) ,
8173 } ) ;
@@ -151,9 +143,6 @@ fn main_loop() -> io::Result<()> {
151143 if let Some ( entry) = entries. get ( token. 0 ) {
152144 // Set the readiness flags from this I/O event.
153145 let readiness = event. readiness ( ) ;
154- entry
155- . readiness
156- . fetch_or ( readiness. as_usize ( ) , Ordering :: SeqCst ) ;
157146
158147 // Wake up reader tasks blocked on this I/O handle.
159148 if !( readiness & reader_interests ( ) ) . is_empty ( ) {
@@ -178,21 +167,21 @@ fn main_loop() -> io::Result<()> {
178167///
179168/// This handle wraps an I/O event source and exposes a "futurized" interface on top of it,
180169/// implementing traits `AsyncRead` and `AsyncWrite`.
181- pub struct IoHandle < T : Evented > {
170+ pub struct Watcher < T : Evented > {
182171 /// Data associated with the I/O handle.
183172 entry : Arc < Entry > ,
184173
185174 /// The I/O event source.
186175 source : Option < T > ,
187176}
188177
189- impl < T : Evented > IoHandle < T > {
178+ impl < T : Evented > Watcher < T > {
190179 /// Creates a new I/O handle.
191180 ///
192181 /// The provided I/O event source will be kept registered inside the reactor's poller for the
193182 /// lifetime of the returned I/O handle.
194- pub fn new ( source : T ) -> IoHandle < T > {
195- IoHandle {
183+ pub fn new ( source : T ) -> Watcher < T > {
184+ Watcher {
196185 entry : REACTOR
197186 . register ( & source)
198187 . expect ( "cannot register an I/O event source" ) ,
@@ -205,91 +194,75 @@ impl<T: Evented> IoHandle<T> {
205194 self . source . as_ref ( ) . unwrap ( )
206195 }
207196
208- /// Polls the I/O handle for reading .
197+ /// Polls the inner I/O source for a non-blocking read operation .
209198 ///
210- /// If reading from the I/O handle would block, `Poll::Pending` will be returned.
211- pub fn poll_readable ( & self , cx : & mut Context < ' _ > ) -> Poll < io:: Result < ( ) > > {
212- let mask = reader_interests ( ) ;
213- let mut readiness = mio:: Ready :: from_usize ( self . entry . readiness . load ( Ordering :: SeqCst ) ) ;
214-
215- if ( readiness & mask) . is_empty ( ) {
216- let mut list = self . entry . readers . lock ( ) . unwrap ( ) ;
217- if list. iter ( ) . all ( |w| !w. will_wake ( cx. waker ( ) ) ) {
218- list. push ( cx. waker ( ) . clone ( ) ) ;
219- }
220-
221- readiness = mio:: Ready :: from_usize ( self . entry . readiness . fetch_or ( 0 , Ordering :: SeqCst ) ) ;
199+ /// If the operation returns an error of the `io::ErrorKind::WouldBlock` kind, the current task
200+ /// will be registered for wakeup when the I/O source becomes readable.
201+ pub fn poll_read_with < ' a , F , R > ( & ' a self , cx : & mut Context < ' _ > , mut f : F ) -> Poll < io:: Result < R > >
202+ where
203+ F : FnMut ( & ' a T ) -> io:: Result < R > ,
204+ {
205+ // If the operation isn't blocked, return its result.
206+ match f ( self . source . as_ref ( ) . unwrap ( ) ) {
207+ Err ( err) if err. kind ( ) == io:: ErrorKind :: WouldBlock => { }
208+ res => return Poll :: Ready ( res) ,
222209 }
223210
224- if ( readiness & mask) . is_empty ( ) {
225- Poll :: Pending
226- } else {
227- Poll :: Ready ( Ok ( ( ) ) )
211+ // Lock the waker list.
212+ let mut list = self . entry . readers . lock ( ) . unwrap ( ) ;
213+
214+ // Try running the operation again.
215+ match f ( self . source . as_ref ( ) . unwrap ( ) ) {
216+ Err ( err) if err. kind ( ) == io:: ErrorKind :: WouldBlock => { }
217+ res => return Poll :: Ready ( res) ,
228218 }
229- }
230219
231- /// Clears the readability status.
232- ///
233- /// This method is usually called when an attempt at reading from the OS-level I/O handle
234- /// returns `io::ErrorKind::WouldBlock`.
235- pub fn clear_readable ( & self , cx : & mut Context < ' _ > ) -> io:: Result < ( ) > {
236- let mask = reader_interests ( ) - hup ( ) ;
237- self . entry
238- . readiness
239- . fetch_and ( !mask. as_usize ( ) , Ordering :: SeqCst ) ;
240-
241- if self . poll_readable ( cx) ?. is_ready ( ) {
242- // Wake the current task.
243- cx. waker ( ) . wake_by_ref ( ) ;
220+ // Register the task if it isn't registered already.
221+ if list. iter ( ) . all ( |w| !w. will_wake ( cx. waker ( ) ) ) {
222+ list. push ( cx. waker ( ) . clone ( ) ) ;
244223 }
245224
246- Ok ( ( ) )
225+ Poll :: Pending
247226 }
248227
249- /// Polls the I/O handle for writing .
228+ /// Polls the inner I/O source for a non-blocking write operation .
250229 ///
251- /// If writing into the I/O handle would block, `Poll::Pending` will be returned.
252- pub fn poll_writable ( & self , cx : & mut Context < ' _ > ) -> Poll < io:: Result < ( ) > > {
253- let mask = writer_interests ( ) ;
254- let mut readiness = mio:: Ready :: from_usize ( self . entry . readiness . load ( Ordering :: SeqCst ) ) ;
255-
256- if ( readiness & mask) . is_empty ( ) {
257- let mut list = self . entry . writers . lock ( ) . unwrap ( ) ;
258- if list. iter ( ) . all ( |w| !w. will_wake ( cx. waker ( ) ) ) {
259- list. push ( cx. waker ( ) . clone ( ) ) ;
260- }
261-
262- readiness = mio:: Ready :: from_usize ( self . entry . readiness . fetch_or ( 0 , Ordering :: SeqCst ) ) ;
230+ /// If the operation returns an error of the `io::ErrorKind::WouldBlock` kind, the current task
231+ /// will be registered for wakeup when the I/O source becomes writable.
232+ pub fn poll_write_with < ' a , F , R > (
233+ & ' a self ,
234+ cx : & mut Context < ' _ > ,
235+ mut f : F ,
236+ ) -> Poll < io:: Result < R > >
237+ where
238+ F : FnMut ( & ' a T ) -> io:: Result < R > ,
239+ {
240+ // If the operation isn't blocked, return its result.
241+ match f ( self . source . as_ref ( ) . unwrap ( ) ) {
242+ Err ( err) if err. kind ( ) == io:: ErrorKind :: WouldBlock => { }
243+ res => return Poll :: Ready ( res) ,
263244 }
264245
265- if ( readiness & mask) . is_empty ( ) {
266- Poll :: Pending
267- } else {
268- Poll :: Ready ( Ok ( ( ) ) )
246+ // Lock the waker list.
247+ let mut list = self . entry . writers . lock ( ) . unwrap ( ) ;
248+
249+ // Try running the operation again.
250+ match f ( self . source . as_ref ( ) . unwrap ( ) ) {
251+ Err ( err) if err. kind ( ) == io:: ErrorKind :: WouldBlock => { }
252+ res => return Poll :: Ready ( res) ,
269253 }
270- }
271254
272- /// Clears the writability status.
273- ///
274- /// This method is usually called when an attempt at writing from the OS-level I/O handle
275- /// returns `io::ErrorKind::WouldBlock`.
276- pub fn clear_writable ( & self , cx : & mut Context < ' _ > ) -> io:: Result < ( ) > {
277- let mask = writer_interests ( ) - hup ( ) ;
278- self . entry
279- . readiness
280- . fetch_and ( !mask. as_usize ( ) , Ordering :: SeqCst ) ;
281-
282- if self . poll_writable ( cx) ?. is_ready ( ) {
283- // Wake the current task.
284- cx. waker ( ) . wake_by_ref ( ) ;
255+ // Register the task if it isn't registered already.
256+ if list. iter ( ) . all ( |w| !w. will_wake ( cx. waker ( ) ) ) {
257+ list. push ( cx. waker ( ) . clone ( ) ) ;
285258 }
286259
287- Ok ( ( ) )
260+ Poll :: Pending
288261 }
289262
290263 /// Deregisters and returns the inner I/O source.
291264 ///
292- /// This method is typically used to convert `IoHandle `s to raw file descriptors/handles.
265+ /// This method is typically used to convert `Watcher `s to raw file descriptors/handles.
293266 pub fn into_inner ( mut self ) -> T {
294267 let source = self . source . take ( ) . unwrap ( ) ;
295268 REACTOR
@@ -299,7 +272,7 @@ impl<T: Evented> IoHandle<T> {
299272 }
300273}
301274
302- impl < T : Evented > Drop for IoHandle < T > {
275+ impl < T : Evented > Drop for Watcher < T > {
303276 fn drop ( & mut self ) {
304277 if let Some ( ref source) = self . source {
305278 REACTOR
@@ -309,125 +282,15 @@ impl<T: Evented> Drop for IoHandle<T> {
309282 }
310283}
311284
312- impl < T : Evented + fmt:: Debug > fmt:: Debug for IoHandle < T > {
285+ impl < T : Evented + fmt:: Debug > fmt:: Debug for Watcher < T > {
313286 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
314- f. debug_struct ( "IoHandle " )
287+ f. debug_struct ( "Watcher " )
315288 . field ( "entry" , & self . entry )
316289 . field ( "source" , & self . source )
317290 . finish ( )
318291 }
319292}
320293
321- impl < T : Evented + std:: io:: Read + Unpin > AsyncRead for IoHandle < T > {
322- fn poll_read (
323- mut self : Pin < & mut Self > ,
324- cx : & mut Context < ' _ > ,
325- buf : & mut [ u8 ] ,
326- ) -> Poll < io:: Result < usize > > {
327- futures_core:: ready!( Pin :: new( & mut * self ) . poll_readable( cx) ?) ;
328-
329- match self . source . as_mut ( ) . unwrap ( ) . read ( buf) {
330- Err ( ref err) if err. kind ( ) == io:: ErrorKind :: WouldBlock => {
331- self . clear_readable ( cx) ?;
332- Poll :: Pending
333- }
334- res => Poll :: Ready ( res) ,
335- }
336- }
337- }
338-
339- impl < ' a , T : Evented + Unpin > AsyncRead for & ' a IoHandle < T >
340- where
341- & ' a T : std:: io:: Read ,
342- {
343- fn poll_read (
344- mut self : Pin < & mut Self > ,
345- cx : & mut Context < ' _ > ,
346- buf : & mut [ u8 ] ,
347- ) -> Poll < io:: Result < usize > > {
348- futures_core:: ready!( Pin :: new( & mut * self ) . poll_readable( cx) ?) ;
349-
350- match self . source . as_ref ( ) . unwrap ( ) . read ( buf) {
351- Err ( ref err) if err. kind ( ) == io:: ErrorKind :: WouldBlock => {
352- self . clear_readable ( cx) ?;
353- Poll :: Pending
354- }
355- res => Poll :: Ready ( res) ,
356- }
357- }
358- }
359-
360- impl < T : Evented + std:: io:: Write + Unpin > AsyncWrite for IoHandle < T > {
361- fn poll_write (
362- mut self : Pin < & mut Self > ,
363- cx : & mut Context < ' _ > ,
364- buf : & [ u8 ] ,
365- ) -> Poll < io:: Result < usize > > {
366- futures_core:: ready!( self . poll_writable( cx) ?) ;
367-
368- match self . source . as_mut ( ) . unwrap ( ) . write ( buf) {
369- Err ( ref err) if err. kind ( ) == io:: ErrorKind :: WouldBlock => {
370- self . clear_writable ( cx) ?;
371- Poll :: Pending
372- }
373- res => Poll :: Ready ( res) ,
374- }
375- }
376-
377- fn poll_flush ( mut self : Pin < & mut Self > , cx : & mut Context < ' _ > ) -> Poll < io:: Result < ( ) > > {
378- futures_core:: ready!( self . poll_writable( cx) ?) ;
379-
380- match self . source . as_mut ( ) . unwrap ( ) . flush ( ) {
381- Err ( ref err) if err. kind ( ) == io:: ErrorKind :: WouldBlock => {
382- self . clear_writable ( cx) ?;
383- Poll :: Pending
384- }
385- res => Poll :: Ready ( res) ,
386- }
387- }
388-
389- fn poll_close ( self : Pin < & mut Self > , _cx : & mut Context < ' _ > ) -> Poll < io:: Result < ( ) > > {
390- Poll :: Ready ( Ok ( ( ) ) )
391- }
392- }
393-
394- impl < ' a , T : Evented + Unpin > AsyncWrite for & ' a IoHandle < T >
395- where
396- & ' a T : std:: io:: Write ,
397- {
398- fn poll_write (
399- self : Pin < & mut Self > ,
400- cx : & mut Context < ' _ > ,
401- buf : & [ u8 ] ,
402- ) -> Poll < io:: Result < usize > > {
403- futures_core:: ready!( self . poll_writable( cx) ?) ;
404-
405- match self . get_ref ( ) . write ( buf) {
406- Err ( ref err) if err. kind ( ) == io:: ErrorKind :: WouldBlock => {
407- self . clear_writable ( cx) ?;
408- Poll :: Pending
409- }
410- res => Poll :: Ready ( res) ,
411- }
412- }
413-
414- fn poll_flush ( self : Pin < & mut Self > , cx : & mut Context < ' _ > ) -> Poll < io:: Result < ( ) > > {
415- futures_core:: ready!( self . poll_writable( cx) ?) ;
416-
417- match self . get_ref ( ) . flush ( ) {
418- Err ( ref err) if err. kind ( ) == io:: ErrorKind :: WouldBlock => {
419- self . clear_writable ( cx) ?;
420- Poll :: Pending
421- }
422- res => Poll :: Ready ( res) ,
423- }
424- }
425-
426- fn poll_close ( self : Pin < & mut Self > , _cx : & mut Context < ' _ > ) -> Poll < io:: Result < ( ) > > {
427- Poll :: Ready ( Ok ( ( ) ) )
428- }
429- }
430-
431294/// Returns a mask containing flags that interest tasks reading from I/O handles.
432295#[ inline]
433296fn reader_interests ( ) -> mio:: Ready {
0 commit comments