use crate as orengine;
use crate::io::io_request_data::IoRequestData;
use crate::io::sys::{AsRawFd, RawFd};
use crate::io::worker::{local_worker, IoWorker};
use orengine_macros::{poll_for_io_request, poll_for_time_bounded_io_request};
use std::future::Future;
use std::pin::Pin;
use std::task::{Context, Poll};
use std::time::{Duration, Instant};
macro_rules! generate_poll {
($name:ident, $name_with_deadline:ident, $method:expr, $method_with_deadline:expr) => {
pub struct $name {
fd: RawFd,
io_request_data: Option<IoRequestData>,
}
impl $name {
pub fn new(fd: RawFd) -> Self {
Self {
fd,
io_request_data: None,
}
}
}
impl Future for $name {
type Output = std::io::Result<()>;
fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
let this = unsafe { self.get_unchecked_mut() };
#[allow(unused, reason = "Cannot write proc_macro else to make it readable.")]
let ret;
poll_for_io_request!((
local_worker().$method(this.fd, unsafe {
this.io_request_data.as_mut().unwrap_unchecked()
}),
()
));
}
}
unsafe impl Send for $name {}
pub struct $name_with_deadline {
fd: RawFd,
io_request_data: Option<IoRequestData>,
deadline: Instant,
}
impl $name_with_deadline {
pub fn new(fd: RawFd, deadline: Instant) -> Self {
Self {
fd,
io_request_data: None,
deadline,
}
}
}
impl Future for $name_with_deadline {
type Output = std::io::Result<()>;
fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
let this = unsafe { self.get_unchecked_mut() };
let worker = local_worker();
#[allow(unused, reason = "Cannot write proc_macro else to make it readable.")]
let ret;
poll_for_time_bounded_io_request!((
worker.$method_with_deadline(
this.fd,
unsafe { this.io_request_data.as_mut().unwrap_unchecked() },
&mut this.deadline
),
()
));
}
}
unsafe impl Send for $name_with_deadline {}
};
}
generate_poll!(
PollRecv,
PollRecvWithDeadline,
poll_fd_read,
poll_fd_read_with_deadline
);
generate_poll!(
PollSend,
PollSendWithDeadline,
poll_fd_write,
poll_fd_write_with_deadline
);
pub trait AsyncPollFd: AsRawFd {
#[inline(always)]
fn poll_recv(&self) -> PollRecv {
PollRecv::new(self.as_raw_fd())
}
#[inline(always)]
fn poll_recv_with_deadline(&self, deadline: Instant) -> PollRecvWithDeadline {
PollRecvWithDeadline::new(self.as_raw_fd(), deadline)
}
#[inline(always)]
fn poll_recv_with_timeout(&self, timeout: Duration) -> PollRecvWithDeadline {
self.poll_recv_with_deadline(Instant::now() + timeout)
}
#[inline(always)]
fn poll_send(&self) -> PollSend {
PollSend::new(self.as_raw_fd())
}
#[inline(always)]
fn poll_send_with_deadline(&self, deadline: Instant) -> PollSendWithDeadline {
PollSendWithDeadline::new(self.as_raw_fd(), deadline)
}
#[inline(always)]
fn poll_send_with_timeout(&self, timeout: Duration) -> PollSendWithDeadline {
self.poll_send_with_deadline(Instant::now() + timeout)
}
}