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§
sourcefn attach(&mut self, fd: RawFd) -> Result<()>
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(())
sourcefn cancel(&mut self, user_data: usize)
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.
sourceunsafe fn poll<'a>(
&mut self,
timeout: Option<Duration>,
ops: &mut impl Iterator<Item = Operation<'a>>,
entries: &mut impl Extend<Entry>
) -> Result<()>
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.