1use core::ffi::c_int;
5use std::io;
6use std::ptr;
7
8use crate::{Event, WAIT_CAPACITY, ffi};
9
10mod ep {
11 pub const EPOLL_CLOEXEC: super::c_int = 0x80000;
12 pub const EPOLL_CTL_ADD: super::c_int = 1;
13 pub const EPOLL_CTL_DEL: super::c_int = 2;
14 pub const EPOLL_CTL_MOD: super::c_int = 3;
15 pub const EPOLLIN: u32 = 0x001;
16 pub const EPOLLOUT: u32 = 0x004;
17 pub const EPOLLERR: u32 = 0x008;
18 pub const EPOLLHUP: u32 = 0x010;
19 pub const EPOLLRDHUP: u32 = 0x2000;
20}
21
22pub struct Poller {
23 epfd: c_int,
24}
25
26impl Poller {
27 pub fn new() -> io::Result<Self> {
28 let epfd = unsafe { ffi::epoll_create1(ep::EPOLL_CLOEXEC) };
29 if epfd < 0 {
30 return Err(io::Error::last_os_error());
31 }
32 Ok(Poller { epfd })
33 }
34
35 fn mask(read: bool, write: bool) -> u32 {
36 let mut m = ep::EPOLLRDHUP;
37 if read {
38 m |= ep::EPOLLIN;
39 }
40 if write {
41 m |= ep::EPOLLOUT;
42 }
43 m
44 }
45
46 fn ctl(&self, op: c_int, fd: i32, read: bool, write: bool) -> io::Result<()> {
47 let mut ev = ffi::EpollEvent {
48 events: Self::mask(read, write),
49 data: fd as u64,
50 };
51 let r = unsafe { ffi::epoll_ctl(self.epfd, op, fd, &mut ev) };
52 if r < 0 {
53 return Err(io::Error::last_os_error());
54 }
55 Ok(())
56 }
57
58 pub fn add(&self, fd: i32, read: bool, write: bool) -> io::Result<()> {
59 self.ctl(ep::EPOLL_CTL_ADD, fd, read, write)
60 }
61
62 pub fn modify(&self, fd: i32, read: bool, write: bool) -> io::Result<()> {
63 self.ctl(ep::EPOLL_CTL_MOD, fd, read, write)
64 }
65
66 pub fn delete(&self, fd: i32) -> io::Result<()> {
67 let r = unsafe { ffi::epoll_ctl(self.epfd, ep::EPOLL_CTL_DEL, fd, ptr::null_mut()) };
68 if r < 0 {
69 return Err(io::Error::last_os_error());
70 }
71 Ok(())
72 }
73
74 pub fn wait(&self, out: &mut Vec<Event>, timeout_ms: Option<i32>) -> io::Result<usize> {
75 out.clear();
76 let mut raw: Vec<ffi::EpollEvent> = Vec::with_capacity(WAIT_CAPACITY);
77 let n = unsafe {
78 ffi::epoll_wait(
79 self.epfd,
80 raw.as_mut_ptr(),
81 WAIT_CAPACITY as c_int,
82 timeout_ms.unwrap_or(-1),
83 )
84 };
85 if n < 0 {
86 let e = io::Error::last_os_error();
87 if e.kind() == io::ErrorKind::Interrupted {
88 return Ok(0);
89 }
90 return Err(e);
91 }
92 unsafe { raw.set_len(n as usize) };
93 for ev in &raw {
94 let flags = ev.events; let fd = ev.data as i32;
96 let hup = flags & (ep::EPOLLHUP | ep::EPOLLERR | ep::EPOLLRDHUP) != 0;
97 out.push(Event {
98 fd,
99 readable: flags & (ep::EPOLLIN | ep::EPOLLHUP | ep::EPOLLERR) != 0,
100 writable: flags & ep::EPOLLOUT != 0,
101 hup,
102 });
103 }
104 Ok(out.len())
105 }
106}
107
108impl Drop for Poller {
109 fn drop(&mut self) {
110 unsafe {
111 ffi::close(self.epfd);
112 }
113 }
114}