1use std::io;
2use std::sync::Arc;
3use std::sync::atomic::{AtomicU64, Ordering};
4use std::sync::mpsc::Sender;
5use std::thread::{self, JoinHandle};
6
7use crossterm::event::{self, Event};
8
9use crate::activity::Activity;
10use crate::command::Report;
11
12#[derive(Debug)]
13#[non_exhaustive]
14pub enum Wake<E> {
15 Input(Event),
16 Lost(io::Error),
17 Event(usize, E),
18 Loaded(usize, u64, E),
19 Activity(Activity),
20 Command(usize, Report),
21 Stamped(u64, usize, E),
22 Signal(i32),
23}
24
25pub struct Waker<E> {
26 sender: Sender<Wake<E>>,
27 screen: usize,
28 epoch: Option<Arc<AtomicU64>>,
29}
30
31impl<E> Clone for Waker<E> {
32 fn clone(&self) -> Self {
33 Waker {
34 sender: self.sender.clone(),
35 screen: self.screen,
36 epoch: self.epoch.clone(),
37 }
38 }
39}
40
41impl<E> std::fmt::Debug for Waker<E> {
42 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
43 f.debug_struct("Waker")
44 .field("screen", &self.screen)
45 .finish_non_exhaustive()
46 }
47}
48
49impl<E: Send + 'static> Waker<E> {
50 pub fn new(sender: Sender<Wake<E>>, screen: usize) -> Self {
51 Waker {
52 sender,
53 screen,
54 epoch: None,
55 }
56 }
57
58 pub(crate) fn epoch(mut self, epoch: Arc<AtomicU64>) -> Self {
59 self.epoch = Some(epoch);
60 self
61 }
62
63 pub fn screen(&self) -> usize {
64 self.screen
65 }
66
67 pub fn send(&self, event: E) -> bool {
68 let wake = match &self.epoch {
69 Some(epoch) => Wake::Stamped(epoch.load(Ordering::SeqCst), self.screen, event),
70 None => Wake::Event(self.screen, event),
71 };
72 self.sender.send(wake).is_ok()
73 }
74}
75
76pub fn listen<E: Send + 'static>(sender: Sender<Wake<E>>) -> JoinHandle<()> {
77 thread::spawn(move || {
78 loop {
79 let read = event::read();
80 let failed = read.is_err();
81 let wake = match read {
82 Ok(input) => Wake::Input(input),
83 Err(error) => Wake::Lost(error),
84 };
85 if sender.send(wake).is_err() || failed {
86 return;
87 }
88 }
89 })
90}