use std::mem; use std::sync::{Mutex, RwLock}; use std::os::unix::io::{RawFd, AsRawFd}; use std::os::raw::{c_void, c_uint};
/// A file descriptor to watch for incoming events (for async I/O). /// /// # Example /// ``` /// extern crate libc; /// extern crate dbus; /// fn main() { /// use dbus::{Connection, BusType, WatchEvent}; /// let c = Connection::get_private(BusType::Session).unwrap(); /// /// // Get a list of fds to poll for /// let mut fds: Vec<_> = c.watch_fds().iter().map(|w| w.to_pollfd()).collect(); /// /// // Poll them with a 1 s timeout /// let r = unsafe { libc::poll(fds.as_mut_ptr(), fds.len() as libc::c_ulong, 1000) }; /// assert!(r >= 0); /// /// // And handle incoming events /// for pfd in fds.iter().filter(|pfd| pfd.revents != 0) { /// for item in c.watch_handle(pfd.fd, WatchEvent::from_revents(pfd.revents)) { /// // Handle item /// println!("Received ConnectionItem: {:?}", item); /// } /// } /// } /// ```
#[repr(C)] #[derive(Debug, PartialEq, Copy, Clone)] /// The enum is here for backwards compatibility mostly. /// /// It should really be bitflags instead. pubenum WatchEvent { /// The fd is readable
Readable = ffi::DBUS_WATCH_READABLE as isize, /// The fd is writable
Writable = ffi::DBUS_WATCH_WRITABLE as isize, /// An error occured on the fd
Error = ffi::DBUS_WATCH_ERROR as isize, /// The fd received a hangup.
Hangup = ffi::DBUS_WATCH_HANGUP as isize,
}
impl WatchEvent { /// After running poll, this transforms the revents into a parameter you can send into `Connection::watch_handle` pubfn from_revents(revents: libc::c_short) -> c_uint { 0 + if (revents & libc::POLLIN) != 0 { WatchEvent::Readable as c_uint } else { 0 } + if (revents & libc::POLLOUT) != 0 { WatchEvent::Writable as c_uint } else { 0 } + if (revents & libc::POLLERR) != 0 { WatchEvent::Error as c_uint } else { 0 } + if (revents & libc::POLLHUP) != 0 { WatchEvent::Hangup as c_uint } else { 0 }
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] /// A file descriptor, and an indication whether it should be read from, written to, or both. pubstruct Watch {
fd: RawFd,
read: bool,
write: bool,
}
impl Watch { /// Get the RawFd this Watch is for pubfn fd(&self) -> RawFd { self.fd } /// Add POLLIN to events to listen for pubfn readable(&self) -> bool { self.read } /// Add POLLOUT to events to listen for pubfn writable(&self) -> bool { self.write } /// Returns the current watch as a libc::pollfd, to use with libc::poll pubfn to_pollfd(&self) -> libc::pollfd {
libc::pollfd { fd: self.fd, revents: 0, events: libc::POLLERR + libc::POLLHUP + ifself.readable() { libc::POLLIN } else { 0 } + ifself.writable() { libc::POLLOUT } else { 0 },
}
} /* pub(crate)unsafefnfrom_raw(watch:*mutffi::DBusWatch)->Self{ letmutw=Watch{fd:ffi::dbus_watch_get_unix_fd(watch),read:false,write:false}; letenabled=ffi::dbus_watch_get_enabled(watch)!=0; ifenabled{ letflags=ffi::dbus_watch_get_flags(watch); w.read=(flags&WatchEvent::Readableasc_uint)!=0; w.write=(flags&WatchEvent::Writableasc_uint)!=0; } w }
*/
}
/// Note - internal struct, not to be used outside API. Moving it outside its box will break things. pubstruct WatchList {
watches: RwLock<Vec<*mut ffi::DBusWatch>>,
enabled_fds: Mutex<Vec<Watch>>,
on_update: Mutex<Box<Fn(Watch) + Send>>,
}
#[cfg(test)] mod test { use libc; usesuper::super::{Connection, Message, BusType, WatchEvent, ConnectionItem, MessageType};
#[test] fnasync() { let c = Connection::get_private(BusType::Session).unwrap();
c.register_object_path("/test").unwrap(); let m = Message::new_method_call(&c.unique_name(), "/test", "com.example.asynctest", "AsyncTest").unwrap(); let serial = c.send(m).unwrap();
println!("Async: sent serial {}", serial);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.