Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bufs #3

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
Cargo.lock
target
libs
.*.swp
31 changes: 31 additions & 0 deletions src/event.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/* Event Traits for converting, building and analyzing events in the selector.
* To be implemented by the selector for each os/platform */

bitflags!(
#[deriving(Show)]
flags IoEventKind: uint {
static IoReadable = 0x001,
static IoWritable = 0x002,
static IoError = 0x004,
static IoHangup = 0x008
}
)


pub trait IoEvent {

fn is_readable(&self) -> bool;

fn is_writable(&self) -> bool;

fn is_hangup(&self) -> bool;

fn is_error(&self) -> bool;

fn to_ioevent(&self) -> IoEventKind;
}

// this should also be part of the trait but until
// we get associated types, I can't think of a good way
//fn from_ioevent(ioevents: IoEventKind) -> OSMaskType;

5 changes: 3 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,15 @@ extern crate log;

pub use buf::{Buf, MutBuf};
pub use error::{MioResult, MioError};
pub use handler::Handler;
pub use token::Token;
pub use io::{IoReader, IoWriter, IoAcceptor, Socket, TcpSocket, TcpAcceptor, UnixSocket, SockAddr};
pub use reactor::Reactor;
pub use slab::Slab;

pub mod buf;
mod error;
mod handler;
mod token;
mod event;
mod io;
mod os;
mod reactor;
Expand Down
106 changes: 68 additions & 38 deletions src/os/epoll.rs
Original file line number Diff line number Diff line change
@@ -1,35 +1,34 @@
use std::mem;
use nix::fcntl::Fd;
use nix::sys::epoll::*;
pub use nix::sys::epoll::*;
use nix::unistd::close;
use error::{MioResult, MioError};
use os::IoDesc;
use reactor::{IoEvent, IoEventKind, IoReadable, IoWritable, IoError};
use super::posix::{IoDesc};
use event::*;

pub struct Selector {
epfd: Fd
epfd: Fd,
pub event_context: [EpollEvent, ..1024]
}

impl Selector {
pub fn new() -> MioResult<Selector> {
let epfd = try!(epoll_create().map_err(MioError::from_sys_error));

Ok(Selector { epfd: epfd })
Ok(Selector { epfd: epfd, event_context: [EpollEvent {events: EpollEventKind::empty(), data: 0}, ..1024] })
}

/// Wait for events from the OS
pub fn select(&mut self, evts: &mut Events, timeout_ms: uint) -> MioResult<()> {
pub fn select(&mut self, timeout_ms: uint) -> MioResult<uint> {
// Wait for epoll events for at most timeout_ms milliseconds
let cnt = try!(epoll_wait(self.epfd, evts.events.as_mut_slice(), timeout_ms)
let cnt = try!(epoll_wait(self.epfd, self.event_context, timeout_ms)
.map_err(MioError::from_sys_error));

evts.len = cnt;
Ok(())
Ok(cnt)
}

/// Register event interests for the given IO handle with the OS
pub fn register(&mut self, io: IoDesc, token: u64) -> MioResult<()> {
let interests = EPOLLIN | EPOLLOUT | EPOLLERR;
pub fn register(&mut self, io: IoDesc, token: u64, events: IoEventKind) -> MioResult<()> {
let interests = from_ioevent(events);

let info = EpollEvent {
events: interests | EPOLLET,
Expand All @@ -39,6 +38,20 @@ impl Selector {
epoll_ctl(self.epfd, EpollCtlAdd, io.fd, &info)
.map_err(MioError::from_sys_error)
}

/// Register event interests for the given IO handle with the OS
pub fn unregister(&mut self, io: IoDesc, token: u64) -> MioResult<()> {
let interests = EpollEventKind::empty();

let info = EpollEvent {
events: interests | EPOLLET,
data: token
};

epoll_ctl(self.epfd, EpollCtlDel, io.fd, &info)
.map_err(MioError::from_sys_error)
}

}

impl Drop for Selector {
Expand All @@ -47,50 +60,67 @@ impl Drop for Selector {
}
}

pub struct Events {
len: uint,
events: [EpollEvent, ..1024]
}

impl Events {
pub fn new() -> Events {
Events {
len: 0,
events: unsafe { mem::uninitialized() }
}
impl IoEvent for EpollEvent {

fn is_readable(&self) -> bool {
self.events.contains(EPOLLIN)
}

#[inline]
pub fn len(&self) -> uint {
self.len
fn is_writable(&self) -> bool {
self.events.contains(EPOLLOUT)
}

#[inline]
pub fn get(&self, idx: uint) -> IoEvent {
if idx >= self.len {
fail!("invalid index");
}
fn is_hangup(&self) -> bool {
self.events.contains(EPOLLHUP) || self.events.contains(EPOLLRDHUP)
}

fn is_error(&self) -> bool {
self.events.contains(EPOLLERR)
}

let epoll = self.events[idx].events;
let mut kind = IoEventKind::empty();

debug!("epoll event = {}", epoll);
fn to_ioevent(&self) -> IoEventKind {

if epoll.contains(EPOLLIN) {
let mut kind = IoEventKind::empty();

if self.events.contains(EPOLLIN) {
kind = kind | IoReadable;
}

if epoll.contains(EPOLLOUT) {
if self.events.contains(EPOLLOUT) {
kind = kind | IoWritable;
}

// EPOLLHUP - Usually means a socket error happened
if epoll.contains(EPOLLERR) {
if self.events.contains(EPOLLERR) {
kind = kind | IoError;
}

let token = self.events[idx].data;
if self.events.contains(EPOLLHUP) || self.events.contains(EPOLLRDHUP) {
kind = kind | IoHangup;
}

IoEvent::new(kind, token)
kind
}
}

fn from_ioevent(ioevents: IoEventKind) -> EpollEventKind {
let mut mask = EpollEventKind::empty();

if ioevents.contains(IoReadable) {
mask = mask | EPOLLIN;
}
if ioevents.contains(IoWritable) {
mask = mask | EPOLLOUT;
}
if ioevents.contains(IoReadable) {
mask = mask | EPOLLHUP | EPOLLRDHUP;
}
// this one probably isnt' necessary, but for completeness...
if ioevents.contains(IoError) {
mask = mask | EPOLLERR;
}

mask
}
10 changes: 5 additions & 5 deletions src/os/mod.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
#[cfg(unix)]
pub use self::posix::*;

#[cfg(target_os = "linux")]
pub use self::epoll::{Events, Selector};
pub use self::epoll::{Selector};

#[cfg(target_os = "macos")]
#[cfg(target_os = "ios")]
pub use self::kqueue::{Events, Selector};

#[cfg(unix)]
pub use self::posix::*;

#[cfg(windows)]
pub use self::windows::*;

#[cfg(target_os = "linux")]
mod epoll;
pub mod epoll;

#[cfg(target_os = "macos")]
#[cfg(target_os = "ios")]
Expand Down
Loading