use std::mem;
use nix::fcntl::Fd;
use nix::sys::epoll::*;
use nix::unistd::close;
use error::{MioResult, MioError};
use os::IoDesc;
use poll::{IoEvent, IoEventKind, IOREADABLE, IOWRITABLE, IOERROR, IOHINTED, IOHUPHINT};
pub struct Selector {
epfd: Fd
}
impl Selector {
pub fn new() -> MioResult<Selector> {
let epfd = try!(epoll_create().map_err(MioError::from_sys_error));
Ok(Selector { epfd: epfd })
}
pub fn select(&mut self, evts: &mut Events, timeout_ms: uint) -> MioResult<()> {
let cnt = try!(epoll_wait(self.epfd, evts.events.as_mut_slice(), timeout_ms)
.map_err(MioError::from_sys_error));
evts.len = cnt;
Ok(())
}
pub fn register(&mut self, io: &IoDesc, token: uint) -> MioResult<()> {
let interests = EPOLLIN | EPOLLOUT | EPOLLERR | EPOLLRDHUP;
let info = EpollEvent {
events: interests | EPOLLET,
data: token as u64
};
epoll_ctl(self.epfd, EpollCtlAdd, io.fd, &info)
.map_err(MioError::from_sys_error)
}
}
impl Drop for Selector {
fn drop(&mut self) {
let _ = close(self.epfd);
}
}
pub struct Events {
len: uint,
events: [EpollEvent, ..1024]
}
impl Events {
pub fn new() -> Events {
Events {
len: 0,
events: unsafe { mem::uninitialized() }
}
}
#[inline]
pub fn len(&self) -> uint {
self.len
}
#[inline]
pub fn get(&self, idx: uint) -> IoEvent {
if idx >= self.len {
panic!("invalid index");
}
let epoll = self.events[idx].events;
let mut kind = IoEventKind::empty() | IOHINTED;
if epoll.contains(EPOLLIN) {
kind = kind | IOREADABLE;
}
if epoll.contains(EPOLLOUT) {
kind = kind | IOWRITABLE;
}
if epoll.contains(EPOLLERR) {
kind = kind | IOERROR;
}
if epoll.contains(EPOLLRDHUP) {
kind = kind | IOHUPHINT;
}
let token = self.events[idx].data;
IoEvent::new(kind, token as uint)
}
}