mrogalski_looper/lib.rs
1//! Clean abstraction for a single-threaded event loop. Built as a lightweight wrapper around the `std::sync::mpsc` package.
2//!
3//! # Example usage:
4//!
5//! ```rust
6//! use mrogalski_looper::{Handler, Sender, run};
7//!
8//! struct ExampleHandler {
9//! data: Vec<i32>,
10//! }
11//!
12//! impl Handler<i32> for ExampleHandler {
13//!
14//! // Invoked right after the `run` function is called.
15//! fn start(&mut self, sender: Sender<i32>) {
16//! for elem in vec![1, 2, 3] {
17//! sender.send(elem.clone()).unwrap();
18//! }
19//! }
20//!
21//! // Called for every `event` sent to the `sender`.
22//! fn handle(&mut self, i: i32) -> bool {
23//! self.data.push(i);
24//! true
25//! }
26//!
27//! // Called after last event is processed or an error occurs.
28//! fn end(self) {
29//! assert_eq!(self.data, vec![1, 2, 3]);
30//! }
31//! }
32//!
33//! // Blocks the current thread until all events are processed.
34//! run(ExampleHandler { data: vec![] });
35//!
36//! ```
37
38#[doc(no_inline)]
39pub use std::sync::mpsc::Sender;
40
41#[cfg(test)]
42mod tests;
43
44/// Handles events sent to the event loop.
45pub trait Handler<EVENT: Send>: Sized {
46 /// Called immediately after starting the event loop.
47 ///
48 /// The `Sender` argument can be used to send new events. It can be cloned and passed to other threads in this method.
49 ///
50 /// When the last sender is dropped and there are no events pending, the event loop terminates.
51 fn start(&mut self, sender: Sender<EVENT>);
52
53 /// Called for every event sent to the event loop.
54 fn handle(&mut self, event: EVENT) -> bool;
55
56 /// Called after event loop terminates.
57 ///
58 /// The default implementation does nothing and can be overriden.
59 fn end(self) {}
60}
61
62/// Runs the event loop on the current thread.
63pub fn run<EVENT: Send, HANDLER: Handler<EVENT>>(mut handler: HANDLER) {
64 let (tx, rx) = std::sync::mpsc::channel();
65 handler.start(tx);
66 let mut running = true;
67 while running {
68 running = match rx.recv() {
69 Ok(event) => handler.handle(event),
70 _ => false,
71 }
72 }
73 handler.end();
74}