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: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<(&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 | |