tiny_std/linux/
epoll.rs
1use rusl::platform::EpollOp;
2pub use rusl::platform::{EpollEvent, EpollEventMask};
3
4use crate::error::{Error, Result};
5use crate::unix::fd::{OwnedFd, RawFd};
6
7pub struct EpollDriver {
8 epoll_fd: OwnedFd,
9}
10
11#[derive(Debug, Copy, Clone)]
12pub enum EpollTimeout {
13 WaitForever,
14 WaitMillis(u32),
15 NoWait,
16}
17
18impl EpollDriver {
19 #[inline]
23 pub fn create(cloexec: bool) -> Result<Self> {
24 let fd = rusl::select::epoll_create(cloexec)?;
25 Ok(Self {
26 epoll_fd: OwnedFd(fd),
27 })
28 }
29
30 #[inline]
36 pub fn register(&self, fd: RawFd, identifier: u64, mask: EpollEventMask) -> Result<()> {
37 rusl::select::epoll_ctl(
38 self.epoll_fd.0,
39 EpollOp::Add,
40 fd,
41 &EpollEvent::new(identifier, mask),
42 )?;
43 Ok(())
44 }
45
46 #[inline]
50 pub fn unregister(&self, fd: RawFd) -> Result<()> {
51 rusl::select::epoll_del(self.epoll_fd.0, fd)?;
52 Ok(())
53 }
54
55 #[inline]
59 pub fn modify(&self, fd: RawFd, identifier: u64, mask: EpollEventMask) -> Result<()> {
60 rusl::select::epoll_ctl(
61 self.epoll_fd.0,
62 EpollOp::Mod,
63 fd,
64 &EpollEvent::new(identifier, mask),
65 )?;
66 Ok(())
67 }
68
69 #[inline]
74 #[expect(clippy::cast_possible_wrap)]
75 pub fn wait(&self, event_buf: &mut [EpollEvent], timeout: EpollTimeout) -> Result<usize> {
76 let num_ready = match timeout {
77 EpollTimeout::WaitForever => rusl::select::epoll_wait(self.epoll_fd.0, event_buf, -1)?,
78 EpollTimeout::WaitMillis(time) => {
79 if time > i32::MAX as u32 {
80 return Err(Error::Uncategorized(
81 "Epoll wait with a timeout bigger than i32::MAX",
82 ));
83 }
84 rusl::select::epoll_wait(self.epoll_fd.0, event_buf, time as i32)?
85 }
86 EpollTimeout::NoWait => rusl::select::epoll_wait(self.epoll_fd.0, event_buf, 0)?,
87 };
88 Ok(num_ready)
89 }
90}
91
92#[cfg(test)]
93mod tests {
94 use super::*;
95 use rusl::platform::STDOUT;
96
97 #[test]
98 fn test_epoll_driver() {
99 let drive = EpollDriver::create(true).unwrap();
100 drive.register(STDOUT, 1, EpollEventMask::EPOLLOUT).unwrap();
101 println!("Dummy out");
102 let mut buf = [EpollEvent::new(0, EpollEventMask::empty())];
103 drive
104 .wait(&mut buf, EpollTimeout::WaitMillis(1_000))
105 .unwrap();
106 assert_eq!(1, buf[0].get_data());
107 assert!(
108 buf[0].get_events().contains(EpollEventMask::EPOLLOUT),
109 "Expected EPOLLOUT, got {:?}",
110 buf[0].get_events()
111 );
112 }
113}