kmon/
event.rs

1use crate::kernel::log::KernelLogs;
2use std::io;
3use std::sync::mpsc;
4use std::thread;
5use std::time::Duration;
6use termion::event::Key;
7use termion::input::TermRead;
8
9/// Terminal event methods
10pub enum Event<I> {
11	Input(I),
12	Kernel(String),
13	Tick,
14}
15
16/// Terminal events
17#[allow(dead_code)]
18pub struct Events {
19	pub tx: mpsc::Sender<Event<Key>>,
20	pub rx: mpsc::Receiver<Event<Key>>,
21	input_handler: thread::JoinHandle<()>,
22	kernel_handler: thread::JoinHandle<()>,
23	tick_handler: thread::JoinHandle<()>,
24}
25
26impl Events {
27	/// Create a new events instance.
28	pub fn new(refresh_rate: u64, kernel_logs: &KernelLogs) -> Self {
29		// Convert refresh rate to Duration from milliseconds.
30		let refresh_rate = Duration::from_millis(refresh_rate);
31		// Create a new asynchronous channel.
32		let (tx, rx) = mpsc::channel();
33		// Handle inputs using stdin stream and sender of the channel.
34		let input_handler = {
35			let tx = tx.clone();
36			thread::spawn(move || {
37				let stdin = io::stdin();
38				for key in stdin.keys().flatten() {
39					tx.send(Event::Input(key)).unwrap();
40				}
41			})
42		};
43		// Handle kernel logs using 'dmesg' output.
44		let kernel_handler = {
45			let tx = tx.clone();
46			let mut kernel_logs = kernel_logs.clone();
47			thread::spawn(move || loop {
48				if kernel_logs.update() {
49					tx.send(Event::Kernel(kernel_logs.output.to_string()))
50						.unwrap_or_default();
51				}
52				thread::sleep(refresh_rate * 10);
53			})
54		};
55		// Create a loop for handling events.
56		let tick_handler = {
57			let tx = tx.clone();
58			thread::spawn(move || loop {
59				tx.send(Event::Tick).unwrap_or_default();
60				thread::sleep(refresh_rate);
61			})
62		};
63		// Return events.
64		Self {
65			tx,
66			rx,
67			input_handler,
68			kernel_handler,
69			tick_handler,
70		}
71	}
72}
73
74#[cfg(test)]
75mod tests {
76	use super::*;
77	use std::error::Error;
78	#[test]
79	fn test_events() -> Result<(), Box<dyn Error>> {
80		let kernel_logs = KernelLogs::default();
81		let events = Events::new(100, &kernel_logs);
82		let mut i = 0;
83		loop {
84			let tx = events.tx.clone();
85			thread::spawn(move || {
86				let _ = tx.send(Event::Input(Key::Char(
87					std::char::from_digit(i, 10).unwrap_or('x'),
88				)));
89			});
90			i += 1;
91			match events.rx.recv()? {
92				Event::Input(v) => {
93					if v == Key::Char('9') {
94						break;
95					}
96				}
97				Event::Tick => thread::sleep(Duration::from_millis(100)),
98				Event::Kernel(log) => assert!(!log.is_empty()),
99			}
100		}
101		Ok(())
102	}
103}