mio_poll_wrapper/
lib.rs

1#![deny(missing_docs)]
2
3//! Simple wrapper around mio's [Poll](https://docs.rs/mio/latest/mio/struct.Poll.html) method.
4//!
5//! ``` rust
6//! extern crate mio;
7//! extern crate mio_poll_wrapper;
8//!
9//! use mio_poll_wrapper::PollWrapper;
10//! use mio::net::TcpListener;
11//! use std::collections::HashMap;
12//!
13//! fn main() {
14//!     let mut handle = PollWrapper::new().unwrap();
15//!
16//!     let listener = TcpListener::bind(&"0.0.0.0:8000".parse().unwrap()).unwrap();
17//!
18//!     let process_token = handle.register(&listener).unwrap();
19//!     let mut clients = HashMap::new();
20//!
21//!     let result: ::std::io::Result<()> = handle.handle(|event, handle| {
22//!         if event.token() == process_token {
23//!             let (stream, addr) = listener.accept()?;
24//!             println!("Accepted socket from {:?}", addr);
25//!             let token = handle.register(&stream)?;
26//!             clients.insert(token, stream);
27//!         } else if let Some(client) = clients.get_mut(&event.token()) {
28//!             println!("Received data from client {:?}", client.peer_addr());
29//!         }
30//!         Ok(())
31//!     });
32//!
33//!     if let Err(e) = result {
34//!         println!("Could not execute: {:?}", e);
35//!     }
36//! }
37//! ```
38
39extern crate mio;
40
41use mio::{Event, Evented, Events, Poll, PollOpt, Ready, Token};
42
43/// A wrapper around mio's Poll method
44///
45/// You can create this
46pub struct PollWrapper {
47    poll: Poll,
48    tokens: Vec<Token>,
49    next_token_id: usize,
50}
51
52impl PollWrapper {
53    /// Create a new poll wrapper
54    pub fn new() -> ::std::io::Result<PollWrapper> {
55        Ok(PollWrapper {
56            poll: Poll::new()?,
57            tokens: Vec::new(),
58            next_token_id: 0,
59        })
60    }
61
62    /// Start the poll routine. Every time an event gets received, the callback handler gets called.
63    ///
64    /// The first argument of the handler is the event that is received.
65    ///
66    /// The second argument is a handle. See [Handle] for more information.
67    pub fn handle<E>(
68        mut self,
69        mut handler: impl FnMut(Event, &mut Handle) -> Result<(), E>,
70    ) -> Result<(), E> {
71        let mut events = Events::with_capacity(10);
72        loop {
73            self.poll.poll(&mut events, None).unwrap();
74            for event in &events {
75                let mut handle = Handle {
76                    poll: &self.poll,
77                    tokens: Vec::new(),
78                    next_token_id: &mut self.next_token_id,
79                };
80                handler(event, &mut handle)?;
81                for token in handle.tokens {
82                    self.tokens.push(token);
83                }
84            }
85        }
86    }
87
88    /// Register an evented with the poll.
89    /// This returns the token that was registered.
90    pub fn register(&mut self, evented: &impl Evented) -> ::std::io::Result<Token> {
91        let token = Token(self.next_token_id);
92        self.next_token_id += 1;
93        self.poll
94            .register(evented, token, Ready::all(), PollOpt::edge())?;
95        self.tokens.push(token);
96        Ok(token)
97    }
98}
99
100/// A handle that gets passed to the callback method of [PollWrapper].
101///
102/// This handle allows you to register evented methods to the poll while the wrapper is running.
103pub struct Handle<'a> {
104    poll: &'a Poll,
105    tokens: Vec<Token>,
106    next_token_id: &'a mut usize,
107}
108
109impl<'a> Handle<'a> {
110    /// Register an evented with the poll.
111    /// This returns the token that was registered.
112    pub fn register(&mut self, evented: &impl Evented) -> ::std::io::Result<Token> {
113        let token = Token(*self.next_token_id);
114        *self.next_token_id += 1;
115        self.poll
116            .register(evented, token, Ready::all(), PollOpt::edge())?;
117        self.tokens.push(token);
118        Ok(token)
119    }
120}