From eefff9a9cc2ee6f17eab3431cc808d5a5e7d31fc Mon Sep 17 00:00:00 2001 From: MaxVerevkin Date: Wed, 6 Sep 2023 20:51:24 +0300 Subject: implement simple event loop abstraction --- src/event_loop.rs | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 src/event_loop.rs (limited to 'src/event_loop.rs') diff --git a/src/event_loop.rs b/src/event_loop.rs new file mode 100644 index 0000000..2300513 --- /dev/null +++ b/src/event_loop.rs @@ -0,0 +1,73 @@ +use std::collections::HashMap; +use std::io; +use std::os::fd::RawFd; + +use anyhow::Result; + +pub struct EventLoop { + pollfds: Vec, + cbs: HashMap Result>>, +} + +pub enum Action { + Keep, + Unregister, +} + +impl EventLoop { + pub fn new() -> Self { + Self { + pollfds: Vec::new(), + cbs: HashMap::new(), + } + } + + pub fn register_with_fd(&mut self, fd: RawFd, cb: F) + where + F: FnMut(&mut D) -> Result + 'static, + { + self.cbs.insert(fd, Box::new(cb)); + } + + pub fn run(&mut self, state: &mut D) -> Result<()> { + if self.cbs.is_empty() { + return Ok(()); + } + + self.pollfds.clear(); + for &fd in self.cbs.keys() { + self.pollfds.push(libc::pollfd { + fd, + events: libc::POLLIN, + revents: 0, + }); + } + + loop { + let result = + unsafe { libc::poll(self.pollfds.as_mut_ptr(), self.pollfds.len() as _, -1) }; + if result == -1 { + let err = io::Error::last_os_error(); + if err.kind() == io::ErrorKind::Interrupted { + continue; + } + return Err(err.into()); + } + break; + } + + for fd in &self.pollfds { + if fd.revents != 0 { + let mut cb = self.cbs.remove(&fd.fd).unwrap(); + match cb(state)? { + Action::Keep => { + self.cbs.insert(fd.fd, cb); + } + Action::Unregister => (), + } + } + } + + Ok(()) + } +} -- cgit v1.3.1