summaryrefslogtreecommitdiffstats
path: root/third_party/rust/alsa/src/poll.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/alsa/src/poll.rs')
-rw-r--r--third_party/rust/alsa/src/poll.rs68
1 files changed, 68 insertions, 0 deletions
diff --git a/third_party/rust/alsa/src/poll.rs b/third_party/rust/alsa/src/poll.rs
new file mode 100644
index 0000000000..3e9191164e
--- /dev/null
+++ b/third_party/rust/alsa/src/poll.rs
@@ -0,0 +1,68 @@
+//! Tiny poll ffi
+//!
+//! A tiny wrapper around libc's poll system call.
+
+use libc;
+use super::error::*;
+use std::io;
+pub use libc::pollfd;
+
+
+bitflags! {
+ pub struct Flags: ::libc::c_short {
+ const IN = ::libc::POLLIN;
+ const PRI = ::libc::POLLPRI;
+ const OUT = ::libc::POLLOUT;
+ const ERR = ::libc::POLLERR;
+ const HUP = ::libc::POLLHUP;
+ const NVAL = ::libc::POLLNVAL;
+ }
+}
+
+pub trait Descriptors {
+ fn count(&self) -> usize;
+ fn fill(&self, _: &mut [pollfd]) -> Result<usize>;
+ fn revents(&self, _: &[pollfd]) -> Result<Flags>;
+
+ /// Wrapper around count and fill - returns an array of pollfds
+ fn get(&self) -> Result<Vec<pollfd>> {
+ let mut v = vec![pollfd { fd: 0, events: 0, revents: 0 }; self.count()];
+ if self.fill(&mut v)? != v.len() { Err(Error::unsupported("did not fill the poll descriptors array")) }
+ else { Ok(v) }
+ }
+}
+
+impl Descriptors for pollfd {
+ fn count(&self) -> usize { 1 }
+ fn fill(&self, a: &mut [pollfd]) -> Result<usize> { a[0] = *self; Ok(1) }
+ fn revents(&self, a: &[pollfd]) -> Result<Flags> { Ok(Flags::from_bits_truncate(a[0].revents)) }
+}
+
+/// Wrapper around the libc poll call.
+pub fn poll(fds: &mut[pollfd], timeout: i32) -> Result<usize> {
+ let r = unsafe { libc::poll(fds.as_mut_ptr(), fds.len() as libc::nfds_t, timeout as libc::c_int) };
+ if r >= 0 { Ok(r as usize) } else {
+ from_code("poll", -io::Error::last_os_error().raw_os_error().unwrap()).map(|_| unreachable!())
+ }
+}
+
+/// Builds a pollfd array, polls it, and returns the poll descriptors which have non-zero revents.
+pub fn poll_all<'a>(desc: &[&'a dyn Descriptors], timeout: i32) -> Result<Vec<(&'a dyn Descriptors, Flags)>> {
+
+ let mut pollfds: Vec<pollfd> = vec!();
+ let mut indices = vec!();
+ for v2 in desc.iter().map(|q| q.get()) {
+ let v = v2?;
+ indices.push(pollfds.len() .. pollfds.len()+v.len());
+ pollfds.extend(v);
+ };
+
+ poll(&mut pollfds, timeout)?;
+
+ let mut res = vec!();
+ for (i, r) in indices.into_iter().enumerate() {
+ let z = desc[i].revents(&pollfds[r])?;
+ if !z.is_empty() { res.push((desc[i], z)); }
+ }
+ Ok(res)
+}