use crate::{
EpollFlags,
executor::{EpollWaker, exec, try_exec},
};
use nix::fcntl::{FcntlArg, OFlag, fcntl};
use std::{
cell::RefCell,
io::Error,
os::fd::{AsFd, AsRawFd, BorrowedFd, RawFd},
pin::Pin,
task::Poll,
};
pub struct Fd<T: AsRawFd> {
inner: T,
ew: Pin<Box<RefCell<EpollWaker>>>,
}
impl<T: AsRawFd> Fd<T> {
pub fn new(inner: T, events: EpollFlags) -> Result<Self, Error> {
let fd = unsafe { BorrowedFd::borrow_raw(inner.as_raw_fd()) };
let flags = OFlag::from_bits_retain(fcntl(fd, FcntlArg::F_GETFL)?);
fcntl(fd, FcntlArg::F_SETFL(flags | OFlag::O_NONBLOCK))?;
let waker_events = events & (EpollFlags::EPOLLIN | EpollFlags::EPOLLOUT);
let s = Self {
inner,
ew: Box::pin(RefCell::new(EpollWaker::new(waker_events))),
};
exec(|e| e.epoll_add(fd, events | EpollFlags::EPOLLET, s.ew.as_ref()))?;
Ok(s)
}
pub fn poll_with_mut<Output, F: FnMut(&mut T, EpollFlags) -> Result<Output, Error>>(
&mut self,
cx: &std::task::Context<'_>,
mut func: F,
) -> Poll<Result<Output, std::io::Error>> {
let ret = self
.ew
.borrow_mut()
.poll_with(cx, |events| func(&mut self.inner, events));
match ret {
crate::executor::ControlFlow::Normal(poll) => poll,
crate::executor::ControlFlow::Yield => {
cx.waker().wake_by_ref();
Poll::Pending
}
}
}
pub const fn with_mut<Output, F: FnMut(&mut T, EpollFlags) -> Result<Output, Error>>(
&mut self,
func: F,
) -> FdWithMutFuture<'_, T, Output, F> {
FdWithMutFuture { fd: self, func }
}
pub fn poll_with<Output, F: FnMut(&T, EpollFlags) -> Result<Output, Error>>(
&self,
cx: &std::task::Context<'_>,
mut func: F,
) -> Poll<Result<Output, std::io::Error>> {
let ret = self
.ew
.borrow_mut()
.poll_with(cx, |events| func(&self.inner, events));
match ret {
crate::executor::ControlFlow::Normal(poll) => poll,
crate::executor::ControlFlow::Yield => {
cx.waker().wake_by_ref();
Poll::Pending
}
}
}
pub const fn with<Output, F: FnMut(&T, EpollFlags) -> Result<Output, Error>>(
&self,
func: F,
) -> FdWithFuture<'_, T, Output, F> {
FdWithFuture { fd: self, func }
}
pub const fn inner(&self) -> &T {
&self.inner
}
pub const fn inner_mut(&mut self) -> &mut T {
&mut self.inner
}
}
impl<T: AsRawFd> Drop for Fd<T> {
fn drop(&mut self) {
let fd = unsafe { BorrowedFd::borrow_raw(self.inner.as_raw_fd()) };
let _ = try_exec(|e| e.epoll_del(fd));
}
}
pub struct AsFdWrapper<T: AsFd> {
inner: T,
}
impl<T: AsFd> AsFdWrapper<T> {
pub const fn new(inner: T) -> Self {
Self { inner }
}
}
impl<T: AsFd> AsRawFd for AsFdWrapper<T> {
fn as_raw_fd(&self) -> RawFd {
self.inner.as_fd().as_raw_fd()
}
}
impl<T: AsFd> std::ops::Deref for AsFdWrapper<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl<T: AsFd> std::ops::DerefMut for AsFdWrapper<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.inner
}
}
#[doc(hidden)]
pub struct FdWithMutFuture<
'a,
T: AsRawFd,
Output,
F: FnMut(&mut T, EpollFlags) -> Result<Output, Error>,
> {
fd: &'a mut Fd<T>,
func: F,
}
impl<T: AsRawFd, Output, F: FnMut(&mut T, EpollFlags) -> Result<Output, Error> + Unpin> Future
for FdWithMutFuture<'_, T, Output, F>
{
type Output = Result<Output, Error>;
fn poll(self: Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> Poll<Self::Output> {
let Self { fd, func, .. } = self.get_mut();
fd.poll_with_mut(cx, func)
}
}
#[doc(hidden)]
pub struct FdWithFuture<'a, T: AsRawFd, Output, F: FnMut(&T, EpollFlags) -> Result<Output, Error>> {
fd: &'a Fd<T>,
func: F,
}
impl<T: AsRawFd, Output, F: FnMut(&T, EpollFlags) -> Result<Output, Error> + Unpin> Future
for FdWithFuture<'_, T, Output, F>
{
type Output = Result<Output, Error>;
fn poll(self: Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> Poll<Self::Output> {
let Self { fd, func, .. } = self.get_mut();
fd.poll_with(cx, func)
}
}