use std::{
cell::{Ref, RefCell, RefMut},
io,
rc::Rc,
};
use crate::{sys::TokenFactory, Poll, Readiness, Token};
pub mod channel;
#[cfg(feature = "executor")]
pub mod futures;
pub mod generic;
pub mod ping;
#[cfg(target_os = "linux")]
pub mod signals;
pub mod timer;
#[derive(Debug)]
pub enum PostAction {
Continue,
Reregister,
Disable,
Remove,
}
pub trait EventSource {
type Event;
type Metadata;
type Ret;
fn process_events<F>(
&mut self,
readiness: Readiness,
token: Token,
callback: F,
) -> std::io::Result<PostAction>
where
F: FnMut(Self::Event, &mut Self::Metadata) -> Self::Ret;
fn register(&mut self, poll: &mut Poll, token_factory: &mut TokenFactory) -> io::Result<()>;
fn reregister(&mut self, poll: &mut Poll, token_factory: &mut TokenFactory) -> io::Result<()>;
fn unregister(&mut self, poll: &mut Poll) -> io::Result<()>;
}
pub(crate) struct DispatcherInner<S, F> {
source: S,
callback: F,
}
impl<Data, S, F> EventDispatcher<Data> for RefCell<DispatcherInner<S, F>>
where
S: EventSource,
F: FnMut(S::Event, &mut S::Metadata, &mut Data) -> S::Ret,
{
fn process_events(
&self,
readiness: Readiness,
token: Token,
data: &mut Data,
) -> std::io::Result<PostAction> {
let mut disp = self.borrow_mut();
let DispatcherInner {
ref mut source,
ref mut callback,
} = *disp;
source.process_events(readiness, token, |event, meta| callback(event, meta, data))
}
fn register(&self, poll: &mut Poll, token_factory: &mut TokenFactory) -> io::Result<()> {
self.borrow_mut().source.register(poll, token_factory)
}
fn reregister(&self, poll: &mut Poll, token_factory: &mut TokenFactory) -> io::Result<()> {
self.borrow_mut().source.reregister(poll, token_factory)
}
fn unregister(&self, poll: &mut Poll) -> io::Result<()> {
self.borrow_mut().source.unregister(poll)
}
}
pub(crate) trait EventDispatcher<Data> {
fn process_events(
&self,
readiness: Readiness,
token: Token,
data: &mut Data,
) -> std::io::Result<PostAction>;
fn register(&self, poll: &mut Poll, token_factory: &mut TokenFactory) -> io::Result<()>;
fn reregister(&self, poll: &mut Poll, token_factory: &mut TokenFactory) -> io::Result<()>;
fn unregister(&self, poll: &mut Poll) -> io::Result<()>;
}
trait ErasedDispatcher<'a, S, Data> {
fn as_source_ref(&self) -> Ref<S>;
fn as_source_mut(&self) -> RefMut<S>;
fn into_source_inner(self: Rc<Self>) -> S;
fn into_event_dispatcher(self: Rc<Self>) -> Rc<dyn EventDispatcher<Data> + 'a>;
}
impl<'a, S, Data, F> ErasedDispatcher<'a, S, Data> for RefCell<DispatcherInner<S, F>>
where
S: EventSource + 'a,
F: FnMut(S::Event, &mut S::Metadata, &mut Data) -> S::Ret + 'a,
{
fn as_source_ref(&self) -> Ref<S> {
Ref::map(self.borrow(), |inner| &inner.source)
}
fn as_source_mut(&self) -> RefMut<S> {
RefMut::map(self.borrow_mut(), |inner| &mut inner.source)
}
fn into_source_inner(self: Rc<Self>) -> S {
if let Ok(ref_cell) = Rc::try_unwrap(self) {
ref_cell.into_inner().source
} else {
panic!("Dispatcher is still registered");
}
}
fn into_event_dispatcher(self: Rc<Self>) -> Rc<dyn EventDispatcher<Data> + 'a>
where
S: 'a,
{
self as Rc<dyn EventDispatcher<Data> + 'a>
}
}
pub struct Dispatcher<'a, S, Data>(Rc<dyn ErasedDispatcher<'a, S, Data> + 'a>);
impl<'a, S, Data> std::fmt::Debug for Dispatcher<'a, S, Data> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str("Dispatcher { ... }")
}
}
impl<'a, S, Data> Dispatcher<'a, S, Data>
where
S: EventSource + 'a,
{
pub fn new<F>(source: S, callback: F) -> Self
where
F: FnMut(S::Event, &mut S::Metadata, &mut Data) -> S::Ret + 'a,
{
Dispatcher(Rc::new(RefCell::new(DispatcherInner { source, callback })))
}
pub fn as_source_ref(&self) -> Ref<S> {
self.0.as_source_ref()
}
pub fn as_source_mut(&self) -> RefMut<S> {
self.0.as_source_mut()
}
pub fn into_source_inner(self) -> S {
self.0.into_source_inner()
}
pub(crate) fn clone_as_event_dispatcher(&self) -> Rc<dyn EventDispatcher<Data> + 'a> {
Rc::clone(&self.0).into_event_dispatcher()
}
}
impl<'a, S, Data> Clone for Dispatcher<'a, S, Data> {
fn clone(&self) -> Dispatcher<'a, S, Data> {
Dispatcher(Rc::clone(&self.0))
}
}
pub struct Idle<'i> {
pub(crate) callback: Rc<RefCell<dyn CancellableIdle + 'i>>,
}
impl<'i> std::fmt::Debug for Idle<'i> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str("Idle { ... }")
}
}
impl<'i> Idle<'i> {
pub fn cancel(self) {
self.callback.borrow_mut().cancel();
}
}
pub(crate) trait CancellableIdle {
fn cancel(&mut self);
}
impl<F> CancellableIdle for Option<F> {
fn cancel(&mut self) {
self.take();
}
}
pub(crate) trait IdleDispatcher<Data> {
fn dispatch(&mut self, data: &mut Data);
}
impl<Data, F> IdleDispatcher<Data> for Option<F>
where
F: FnMut(&mut Data),
{
fn dispatch(&mut self, data: &mut Data) {
if let Some(callabck) = self.as_mut() {
callabck(data);
}
}
}