Skip to main content

goud_engine/core/event/
queue.rs

1//! Double-buffered event queue storage.
2
3use crate::core::event::traits::Event;
4
5/// Double-buffered event queue for storing events of a single type.
6///
7/// EventQueue uses a double-buffer pattern where events are written to the
8/// active buffer and read from the inactive buffer. At the end of each frame,
9/// `swap_buffers` is called to switch which buffer is active.
10///
11/// # Double-Buffer Pattern
12///
13/// ```text
14/// Frame N:
15///   - Systems write new events to Buffer A (active write buffer)
16///   - Systems read events from Buffer B (read buffer from Frame N-1)
17///
18/// End of Frame N: swap_buffers()
19///
20/// Frame N+1:
21///   - Systems write new events to Buffer B (now active write buffer)
22///   - Systems read events from Buffer A (read buffer from Frame N)
23/// ```
24///
25/// This pattern ensures:
26/// - Writers and readers never access the same buffer simultaneously
27/// - Events persist for exactly one frame after being written
28/// - No locking required within a single-threaded frame
29///
30/// # Example
31///
32/// ```rust
33/// use goud_engine::core::event::EventQueue;
34///
35/// #[derive(Debug, Clone, PartialEq)]
36/// struct DamageEvent { amount: u32 }
37///
38/// let mut queue: EventQueue<DamageEvent> = EventQueue::new();
39///
40/// // Write to active buffer
41/// queue.send(DamageEvent { amount: 10 });
42/// queue.send(DamageEvent { amount: 25 });
43///
44/// // Read buffer is empty (events are in write buffer)
45/// assert!(queue.drain().collect::<Vec<_>>().is_empty());
46///
47/// // Swap buffers at frame boundary
48/// queue.swap_buffers();
49///
50/// // Now we can read the events
51/// let events: Vec<_> = queue.drain().collect();
52/// assert_eq!(events.len(), 2);
53/// assert_eq!(events[0].amount, 10);
54/// assert_eq!(events[1].amount, 25);
55/// ```
56pub struct EventQueue<E: Event> {
57    /// First buffer for events
58    events_a: Vec<E>,
59    /// Second buffer for events
60    events_b: Vec<E>,
61    /// Which buffer is currently the write buffer.
62    /// - false: Buffer A is write, Buffer B is read
63    /// - true: Buffer B is write, Buffer A is read
64    active_buffer: bool,
65}
66
67impl<E: Event> EventQueue<E> {
68    /// Creates a new empty EventQueue.
69    ///
70    /// Both buffers start empty, and Buffer A is the initial write buffer.
71    ///
72    /// # Example
73    ///
74    /// ```rust
75    /// use goud_engine::core::event::EventQueue;
76    ///
77    /// struct MyEvent { data: i32 }
78    /// let queue: EventQueue<MyEvent> = EventQueue::new();
79    /// assert!(queue.is_empty());
80    /// ```
81    #[must_use]
82    pub fn new() -> Self {
83        Self {
84            events_a: Vec::new(),
85            events_b: Vec::new(),
86            active_buffer: false,
87        }
88    }
89
90    /// Sends an event to the write buffer.
91    ///
92    /// The event will be available for reading after the next `swap_buffers` call.
93    ///
94    /// # Example
95    ///
96    /// ```rust
97    /// use goud_engine::core::event::EventQueue;
98    ///
99    /// struct ScoreEvent { points: i32 }
100    /// let mut queue: EventQueue<ScoreEvent> = EventQueue::new();
101    ///
102    /// queue.send(ScoreEvent { points: 100 });
103    /// queue.send(ScoreEvent { points: 50 });
104    ///
105    /// assert_eq!(queue.len(), 2);
106    /// ```
107    pub fn send(&mut self, event: E) {
108        self.write_buffer_mut().push(event);
109    }
110
111    /// Drains all events from the read buffer, returning an iterator.
112    ///
113    /// After draining, the read buffer will be empty. This is the primary
114    /// way to consume events during a frame.
115    ///
116    /// # Example
117    ///
118    /// ```rust
119    /// use goud_engine::core::event::EventQueue;
120    ///
121    /// #[derive(Debug)]
122    /// struct Event { id: u32 }
123    ///
124    /// let mut queue: EventQueue<Event> = EventQueue::new();
125    /// queue.send(Event { id: 1 });
126    /// queue.send(Event { id: 2 });
127    /// queue.swap_buffers();
128    ///
129    /// for event in queue.drain() {
130    ///     println!("Processing event: {:?}", event);
131    /// }
132    /// ```
133    pub fn drain(&mut self) -> impl Iterator<Item = E> + '_ {
134        self.read_buffer_mut().drain(..)
135    }
136
137    /// Swaps the active and read buffers.
138    ///
139    /// This should be called exactly once per frame, typically at the frame
140    /// boundary. After swapping:
141    /// - The old write buffer becomes the new read buffer
142    /// - The old read buffer (now cleared) becomes the new write buffer
143    ///
144    /// # Example
145    ///
146    /// ```rust
147    /// use goud_engine::core::event::EventQueue;
148    ///
149    /// struct FrameEvent;
150    /// let mut queue: EventQueue<FrameEvent> = EventQueue::new();
151    ///
152    /// // Frame 1: send events
153    /// queue.send(FrameEvent);
154    ///
155    /// // End of Frame 1
156    /// queue.swap_buffers();
157    ///
158    /// // Frame 2: events from Frame 1 are now readable
159    /// let count = queue.drain().count();
160    /// assert_eq!(count, 1);
161    /// ```
162    pub fn swap_buffers(&mut self) {
163        // Clear the read buffer before it becomes the write buffer
164        self.read_buffer_mut().clear();
165        // Swap which buffer is active
166        self.active_buffer = !self.active_buffer;
167    }
168
169    /// Clears both buffers, removing all events.
170    ///
171    /// This is useful for resetting the event system, such as when
172    /// transitioning between game states.
173    ///
174    /// # Example
175    ///
176    /// ```rust
177    /// use goud_engine::core::event::EventQueue;
178    ///
179    /// struct Event;
180    /// let mut queue: EventQueue<Event> = EventQueue::new();
181    ///
182    /// queue.send(Event);
183    /// queue.swap_buffers();
184    /// queue.send(Event);
185    ///
186    /// queue.clear();
187    ///
188    /// assert!(queue.is_empty());
189    /// assert!(queue.drain().next().is_none());
190    /// ```
191    pub fn clear(&mut self) {
192        self.events_a.clear();
193        self.events_b.clear();
194    }
195
196    /// Returns `true` if the write buffer has no pending events.
197    ///
198    /// Note: This only checks the write buffer. The read buffer may still
199    /// contain events from the previous frame.
200    ///
201    /// # Example
202    ///
203    /// ```rust
204    /// use goud_engine::core::event::EventQueue;
205    ///
206    /// struct Event;
207    /// let mut queue: EventQueue<Event> = EventQueue::new();
208    ///
209    /// assert!(queue.is_empty());
210    ///
211    /// queue.send(Event);
212    /// assert!(!queue.is_empty());
213    /// ```
214    #[must_use]
215    pub fn is_empty(&self) -> bool {
216        self.write_buffer().is_empty()
217    }
218
219    /// Returns the number of events in the write buffer.
220    ///
221    /// Note: This only counts events in the write buffer (pending events).
222    /// Use `read_len()` to count events available for reading.
223    ///
224    /// # Example
225    ///
226    /// ```rust
227    /// use goud_engine::core::event::EventQueue;
228    ///
229    /// struct Event;
230    /// let mut queue: EventQueue<Event> = EventQueue::new();
231    ///
232    /// assert_eq!(queue.len(), 0);
233    ///
234    /// queue.send(Event);
235    /// queue.send(Event);
236    /// queue.send(Event);
237    ///
238    /// assert_eq!(queue.len(), 3);
239    /// ```
240    #[must_use]
241    pub fn len(&self) -> usize {
242        self.write_buffer().len()
243    }
244
245    /// Returns the number of events available for reading.
246    ///
247    /// # Example
248    ///
249    /// ```rust
250    /// use goud_engine::core::event::EventQueue;
251    ///
252    /// struct Event;
253    /// let mut queue: EventQueue<Event> = EventQueue::new();
254    ///
255    /// queue.send(Event);
256    /// queue.send(Event);
257    ///
258    /// // Events are in write buffer, not yet readable
259    /// assert_eq!(queue.read_len(), 0);
260    ///
261    /// queue.swap_buffers();
262    ///
263    /// // Now they're in the read buffer
264    /// assert_eq!(queue.read_len(), 2);
265    /// ```
266    #[must_use]
267    pub fn read_len(&self) -> usize {
268        self.read_buffer().len()
269    }
270
271    /// Returns a reference to the write buffer.
272    #[inline]
273    fn write_buffer(&self) -> &Vec<E> {
274        if self.active_buffer {
275            &self.events_b
276        } else {
277            &self.events_a
278        }
279    }
280
281    /// Returns a mutable reference to the write buffer.
282    #[inline]
283    fn write_buffer_mut(&mut self) -> &mut Vec<E> {
284        if self.active_buffer {
285            &mut self.events_b
286        } else {
287            &mut self.events_a
288        }
289    }
290
291    /// Returns a reference to the read buffer.
292    ///
293    /// This is exposed for use by [`crate::core::event::EventReader`] to access events without draining.
294    #[inline]
295    pub fn read_buffer(&self) -> &Vec<E> {
296        if self.active_buffer {
297            &self.events_a
298        } else {
299            &self.events_b
300        }
301    }
302
303    /// Returns a mutable reference to the read buffer.
304    #[inline]
305    fn read_buffer_mut(&mut self) -> &mut Vec<E> {
306        if self.active_buffer {
307            &mut self.events_a
308        } else {
309            &mut self.events_b
310        }
311    }
312}
313
314impl<E: Event> Default for EventQueue<E> {
315    fn default() -> Self {
316        Self::new()
317    }
318}