#[cfg(all(
not(mio_unsupported_force_poll_poll),
not(all(
not(mio_unsupported_force_waker_pipe),
any(
target_os = "freebsd",
target_os = "ios",
target_os = "macos",
target_os = "tvos",
target_os = "watchos",
)
)),
not(any(target_os = "solaris", target_os = "vita")),
))]
mod fdbased {
#[cfg(all(
not(mio_unsupported_force_waker_pipe),
any(target_os = "linux", target_os = "android"),
))]
use crate::sys::unix::waker::eventfd::WakerInternal;
#[cfg(any(
mio_unsupported_force_waker_pipe,
target_os = "aix",
target_os = "dragonfly",
target_os = "illumos",
target_os = "netbsd",
target_os = "openbsd",
target_os = "redox",
))]
use crate::sys::unix::waker::pipe::WakerInternal;
use crate::sys::Selector;
use crate::{Interest, Token};
use std::io;
use std::os::unix::io::AsRawFd;
#[derive(Debug)]
pub struct Waker {
waker: WakerInternal,
}
impl Waker {
pub fn new(selector: &Selector, token: Token) -> io::Result<Waker> {
let waker = WakerInternal::new()?;
selector.register(waker.as_raw_fd(), token, Interest::READABLE)?;
Ok(Waker { waker })
}
pub fn wake(&self) -> io::Result<()> {
self.waker.wake()
}
}
}
#[cfg(all(
not(mio_unsupported_force_poll_poll),
not(all(
not(mio_unsupported_force_waker_pipe),
any(
target_os = "freebsd",
target_os = "ios",
target_os = "macos",
target_os = "tvos",
target_os = "watchos",
)
)),
not(any(target_os = "solaris", target_os = "vita")),
))]
pub use self::fdbased::Waker;
#[cfg(all(
not(mio_unsupported_force_waker_pipe),
any(target_os = "linux", target_os = "android", target_os = "espidf")
))]
mod eventfd {
use std::fs::File;
use std::io::{self, Read, Write};
use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
#[derive(Debug)]
pub struct WakerInternal {
fd: File,
}
impl WakerInternal {
pub fn new() -> io::Result<WakerInternal> {
#[cfg(not(target_os = "espidf"))]
let flags = libc::EFD_CLOEXEC | libc::EFD_NONBLOCK;
#[cfg(target_os = "espidf")]
let flags = 0;
let fd = syscall!(eventfd(0, flags))?;
let file = unsafe { File::from_raw_fd(fd) };
Ok(WakerInternal { fd: file })
}
pub fn wake(&self) -> io::Result<()> {
let buf: [u8; 8] = 1u64.to_ne_bytes();
match (&self.fd).write(&buf) {
Ok(_) => Ok(()),
Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => {
self.reset()?;
self.wake()
}
Err(err) => Err(err),
}
}
#[cfg(mio_unsupported_force_poll_poll)]
pub fn ack_and_reset(&self) {
let _ = self.reset();
}
fn reset(&self) -> io::Result<()> {
let mut buf: [u8; 8] = 0u64.to_ne_bytes();
match (&self.fd).read(&mut buf) {
Ok(_) => Ok(()),
Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => Ok(()),
Err(err) => Err(err),
}
}
}
impl AsRawFd for WakerInternal {
fn as_raw_fd(&self) -> RawFd {
self.fd.as_raw_fd()
}
}
}
#[cfg(all(
mio_unsupported_force_poll_poll,
not(mio_unsupported_force_waker_pipe),
any(target_os = "linux", target_os = "android", target_os = "espidf")
))]
pub(crate) use self::eventfd::WakerInternal;
#[cfg(all(
not(mio_unsupported_force_waker_pipe),
any(
target_os = "freebsd",
target_os = "ios",
target_os = "macos",
target_os = "tvos",
target_os = "watchos",
)
))]
mod kqueue {
use crate::sys::Selector;
use crate::Token;
use std::io;
#[derive(Debug)]
pub struct Waker {
selector: Selector,
token: Token,
}
impl Waker {
pub fn new(selector: &Selector, token: Token) -> io::Result<Waker> {
let selector = selector.try_clone()?;
selector.setup_waker(token)?;
Ok(Waker { selector, token })
}
pub fn wake(&self) -> io::Result<()> {
self.selector.wake(self.token)
}
}
}
#[cfg(all(
not(mio_unsupported_force_waker_pipe),
any(
target_os = "freebsd",
target_os = "ios",
target_os = "macos",
target_os = "tvos",
target_os = "watchos",
)
))]
pub use self::kqueue::Waker;
#[cfg(any(
mio_unsupported_force_waker_pipe,
target_os = "aix",
target_os = "dragonfly",
target_os = "illumos",
target_os = "netbsd",
target_os = "openbsd",
target_os = "redox",
target_os = "solaris",
target_os = "vita",
))]
mod pipe {
use crate::sys::unix::pipe;
use std::fs::File;
use std::io::{self, Read, Write};
use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
#[derive(Debug)]
pub struct WakerInternal {
sender: File,
receiver: File,
}
impl WakerInternal {
pub fn new() -> io::Result<WakerInternal> {
let [receiver, sender] = pipe::new_raw()?;
let sender = unsafe { File::from_raw_fd(sender) };
let receiver = unsafe { File::from_raw_fd(receiver) };
Ok(WakerInternal { sender, receiver })
}
pub fn wake(&self) -> io::Result<()> {
#[cfg(target_os = "illumos")]
self.empty();
match (&self.sender).write(&[1]) {
Ok(_) => Ok(()),
Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => {
self.empty();
self.wake()
}
Err(ref err) if err.kind() == io::ErrorKind::Interrupted => self.wake(),
Err(err) => Err(err),
}
}
#[cfg(any(
mio_unsupported_force_poll_poll,
target_os = "solaris",
target_os = "vita"
))]
pub fn ack_and_reset(&self) {
self.empty();
}
fn empty(&self) {
let mut buf = [0; 4096];
loop {
match (&self.receiver).read(&mut buf) {
Ok(n) if n > 0 => continue,
_ => return,
}
}
}
}
impl AsRawFd for WakerInternal {
fn as_raw_fd(&self) -> RawFd {
self.receiver.as_raw_fd()
}
}
}
#[cfg(any(
all(
mio_unsupported_force_poll_poll,
any(
mio_unsupported_force_waker_pipe,
target_os = "aix",
target_os = "dragonfly",
target_os = "illumos",
target_os = "netbsd",
target_os = "openbsd",
target_os = "redox",
)
),
target_os = "solaris",
target_os = "vita",
))]
pub(crate) use self::pipe::WakerInternal;
#[cfg(any(
mio_unsupported_force_poll_poll,
target_os = "solaris",
target_os = "vita"
))]
mod poll {
use crate::sys::Selector;
use crate::Token;
use std::io;
#[derive(Debug)]
pub struct Waker {
selector: Selector,
token: Token,
}
impl Waker {
pub fn new(selector: &Selector, token: Token) -> io::Result<Waker> {
Ok(Waker {
selector: selector.try_clone()?,
token,
})
}
pub fn wake(&self) -> io::Result<()> {
self.selector.wake(self.token)
}
}
}
#[cfg(any(
mio_unsupported_force_poll_poll,
target_os = "solaris",
target_os = "vita"
))]
pub use self::poll::Waker;