Trait compio::driver::Poller

source ·
pub trait Poller {
    // Required methods
    fn attach(&mut self, fd: RawFd) -> Result<()>;
    fn cancel(&mut self, user_data: usize);
    unsafe fn poll<'a>(
        &mut self,
        timeout: Option<Duration>,
        ops: &mut impl Iterator<Item = Operation<'a>>,
        entries: &mut impl Extend<Entry>
    ) -> Result<()>;
}
Expand description

An abstract of Driver. It contains some low-level actions of completion-based IO.

You don’t need them unless you are controlling a Driver yourself.

Examples

use std::net::SocketAddr;

use arrayvec::ArrayVec;
use compio::{
    buf::IntoInner,
    driver::{AsRawFd, Driver, Entry, Poller},
    net::UdpSocket,
    op,
};

let first_addr: SocketAddr = "127.0.0.1:0".parse().unwrap();
let second_addr: SocketAddr = "127.0.0.1:0".parse().unwrap();

// bind sockets
let socket = UdpSocket::bind(first_addr).unwrap();
let first_addr = socket.local_addr().unwrap();
let other_socket = UdpSocket::bind(second_addr).unwrap();
let second_addr = other_socket.local_addr().unwrap();

// connect sockets
socket.connect(second_addr).unwrap();
other_socket.connect(first_addr).unwrap();

let mut driver = Driver::new().unwrap();
driver.attach(socket.as_raw_fd()).unwrap();
driver.attach(other_socket.as_raw_fd()).unwrap();

// write data
let mut op_write = op::Send::new(socket.as_raw_fd(), "hello world");

// read data
let buf = Vec::with_capacity(32);
let mut op_read = op::Recv::new(other_socket.as_raw_fd(), buf);

let ops = [(&mut op_write, 1).into(), (&mut op_read, 2).into()];
let mut entries = ArrayVec::<Entry, 2>::new();
unsafe {
    driver
        .poll(None, &mut ops.into_iter(), &mut entries)
        .unwrap()
};
while entries.len() < 2 {
    unsafe {
        driver
            .poll(None, &mut [].into_iter(), &mut entries)
            .unwrap()
    };
}

let mut n_bytes = 0;
for entry in entries {
    match entry.user_data() {
        1 => {
            entry.into_result().unwrap();
        }
        2 => {
            n_bytes = entry.into_result().unwrap();
        }
        _ => unreachable!(),
    }
}

let mut buf = op_read.into_inner().into_inner();
unsafe { buf.set_len(n_bytes) };
assert_eq!(buf, b"hello world");

Required Methods§

source

fn attach(&mut self, fd: RawFd) -> Result<()>

Attach an fd to the driver.

Platform specific
  • IOCP: it will be attached to the completion port. An fd could only be attached to one driver, and could only be attached once, even if you try_clone it. It will cause unexpected result to attach the handle with one driver and push an op to another driver.
  • io-uring/mio: it will do nothing and return Ok(())
source

fn cancel(&mut self, user_data: usize)

Cancel an operation with the pushed user-defined data.

The cancellation is not reliable. The underlying operation may continue, but just don’t return from Poller::poll. Therefore, although an operation is cancelled, you should not reuse its user_data.

It is well-defined to cancel before polling. If the submitted operation contains a cancelled user-defined data, the operation will be ignored.

source

unsafe fn poll<'a>( &mut self, timeout: Option<Duration>, ops: &mut impl Iterator<Item = Operation<'a>>, entries: &mut impl Extend<Entry> ) -> Result<()>

Poll the driver with an optional timeout.

The operations in ops may not be totally consumed. This method will try its best to consume them, but if an error occurs, it will return immediately.

If there are no tasks completed, this call will block and wait. If no timeout specified, it will block forever. To interrupt the blocking, see Event.

Safety
  • Operations should be alive until Poller::poll returns its result.
  • User defined data should be unique.

Implementors§