| 1 | /// Associates readiness events with [`event::Source`]s. |
| 2 | /// |
| 3 | /// `Token` is a wrapper around `usize` and is used as an argument to |
| 4 | /// [`Registry::register`] and [`Registry::reregister`]. |
| 5 | /// |
| 6 | /// See [`Poll`] for more documentation on polling. |
| 7 | /// |
| 8 | /// [`event::Source`]: ./event/trait.Source.html |
| 9 | /// [`Poll`]: struct.Poll.html |
| 10 | /// [`Registry::register`]: struct.Registry.html#method.register |
| 11 | /// [`Registry::reregister`]: struct.Registry.html#method.reregister |
| 12 | /// |
| 13 | /// # Example |
| 14 | /// |
| 15 | /// Using `Token` to track which socket generated the event. In this example, |
| 16 | /// `HashMap` is used, but usually something like [`slab`] is better. |
| 17 | /// |
| 18 | /// [`slab`]: https://crates.io/crates/slab |
| 19 | /// |
| 20 | #[cfg_attr (all(feature = "os-poll" , feature = "net" ), doc = "```" )] |
| 21 | #[cfg_attr (not(all(feature = "os-poll" , feature = "net" )), doc = "```ignore" )] |
| 22 | /// # use std::error::Error; |
| 23 | /// # fn main() -> Result<(), Box<dyn Error>> { |
| 24 | /// use mio::{Events, Interest, Poll, Token}; |
| 25 | /// use mio::net::TcpListener; |
| 26 | /// |
| 27 | /// use std::thread; |
| 28 | /// use std::io::{self, Read}; |
| 29 | /// use std::collections::HashMap; |
| 30 | /// |
| 31 | /// // After this number of sockets is accepted, the server will shutdown. |
| 32 | /// const MAX_SOCKETS: usize = 32; |
| 33 | /// |
| 34 | /// // Pick a token that will not be used by any other socket and use that one |
| 35 | /// // for the listener. |
| 36 | /// const LISTENER: Token = Token(1024); |
| 37 | /// |
| 38 | /// // Used to store the sockets. |
| 39 | /// let mut sockets = HashMap::new(); |
| 40 | /// |
| 41 | /// // This is used to generate a unique token for a socket |
| 42 | /// let mut next_socket_index = 0; |
| 43 | /// |
| 44 | /// // The `Poll` instance |
| 45 | /// let mut poll = Poll::new()?; |
| 46 | /// |
| 47 | /// // Tcp listener |
| 48 | /// let mut listener = TcpListener::bind("127.0.0.1:0" .parse()?)?; |
| 49 | /// |
| 50 | /// // Register the listener |
| 51 | /// poll.registry().register(&mut listener, LISTENER, Interest::READABLE)?; |
| 52 | /// |
| 53 | /// // Spawn a thread that will connect a bunch of sockets then close them |
| 54 | /// let addr = listener.local_addr()?; |
| 55 | /// thread::spawn(move || { |
| 56 | /// use std::net::TcpStream; |
| 57 | /// |
| 58 | /// // +1 here is to connect an extra socket to signal the socket to close |
| 59 | /// for _ in 0..(MAX_SOCKETS+1) { |
| 60 | /// // Connect then drop the socket |
| 61 | /// let _ = TcpStream::connect(addr).unwrap(); |
| 62 | /// } |
| 63 | /// }); |
| 64 | /// |
| 65 | /// // Event storage |
| 66 | /// let mut events = Events::with_capacity(1024); |
| 67 | /// |
| 68 | /// // Read buffer, this will never actually get filled |
| 69 | /// let mut buf = [0; 256]; |
| 70 | /// |
| 71 | /// // The main event loop |
| 72 | /// loop { |
| 73 | /// // Wait for events |
| 74 | /// poll.poll(&mut events, None)?; |
| 75 | /// |
| 76 | /// for event in &events { |
| 77 | /// match event.token() { |
| 78 | /// LISTENER => { |
| 79 | /// // Perform operations in a loop until `WouldBlock` is |
| 80 | /// // encountered. |
| 81 | /// loop { |
| 82 | /// match listener.accept() { |
| 83 | /// Ok((mut socket, _)) => { |
| 84 | /// // Shutdown the server |
| 85 | /// if next_socket_index == MAX_SOCKETS { |
| 86 | /// return Ok(()); |
| 87 | /// } |
| 88 | /// |
| 89 | /// // Get the token for the socket |
| 90 | /// let token = Token(next_socket_index); |
| 91 | /// next_socket_index += 1; |
| 92 | /// |
| 93 | /// // Register the new socket w/ poll |
| 94 | /// poll.registry().register(&mut socket, token, Interest::READABLE)?; |
| 95 | /// |
| 96 | /// // Store the socket |
| 97 | /// sockets.insert(token, socket); |
| 98 | /// } |
| 99 | /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { |
| 100 | /// // Socket is not ready anymore, stop accepting |
| 101 | /// break; |
| 102 | /// } |
| 103 | /// e => panic!("err={:?}" , e), // Unexpected error |
| 104 | /// } |
| 105 | /// } |
| 106 | /// } |
| 107 | /// token => { |
| 108 | /// // Always operate in a loop |
| 109 | /// loop { |
| 110 | /// match sockets.get_mut(&token).unwrap().read(&mut buf) { |
| 111 | /// Ok(0) => { |
| 112 | /// // Socket is closed, remove it from the map |
| 113 | /// sockets.remove(&token); |
| 114 | /// break; |
| 115 | /// } |
| 116 | /// // Data is not actually sent in this example |
| 117 | /// Ok(_) => unreachable!(), |
| 118 | /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { |
| 119 | /// // Socket is not ready anymore, stop reading |
| 120 | /// break; |
| 121 | /// } |
| 122 | /// e => panic!("err={:?}" , e), // Unexpected error |
| 123 | /// } |
| 124 | /// } |
| 125 | /// } |
| 126 | /// } |
| 127 | /// } |
| 128 | /// } |
| 129 | /// # } |
| 130 | /// ``` |
| 131 | #[derive (Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] |
| 132 | pub struct Token(pub usize); |
| 133 | |
| 134 | impl From<Token> for usize { |
| 135 | fn from(val: Token) -> usize { |
| 136 | val.0 |
| 137 | } |
| 138 | } |
| 139 | |