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!(),
    }
}