use core::{cell::UnsafeCell, ptr::null};
use crate::result::{Error, Result};
#[repr(C)]
pub struct PollRequest<'a> {
fd: linux_unsafe::int,
events: linux_unsafe::short,
revents: UnsafeCell<linux_unsafe::short>, _phantom: core::marker::PhantomData<&'a super::File>,
}
impl<'a> PollRequest<'a> {
#[inline]
pub const fn new<'f: 'a>(file: &'f super::File) -> Self {
let fd = file.fd;
Self {
fd,
events: 0,
revents: UnsafeCell::new(0),
_phantom: core::marker::PhantomData,
}
}
#[inline(always)]
pub unsafe fn events_raw(mut self, bitmask: core::ffi::c_short) -> Self {
self.events = bitmask;
self
}
#[inline(always)]
pub unsafe fn or_events_raw(mut self, bitmask: core::ffi::c_short) -> Self {
self.events |= bitmask;
self
}
#[inline(always)]
pub fn response(&self) -> PollResponse {
PollResponse::new(unsafe { *self.revents.get() })
}
}
#[derive(Clone, Copy, Debug)]
#[repr(transparent)]
pub struct PollResponse {
revents: core::ffi::c_short,
}
impl PollResponse {
#[inline(always)]
const fn new(raw: core::ffi::c_short) -> Self {
Self { revents: raw }
}
#[inline(always)]
pub const fn raw_result(&self) -> core::ffi::c_short {
self.revents
}
#[inline(always)]
pub const fn readable(&self) -> bool {
(self.revents & linux_unsafe::POLLIN) != 0
}
#[inline(always)]
pub const fn writable(&self) -> bool {
(self.revents & linux_unsafe::POLLOUT) != 0
}
#[inline(always)]
pub const fn error(&self) -> bool {
(self.revents & linux_unsafe::POLLERR) != 0
}
#[inline(always)]
pub const fn hung_up(&self) -> bool {
(self.revents & linux_unsafe::POLLERR) != 0
}
#[inline(always)]
pub const fn exception(&self) -> bool {
(self.revents & linux_unsafe::POLLPRI) != 0
}
#[inline(always)]
pub const fn invalid(&self) -> bool {
(self.revents & linux_unsafe::POLLNVAL) != 0
}
}
pub fn poll(reqs: &mut [PollRequest], timeout: linux_unsafe::int) -> Result<linux_unsafe::int> {
let reqs_ptr = reqs.as_ptr() as *mut linux_unsafe::pollfd;
if reqs.len() > (!(0 as linux_unsafe::nfds_t)) as usize {
return Err(Error::new(22)); }
let reqs_count = reqs.len() as linux_unsafe::nfds_t;
let tmo = linux_unsafe::timespec {
tv_sec: (timeout / 1000) as linux_unsafe::long,
tv_nsec: ((timeout % 1000) * 1_000_000) as linux_unsafe::long,
};
let tmo_p = &tmo as *const _;
let result = unsafe { linux_unsafe::ppoll(reqs_ptr, reqs_count, tmo_p, null()) };
result.map(|count| count as _).map_err(|e| e.into())
}