| 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 | pub use libc::pollfd; |
| 9 | |
| 10 | |
| 11 | bitflags! { |
| 12 | #[repr (transparent)] |
| 13 | #[derive (Debug, Clone, Copy, PartialEq, Eq, Hash)] |
| 14 | pub struct Flags: ::libc::c_short { |
| 15 | const IN = ::libc::POLLIN; |
| 16 | const PRI = ::libc::POLLPRI; |
| 17 | const OUT = ::libc::POLLOUT; |
| 18 | const ERR = ::libc::POLLERR; |
| 19 | const HUP = ::libc::POLLHUP; |
| 20 | const NVAL = ::libc::POLLNVAL; |
| 21 | } |
| 22 | } |
| 23 | |
| 24 | pub trait Descriptors { |
| 25 | fn count(&self) -> usize; |
| 26 | fn fill(&self, _: &mut [pollfd]) -> Result<usize>; |
| 27 | fn revents(&self, _: &[pollfd]) -> Result<Flags>; |
| 28 | |
| 29 | /// Wrapper around count and fill - returns an array of pollfds |
| 30 | fn get(&self) -> Result<Vec<pollfd>> { |
| 31 | let mut v: Vec = vec![pollfd { fd: 0, events: 0, revents: 0 }; self.count()]; |
| 32 | if self.fill(&mut v)? != v.len() { Err(Error::unsupported(func:"did not fill the poll descriptors array" )) } |
| 33 | else { Ok(v) } |
| 34 | } |
| 35 | } |
| 36 | |
| 37 | impl Descriptors for pollfd { |
| 38 | fn count(&self) -> usize { 1 } |
| 39 | fn fill(&self, a: &mut [pollfd]) -> Result<usize> { a[0] = *self; Ok(1) } |
| 40 | fn revents(&self, a: &[pollfd]) -> Result<Flags> { Ok(Flags::from_bits_truncate(bits:a[0].revents)) } |
| 41 | } |
| 42 | |
| 43 | /// Wrapper around the libc poll call. |
| 44 | pub fn poll(fds: &mut[pollfd], timeout: i32) -> Result<usize> { |
| 45 | let r: i32 = unsafe { libc::poll(fds.as_mut_ptr(), nfds:fds.len() as libc::nfds_t, timeout as libc::c_int) }; |
| 46 | if r >= 0 { Ok(r as usize) } else { |
| 47 | from_code("poll" , -io::Error::last_os_error().raw_os_error().unwrap()).map(|_| unreachable!()) |
| 48 | } |
| 49 | } |
| 50 | |
| 51 | /// Builds a pollfd array, polls it, and returns the poll descriptors which have non-zero revents. |
| 52 | pub fn poll_all<'a>(desc: &[&'a dyn Descriptors], timeout: i32) -> Result<Vec<(&'a dyn Descriptors, Flags)>> { |
| 53 | |
| 54 | let mut pollfds: Vec<pollfd> = vec!(); |
| 55 | let mut indices: Vec> = vec!(); |
| 56 | for v2: Result, Error> in desc.iter().map(|q: &&dyn Descriptors| q.get()) { |
| 57 | let v: Vec = v2?; |
| 58 | indices.push(pollfds.len() .. pollfds.len()+v.len()); |
| 59 | pollfds.extend(iter:v); |
| 60 | }; |
| 61 | |
| 62 | poll(&mut pollfds, timeout)?; |
| 63 | |
| 64 | let mut res: Vec<(&'a dyn Descriptors, Flags)> = vec!(); |
| 65 | for (i: usize, r: Range) in indices.into_iter().enumerate() { |
| 66 | let z: Flags = desc[i].revents(&pollfds[r])?; |
| 67 | if !z.is_empty() { res.push((desc[i], z)); } |
| 68 | } |
| 69 | Ok(res) |
| 70 | } |
| 71 | |