| 1 | #![deny ( |
| 2 | missing_docs, |
| 3 | missing_debug_implementations, |
| 4 | rust_2018_idioms, |
| 5 | unused_imports, |
| 6 | dead_code |
| 7 | )] |
| 8 | #![cfg_attr (docsrs, feature(doc_cfg))] |
| 9 | // Disallow warnings when running tests. |
| 10 | #![cfg_attr (test, deny(warnings))] |
| 11 | // Disallow warnings in examples. |
| 12 | #![doc (test(attr(deny(warnings))))] |
| 13 | |
| 14 | //! Mio is a fast, low-level I/O library for Rust focusing on non-blocking APIs |
| 15 | //! and event notification for building high performance I/O apps with as little |
| 16 | //! overhead as possible over the OS abstractions. |
| 17 | //! |
| 18 | //! # Usage |
| 19 | //! |
| 20 | //! Using Mio starts by creating a [`Poll`], which reads events from the OS and |
| 21 | //! puts them into [`Events`]. You can handle I/O events from the OS with it. |
| 22 | //! |
| 23 | //! For more detail, see [`Poll`]. |
| 24 | //! |
| 25 | //! [`Poll`]: ../mio/struct.Poll.html |
| 26 | //! [`Events`]: ../mio/event/struct.Events.html |
| 27 | //! |
| 28 | //! ## Examples |
| 29 | //! |
| 30 | //! Examples can found in the `examples` directory of the source code, or [on |
| 31 | //! GitHub]. |
| 32 | //! |
| 33 | //! [on GitHub]: https://github.com/tokio-rs/mio/tree/master/examples |
| 34 | //! |
| 35 | //! ## Guide |
| 36 | //! |
| 37 | //! A getting started guide is available in the [`guide`] module. |
| 38 | //! |
| 39 | //! ## Available features |
| 40 | //! |
| 41 | //! The available features are described in the [`features`] module. |
| 42 | |
| 43 | // macros used internally |
| 44 | #[macro_use ] |
| 45 | mod macros; |
| 46 | |
| 47 | mod interest; |
| 48 | mod poll; |
| 49 | mod sys; |
| 50 | mod token; |
| 51 | #[cfg (not(target_os = "wasi" ))] |
| 52 | mod waker; |
| 53 | |
| 54 | pub mod event; |
| 55 | |
| 56 | cfg_io_source! { |
| 57 | mod io_source; |
| 58 | } |
| 59 | |
| 60 | cfg_net! { |
| 61 | pub mod net; |
| 62 | } |
| 63 | |
| 64 | #[doc (no_inline)] |
| 65 | pub use event::Events; |
| 66 | pub use interest::Interest; |
| 67 | pub use poll::{Poll, Registry}; |
| 68 | pub use token::Token; |
| 69 | #[cfg (not(target_os = "wasi" ))] |
| 70 | pub use waker::Waker; |
| 71 | |
| 72 | #[cfg (all(unix, feature = "os-ext" ))] |
| 73 | #[cfg_attr (docsrs, doc(cfg(all(unix, feature = "os-ext" ))))] |
| 74 | pub mod unix { |
| 75 | //! Unix only extensions. |
| 76 | |
| 77 | pub mod pipe { |
| 78 | //! Unix pipe. |
| 79 | //! |
| 80 | //! See the [`new`] function for documentation. |
| 81 | |
| 82 | pub use crate::sys::pipe::{new, Receiver, Sender}; |
| 83 | } |
| 84 | |
| 85 | pub use crate::sys::SourceFd; |
| 86 | } |
| 87 | |
| 88 | #[cfg (all(target_os = "hermit" , feature = "os-ext" ))] |
| 89 | #[cfg_attr (docsrs, doc(cfg(all(target_os = "hermit" , feature = "os-ext" ))))] |
| 90 | pub mod hermit { |
| 91 | //! Hermit only extensions. |
| 92 | |
| 93 | pub use crate::sys::SourceFd; |
| 94 | } |
| 95 | |
| 96 | #[cfg (all(windows, feature = "os-ext" ))] |
| 97 | #[cfg_attr (docsrs, doc(cfg(all(windows, feature = "os-ext" ))))] |
| 98 | pub mod windows { |
| 99 | //! Windows only extensions. |
| 100 | |
| 101 | pub use crate::sys::named_pipe::NamedPipe; |
| 102 | } |
| 103 | |
| 104 | pub mod features { |
| 105 | //! # Mio's optional features. |
| 106 | //! |
| 107 | //! This document describes the available features in Mio. |
| 108 | //! |
| 109 | #![cfg_attr (feature = "os-poll" , doc = "## `os-poll` (enabled)" )] |
| 110 | #![cfg_attr (not(feature = "os-poll" ), doc = "## `os-poll` (disabled)" )] |
| 111 | //! |
| 112 | //! Mio by default provides only a shell implementation that `panic!`s the |
| 113 | //! moment it is actually run. To run it requires OS support, this is |
| 114 | //! enabled by activating the `os-poll` feature. |
| 115 | //! |
| 116 | //! This makes `Poll`, `Registry` and `Waker` functional. |
| 117 | //! |
| 118 | #![cfg_attr (feature = "os-ext" , doc = "## `os-ext` (enabled)" )] |
| 119 | #![cfg_attr (not(feature = "os-ext" ), doc = "## `os-ext` (disabled)" )] |
| 120 | //! |
| 121 | //! `os-ext` enables additional OS specific facilities. These facilities can |
| 122 | //! be found in the `unix` and `windows` module. |
| 123 | //! |
| 124 | #![cfg_attr (feature = "net" , doc = "## Network types (enabled)" )] |
| 125 | #![cfg_attr (not(feature = "net" ), doc = "## Network types (disabled)" )] |
| 126 | //! |
| 127 | //! The `net` feature enables networking primitives in the `net` module. |
| 128 | } |
| 129 | |
| 130 | pub mod guide { |
| 131 | //! # Getting started guide. |
| 132 | //! |
| 133 | //! In this guide we'll do the following: |
| 134 | //! |
| 135 | //! 1. Create a [`Poll`] instance (and learn what it is). |
| 136 | //! 2. Register an [event source]. |
| 137 | //! 3. Create an event loop. |
| 138 | //! |
| 139 | //! At the end you'll have a very small (but quick) TCP server that accepts |
| 140 | //! connections and then drops (disconnects) them. |
| 141 | //! |
| 142 | //! ## 1. Creating a `Poll` instance |
| 143 | //! |
| 144 | //! Using Mio starts by creating a [`Poll`] instance, which monitors events |
| 145 | //! from the OS and puts them into [`Events`]. This allows us to execute I/O |
| 146 | //! operations based on what operations are ready. |
| 147 | //! |
| 148 | //! [`Poll`]: ../struct.Poll.html |
| 149 | //! [`Events`]: ../event/struct.Events.html |
| 150 | //! |
| 151 | #![cfg_attr (feature = "os-poll" , doc = "```" )] |
| 152 | #![cfg_attr (not(feature = "os-poll" ), doc = "```ignore" )] |
| 153 | //! # use mio::{Poll, Events}; |
| 154 | //! # fn main() -> std::io::Result<()> { |
| 155 | //! // `Poll` allows for polling of readiness events. |
| 156 | //! let poll = Poll::new()?; |
| 157 | //! // `Events` is collection of readiness `Event`s and can be filled by |
| 158 | //! // calling `Poll::poll`. |
| 159 | //! let events = Events::with_capacity(128); |
| 160 | //! # drop((poll, events)); |
| 161 | //! # Ok(()) |
| 162 | //! # } |
| 163 | //! ``` |
| 164 | //! |
| 165 | //! For example if we're using a [`TcpListener`], we'll only want to |
| 166 | //! attempt to accept an incoming connection *iff* any connections are |
| 167 | //! queued and ready to be accepted. We don't want to waste our time if no |
| 168 | //! connections are ready. |
| 169 | //! |
| 170 | //! [`TcpListener`]: ../net/struct.TcpListener.html |
| 171 | //! |
| 172 | //! ## 2. Registering event source |
| 173 | //! |
| 174 | //! After we've created a [`Poll`] instance that monitors events from the OS |
| 175 | //! for us, we need to provide it with a source of events. This is done by |
| 176 | //! registering an [event source]. As the name “event source” suggests it is |
| 177 | //! a source of events which can be polled using a `Poll` instance. On Unix |
| 178 | //! systems this is usually a file descriptor, or a socket/handle on |
| 179 | //! Windows. |
| 180 | //! |
| 181 | //! In the example below we'll use a [`TcpListener`] for which we'll receive |
| 182 | //! an event (from [`Poll`]) once a connection is ready to be accepted. |
| 183 | //! |
| 184 | //! [event source]: ../event/trait.Source.html |
| 185 | //! |
| 186 | #![cfg_attr (all(feature = "os-poll" , feature = "net" ), doc = "```" )] |
| 187 | #![cfg_attr (not(all(feature = "os-poll" , feature = "net" )), doc = "```ignore" )] |
| 188 | //! # use mio::net::TcpListener; |
| 189 | //! # use mio::{Poll, Token, Interest}; |
| 190 | //! # fn main() -> std::io::Result<()> { |
| 191 | //! # let poll = Poll::new()?; |
| 192 | //! # let address = "127.0.0.1:0" .parse().unwrap(); |
| 193 | //! // Create a `TcpListener`, binding it to `address`. |
| 194 | //! let mut listener = TcpListener::bind(address)?; |
| 195 | //! |
| 196 | //! // Next we register it with `Poll` to receive events for it. The `SERVER` |
| 197 | //! // `Token` is used to determine that we received an event for the listener |
| 198 | //! // later on. |
| 199 | //! const SERVER: Token = Token(0); |
| 200 | //! poll.registry().register(&mut listener, SERVER, Interest::READABLE)?; |
| 201 | //! # Ok(()) |
| 202 | //! # } |
| 203 | //! ``` |
| 204 | //! |
| 205 | //! Multiple event sources can be [registered] (concurrently), so we can |
| 206 | //! monitor multiple sources at a time. |
| 207 | //! |
| 208 | //! [registered]: ../struct.Registry.html#method.register |
| 209 | //! |
| 210 | //! ## 3. Creating the event loop |
| 211 | //! |
| 212 | //! After we've created a [`Poll`] instance and registered one or more |
| 213 | //! [event sources] with it, we can [poll] it for events. Polling for events |
| 214 | //! is simple, we need a container to store the events: [`Events`] and need |
| 215 | //! to do something based on the polled events (this part is up to you, we |
| 216 | //! can't do it all!). If we do this in a loop we've got ourselves an event |
| 217 | //! loop. |
| 218 | //! |
| 219 | //! The example below shows the event loop in action, completing our small |
| 220 | //! TCP server. |
| 221 | //! |
| 222 | //! [poll]: ../struct.Poll.html#method.poll |
| 223 | //! [event sources]: ../event/trait.Source.html |
| 224 | //! |
| 225 | #![cfg_attr (all(feature = "os-poll" , feature = "net" ), doc = "```" )] |
| 226 | #![cfg_attr (not(all(feature = "os-poll" , feature = "net" )), doc = "```ignore" )] |
| 227 | //! # use std::io; |
| 228 | //! # use std::time::Duration; |
| 229 | //! # use mio::net::TcpListener; |
| 230 | //! # use mio::{Poll, Token, Interest, Events}; |
| 231 | //! # fn main() -> io::Result<()> { |
| 232 | //! # let mut poll = Poll::new()?; |
| 233 | //! # let mut events = Events::with_capacity(128); |
| 234 | //! # let address = "127.0.0.1:0" .parse().unwrap(); |
| 235 | //! # let mut listener = TcpListener::bind(address)?; |
| 236 | //! # const SERVER: Token = Token(0); |
| 237 | //! # poll.registry().register(&mut listener, SERVER, Interest::READABLE)?; |
| 238 | //! // Start our event loop. |
| 239 | //! loop { |
| 240 | //! // Poll the OS for events, waiting at most 100 milliseconds. |
| 241 | //! poll.poll(&mut events, Some(Duration::from_millis(100)))?; |
| 242 | //! |
| 243 | //! // Process each event. |
| 244 | //! for event in events.iter() { |
| 245 | //! // We can use the token we previously provided to `register` to |
| 246 | //! // determine for which type the event is. |
| 247 | //! match event.token() { |
| 248 | //! SERVER => loop { |
| 249 | //! // One or more connections are ready, so we'll attempt to |
| 250 | //! // accept them (in a loop). |
| 251 | //! match listener.accept() { |
| 252 | //! Ok((connection, address)) => { |
| 253 | //! println!("Got a connection from: {}" , address); |
| 254 | //! # drop(connection); |
| 255 | //! }, |
| 256 | //! // A "would block error" is returned if the operation |
| 257 | //! // is not ready, so we'll stop trying to accept |
| 258 | //! // connections. |
| 259 | //! Err(ref err) if would_block(err) => break, |
| 260 | //! Err(err) => return Err(err), |
| 261 | //! } |
| 262 | //! } |
| 263 | //! # _ => unreachable!(), |
| 264 | //! } |
| 265 | //! } |
| 266 | //! # return Ok(()); |
| 267 | //! } |
| 268 | //! |
| 269 | //! fn would_block(err: &io::Error) -> bool { |
| 270 | //! err.kind() == io::ErrorKind::WouldBlock |
| 271 | //! } |
| 272 | //! # } |
| 273 | //! ``` |
| 274 | } |
| 275 | |