#![no_std]
#![deny(missing_docs)]
extern crate alloc;
use alloc::{boxed::Box, sync::Arc, vec::Vec};
use core::{marker::PhantomData, task::Waker};
use bitflags::bitflags;
use linux_raw_sys::general::*;
bitflags! {
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
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 enum SharedObserver {}
pub enum ExclusiveConsumer {}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum RegistrationMode {
Shared,
Exclusive,
}
pub trait PollRegistration: Send {
fn was_notified(&self) -> bool;
}
pub trait PollSource: Send + Sync {
unsafe fn register(
&self,
waker: &Waker,
interests: IoEvents,
mode: RegistrationMode,
) -> Option<Box<dyn PollRegistration>>;
}
impl<T: PollSource + ?Sized> PollSource for Arc<T> {
unsafe fn register(
&self,
waker: &Waker,
interests: IoEvents,
mode: RegistrationMode,
) -> Option<Box<dyn PollRegistration>> {
unsafe { self.as_ref().register(waker, interests, mode) }
}
}
struct OwnedRegistration {
lease: Box<dyn PollRegistration>,
mode: RegistrationMode,
}
#[must_use = "dropping the registrar immediately cancels its poll registrations"]
pub struct PollRegistrar<M> {
waker: Waker,
registrations: Vec<OwnedRegistration>,
mode: PhantomData<fn() -> M>,
}
impl<M> PollRegistrar<M> {
pub fn new(waker: &Waker) -> Self {
Self {
waker: waker.clone(),
registrations: Vec::new(),
mode: PhantomData,
}
}
pub fn reset(&mut self, waker: &Waker) {
self.registrations.clear();
self.waker.clone_from(waker);
}
pub fn clear(&mut self) {
self.registrations.clear();
}
pub fn is_empty(&self) -> bool {
self.registrations.is_empty()
}
unsafe fn register_mode(
&mut self,
source: &dyn PollSource,
interests: IoEvents,
mode: RegistrationMode,
) {
if interests.is_empty() {
return;
}
if let Some(lease) = unsafe { source.register(&self.waker, interests, mode) } {
self.registrations.push(OwnedRegistration { lease, mode });
}
}
}
impl PollRegistrar<SharedObserver> {
pub unsafe fn register(&mut self, source: &dyn PollSource, interests: IoEvents) {
unsafe { self.register_mode(source, interests, RegistrationMode::Shared) };
}
}
impl PollRegistrar<ExclusiveConsumer> {
pub fn was_exclusively_notified(&self) -> bool {
self.registrations.iter().any(|registration| {
registration.mode == RegistrationMode::Exclusive && registration.lease.was_notified()
})
}
pub unsafe fn register_exclusive(&mut self, source: &dyn PollSource, interests: IoEvents) {
unsafe { self.register_mode(source, interests, RegistrationMode::Exclusive) };
}
pub unsafe fn register_shared(&mut self, source: &dyn PollSource, interests: IoEvents) {
unsafe { self.register_mode(source, interests, RegistrationMode::Shared) };
}
}
pub trait SharedRegistrationSink {
fn waker(&self) -> &Waker;
unsafe fn register_shared(&mut self, source: &dyn PollSource, interests: IoEvents);
}
pub trait ExclusiveRegistrationSink {
fn waker(&self) -> &Waker;
unsafe fn register_exclusive(&mut self, source: &dyn PollSource, interests: IoEvents);
fn as_shared(&mut self) -> &mut dyn SharedRegistrationSink;
}
impl SharedRegistrationSink for PollRegistrar<SharedObserver> {
fn waker(&self) -> &Waker {
&self.waker
}
unsafe fn register_shared(&mut self, source: &dyn PollSource, interests: IoEvents) {
unsafe { self.register(source, interests) };
}
}
impl SharedRegistrationSink for PollRegistrar<ExclusiveConsumer> {
fn waker(&self) -> &Waker {
&self.waker
}
unsafe fn register_shared(&mut self, source: &dyn PollSource, interests: IoEvents) {
unsafe { self.register_shared(source, interests) };
}
}
impl ExclusiveRegistrationSink for PollRegistrar<ExclusiveConsumer> {
fn waker(&self) -> &Waker {
&self.waker
}
unsafe fn register_exclusive(&mut self, source: &dyn PollSource, interests: IoEvents) {
unsafe { self.register_exclusive(source, interests) };
}
fn as_shared(&mut self) -> &mut dyn SharedRegistrationSink {
self
}
}
pub trait Pollable {
fn poll(&self) -> IoEvents;
unsafe fn register_shared(&self, sink: &mut dyn SharedRegistrationSink, events: IoEvents);
unsafe fn register_exclusive(
&self,
sink: &mut dyn ExclusiveRegistrationSink,
events: IoEvents,
) {
unsafe { self.register_shared(sink.as_shared(), events) };
}
}