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; /// Possible actions that can be requested to the event loop by an /// event source once its events have been processed. /// /// `PostAction` values can be combined with the `|` (bit-or) operator (or with /// `|=`) with the result that: /// - if both values are identical, the result is that value /// - if they are different, the result is [`Reregister`](PostAction::Reregister) /// /// Bit-or-ing these results is useful for composed sources to combine the /// results of their child sources, but note that it only applies to the child /// sources. For example, if every child source returns `Continue`, the result /// will be `Continue`, but the parent source might still need to return /// `Reregister` or something else depending on any additional logic it uses. #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum PostAction { /// Continue listening for events on this source as before Continue, /// Trigger a re-registration of this source Reregister, /// Disable this source /// /// Has the same effect as [`LoopHandle::disable`](crate::LoopHandle#method.disable) Disable, /// Remove this source from the eventloop /// /// Has the same effect as [`LoopHandle::kill`](crate::LoopHandle#method.kill) Remove, } /// Combines `PostAction` values returned from nested event sources. 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 } } } /// Combines `PostAction` values returned from nested event sources. impl BitOrAssign for PostAction { fn bitor_assign(&mut self, rhs: Self) { if *self != rhs { *self = Self::Reregister; } } } /// Trait representing an event source /// /// This is the trait you need to implement if you wish to create your own /// calloop-compatible event sources. /// /// The 3 associated types define the type of closure the user will need to /// provide to process events for your event source. /// /// The `process_events` method will be called when one of the FD you registered /// is ready, with the associated readiness and token. /// /// The `register`, `reregister` and `unregister` methods are plumbing to let your /// source register itself with the polling system. See their documentation for details. /// /// In case your event source needs to do some special processing before or after a /// polling session occurs (to prepare the underlying source for polling, and cleanup /// after that), you can override [`NEEDS_EXTRA_LIFECYCLE_EVENTS`] to `true`. /// For all sources for which that constant is `true`, the methods [`before_sleep`] and /// [`before_handle_events`] will be called. /// [`before_sleep`] is called before the polling system performs a poll operation. /// [`before_handle_events`] is called before any process_events methods have been called. /// This means that during `process_events` you can assume that all cleanup has occured on /// all sources. /// /// [`NEEDS_EXTRA_LIFECYCLE_EVENTS`]: EventSource::NEEDS_EXTRA_LIFECYCLE_EVENTS /// [`before_sleep`]: EventSource::before_sleep /// [`before_handle_events`]: EventSource::before_handle_events pub trait EventSource { /// The type of events generated by your source. type Event; /// Some metadata of your event source /// /// This is typically useful if your source contains some internal state that /// the user may need to interact with when processing events. The user callback /// will receive a `&mut Metadata` reference. /// /// Set to `()` if not needed. type Metadata; /// The return type of the user callback /// /// If the user needs to return some value back to your event source once its /// processing is finshed (to indicate success or failure for example), you can /// specify it using this type. /// /// Set to `()` if not needed. type Ret; /// The error type returned from /// [`process_events()`](Self::process_events()) (not the user callback!). type Error: Into>; /// Process any relevant events /// /// This method will be called every time one of the FD you registered becomes /// ready, including the readiness details and the associated token. /// /// Your event source will then do some processing of the file descriptor(s) to generate /// events, and call the provided `callback` for each one of them. /// /// You should ensure you drained the file descriptors of their events, especially if using /// edge-triggered mode. fn process_events( &mut self, readiness: Readiness, token: Token, callback: F, ) -> Result where F: FnMut(Self::Event, &mut Self::Metadata) -> Self::Ret; /// Register yourself to this poll instance /// /// You should register all your relevant file descriptors to the provided [`Poll`](crate::Poll) /// using its [`Poll::register`](crate::Poll#method.register) method. /// /// If you need to register more than one file descriptor, you can change the /// `sub_id` field of the [`Token`](crate::Token) to differentiate between them. fn register(&mut self, poll: &mut Poll, token_factory: &mut TokenFactory) -> crate::Result<()>; /// Re-register your file descriptors /// /// Your should update the registration of all your relevant file descriptor to /// the provided [`Poll`](crate::Poll) using its [`Poll::reregister`](crate::Poll#method.reregister), /// if necessary. fn reregister( &mut self, poll: &mut Poll, token_factory: &mut TokenFactory, ) -> crate::Result<()>; /// Unregister your file descriptors /// /// You should unregister all your file descriptors from this [`Poll`](crate::Poll) using its /// [`Poll::unregister`](crate::Poll#method.unregister) method. fn unregister(&mut self, poll: &mut Poll) -> crate::Result<()>; /// Whether this source needs to be sent the [`EventSource::before_sleep`] /// and [`EventSource::before_handle_events`] notifications. These are opt-in because /// they require more expensive checks, and almost all sources will not need these notifications const NEEDS_EXTRA_LIFECYCLE_EVENTS: bool = false; /// Notification that a single `poll` is about to begin /// /// Use this to perform operations which must be done before polling, /// but which may conflict with other event handlers. For example, /// if polling requires a lock to be taken /// /// If this returns Ok(Some), this will be treated as an event arriving in polling, and /// your event handler will be called with the returned `Token` and `Readiness`. /// Polling will however still occur, but with a timeout of 0, so additional events /// from this or other sources may also be handled in the same iterations. /// The returned `Token` must belong to this source // If you need to return multiple synthetic events from this notification, please // open an issue fn before_sleep(&mut self) -> crate::Result> { Ok(None) } /// Notification that polling is complete, and [`EventSource::process_events`] will /// be called with the given events for this source. The iterator may be empty, /// which indicates that no events were generated for this source /// /// Please note, the iterator excludes any synthetic events returned from /// [`EventSource::before_sleep`] /// /// Use this to perform a cleanup before event handlers with arbitrary /// code may run. This could be used to drop a lock obtained in /// [`EventSource::before_sleep`] #[allow(unused_variables)] fn before_handle_events(&mut self, events: EventIterator<'_>) {} } /// Blanket implementation for boxed event sources. [`EventSource`] is not an /// object safe trait, so this does not include trait objects. impl EventSource for Box { type Event = T::Event; type Metadata = T::Metadata; type Ret = T::Ret; type Error = T::Error; fn process_events( &mut self, readiness: Readiness, token: Token, callback: F, ) -> Result 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> { T::before_sleep(&mut **self) } fn before_handle_events(&mut self, events: EventIterator) { T::before_handle_events(&mut **self, events) } } /// Blanket implementation for exclusive references to event sources. /// [`EventSource`] is not an object safe trait, so this does not include trait /// objects. impl EventSource for &mut T { type Event = T::Event; type Metadata = T::Metadata; type Ret = T::Ret; type Error = T::Error; fn process_events( &mut self, readiness: Readiness, token: Token, callback: F, ) -> Result 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> { T::before_sleep(&mut **self) } fn before_handle_events(&mut self, events: EventIterator) { T::before_handle_events(&mut **self, events) } } pub(crate) struct DispatcherInner { source: S, callback: F, needs_additional_lifecycle_events: bool, } impl EventDispatcher for RefCell> 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 { 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::() ); 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 { 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 { 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> { 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 { fn process_events( &self, readiness: Readiness, token: Token, data: &mut Data, ) -> crate::Result; 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; fn unregister( &self, poll: &mut Poll, additional_lifecycle_register: &mut AdditionalLifecycleEventsSet, registration_token: RegistrationToken, ) -> crate::Result; fn before_sleep(&self) -> crate::Result>; fn before_handle_events(&self, events: EventIterator<'_>); } #[derive(Default)] /// The list of events pub(crate) struct AdditionalLifecycleEventsSet { /// The list of sources pub(crate) values: Vec, } impl AdditionalLifecycleEventsSet { fn register(&mut self, token: RegistrationToken) { self.values.push(token) } fn unregister(&mut self, token: RegistrationToken) { self.values.retain(|it| it != &token) } } // An internal trait to erase the `F` type parameter of `DispatcherInner` trait ErasedDispatcher<'a, S, Data> { fn as_source_ref(&self) -> Ref; fn as_source_mut(&self) -> RefMut; fn into_source_inner(self: Rc) -> S; fn into_event_dispatcher(self: Rc) -> Rc + 'a>; } impl<'a, S, Data, F> ErasedDispatcher<'a, S, Data> for RefCell> where S: EventSource + 'a, F: FnMut(S::Event, &mut S::Metadata, &mut Data) -> S::Ret + 'a, { fn as_source_ref(&self) -> Ref { Ref::map(self.borrow(), |inner| &inner.source) } fn as_source_mut(&self) -> RefMut { RefMut::map(self.borrow_mut(), |inner| &mut inner.source) } fn into_source_inner(self: Rc) -> 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) -> Rc + 'a> where S: 'a, { self as Rc + 'a> } } /// An event source with its callback. /// /// The `Dispatcher` can be registered in an event loop. /// Use the `as_source_{ref,mut}` functions to interact with the event source. /// Use `into_source_inner` to get the event source back. pub struct Dispatcher<'a, S, Data>(Rc + '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, { /// Builds a dispatcher. /// /// The resulting `Dispatcher` pub fn new(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, }))) } /// Returns an immutable reference to the event source. /// /// # Panics /// /// Has the same semantics as `RefCell::borrow()`. /// /// The dispatcher being mutably borrowed while its events are dispatched, /// this method will panic if invoked from within the associated dispatching closure. pub fn as_source_ref(&self) -> Ref { self.0.as_source_ref() } /// Returns a mutable reference to the event source. /// /// # Panics /// /// Has the same semantics as `RefCell::borrow_mut()`. /// /// The dispatcher being mutably borrowed while its events are dispatched, /// this method will panic if invoked from within the associated dispatching closure. pub fn as_source_mut(&self) -> RefMut { self.0.as_source_mut() } /// Consumes the Dispatcher and returns the inner event source. /// /// # Panics /// /// Panics if the `Dispatcher` is still registered. pub fn into_source_inner(self) -> S { self.0.into_source_inner() } pub(crate) fn clone_as_event_dispatcher(&self) -> Rc + '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)) } } /// An idle callback that was inserted in this loop /// /// This handle allows you to cancel the callback. Dropping /// it will *not* cancel it. pub struct Idle<'i> { pub(crate) callback: Rc>, } 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> { /// Cancel the idle callback if it was not already run pub fn cancel(self) { self.callback.borrow_mut().cancel(); } } pub(crate) trait CancellableIdle { fn cancel(&mut self); } impl CancellableIdle for Option { fn cancel(&mut self) { self.take(); } } pub(crate) trait IdleDispatcher { fn dispatch(&mut self, data: &mut Data); } impl IdleDispatcher for Option 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 event source boxing. #[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 event source trait methods via mut ref. #[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 PostAction combinations. #[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 PostAction self-assignment. #[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); } }