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
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
//! 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.
//!
//! The main target use of this event loop is thus for apps that expect to spend
//! most of their time waiting for events and wishes to do so in a cheap and convenient
//! way. It is not meant for large scale high performance IO.
//!
//! ## How to use it
//!
//! ```no_run
//! extern crate calloop;
//!
//! use calloop::{generic::Generic, EventLoop, Interest, Mode};
//!
//! use std::time::Duration;
//!
//! fn main() {
//!     // Create the event loop
//!     let mut event_loop = EventLoop::try_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 source callbacks
//!     let handle = event_loop.handle();
//!
//!     // Inserting an event source takes this general form
//!     // it can also be done from within the callback of an other event source
//! #   let (_ping, source) = calloop::ping::make_ping().unwrap();
//!     handle.insert_source(
//!         // a type implementing the EventSource trait
//!         source,
//!         // a callback that is invoked whenever this source generates an event
//!         |event, metadata, shared_data| {
//!             // This callback is given 3 values:
//!             // - the event generated by the source
//!             // - &mut access to some metadata, specific to the event source
//!             // - &mut access to the global shared data that was passed to EventLoop::dispatch
//!         }
//!     );
//!
//!     // Actual run of your loop
//!     //
//!     // Dispatch received events to their callbacks, waiting at most 20 ms for
//!     // new events between each invocation of the provided callback.
//!     //
//!     // The `&mut shared_data` is a mutable reference that will be forwarded to all
//!     // your callbacks, allowing them to share some state
//! #   let mut shared_data = ();
//!     event_loop.run(Duration::from_millis(20), &mut shared_data, |shared_data| {
//!         /*
//!         * Insert here the processing you need to do do between each waiting session
//!         * like your drawing logic if you're doing a GUI app for example.
//!         */
//!     });
//! }
//! ```
//!
//! ## 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](channel)
//! - [Timers](timer)
//! - [unix signals](signals) on Linux
//!
//! 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`](EventLoop#method.dispatch), once all
//! events from the sources have been processed.
//!
//! ## Async/Await compatibility
//!
//! `calloop` can be used with futures, both as an executor and for monitoring Async IO.
//!
//! Activating the `executor` cargo feature will add the [`futures`] module, which provides
//! a future executor that can be inserted into an [`EventLoop`] as yet another [`EventSource`].
//!
//! IO objects can be made Async-aware via the [`LoopHandle::adapt_io`](LoopHandle#method.adapt_io)
//! method. Waking up the futures using these objects is handled by the associated [`EventLoop`]
//! directly.
//!
//! ## 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.
//!
//! ## Platforms support
//!
//! Currently, only Linux and the *BSD are supported.

#![warn(missing_docs)]

mod sys;

pub use sys::{Interest, Mode, Poll, Readiness, Token};

pub use self::loop_logic::{EventLoop, InsertError, LoopHandle, LoopSignal, RegistrationToken};
pub use self::sources::*;

pub mod io;
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!(),
    }
}