diff options
| author | MaxVerevkin <maxxverrr@gmail.com> | 2023-09-06 20:51:24 +0300 |
|---|---|---|
| committer | MaxVerevkin <maxxverrr@gmail.com> | 2023-09-06 20:51:24 +0300 |
| commit | eefff9a9cc2ee6f17eab3431cc808d5a5e7d31fc (patch) | |
| tree | 53759118e4bf1762f512baaea6ee80cc8824513a /src/event_loop.rs | |
| parent | 96543db93cab410c15e4b4b8b3fc589d3c7066ee (diff) | |
| download | i3bar-mango-eefff9a9cc2ee6f17eab3431cc808d5a5e7d31fc.tar.gz | |
implement simple event loop abstraction
Diffstat (limited to 'src/event_loop.rs')
| -rw-r--r-- | src/event_loop.rs | 73 |
1 files changed, 73 insertions, 0 deletions
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<D> { + pollfds: Vec<libc::pollfd>, + cbs: HashMap<RawFd, Box<dyn FnMut(&mut D) -> Result<Action>>>, +} + +pub enum Action { + Keep, + Unregister, +} + +impl<D> EventLoop<D> { + pub fn new() -> Self { + Self { + pollfds: Vec::new(), + cbs: HashMap::new(), + } + } + + pub fn register_with_fd<F>(&mut self, fd: RawFd, cb: F) + where + F: FnMut(&mut D) -> Result<Action> + '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(()) + } +} |
