]> git.proxmox.com Git - pve-lxc-syscalld.git/blame - src/io/polled_fd.rs
switch back to tokio now that it's stable and packaged
[pve-lxc-syscalld.git] / src / io / polled_fd.rs
CommitLineData
5bd0c562
WB
1use std::io;
2use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
3use std::task::{Context, Poll};
4
5use mio::event::Evented;
6use mio::unix::EventedFd as MioEventedFd;
7use mio::Poll as MioPoll;
8use mio::{PollOpt, Ready, Token};
9use tokio::io::PollEvented;
10
11use crate::tools::Fd;
12
13#[repr(transparent)]
14pub struct EventedFd {
15 fd: Fd,
16}
17
18impl EventedFd {
19 #[inline]
20 pub fn new(fd: Fd) -> Self {
21 Self { fd }
22 }
23}
24
25impl AsRawFd for EventedFd {
26 #[inline]
27 fn as_raw_fd(&self) -> RawFd {
28 self.fd.as_raw_fd()
29 }
30}
31
32impl FromRawFd for EventedFd {
33 #[inline]
34 unsafe fn from_raw_fd(fd: RawFd) -> Self {
35 Self::new(Fd::from_raw_fd(fd))
36 }
37}
38
39impl IntoRawFd for EventedFd {
40 #[inline]
41 fn into_raw_fd(self) -> RawFd {
42 self.fd.into_raw_fd()
43 }
44}
45
46impl Evented for EventedFd {
47 fn register(
48 &self,
49 poll: &MioPoll,
50 token: Token,
51 interest: Ready,
52 opts: PollOpt,
53 ) -> io::Result<()> {
54 MioEventedFd(self.fd.as_ref()).register(poll, token, interest, opts)
55 }
56
57 fn reregister(
58 &self,
59 poll: &MioPoll,
60 token: Token,
61 interest: Ready,
62 opts: PollOpt,
63 ) -> io::Result<()> {
64 MioEventedFd(self.fd.as_ref()).reregister(poll, token, interest, opts)
65 }
66
67 fn deregister(&self, poll: &MioPoll) -> io::Result<()> {
68 MioEventedFd(self.fd.as_ref()).deregister(poll)
69 }
70}
71
72#[repr(transparent)]
73pub struct PolledFd {
74 fd: PollEvented<EventedFd>,
75}
76
77impl PolledFd {
78 pub fn new(fd: Fd) -> tokio::io::Result<Self> {
79 Ok(Self {
80 fd: PollEvented::new(EventedFd::new(fd))?,
81 })
82 }
83
84 pub fn wrap_read<T>(
85 &self,
86 cx: &mut Context,
87 func: impl FnOnce() -> io::Result<T>,
88 ) -> Poll<io::Result<T>> {
89 ready!(self.fd.poll_read_ready(cx, mio::Ready::readable()))?;
90 match func() {
91 Ok(out) => Poll::Ready(Ok(out)),
92 Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => {
93 self.fd.clear_read_ready(cx, mio::Ready::readable())?;
94 Poll::Pending
95 }
96 Err(err) => Poll::Ready(Err(err)),
97 }
98 }
99
100 pub fn wrap_write<T>(
101 &self,
102 cx: &mut Context,
103 func: impl FnOnce() -> io::Result<T>,
104 ) -> Poll<io::Result<T>> {
105 ready!(self.fd.poll_write_ready(cx))?;
106 match func() {
107 Ok(out) => Poll::Ready(Ok(out)),
108 Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => {
109 self.fd.clear_write_ready(cx)?;
110 Poll::Pending
111 }
112 Err(err) => Poll::Ready(Err(err)),
113 }
114 }
115}
116
117impl AsRawFd for PolledFd {
118 #[inline]
119 fn as_raw_fd(&self) -> RawFd {
120 self.fd.get_ref().as_raw_fd()
121 }
122}
123
124impl IntoRawFd for PolledFd {
125 #[inline]
126 fn into_raw_fd(self) -> RawFd {
127 // for the kind of resource we're managing it should always be possible to extract it from
128 // its driver
129 self.fd
130 .into_inner()
131 .expect("failed to remove polled file descriptor from reactor")
132 .into_raw_fd()
133 }
134}