1use crate::event::Event;
28use crate::handler::{HandlerFn, HandlerId, HandlerRegistry};
29use crossbeam_channel::{Receiver, RecvTimeoutError, SendError, Sender};
30use std::sync::atomic::{AtomicBool, AtomicU64, Ordering};
31use std::sync::{Arc, Mutex, RwLock};
32use std::time::Duration;
33
34#[derive(Debug, Clone, Copy, PartialEq, Eq)]
37pub enum PutError {
38 Stopped,
40}
41
42pub struct EventEngine {
44 interval: Duration,
46 sender: RwLock<Option<Sender<Event>>>,
49 receiver: Mutex<Option<Receiver<Event>>>,
52 handlers: Arc<HandlerRegistry>,
54 active: Arc<AtomicBool>,
56 worker: Mutex<Option<std::thread::JoinHandle<()>>>,
58 timer: Mutex<Option<std::thread::JoinHandle<()>>>,
60 pending: Arc<AtomicU64>,
62}
63
64impl Default for EventEngine {
65 fn default() -> Self {
66 Self::new()
67 }
68}
69
70impl EventEngine {
71 pub fn new() -> Self {
73 Self::with_interval(Duration::from_secs(1))
74 }
75
76 pub fn with_interval(interval: Duration) -> Self {
78 let (tx, rx) = crossbeam_channel::unbounded();
79 Self {
80 interval,
81 sender: RwLock::new(Some(tx)),
82 receiver: Mutex::new(Some(rx)),
83 handlers: Arc::default(),
84 active: Arc::new(AtomicBool::new(false)),
85 worker: Mutex::new(None),
86 timer: Mutex::new(None),
87 pending: Arc::new(AtomicU64::new(0)),
88 }
89 }
90
91 pub fn start(&self) {
94 let Some(rx) = self.receiver.lock().unwrap().take() else {
97 return;
98 };
99 self.active.store(true, Ordering::SeqCst);
100
101 let worker = std::thread::Builder::new()
102 .name("ek-event-dispatch".into())
103 .spawn({
104 let handlers = self.handlers.clone();
105 let active = self.active.clone();
106 let pending = self.pending.clone();
107 move || run_dispatch(rx, handlers, active, pending)
108 })
109 .expect("spawn dispatch thread");
110
111 let timer = std::thread::Builder::new()
112 .name("ek-event-timer".into())
113 .spawn({
114 let sender = self.sender.read().unwrap().clone();
115 let active = self.active.clone();
116 let step = self.interval;
117 let pending = self.pending.clone();
118 move || run_timer(sender, active, step, pending)
119 })
120 .expect("spawn timer thread");
121
122 *self.worker.lock().unwrap() = Some(worker);
123 *self.timer.lock().unwrap() = Some(timer);
124 }
125
126 pub fn put(&self, event: Event) -> Result<(), PutError> {
129 self.pending.fetch_add(1, Ordering::AcqRel);
130 let sent = match self.sender.read().unwrap().as_ref() {
131 Some(tx) => tx.send(event),
132 None => {
133 self.pending.fetch_sub(1, Ordering::AcqRel);
134 return Err(PutError::Stopped);
135 }
136 };
137 match sent {
138 Ok(()) => Ok(()),
139 Err(SendError(_)) => {
140 self.pending.fetch_sub(1, Ordering::AcqRel);
141 Err(PutError::Stopped)
142 }
143 }
144 }
145
146 pub fn register(&self, event_type: impl Into<String>, f: HandlerFn) -> HandlerId {
149 self.handlers.register(event_type, f)
150 }
151
152 pub fn unregister(&self, id: HandlerId) -> bool {
154 self.handlers.unregister(id)
155 }
156
157 pub fn register_general(&self, f: HandlerFn) -> HandlerId {
159 self.handlers.register_general(f)
160 }
161
162 pub fn unregister_general(&self, id: HandlerId) -> bool {
164 self.handlers.unregister_general(id)
165 }
166
167 pub fn is_active(&self) -> bool {
169 self.active.load(Ordering::SeqCst)
170 }
171
172 pub fn pending_events(&self) -> u64 {
176 self.pending.load(Ordering::SeqCst)
177 }
178
179 pub fn stop(&self) {
182 if !self.active.swap(false, Ordering::SeqCst) {
183 return; }
185 *self.sender.write().unwrap() = None;
187 let timer_handle = self.timer.lock().unwrap().take();
189 if let Some(t) = timer_handle {
190 let _ = t.join();
191 }
192 let worker_handle = self.worker.lock().unwrap().take();
193 if let Some(w) = worker_handle {
194 let _ = w.join();
195 }
196 self.pending.store(0, Ordering::SeqCst);
198 }
199}
200
201fn run_dispatch(
203 rx: Receiver<Event>,
204 handlers: Arc<HandlerRegistry>,
205 active: Arc<AtomicBool>,
206 pending: Arc<AtomicU64>,
207) {
208 const POLL: Duration = Duration::from_secs(1);
209 loop {
210 if !active.load(Ordering::SeqCst) {
211 break;
212 }
213 match rx.recv_timeout(POLL) {
214 Ok(event) => {
215 pending.fetch_sub(1, Ordering::AcqRel);
216 process_event(&event, &handlers);
217 }
218 Err(RecvTimeoutError::Timeout) => continue, Err(RecvTimeoutError::Disconnected) => break,
220 }
221 }
222}
223
224fn run_timer(
226 sender: Option<Sender<Event>>,
227 active: Arc<AtomicBool>,
228 step: Duration,
229 pending: Arc<AtomicU64>,
230) {
231 let Some(sender) = sender else { return };
232 loop {
233 std::thread::sleep(step);
234 if !active.load(Ordering::SeqCst) {
235 break;
236 }
237 pending.fetch_add(1, Ordering::AcqRel);
238 if sender.send(Event::new(crate::EVENT_TIMER)).is_err() {
239 pending.fetch_sub(1, Ordering::AcqRel);
240 break;
241 }
242 }
243}
244
245fn process_event(event: &Event, handlers: &HandlerRegistry) {
248 for f in handlers.snapshot(&event.event_type) {
249 let _ = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| f(event)));
250 }
251}