1 个不稳定版本

0.1.0 2024年1月14日

#1505异步

MIT 许可证

400KB
7K SLoC

verypoll - 只轮询IO。


lib.rs:

verypoll是一个针对Rust的快速、低级I/O库,专注于非阻塞API和事件通知,以尽可能小的开销在操作系统抽象之上构建高性能I/O应用。

用法

使用verypoll首先创建一个Poll实例,它从操作系统读取事件并将它们放入Events。您可以使用它来处理来自操作系统的I/O事件。

更多详情请参阅Poll

指南

入门指南可在guide模块中找到。

可用功能

可用功能在features模块中描述。仅Unix扩展。Unix管道。

请参阅[new]函数的文档。仅Windows扩展。

verypoll的可选功能。

本文档描述了verypoll中的可用功能。

verypoll默认只提供shell实现,当实际运行时会panic!。要运行它需要操作系统支持,这可以通过激活os-poll功能来实现。

这使得PollRegistryWaker能够正常工作。

os-ext启用额外的操作系统特定功能。这些功能可以在unixwindows模块中找到。

net功能在net模块中启用网络原语。

入门指南。

在这个指南中,我们将做以下事情:

  1. 创建一个Poll实例(并了解它是什么)。
  2. 注册一个[事件源]。
  3. 创建一个事件循环。

最后,您将拥有一个非常小但快速的TCP服务器,该服务器接受连接然后断开。

1. 创建一个Poll实例

使用verypoll首先创建一个Poll实例,它监视来自操作系统的事件并将它们放入Events。这使得我们可以根据准备的操作执行I/O操作。

use verypoll::{Poll, Events};

fn main() -> std::io::Result<()> {

// Poll 允许轮询就绪事件。 let poll = Poll::new()?; // Events 是就绪 Event 集合,可以通过调用 Poll::poll. let events = Events::with_capacity(128);

drop((poll, events));

Ok(())

}


For example if we're using a [`TcpListener`],  we'll only want to
attempt to accept an incoming connection *iff* any connections are
queued and ready to be accepted. We don't want to waste our time if no
connections are ready.

[`TcpListener`]: ../net/struct.TcpListener.html

## 2. Registering event source

After we've created a [`Poll`] instance that monitors events from the OS
for us, we need to provide it with a source of events. This is done by
registering an [event source]. As the name “event source” suggests it is
a source of events which can be polled using a `Poll` instance. On Unix
systems this is usually a file descriptor, or a socket/handle on
Windows.

In the example below we'll use a [`TcpListener`] for which we'll receive
an event (from [`Poll`]) once a connection is ready to be accepted.

[event source]: ../event/trait.Source.html

// Create a `TcpListener`, binding it to `address`.
let mut listener = TcpListener::bind(address)?;

// Next we register it with `Poll` to receive events for it. The `SERVER`
// `Token` is used to determine that we received an event for the listener
// later on.
const SERVER: Token = Token(0);
poll.registry().register(&mut listener, SERVER, Interest::READABLE)?;

可以同时注册多个事件源(concurrently),因此可以一次监控多个源。

3. 创建事件循环

在创建了一个 Poll 实例,并使用它注册了一个或多个 事件源 后,我们可以对该实例进行事件轮询。轮询事件很简单,我们需要一个容器来存储事件:Events,并且需要根据轮询到的事件执行一些操作(这部分取决于你,我们无法全部完成!)。如果我们以循环的方式执行这个过程,我们就得到了一个事件循环。

下面的示例展示了事件循环的实际应用,完成了我们的小型 TCP 服务器。

use std::io;

use std::time::Duration;

use verypoll::net::TcpListener;

use verypoll::{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 { // 轮询操作系统事件,最长等待 100 毫秒。 poll.poll(&mut events, Some(Duration::from_millis(100)))?;

 // Process each event.
 for event in events.iter() {
     // We can use the token we previously provided to `register` to
     // determine for which type the event is.
     match event.token() {
         SERVER => loop {
             // One or more connections are ready, so we'll attempt to
             // accept them (in a loop).
             match listener.accept() {
                 Ok((connection, address)) => {
                     println!("Got a connection from: {}", address);

drop(connection);

                 },
                 // A "would block error" is returned if the operation
                 // is not ready, so we'll stop trying to accept
                 // connections.
                 Err(ref err) if would_block(err) => break,
                 Err(err) => return Err(err),
             }
         }

_ => unreachable!(),

     }
 }

return Ok(());

}

fn would_block(err: &io::Error) -> bool { err.kind() == io::ErrorKind::WouldBlock }

}

依赖项

~0–9MB
~71K SLoC