Wraps epoll system calls
This commit is contained in:
parent
26a34c3eae
commit
1d7857199d
162
rust/src/system/epoll.rs
Normal file
162
rust/src/system/epoll.rs
Normal file
@ -0,0 +1,162 @@
|
||||
use std::os::unix::io::{RawFd,AsRawFd};
|
||||
use std::ptr;
|
||||
use crate::system::{Result,Error};
|
||||
use std::time::Duration;
|
||||
|
||||
use libc::{epoll_event, c_int, EPOLLIN, EPOLLHUP, EPOLL_CTL_DEL, EPOLL_CTL_ADD, EPOLL_CLOEXEC, EINTR, EINVAL};
|
||||
|
||||
const MAX_EVENTS: usize = 32;
|
||||
|
||||
pub struct Event(epoll_event);
|
||||
|
||||
impl Event {
|
||||
pub fn id(&self) -> u64 {
|
||||
self.0.u64
|
||||
}
|
||||
pub fn is_readable(&self) -> bool {
|
||||
self.is_event(EPOLLIN)
|
||||
}
|
||||
|
||||
pub fn is_hangup(&self) -> bool {
|
||||
self.is_event(EPOLLHUP)
|
||||
}
|
||||
|
||||
fn is_event(&self, flag: c_int) -> bool {
|
||||
self.events() & flag as u32 != 0
|
||||
}
|
||||
|
||||
pub fn events(&self) -> u32 {
|
||||
self.0.events
|
||||
}
|
||||
}
|
||||
|
||||
pub struct EPoll {
|
||||
fd: RawFd,
|
||||
events: PollEvents,
|
||||
}
|
||||
|
||||
impl EPoll {
|
||||
pub fn new() -> Result<EPoll> {
|
||||
match unsafe { libc::epoll_create1(EPOLL_CLOEXEC) } {
|
||||
-1 => Err(Error::last_os_error()),
|
||||
fd => Ok(EPoll {
|
||||
fd,
|
||||
events: PollEvents::new(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_read(&self, fd: RawFd, id: u64) -> Result<()> {
|
||||
let mut evt = epoll_event {
|
||||
events: EPOLLIN as u32,
|
||||
u64: id
|
||||
};
|
||||
match unsafe { libc::epoll_ctl(self.fd, EPOLL_CTL_ADD, fd, &mut evt) } {
|
||||
-1 => Err(Error::last_os_error()),
|
||||
_ => Ok(()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn delete(&self, fd: RawFd) -> Result<()> {
|
||||
match unsafe { libc::epoll_ctl(self.fd, EPOLL_CTL_DEL, fd, ptr::null_mut()) } {
|
||||
-1 => Err(Error::last_os_error()),
|
||||
_ => Ok(()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn wait_timeout(&mut self,timeout: Duration) -> Result<PollEvents> {
|
||||
let ms = timeout.as_millis() as u32;
|
||||
self.wait_ms(ms as c_int)
|
||||
}
|
||||
|
||||
pub fn wait(&mut self) -> Result<PollEvents> {
|
||||
self.wait_ms(-1)
|
||||
}
|
||||
|
||||
fn wait_ms(&mut self, timeout: c_int) -> Result<PollEvents> {
|
||||
let mut events = PollEvents::new();
|
||||
let nevents = events.len() as c_int;
|
||||
loop {
|
||||
let ret = unsafe {
|
||||
libc::epoll_wait(self.fd, events.events_ptr(), nevents, timeout)
|
||||
};
|
||||
|
||||
if ret == -1 && Error::last_os_error() != Error::from_raw_os_error(EINTR) {
|
||||
return Err(Error::last_os_error());
|
||||
} else if ret as usize > events.len() {
|
||||
return Err(Error::from_raw_os_error(EINVAL));
|
||||
} else if ret != -1 {
|
||||
events.count = ret as usize;
|
||||
return Ok(events)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRawFd for EPoll {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.fd
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for EPoll {
|
||||
fn drop(&mut self) {
|
||||
unsafe { libc::close(self.fd); }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct PollEvents {
|
||||
count: usize,
|
||||
events: [epoll_event; MAX_EVENTS],
|
||||
}
|
||||
|
||||
impl PollEvents {
|
||||
fn new() -> Self {
|
||||
PollEvents {
|
||||
count: 0,
|
||||
events: [epoll_event{ events: 0, u64: 0 }; MAX_EVENTS],
|
||||
}
|
||||
}
|
||||
pub fn iter(&self) -> PollEventIter {
|
||||
PollEventIter::new(&self.events[..self.count])
|
||||
}
|
||||
|
||||
fn events_ptr(&mut self) -> *mut epoll_event {
|
||||
self.events.as_mut_ptr()
|
||||
}
|
||||
|
||||
fn len(&self) -> usize {
|
||||
self.events.len()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PollEventIter<'a> {
|
||||
idx: usize,
|
||||
events: &'a [epoll_event],
|
||||
}
|
||||
|
||||
impl <'a> PollEventIter<'a> {
|
||||
fn new(events: &'a [epoll_event]) -> Self {
|
||||
PollEventIter {
|
||||
idx: 0,
|
||||
events,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl <'a> Iterator for PollEventIter<'a> {
|
||||
type Item = Event;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.idx == self.events.len() {
|
||||
None
|
||||
} else {
|
||||
let ev = self.events[self.idx].clone();
|
||||
self.idx += 1;
|
||||
Some(Event(ev))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user