1//! Tiny poll ffi
2//!
3//! A tiny wrapper around libc's poll system call.
4
5use libc;
6use super::error::*;
7use std::io;
8pub use libc::pollfd;
9
10
11bitflags! {
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
24pub 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
37impl 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.
44pub fn poll(fds: &mut[pollfd], timeout: i32) -> Result<usize> {
45 let r: i32 = unsafe { libc::poll(fds: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.
52pub 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<(&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