retty_io/lib.rs
1// retty-io targets old versions of the Rust compiler. In order to do this, uses
2// deprecated APIs.
3#![allow(
4 bare_trait_objects,
5 deprecated,
6 unknown_lints,
7 unstable_name_collisions
8)]
9//#![deny(missing_docs, missing_debug_implementations)]
10//#![cfg_attr(test, deny(warnings))]
11// Many of retty-io's public methods violate this lint, but they can't be fixed
12// without a breaking change.
13#![cfg_attr(feature = "cargo-clippy", allow(clippy::trivially_copy_pass_by_ref))]
14
15//! A fast, low-level IO library for Rust focusing on non-blocking APIs, event
16//! notification, and other useful utilities for building high performance IO
17//! apps.
18//!
19//! # Features
20//!
21//! * Non-blocking TCP, UDP
22//! * Timer, Channel, Broadcast
23//! * I/O event notification queue backed by epoll, kqueue, and IOCP
24//! * Zero allocations at runtime
25//! * Platform specific extensions
26//!
27//! # Non-goals
28//!
29//! The following are specifically omitted from retty-io and are left to the user or higher-level libraries.
30//!
31//! * File operations
32//! * Thread pools / multi-threaded event loop
33//!
34//! # Platforms
35//!
36//! Currently supported platforms:
37//!
38//! * Linux
39//! * OS X
40//! * Windows
41//! * FreeBSD
42//! * NetBSD
43//! * Android
44//! * iOS
45//!
46//! retty-io can handle interfacing with each of the event notification systems of the aforementioned platforms. The details of
47//! their implementation are further discussed in [`Poll`].
48//!
49//! # Usage
50//!
51//! Using retty-io starts by creating a [`Poll`], which reads events from the OS and
52//! put them into [`Events`]. You can handle IO events from the OS with it.
53//!
54//! For more detail, see [`Poll`].
55//!
56//! [`Poll`]: struct.Poll.html
57//! [`Events`]: struct.Events.html
58//!
59//! # Example
60//!
61//! ```
62//! use retty_io::*;
63//! use retty_io::net::{TcpListener, TcpStream};
64//!
65//! // Setup some tokens to allow us to identify which event is
66//! // for which socket.
67//! const SERVER: Token = Token(0);
68//! const CLIENT: Token = Token(1);
69//!
70//! let addr = "127.0.0.1:13265".parse().unwrap();
71//!
72//! // Setup the server socket
73//! let server = TcpListener::bind(&addr).unwrap();
74//!
75//! // Create a poll instance
76//! let poll = Poll::new().unwrap();
77//!
78//! // Start listening for incoming connections
79//! poll.register(&server, SERVER, Ready::readable(),
80//! PollOpt::edge()).unwrap();
81//!
82//! // Setup the client socket
83//! let sock = TcpStream::connect(&addr).unwrap();
84//!
85//! // Register the socket
86//! poll.register(&sock, CLIENT, Ready::readable(),
87//! PollOpt::edge()).unwrap();
88//!
89//! // Create storage for events
90//! let mut events = Events::with_capacity(1024);
91//!
92//! loop {
93//! poll.poll(&mut events, None).unwrap();
94//!
95//! for event in events.iter() {
96//! match event.token() {
97//! SERVER => {
98//! // Accept and drop the socket immediately, this will close
99//! // the socket and notify the client of the EOF.
100//! let _ = server.accept();
101//! }
102//! CLIENT => {
103//! // The server just shuts down the socket, let's just exit
104//! // from our event loop.
105//! return;
106//! }
107//! _ => unreachable!(),
108//! }
109//! }
110//! }
111//!
112//! ```
113
114extern crate crossbeam;
115extern crate iovec;
116extern crate net2;
117extern crate slab;
118
119#[cfg(target_os = "fuchsia")]
120extern crate fuchsia_zircon as zircon;
121#[cfg(target_os = "fuchsia")]
122extern crate fuchsia_zircon_sys as zircon_sys;
123
124#[cfg(unix)]
125extern crate libc;
126
127#[cfg(windows)]
128extern crate miow;
129
130#[cfg(windows)]
131extern crate winapi;
132
133#[cfg(windows)]
134extern crate kernel32;
135
136#[macro_use]
137extern crate log;
138
139mod event_imp;
140mod io;
141mod poll;
142mod sys;
143mod token;
144
145pub mod broadcast;
146pub mod channel;
147pub mod lazycell;
148pub mod net;
149pub mod timer;
150
151#[deprecated(since = "0.6.5", note = "update to use `Poll`")]
152#[cfg(feature = "with-deprecated")]
153#[doc(hidden)]
154pub mod deprecated;
155
156#[deprecated(since = "0.6.5", note = "use iovec crate directly")]
157#[cfg(feature = "with-deprecated")]
158#[doc(hidden)]
159pub use iovec::IoVec;
160
161#[deprecated(since = "0.6.6", note = "use net module instead")]
162#[cfg(feature = "with-deprecated")]
163#[doc(hidden)]
164pub mod tcp {
165 pub use net::{TcpListener, TcpStream};
166 pub use std::net::Shutdown;
167}
168
169pub use event_imp::{PollOpt, Ready};
170pub use poll::{Poll, Registration, SetReadiness};
171pub use token::Token;
172
173pub mod event {
174 //! Readiness event types and utilities.
175
176 pub use super::event_imp::{Event, Evented};
177 pub use super::poll::{Events, Iter};
178}
179
180pub use event::Events;
181
182#[deprecated(since = "0.6.5", note = "use events:: instead")]
183#[cfg(feature = "with-deprecated")]
184#[doc(hidden)]
185pub use event::{Event, Evented};
186
187#[deprecated(since = "0.6.5", note = "use events::Iter instead")]
188#[cfg(feature = "with-deprecated")]
189#[doc(hidden)]
190pub use poll::Iter as EventsIter;
191
192#[deprecated(since = "0.6.5", note = "std::io::Error can avoid the allocation now")]
193#[cfg(feature = "with-deprecated")]
194#[doc(hidden)]
195pub use io::deprecated::would_block;
196
197#[cfg(all(unix, not(target_os = "fuchsia")))]
198pub mod unix {
199 //! Unix only extensions
200 pub use sys::unix::UnixReady;
201 pub use sys::EventedFd;
202}
203
204#[cfg(target_os = "fuchsia")]
205pub mod fuchsia {
206 //! Fuchsia-only extensions
207 //!
208 //! # Stability
209 //!
210 //! This module depends on the [magenta-sys crate](https://crates.io/crates/magenta-sys)
211 //! and so might introduce breaking changes, even on minor releases,
212 //! so long as that crate remains unstable.
213 pub use sys::fuchsia::{zx_signals_t, FuchsiaReady};
214 pub use sys::EventedHandle;
215}
216
217/// Windows-only extensions to the retty-io crate.
218///
219/// retty-io on windows is currently implemented with IOCP for a high-performance
220/// implementation of asynchronous I/O. retty-io then provides TCP and UDP as sample
221/// bindings for the system to connect networking types to asynchronous I/O. On
222/// Unix this scheme is then also extensible to all other file descriptors with
223/// the `EventedFd` type, but on Windows no such analog is available. The
224/// purpose of this module, however, is to similarly provide a mechanism for
225/// foreign I/O types to get hooked up into the IOCP event loop.
226///
227/// This module provides two types for interfacing with a custom IOCP handle:
228///
229/// * `Binding` - this type is intended to govern binding with retty-io's `Poll`
230/// type. Each I/O object should contain an instance of `Binding` that's
231/// interfaced with for the implementation of the `Evented` trait. The
232/// `register`, `reregister`, and `deregister` methods for the `Evented` trait
233/// all have rough analogs with `Binding`.
234///
235/// Note that this type **does not handle readiness**. That is, this type does
236/// not handle whether sockets are readable/writable/etc. It's intended that
237/// IOCP types will internally manage this state with a `SetReadiness` type
238/// from the `poll` module. The `SetReadiness` is typically lazily created on
239/// the first time that `Evented::register` is called and then stored in the
240/// I/O object.
241///
242/// Also note that for types which represent streams of bytes the retty-io
243/// interface of *readiness* doesn't map directly to the Windows model of
244/// *completion*. This means that types will have to perform internal
245/// buffering to ensure that a readiness interface can be provided. For a
246/// sample implementation see the TCP/UDP modules in retty-io itself.
247///
248/// * `Overlapped` - this type is intended to be used as the concrete instances
249/// of the `OVERLAPPED` type that most win32 methods expect. It's crucial, for
250/// safety, that all asynchronous operations are initiated with an instance of
251/// `Overlapped` and not another instantiation of `OVERLAPPED`.
252///
253/// retty-io's `Overlapped` type is created with a function pointer that receives
254/// a `OVERLAPPED_ENTRY` type when called. This `OVERLAPPED_ENTRY` type is
255/// defined in the `winapi` crate. Whenever a completion is posted to an IOCP
256/// object the `OVERLAPPED` that was signaled will be interpreted as
257/// `Overlapped` in the retty-io crate and this function pointer will be invoked.
258/// Through this function pointer, and through the `OVERLAPPED` pointer,
259/// implementations can handle management of I/O events.
260///
261/// When put together these two types enable custom Windows handles to be
262/// registered with retty-io's event loops. The `Binding` type is used to associate
263/// handles and the `Overlapped` type is used to execute I/O operations. When
264/// the I/O operations are completed a custom function pointer is called which
265/// typically modifies a `SetReadiness` set by `Evented` methods which will get
266/// later hooked into the retty-io event loop.
267#[cfg(windows)]
268pub mod windows {
269
270 pub use sys::{Binding, Overlapped};
271}
272
273#[cfg(feature = "with-deprecated")]
274mod convert {
275 use std::time::Duration;
276
277 const NANOS_PER_MILLI: u32 = 1_000_000;
278 const MILLIS_PER_SEC: u64 = 1_000;
279
280 /// Convert a `Duration` to milliseconds, rounding up and saturating at
281 /// `u64::MAX`.
282 ///
283 /// The saturating is fine because `u64::MAX` milliseconds are still many
284 /// million years.
285 pub fn millis(duration: Duration) -> u64 {
286 // Round up.
287 let millis = (duration.subsec_nanos() + NANOS_PER_MILLI - 1) / NANOS_PER_MILLI;
288 duration
289 .as_secs()
290 .saturating_mul(MILLIS_PER_SEC)
291 .saturating_add(u64::from(millis))
292 }
293}