1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
//! Calloop, a Callback-based Event Loop //! //! This crate provides an `EventLoop` type, which is a small abstraction //! over a polling system. The main difference between this crate //! and other traditional rust event loops is that it is based on callbacks: //! you can register several event sources, each being associated with a callback //! closure that will be invoked whenever the associated event source generates //! events. //! //! This crate was initially an implementation detail of `wayland-server`, and has been //! split-off for reuse. I expect it to be more useful for GUI programs or graphical //! servers (like wayland-based apps) than performance critial networking code, which are //! more versed towards `tokio` and async-await. It mostly shines in the conception of //! modular infrastructures, allowing different modules to use the same event loop without //! needing to know about each other. //! //! ## How to use it //! //! ``` //! extern crate calloop; //! //! use std::time::Duration; //! //! fn main() { //! // Create the event loop //! let mut event_loop = calloop::EventLoop::new().expect("Failed to initialize the event loop!"); //! // Retrieve an handle. It is used to insert new sources into the event loop //! // It can be cloned, allowing you to insert sources from within sources //! let handle = event_loop.handle(); //! //! /* //! * Setup your program, inserting event sources in the loop //! */ //! //! // Actual run of your loop //! loop { //! // Dispatch received events to their callbacks, waiting at most 20 ms for //! // new events //! // //! // The `&mut shared_data` is a mutable reference that will be forwarded to all //! // your callbacks, allowing them to easily share some state //! # let mut shared_data = (); //! event_loop.dispatch(Duration::from_millis(20), &mut shared_data); //! //! /* //! * Insert here the processing you need to do do between each event loop run //! * like your drawing logic if you're doing a GUI app for example. //! */ //! //! # break; //! } //! } //! ``` //! //! ## Event source types //! //! The event loop is backed by an OS provided polling selector (epoll on Linux). //! //! This crate also provide some adapters for common event sources such as: //! //! - MPSC channels //! - Timers //! - unix signals //! //! As well as generic objects backed by file descriptors. //! //! It is also possible to insert "idle" callbacks. These callbacks represent computations that //! need to be done at some point, but are not as urgent as processing the events. These callbacks //! are stored and then executed during `EventLoop::dispatch(..)`, once all events from the sources //! have been processed. //! //! ## Custom event sources //! //! You can create custom event sources can will be inserted in the event loop by //! implementing the `EventSource` trait. This can be done either directly from the file //! descriptors of your source of interest, or by wrapping an other event source and further //! processing its events. An `EventSource` can register more than one file descriptor and //! aggregate them. #![warn(missing_docs)] mod sys; pub use sys::{Interest, Mode, Poll, Readiness, Token}; pub use self::loop_logic::{EventLoop, InsertError, LoopHandle, LoopSignal}; pub use self::sources::*; mod list; mod loop_logic; mod sources; fn no_nix_err(err: nix::Error) -> std::io::Error { match err { ::nix::Error::Sys(errno) => errno.into(), _ => unreachable!(), } }