use std::{
cell::{Ref, RefCell, RefMut},
ops::{BitOr, BitOrAssign},
rc::Rc,
};
use log::trace;
pub use crate::loop_logic::EventIterator;
use crate::{sys::TokenFactory, Poll, Readiness, RegistrationToken, Token};
pub mod channel;
#[cfg(feature = "executor")]
#[cfg_attr(docsrs, doc(cfg(feature = "executor")))]
pub mod futures;
pub mod generic;
pub mod ping;
#[cfg(all(target_os = "linux", feature = "signals"))]
#[cfg_attr(docsrs, doc(cfg(target_os = "linux")))]
pub mod signals;
pub mod timer;
pub mod transient;
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum PostAction {
Continue,
Reregister,
Disable,
Remove,
}
impl BitOr for PostAction {
type Output = Self;
fn bitor(self, rhs: Self) -> Self::Output {
if matches!(self, x if x == rhs) {
self
} else {
Self::Reregister
}
}
}
impl BitOrAssign for PostAction {
fn bitor_assign(&mut self, rhs: Self) {
if *self != rhs {
*self = Self::Reregister;
}
}
}
pub trait EventSource {
type Event;
type Metadata;
type Ret;
type Error: Into<Box<dyn std::error::Error + Sync + Send>>;
fn process_events<F>(
&mut self,
readiness: Readiness,
token: Token,
callback: F,
) -> Result<PostAction, Self::Error>
where
F: FnMut(Self::Event, &mut Self::Metadata) -> Self::Ret;
fn register(&mut self, poll: &mut Poll, token_factory: &mut TokenFactory) -> crate::Result<()>;
fn reregister(
&mut self,
poll: &mut Poll,
token_factory: &mut TokenFactory,
) -> crate::Result<()>;
fn unregister(&mut self, poll: &mut Poll) -> crate::Result<()>;
const NEEDS_EXTRA_LIFECYCLE_EVENTS: bool = false;
fn before_sleep(&mut self) -> crate::Result<Option<(Readiness, Token)>> {
Ok(None)
}
#[allow(unused_variables)]
fn before_handle_events(&mut self, events: EventIterator<'_>) {}
}
impl<T: EventSource> EventSource for Box<T> {
type Event = T::Event;
type Metadata = T::Metadata;
type Ret = T::Ret;
type Error = T::Error;
fn process_events<F>(
&mut self,
readiness: Readiness,
token: Token,
callback: F,
) -> Result<PostAction, Self::Error>
where
F: FnMut(Self::Event, &mut Self::Metadata) -> Self::Ret,
{
T::process_events(&mut **self, readiness, token, callback)
}
fn register(&mut self, poll: &mut Poll, token_factory: &mut TokenFactory) -> crate::Result<()> {
T::register(&mut **self, poll, token_factory)
}
fn reregister(
&mut self,
poll: &mut Poll,
token_factory: &mut TokenFactory,
) -> crate::Result<()> {
T::reregister(&mut **self, poll, token_factory)
}
fn unregister(&mut self, poll: &mut Poll) -> crate::Result<()> {
T::unregister(&mut **self, poll)
}
const NEEDS_EXTRA_LIFECYCLE_EVENTS: bool = T::NEEDS_EXTRA_LIFECYCLE_EVENTS;
fn before_sleep(&mut self) -> crate::Result<Option<(Readiness, Token)>> {
T::before_sleep(&mut **self)
}
fn before_handle_events(&mut self, events: EventIterator) {
T::before_handle_events(&mut **self, events)
}
}
impl<T: EventSource> EventSource for &mut T {
type Event = T::Event;
type Metadata = T::Metadata;
type Ret = T::Ret;
type Error = T::Error;
fn process_events<F>(
&mut self,
readiness: Readiness,
token: Token,
callback: F,
) -> Result<PostAction, Self::Error>
where
F: FnMut(Self::Event, &mut Self::Metadata) -> Self::Ret,
{
T::process_events(&mut **self, readiness, token, callback)
}
fn register(&mut self, poll: &mut Poll, token_factory: &mut TokenFactory) -> crate::Result<()> {
T::register(&mut **self, poll, token_factory)
}
fn reregister(
&mut self,
poll: &mut Poll,
token_factory: &mut TokenFactory,
) -> crate::Result<()> {
T::reregister(&mut **self, poll, token_factory)
}
fn unregister(&mut self, poll: &mut Poll) -> crate::Result<()> {
T::unregister(&mut **self, poll)
}
const NEEDS_EXTRA_LIFECYCLE_EVENTS: bool = T::NEEDS_EXTRA_LIFECYCLE_EVENTS;
fn before_sleep(&mut self) -> crate::Result<Option<(Readiness, Token)>> {
T::before_sleep(&mut **self)
}
fn before_handle_events(&mut self, events: EventIterator) {
T::before_handle_events(&mut **self, events)
}
}
pub(crate) struct DispatcherInner<S, F> {
source: S,
callback: F,
needs_additional_lifecycle_events: bool,
}
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,
) -> crate::Result<PostAction> {
let mut disp = self.borrow_mut();
let DispatcherInner {
ref mut source,
ref mut callback,
..
} = *disp;
trace!(
"[calloop] Processing events for source type {}",
std::any::type_name::<S>()
);
source
.process_events(readiness, token, |event, meta| callback(event, meta, data))
.map_err(|e| crate::Error::OtherError(e.into()))
}
fn register(
&self,
poll: &mut Poll,
additional_lifecycle_register: &mut AdditionalLifecycleEventsSet,
token_factory: &mut TokenFactory,
) -> crate::Result<()> {
let mut this = self.borrow_mut();
if this.needs_additional_lifecycle_events {
additional_lifecycle_register.register(token_factory.registration_token());
}
this.source.register(poll, token_factory)
}
fn reregister(
&self,
poll: &mut Poll,
additional_lifecycle_register: &mut AdditionalLifecycleEventsSet,
token_factory: &mut TokenFactory,
) -> crate::Result<bool> {
if let Ok(mut me) = self.try_borrow_mut() {
me.source.reregister(poll, token_factory)?;
if me.needs_additional_lifecycle_events {
additional_lifecycle_register.register(token_factory.registration_token());
}
Ok(true)
} else {
Ok(false)
}
}
fn unregister(
&self,
poll: &mut Poll,
additional_lifecycle_register: &mut AdditionalLifecycleEventsSet,
registration_token: RegistrationToken,
) -> crate::Result<bool> {
if let Ok(mut me) = self.try_borrow_mut() {
me.source.unregister(poll)?;
if me.needs_additional_lifecycle_events {
additional_lifecycle_register.unregister(registration_token);
}
Ok(true)
} else {
Ok(false)
}
}
fn before_sleep(&self) -> crate::Result<Option<(Readiness, Token)>> {
let mut disp = self.borrow_mut();
let DispatcherInner { ref mut source, .. } = *disp;
source.before_sleep()
}
fn before_handle_events(&self, events: EventIterator<'_>) {
let mut disp = self.borrow_mut();
let DispatcherInner { ref mut source, .. } = *disp;
source.before_handle_events(events);
}
}
pub(crate) trait EventDispatcher<Data> {
fn process_events(
&self,
readiness: Readiness,
token: Token,
data: &mut Data,
) -> crate::Result<PostAction>;
fn register(
&self,
poll: &mut Poll,
additional_lifecycle_register: &mut AdditionalLifecycleEventsSet,
token_factory: &mut TokenFactory,
) -> crate::Result<()>;
fn reregister(
&self,
poll: &mut Poll,
additional_lifecycle_register: &mut AdditionalLifecycleEventsSet,
token_factory: &mut TokenFactory,
) -> crate::Result<bool>;
fn unregister(
&self,
poll: &mut Poll,
additional_lifecycle_register: &mut AdditionalLifecycleEventsSet,
registration_token: RegistrationToken,
) -> crate::Result<bool>;
fn before_sleep(&self) -> crate::Result<Option<(Readiness, Token)>>;
fn before_handle_events(&self, events: EventIterator<'_>);
}
#[derive(Default)]
pub(crate) struct AdditionalLifecycleEventsSet {
pub(crate) values: Vec<RegistrationToken>,
}
impl AdditionalLifecycleEventsSet {
fn register(&mut self, token: RegistrationToken) {
self.values.push(token)
}
fn unregister(&mut self, token: RegistrationToken) {
self.values.retain(|it| it != &token)
}
}
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> {
#[cfg_attr(feature = "nightly_coverage", coverage(off))]
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,
needs_additional_lifecycle_events: S::NEEDS_EXTRA_LIFECYCLE_EVENTS,
})))
}
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> {
#[cfg_attr(feature = "nightly_coverage", coverage(off))]
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);
}
}
}
#[cfg(test)]
mod tests {
use std::time::Duration;
use crate::{ping::make_ping, EventLoop};
#[test]
fn test_boxed_source() {
let mut fired = false;
let (pinger, source) = make_ping().unwrap();
let boxed = Box::new(source);
let mut event_loop = EventLoop::try_new().unwrap();
let handle = event_loop.handle();
let token = handle
.insert_source(boxed, |_, _, fired| *fired = true)
.unwrap();
pinger.ping();
event_loop
.dispatch(Duration::new(0, 0), &mut fired)
.unwrap();
assert!(fired);
fired = false;
handle.update(&token).unwrap();
pinger.ping();
event_loop
.dispatch(Duration::new(0, 0), &mut fired)
.unwrap();
assert!(fired);
fired = false;
handle.remove(token);
event_loop
.dispatch(Duration::new(0, 0), &mut fired)
.unwrap();
assert!(!fired);
}
#[test]
fn test_mut_ref_source() {
let mut fired = false;
let (pinger, mut source) = make_ping().unwrap();
let source_ref = &mut source;
let mut event_loop = EventLoop::try_new().unwrap();
let handle = event_loop.handle();
let token = handle
.insert_source(source_ref, |_, _, fired| *fired = true)
.unwrap();
pinger.ping();
event_loop
.dispatch(Duration::new(0, 0), &mut fired)
.unwrap();
assert!(fired);
fired = false;
handle.update(&token).unwrap();
pinger.ping();
event_loop
.dispatch(Duration::new(0, 0), &mut fired)
.unwrap();
assert!(fired);
fired = false;
handle.remove(token);
event_loop
.dispatch(Duration::new(0, 0), &mut fired)
.unwrap();
assert!(!fired);
}
#[test]
fn post_action_combine() {
use super::PostAction::*;
assert_eq!(Continue | Continue, Continue);
assert_eq!(Continue | Reregister, Reregister);
assert_eq!(Continue | Disable, Reregister);
assert_eq!(Continue | Remove, Reregister);
assert_eq!(Reregister | Continue, Reregister);
assert_eq!(Reregister | Reregister, Reregister);
assert_eq!(Reregister | Disable, Reregister);
assert_eq!(Reregister | Remove, Reregister);
assert_eq!(Disable | Continue, Reregister);
assert_eq!(Disable | Reregister, Reregister);
assert_eq!(Disable | Disable, Disable);
assert_eq!(Disable | Remove, Reregister);
assert_eq!(Remove | Continue, Reregister);
assert_eq!(Remove | Reregister, Reregister);
assert_eq!(Remove | Disable, Reregister);
assert_eq!(Remove | Remove, Remove);
}
#[test]
fn post_action_combine_assign() {
use super::PostAction::*;
let mut action = Continue;
action |= Continue;
assert_eq!(action, Continue);
let mut action = Continue;
action |= Reregister;
assert_eq!(action, Reregister);
let mut action = Continue;
action |= Disable;
assert_eq!(action, Reregister);
let mut action = Continue;
action |= Remove;
assert_eq!(action, Reregister);
let mut action = Reregister;
action |= Continue;
assert_eq!(action, Reregister);
let mut action = Reregister;
action |= Reregister;
assert_eq!(action, Reregister);
let mut action = Reregister;
action |= Disable;
assert_eq!(action, Reregister);
let mut action = Reregister;
action |= Remove;
assert_eq!(action, Reregister);
let mut action = Disable;
action |= Continue;
assert_eq!(action, Reregister);
let mut action = Disable;
action |= Reregister;
assert_eq!(action, Reregister);
let mut action = Disable;
action |= Disable;
assert_eq!(action, Disable);
let mut action = Disable;
action |= Remove;
assert_eq!(action, Reregister);
let mut action = Remove;
action |= Continue;
assert_eq!(action, Reregister);
let mut action = Remove;
action |= Reregister;
assert_eq!(action, Reregister);
let mut action = Remove;
action |= Disable;
assert_eq!(action, Reregister);
let mut action = Remove;
action |= Remove;
assert_eq!(action, Remove);
}
}