mio

repository·master·Indexed 27 days ago

https://github.com/tokio-rs/mio

A fast, low-level, non-blocking I/O library for Rust that provides a thin abstraction over OS-specific event notification systems such as epoll, kqueue, and IOCP. It allows users to monitor multiple I/O sources using a Poll instance, Registry, and Tokens to handle readiness events like READABLE and WRITABLE.

Tokens
2.6K
Snippets
2
Records
10
Agent score
42%

What's inside mio

  1. Supported Platforms

    master

    Mio supports a wide range of platforms by interfacing with their native event systems (epoll, kqueue, IOCP, etc.):

    • Android (API level 21)
    • DragonFly BSD
    • FreeBSD
    • Linux
    • NetBSD
    • OpenBSD
    • WASI
    • Windows (uses the wepoll strategy via Windows AFD)
    • Wine
    • iOS
    • macOS
    • Solaris
  2. Get started with Mio

    master

    Mio is a low-level I/O library for Rust focusing on non-blocking APIs and event notification. To use Mio, follow these three steps:

    1. Create a Poll instance: This monitors events from the OS and puts them into Events.
    2. Register an event source: Provide a source (like a TcpListener) to the Poll instance using a Token to identify it later.
    3. Create an event loop: Call poll.poll() in a loop to retrieve events and process them based on their associated Token.
    use std::io;
    use std::time::Duration;
    use mio::net::TcpListener;
    use mio::{Poll, Token, Interest, Events};
    
    fn main() -> io::Result<()> {
        let mut poll = Poll::new()?;
        let mut events = Events::with_capacity(128);
        let address = "127.0.0.1:0".parse().unwrap();
        let mut listener = TcpListener::bind(address)?;
        
        const SERVER: Token = Token(0);
        poll.registry().register(&mut listener, SERVER, Interest::READABLE)?;
    
        loop {
            poll.poll(&mut events, Some(Duration::from_millis(100)))?;
    
            for event in events.iter() {
                match event.token() {
                    SERVER => loop {
                        match listener.accept() {
                            Ok((connection, address)) => {
                                println!("Got a connection from: {}", address);
                                drop(connection);
                            },
                            Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => break,
                            Err(err) => return Err(err),
                        }
                    }
                    _ => unreachable!(),
                }
            }
        }
    }
  3. Basic Usage with TcpListener and TcpStream

    master

    Mio uses a Poll instance to monitor multiple I/O sources for events. You register sockets (like TcpListener or TcpStream) with a Registry using a unique Token to identify them when events occur. The event loop typically calls poll.poll() to block until events are ready, then iterates through the Events to process them based on the provided Token and event type (e.g., is_readable(), is_writable()).

    use std::error::Error;
    
    use mio::net::{TcpListener, TcpStream};
    use mio::{Events, Interest, Poll, Token};
    
    // Some tokens to allow us to identify which event is for which socket.
    const SERVER: Token = Token(0);
    const CLIENT: Token = Token(1);
    
    fn main() -> Result<(), Box<dyn Error>> {
        // Create a poll instance.
        let mut poll = Poll::new()?;
        // Create storage for events.
        let mut events = Events::with_capacity(128);
    
        // Setup the server socket.
        let addr = "127.0.0.1:13265".parse()?;
        let mut server = TcpListener::bind(addr)?;
        // Start listening for incoming connections.
        poll.registry()
            .register(&mut server, SERVER, Interest::READABLE)?;
    
        // Setup the client socket.
        let mut client = TcpStream::connect(addr)?;
        // Register the socket.
        poll.registry()
            .register(&mut client, CLIENT, Interest::READABLE | Interest::WRITABLE)?;
    
        // Start an event loop.
        loop {
            // Poll Mio for events, blocking until we get an event.
            poll.poll(&mut events, None)?;
    
            // Process each event.
            for event in events.iter() {
                // We can use the token we previously provided to `register` to
                // determine for which socket the event is.
                match event.token() {
                    SERVER => {
                        // If this is an event for the server, it means a connection is ready to be accepted.
                        // Accept the connection and drop it immediately. This will
                        // close the socket and notify the client of the EOF.
                        let connection = server.accept();
                        drop(connection);
                    }
                    CLIENT => {
                        if event.is_writable() {
                            // We can (likely) write to the socket without blocking.
                        }
    
                        if event.is_readable() {
                            // We can (likely) read from the socket without blocking.
                        }
    
                        // Since the server just shuts down the connection, let's
                        // just exit from our event loop.
                        return Ok(());
                    }
                    // We don't expect any events with tokens other than those we provided.
                    _ => unreachable!(),
                }
            }
        }
    }
  4. Minimum Supported Rust Version (MSRV) by Mio version

    master

    If you are constrained by your Rust compiler version, refer to the following MSRV requirements:

    • v0.8: Rust 1.46
    • v1.0: Rust 1.70
    • v1.1: Rust 1.71
    • v1.2: Rust 1.71
  5. Unofficial Unsupported Implementation Flags

    master

    Mio does not officially support secondary implementations on platforms, but provides cfg flags to force specific implementations if the 'best' default is unsuitable for your use case. Note: These flags are not officially supported and may be removed in the future.

    • mio_unsupported_force_poll_poll: Uses an implementation based on poll(2) for mio::Poll.
    • mio_unsupported_force_waker_pipe: Uses an implementation based on pipe(2) for mio::Waker.
  6. Core Mio types

    master

    The following types are the primary entry points for using Mio:

    • Poll: Monitors readiness events from the OS.
    • Registry: Used to register event sources with a Poll instance.
    • Events: A collection of readiness Events filled by calling Poll::poll.
    • Token: A user-defined identifier used to associate an event with a specific source.
    • Interest: Specifies which types of events (e.g., READABLE, WRITABLE) a source is interested in.
  7. Windows-specific extensions

    master

    When the os-ext feature is enabled on Windows, you can access the windows module:

    • windows::NamedPipe: Provides named pipe support.
    • windows::SourceFd: Provides access to the underlying handle.
  8. Unix-specific extensions

    master

    When the os-ext feature is enabled on Unix systems, you can access the unix module for additional facilities:

    • unix::pipe: Provides Unix pipes via new, Receiver, and Sender.
    • unix::SourceFd: Provides access to the underlying file descriptor.
  9. Mio available features

    master

    Mio uses Cargo features to enable specific capabilities. By default, Mio provides only a shell implementation that panics when run. You must activate the following features to use it:

    • os-poll: Required for functional use. Enables Poll, Registry, and Waker by providing OS-specific polling support.
    • net: Enables networking primitives in the net module.
    • os-ext: Enables additional OS-specific facilities found in the unix and windows modules.