1 //! Tiny poll ffi
2 //!
3 //! A tiny wrapper around libc's poll system call.
4 
5 use libc;
6 use super::error::*;
7 use std::io;
8 use libc::pollfd;
9 
10 
11 bitflags! {
12     pub struct PollFlags: ::libc::c_short {
13         const POLLIN  = ::libc::POLLIN;
14         const POLLPRI = ::libc::POLLPRI;
15         const POLLOUT = ::libc::POLLOUT;
16         const POLLERR = ::libc::POLLERR;
17         const POLLHUP = ::libc::POLLHUP;
18         const POLLNVAL = ::libc::POLLNVAL;
19     }
20 }
21 
22 pub trait PollDescriptors {
count(&self) -> usize23     fn count(&self) -> usize;
fill(&self, &mut [pollfd]) -> Result<usize>24     fn fill(&self, &mut [pollfd]) -> Result<usize>;
revents(&self, &[pollfd]) -> Result<PollFlags>25     fn revents(&self, &[pollfd]) -> Result<PollFlags>;
26 
27     /// Wrapper around count and fill - returns an array of pollfds
get(&self) -> Result<Vec<pollfd>>28     fn get(&self) -> Result<Vec<pollfd>> {
29         let mut v = vec![pollfd { fd: 0, events: 0, revents: 0 }; self.count()];
30         if try!(self.fill(&mut v)) != v.len() { Err(Error::unsupported("did not fill the poll descriptors array")) }
31         else { Ok(v) }
32     }
33 }
34 
35 impl PollDescriptors for pollfd {
count(&self) -> usize36     fn count(&self) -> usize { 1 }
fill(&self, a: &mut [pollfd]) -> Result<usize>37     fn fill(&self, a: &mut [pollfd]) -> Result<usize> { a[0] = self.clone(); Ok(1) }
revents(&self, a: &[pollfd]) -> Result<PollFlags>38     fn revents(&self, a: &[pollfd]) -> Result<PollFlags> { Ok(PollFlags::from_bits_truncate(a[0].revents)) }
39 }
40 
41 /// Wrapper around the libc poll call.
poll(fds: &mut[pollfd], timeout: i32) -> Result<usize>42 pub fn poll(fds: &mut[pollfd], timeout: i32) -> Result<usize> {
43     let r = unsafe { libc::poll(fds.as_mut_ptr(), fds.len() as libc::c_ulong, timeout as libc::c_int) };
44     if r >= 0 { Ok(r as usize) } else {
45          from_code("poll", -io::Error::last_os_error().raw_os_error().unwrap()).map(|_| unreachable!())
46     }
47 }
48 
49 /// Builds a pollfd array, polls it, and returns the poll descriptors which have non-zero revents.
poll_all<'a>(desc: &[&'a PollDescriptors], timeout: i32) -> Result<Vec<(&'a PollDescriptors, PollFlags)>>50 pub fn poll_all<'a>(desc: &[&'a PollDescriptors], timeout: i32) -> Result<Vec<(&'a PollDescriptors, PollFlags)>> {
51 
52     let mut pollfds: Vec<pollfd> = vec!();
53     let mut indices = vec!();
54     for v2 in desc.iter().map(|q| q.get()) {
55         let v = try!(v2);
56         indices.push(pollfds.len() .. pollfds.len()+v.len());
57         pollfds.extend(v);
58     };
59 
60     try!(poll(&mut pollfds, timeout));
61 
62     let mut res = vec!();
63     for (i, r) in indices.into_iter().enumerate() {
64         let z = try!(desc[i].revents(&pollfds[r]));
65         if !z.is_empty() { res.push((desc[i], z)); }
66     }
67     Ok(res)
68 }
69