|
24 | 24 | //! Poll engine provided by the [`popol`] crate.
|
25 | 25 |
|
26 | 26 | use std::collections::VecDeque;
|
27 |
| -use std::io; |
28 |
| -use std::io::{Error, Write}; |
| 27 | +use std::io::{self, Error}; |
29 | 28 | use std::os::unix::io::{AsRawFd, RawFd};
|
30 |
| -use std::os::unix::net::UnixStream; |
31 | 29 | use std::sync::Arc;
|
32 | 30 | use std::time::Duration;
|
33 | 31 |
|
@@ -64,7 +62,7 @@ impl Poller {
|
64 | 62 | }
|
65 | 63 |
|
66 | 64 | impl Poll for Poller {
|
67 |
| - type Waker = UnixStream; |
| 65 | + type Waker = PopolWaker; |
68 | 66 |
|
69 | 67 | fn register(&mut self, fd: &impl AsRawFd, interest: IoType) {
|
70 | 68 | #[cfg(feature = "log")]
|
@@ -162,68 +160,43 @@ impl From<IoType> for popol::Interest {
|
162 | 160 | }
|
163 | 161 | }
|
164 | 162 |
|
165 |
| -impl Waker for UnixStream { |
166 |
| - type Send = Arc<UnixStream>; |
167 |
| - type Recv = UnixStream; |
| 163 | +/// Wrapper type around the waker provided by `popol` crate. |
| 164 | +#[derive(Clone)] |
| 165 | +pub struct PopolWaker(Arc<popol::Waker>); |
| 166 | + |
| 167 | +impl Waker for PopolWaker { |
| 168 | + type Send = Self; |
| 169 | + type Recv = Self; |
168 | 170 |
|
169 | 171 | fn pair() -> Result<(Self::Send, Self::Recv), Error> {
|
170 |
| - let (waker_writer, waker_reader) = UnixStream::pair()?; |
171 |
| - waker_reader.set_nonblocking(true)?; |
172 |
| - waker_writer.set_nonblocking(true)?; |
173 |
| - Ok((Arc::new(waker_writer), waker_reader)) |
| 172 | + let waker = Arc::new(popol::Waker::new()?); |
| 173 | + Ok((PopolWaker(waker.clone()), PopolWaker(waker))) |
174 | 174 | }
|
175 | 175 | }
|
176 | 176 |
|
177 |
| -impl WakerRecv for UnixStream { |
178 |
| - fn reset(&self) { reset_fd(self).expect("waker failure"); } |
| 177 | +impl io::Read for PopolWaker { |
| 178 | + fn read(&mut self, _buf: &mut [u8]) -> io::Result<usize> { |
| 179 | + self.reset(); |
| 180 | + // Waker reads only when there is something which was sent. |
| 181 | + // That's why we just return here. |
| 182 | + Ok(0) |
| 183 | + } |
179 | 184 | }
|
180 | 185 |
|
181 |
| -impl WakerSend for Arc<UnixStream> { |
182 |
| - fn wake(&self) -> io::Result<()> { |
183 |
| - loop { |
184 |
| - let mut waker = self.as_ref(); |
185 |
| - match (&mut waker).write_all(&[0x1]) { |
186 |
| - Ok(_) => return Ok(()), |
187 |
| - Err(e) if e.kind() == io::ErrorKind::WouldBlock => { |
188 |
| - #[cfg(feature = "log")] |
189 |
| - log::error!(target: "reactor-controller", "Waker write queue got overfilled, resetting and repeating..."); |
190 |
| - reset_fd(&self.as_raw_fd())?; |
191 |
| - } |
192 |
| - Err(e) if e.kind() == io::ErrorKind::Interrupted => { |
193 |
| - #[cfg(feature = "log")] |
194 |
| - log::error!(target: "reactor-controller", "Waker failure, repeating..."); |
195 |
| - } |
196 |
| - Err(e) => { |
197 |
| - #[cfg(feature = "log")] |
198 |
| - log::error!(target: "reactor-controller", "Waker error: {e}"); |
199 |
| - |
200 |
| - return Err(e); |
201 |
| - } |
202 |
| - } |
203 |
| - } |
204 |
| - } |
| 186 | +impl AsRawFd for PopolWaker { |
| 187 | + fn as_raw_fd(&self) -> RawFd { self.0.as_ref().as_raw_fd() } |
205 | 188 | }
|
206 | 189 |
|
207 |
| -fn reset_fd(fd: &impl AsRawFd) -> io::Result<()> { |
208 |
| - let mut buf = [0u8; 4096]; |
209 |
| - |
210 |
| - loop { |
211 |
| - // We use a low-level "read" here because the alternative is to create a `UnixStream` |
212 |
| - // from the `RawFd`, which has "drop" semantics which we want to avoid. |
213 |
| - match unsafe { |
214 |
| - libc::read(fd.as_raw_fd(), buf.as_mut_ptr() as *mut libc::c_void, buf.len()) |
215 |
| - } { |
216 |
| - -1 => match io::Error::last_os_error() { |
217 |
| - e if e.kind() == io::ErrorKind::WouldBlock => return Ok(()), |
218 |
| - e => { |
219 |
| - #[cfg(feature = "log")] |
220 |
| - log::error!(target: "reactor-controller", "Unable to reset waker queue: {e}"); |
221 |
| - |
222 |
| - return Err(e); |
223 |
| - } |
224 |
| - }, |
225 |
| - 0 => return Ok(()), |
226 |
| - _ => continue, |
| 190 | +impl WakerRecv for PopolWaker { |
| 191 | + fn reset(&self) { |
| 192 | + if let Err(e) = popol::Waker::reset(self.0.as_ref()) { |
| 193 | + #[cfg(feature = "log")] |
| 194 | + log::error!(target: "reactor-controller", "Unable to reset waker queue: {e}"); |
| 195 | + panic!("unable to reset waker queue. Details: {e}"); |
227 | 196 | }
|
228 | 197 | }
|
229 | 198 | }
|
| 199 | + |
| 200 | +impl WakerSend for PopolWaker { |
| 201 | + fn wake(&self) -> io::Result<()> { self.0.wake() } |
| 202 | +} |
0 commit comments