Skip to main content

ass_editor/events/
dispatch.rs

1//! Event dispatch for [`EventChannel`].
2//!
3//! Implements synchronous and batched delivery to registered handlers,
4//! statistics bookkeeping, and the optional asynchronous channel plumbing
5//! gated behind the `async` feature.
6
7use super::channel::EventChannel;
8use super::DocumentEvent;
9use crate::core::Result;
10
11#[cfg(not(feature = "std"))]
12use alloc::vec::Vec;
13
14#[cfg(feature = "async")]
15use futures::channel::mpsc;
16
17impl EventChannel {
18    /// Dispatch an event to all registered handlers
19    pub fn dispatch(&mut self, event: DocumentEvent) -> Result<()> {
20        #[cfg(feature = "std")]
21        let start_time = std::time::Instant::now();
22
23        self.stats.events_dispatched += 1;
24
25        let mut filtered_count = 0;
26        #[cfg(feature = "std")]
27        let mut processed_count = 0;
28
29        #[cfg(feature = "multi-thread")]
30        {
31            let mut handlers =
32                self.handlers
33                    .write()
34                    .map_err(|_| crate::core::EditorError::ThreadSafetyError {
35                        message: "Failed to acquire write lock for handlers".to_string(),
36                    })?;
37
38            for handler_info in handlers.iter_mut() {
39                if handler_info.filter.matches(&event) {
40                    handler_info.handler.handle_event(&event)?;
41                    handler_info.events_processed += 1;
42                    #[cfg(feature = "std")]
43                    {
44                        processed_count += 1;
45                    }
46                } else {
47                    filtered_count += 1;
48                }
49            }
50        }
51
52        #[cfg(not(feature = "multi-thread"))]
53        {
54            let mut handlers = self.handlers.borrow_mut();
55
56            for handler_info in handlers.iter_mut() {
57                if handler_info.filter.matches(&event) {
58                    handler_info.handler.handle_event(&event)?;
59                    handler_info.events_processed += 1;
60                    #[cfg(feature = "std")]
61                    {
62                        processed_count += 1;
63                    }
64                } else {
65                    filtered_count += 1;
66                }
67            }
68        }
69
70        self.stats.events_filtered += filtered_count;
71
72        // Update average processing time
73        #[cfg(feature = "std")]
74        {
75            let processing_time = start_time.elapsed().as_micros() as u64;
76            if self.stats.events_dispatched == 1 {
77                self.stats.avg_processing_time_us = processing_time;
78            } else {
79                self.stats.avg_processing_time_us =
80                    (self.stats.avg_processing_time_us + processing_time) / 2;
81            }
82        }
83
84        if self.config.enable_logging {
85            #[cfg(feature = "std")]
86            eprintln!(
87                "Event dispatched: {} -> {} handlers (filtered: {})",
88                event.description(),
89                processed_count,
90                filtered_count
91            );
92        }
93
94        Ok(())
95    }
96
97    /// Dispatch multiple events in a batch
98    pub fn dispatch_batch(&mut self, events: Vec<DocumentEvent>) -> Result<()> {
99        if self.config.enable_batching && events.len() <= self.config.max_batch_size {
100            // Process as a batch
101            for event in events {
102                self.dispatch(event)?;
103            }
104        } else {
105            // Process individually
106            for event in events {
107                self.dispatch(event)?;
108            }
109        }
110        Ok(())
111    }
112
113    /// Setup async event processing (requires async feature)
114    #[cfg(feature = "async")]
115    pub fn setup_async(&mut self) -> mpsc::UnboundedReceiver<DocumentEvent> {
116        let (sender, receiver) = mpsc::unbounded();
117        self.async_sender = Some(sender);
118        receiver
119    }
120
121    /// Dispatch event asynchronously (requires async feature)
122    #[cfg(feature = "async")]
123    pub fn dispatch_async(&mut self, event: DocumentEvent) -> Result<()> {
124        if let Some(ref sender) = self.async_sender {
125            sender
126                .unbounded_send(event)
127                .map_err(|_| crate::core::EditorError::CommandFailed {
128                    message: "Failed to send async event".to_string(),
129                })?;
130            self.stats.async_events_queued += 1;
131        } else {
132            return Err(crate::core::EditorError::FeatureNotEnabled {
133                feature: "async event processing".to_string(),
134                required_feature: "async".to_string(),
135            });
136        }
137        Ok(())
138    }
139}