#![no_std]
#![deny(missing_docs)]
extern crate alloc;
use alloc::{boxed::Box, sync::Arc, task::Wake};
use core::{
mem::MaybeUninit,
task::{Context, Waker},
};
use bitflags::bitflags;
use linux_raw_sys::general::*;
use spin::{Lazy, Mutex};
bitflags! {
#[derive(Debug, Clone, Copy)]
pub struct IoEvents: u32 {
const IN = POLLIN;
const PRI = POLLPRI;
const OUT = POLLOUT;
const ERR = POLLERR;
const HUP = POLLHUP;
const NVAL = POLLNVAL;
const RDNORM = POLLRDNORM;
const RDBAND = POLLRDBAND;
const WRNORM = POLLWRNORM;
const WRBAND = POLLWRBAND;
const MSG = POLLMSG;
const REMOVE = POLLREMOVE;
const RDHUP = POLLRDHUP;
const ALWAYS_POLL = Self::ERR.bits() | Self::HUP.bits();
}
}
pub trait Pollable {
fn poll(&self) -> IoEvents;
fn register(&self, context: &mut Context<'_>, events: IoEvents);
}
const POLL_SET_CAPACITY: usize = 64;
struct Inner {
entries: Box<[MaybeUninit<Waker>]>,
cursor: usize,
}
impl Inner {
fn new() -> Self {
Self {
entries: Box::new_uninit_slice(POLL_SET_CAPACITY),
cursor: 0,
}
}
fn len(&self) -> usize {
self.cursor.min(POLL_SET_CAPACITY)
}
fn is_empty(&self) -> bool {
self.cursor == 0
}
fn register(&mut self, waker: &Waker) {
let slot = self.cursor % POLL_SET_CAPACITY;
if self.cursor >= POLL_SET_CAPACITY {
let old = unsafe { self.entries[slot].assume_init_read() };
if !old.will_wake(waker) {
old.wake();
}
self.cursor = ((slot + 1) % POLL_SET_CAPACITY) + POLL_SET_CAPACITY;
} else {
self.cursor += 1;
}
self.entries[slot].write(waker.clone());
}
}
impl Drop for Inner {
fn drop(&mut self) {
for i in 0..self.len() {
unsafe { self.entries[i].assume_init_read() }.wake();
}
}
}
pub struct PollSet(Lazy<Mutex<Inner>>);
impl Default for PollSet {
fn default() -> Self {
Self::new()
}
}
impl PollSet {
pub const fn new() -> Self {
Self(Lazy::new(|| Mutex::new(Inner::new())))
}
pub fn register(&self, waker: &Waker) {
self.0.lock().register(waker);
}
pub fn wake(&self) -> usize {
let mut guard = self.0.lock();
if guard.is_empty() {
return 0;
}
let inner = core::mem::replace(&mut *guard, Inner::new());
drop(guard);
inner.len()
}
}
impl Drop for PollSet {
fn drop(&mut self) {
self.wake();
}
}
impl Wake for PollSet {
fn wake(self: Arc<Self>) {
self.as_ref().wake();
}
fn wake_by_ref(self: &Arc<Self>) {
self.as_ref().wake();
}
}