bevy_ecs/event/collections.rs
1use alloc::vec::Vec;
2use bevy_ecs::{
3 change_detection::MaybeLocation,
4 event::{Event, EventCursor, EventId, EventInstance},
5 resource::Resource,
6};
7use core::{
8 marker::PhantomData,
9 ops::{Deref, DerefMut},
10};
11#[cfg(feature = "bevy_reflect")]
12use {
13 bevy_ecs::reflect::ReflectResource,
14 bevy_reflect::{std_traits::ReflectDefault, Reflect},
15};
16
17/// An event collection that represents the events that occurred within the last two
18/// [`Events::update`] calls.
19/// Events can be written to using an [`EventWriter`]
20/// and are typically cheaply read using an [`EventReader`].
21///
22/// Each event can be consumed by multiple systems, in parallel,
23/// with consumption tracked by the [`EventReader`] on a per-system basis.
24///
25/// If no [ordering](https://github.com/bevyengine/bevy/blob/main/examples/ecs/ecs_guide.rs)
26/// is applied between writing and reading systems, there is a risk of a race condition.
27/// This means that whether the events arrive before or after the next [`Events::update`] is unpredictable.
28///
29/// This collection is meant to be paired with a system that calls
30/// [`Events::update`] exactly once per update/frame.
31///
32/// [`event_update_system`] is a system that does this, typically initialized automatically using
33/// [`add_event`](https://docs.rs/bevy/*/bevy/app/struct.App.html#method.add_event).
34/// [`EventReader`]s are expected to read events from this collection at least once per loop/frame.
35/// Events will persist across a single frame boundary and so ordering of event producers and
36/// consumers is not critical (although poorly-planned ordering may cause accumulating lag).
37/// If events are not handled by the end of the frame after they are updated, they will be
38/// dropped silently.
39///
40/// # Example
41/// ```
42/// use bevy_ecs::event::{Event, Events};
43///
44/// #[derive(Event)]
45/// struct MyEvent {
46/// value: usize
47/// }
48///
49/// // setup
50/// let mut events = Events::<MyEvent>::default();
51/// let mut cursor = events.get_cursor();
52///
53/// // run this once per update/frame
54/// events.update();
55///
56/// // somewhere else: send an event
57/// events.send(MyEvent { value: 1 });
58///
59/// // somewhere else: read the events
60/// for event in cursor.read(&events) {
61/// assert_eq!(event.value, 1)
62/// }
63///
64/// // events are only processed once per reader
65/// assert_eq!(cursor.read(&events).count(), 0);
66/// ```
67///
68/// # Details
69///
70/// [`Events`] is implemented using a variation of a double buffer strategy.
71/// Each call to [`update`](Events::update) swaps buffers and clears out the oldest one.
72/// - [`EventReader`]s will read events from both buffers.
73/// - [`EventReader`]s that read at least once per update will never drop events.
74/// - [`EventReader`]s that read once within two updates might still receive some events
75/// - [`EventReader`]s that read after two updates are guaranteed to drop all events that occurred
76/// before those updates.
77///
78/// The buffers in [`Events`] will grow indefinitely if [`update`](Events::update) is never called.
79///
80/// An alternative call pattern would be to call [`update`](Events::update)
81/// manually across frames to control when events are cleared.
82/// This complicates consumption and risks ever-expanding memory usage if not cleaned up,
83/// but can be done by adding your event as a resource instead of using
84/// [`add_event`](https://docs.rs/bevy/*/bevy/app/struct.App.html#method.add_event).
85///
86/// [Example usage.](https://github.com/bevyengine/bevy/blob/latest/examples/ecs/event.rs)
87/// [Example usage standalone.](https://github.com/bevyengine/bevy/blob/latest/crates/bevy_ecs/examples/events.rs)
88///
89/// [`EventReader`]: super::EventReader
90/// [`EventWriter`]: super::EventWriter
91/// [`event_update_system`]: super::event_update_system
92#[derive(Debug, Resource)]
93#[cfg_attr(feature = "bevy_reflect", derive(Reflect), reflect(Resource, Default))]
94pub struct Events<E: Event> {
95 /// Holds the oldest still active events.
96 /// Note that `a.start_event_count + a.len()` should always be equal to `events_b.start_event_count`.
97 pub(crate) events_a: EventSequence<E>,
98 /// Holds the newer events.
99 pub(crate) events_b: EventSequence<E>,
100 pub(crate) event_count: usize,
101}
102
103// Derived Default impl would incorrectly require E: Default
104impl<E: Event> Default for Events<E> {
105 fn default() -> Self {
106 Self {
107 events_a: Default::default(),
108 events_b: Default::default(),
109 event_count: Default::default(),
110 }
111 }
112}
113
114impl<E: Event> Events<E> {
115 /// Returns the index of the oldest event stored in the event buffer.
116 pub fn oldest_event_count(&self) -> usize {
117 self.events_a.start_event_count
118 }
119
120 /// "Sends" an `event` by writing it to the current event buffer.
121 /// [`EventReader`](super::EventReader)s can then read the event.
122 /// This method returns the [ID](`EventId`) of the sent `event`.
123 #[track_caller]
124 pub fn send(&mut self, event: E) -> EventId<E> {
125 self.send_with_caller(event, MaybeLocation::caller())
126 }
127
128 pub(crate) fn send_with_caller(&mut self, event: E, caller: MaybeLocation) -> EventId<E> {
129 let event_id = EventId {
130 id: self.event_count,
131 caller,
132 _marker: PhantomData,
133 };
134 #[cfg(feature = "detailed_trace")]
135 tracing::trace!("Events::send() -> id: {}", event_id);
136
137 let event_instance = EventInstance { event_id, event };
138
139 self.events_b.push(event_instance);
140 self.event_count += 1;
141
142 event_id
143 }
144
145 /// Sends a list of `events` all at once, which can later be read by [`EventReader`](super::EventReader)s.
146 /// This is more efficient than sending each event individually.
147 /// This method returns the [IDs](`EventId`) of the sent `events`.
148 #[track_caller]
149 pub fn send_batch(&mut self, events: impl IntoIterator<Item = E>) -> SendBatchIds<E> {
150 let last_count = self.event_count;
151
152 self.extend(events);
153
154 SendBatchIds {
155 last_count,
156 event_count: self.event_count,
157 _marker: PhantomData,
158 }
159 }
160
161 /// Sends the default value of the event. Useful when the event is an empty struct.
162 /// This method returns the [ID](`EventId`) of the sent `event`.
163 #[track_caller]
164 pub fn send_default(&mut self) -> EventId<E>
165 where
166 E: Default,
167 {
168 self.send(Default::default())
169 }
170
171 /// Gets a new [`EventCursor`]. This will include all events already in the event buffers.
172 pub fn get_cursor(&self) -> EventCursor<E> {
173 EventCursor::default()
174 }
175
176 /// Gets a new [`EventCursor`]. This will ignore all events already in the event buffers.
177 /// It will read all future events.
178 pub fn get_cursor_current(&self) -> EventCursor<E> {
179 EventCursor {
180 last_event_count: self.event_count,
181 ..Default::default()
182 }
183 }
184
185 /// Swaps the event buffers and clears the oldest event buffer. In general, this should be
186 /// called once per frame/update.
187 ///
188 /// If you need access to the events that were removed, consider using [`Events::update_drain`].
189 pub fn update(&mut self) {
190 core::mem::swap(&mut self.events_a, &mut self.events_b);
191 self.events_b.clear();
192 self.events_b.start_event_count = self.event_count;
193 debug_assert_eq!(
194 self.events_a.start_event_count + self.events_a.len(),
195 self.events_b.start_event_count
196 );
197 }
198
199 /// Swaps the event buffers and drains the oldest event buffer, returning an iterator
200 /// of all events that were removed. In general, this should be called once per frame/update.
201 ///
202 /// If you do not need to take ownership of the removed events, use [`Events::update`] instead.
203 #[must_use = "If you do not need the returned events, call .update() instead."]
204 pub fn update_drain(&mut self) -> impl Iterator<Item = E> + '_ {
205 core::mem::swap(&mut self.events_a, &mut self.events_b);
206 let iter = self.events_b.events.drain(..);
207 self.events_b.start_event_count = self.event_count;
208 debug_assert_eq!(
209 self.events_a.start_event_count + self.events_a.len(),
210 self.events_b.start_event_count
211 );
212
213 iter.map(|e| e.event)
214 }
215
216 #[inline]
217 fn reset_start_event_count(&mut self) {
218 self.events_a.start_event_count = self.event_count;
219 self.events_b.start_event_count = self.event_count;
220 }
221
222 /// Removes all events.
223 #[inline]
224 pub fn clear(&mut self) {
225 self.reset_start_event_count();
226 self.events_a.clear();
227 self.events_b.clear();
228 }
229
230 /// Returns the number of events currently stored in the event buffer.
231 #[inline]
232 pub fn len(&self) -> usize {
233 self.events_a.len() + self.events_b.len()
234 }
235
236 /// Returns true if there are no events currently stored in the event buffer.
237 #[inline]
238 pub fn is_empty(&self) -> bool {
239 self.len() == 0
240 }
241
242 /// Creates a draining iterator that removes all events.
243 pub fn drain(&mut self) -> impl Iterator<Item = E> + '_ {
244 self.reset_start_event_count();
245
246 // Drain the oldest events first, then the newest
247 self.events_a
248 .drain(..)
249 .chain(self.events_b.drain(..))
250 .map(|i| i.event)
251 }
252
253 /// Iterates over events that happened since the last "update" call.
254 /// WARNING: You probably don't want to use this call. In most cases you should use an
255 /// [`EventReader`]. You should only use this if you know you only need to consume events
256 /// between the last `update()` call and your call to `iter_current_update_events`.
257 /// If events happen outside that window, they will not be handled. For example, any events that
258 /// happen after this call and before the next `update()` call will be dropped.
259 ///
260 /// [`EventReader`]: super::EventReader
261 pub fn iter_current_update_events(&self) -> impl ExactSizeIterator<Item = &E> {
262 self.events_b.iter().map(|i| &i.event)
263 }
264
265 /// Get a specific event by id if it still exists in the events buffer.
266 pub fn get_event(&self, id: usize) -> Option<(&E, EventId<E>)> {
267 if id < self.oldest_event_count() {
268 return None;
269 }
270
271 let sequence = self.sequence(id);
272 let index = id.saturating_sub(sequence.start_event_count);
273
274 sequence
275 .get(index)
276 .map(|instance| (&instance.event, instance.event_id))
277 }
278
279 /// Which event buffer is this event id a part of.
280 fn sequence(&self, id: usize) -> &EventSequence<E> {
281 if id < self.events_b.start_event_count {
282 &self.events_a
283 } else {
284 &self.events_b
285 }
286 }
287}
288
289impl<E: Event> Extend<E> for Events<E> {
290 #[track_caller]
291 fn extend<I>(&mut self, iter: I)
292 where
293 I: IntoIterator<Item = E>,
294 {
295 let old_count = self.event_count;
296 let mut event_count = self.event_count;
297 let events = iter.into_iter().map(|event| {
298 let event_id = EventId {
299 id: event_count,
300 caller: MaybeLocation::caller(),
301 _marker: PhantomData,
302 };
303 event_count += 1;
304 EventInstance { event_id, event }
305 });
306
307 self.events_b.extend(events);
308
309 if old_count != event_count {
310 #[cfg(feature = "detailed_trace")]
311 tracing::trace!(
312 "Events::extend() -> ids: ({}..{})",
313 self.event_count,
314 event_count
315 );
316 }
317
318 self.event_count = event_count;
319 }
320}
321
322#[derive(Debug)]
323#[cfg_attr(feature = "bevy_reflect", derive(Reflect), reflect(Default))]
324pub(crate) struct EventSequence<E: Event> {
325 pub(crate) events: Vec<EventInstance<E>>,
326 pub(crate) start_event_count: usize,
327}
328
329// Derived Default impl would incorrectly require E: Default
330impl<E: Event> Default for EventSequence<E> {
331 fn default() -> Self {
332 Self {
333 events: Default::default(),
334 start_event_count: Default::default(),
335 }
336 }
337}
338
339impl<E: Event> Deref for EventSequence<E> {
340 type Target = Vec<EventInstance<E>>;
341
342 fn deref(&self) -> &Self::Target {
343 &self.events
344 }
345}
346
347impl<E: Event> DerefMut for EventSequence<E> {
348 fn deref_mut(&mut self) -> &mut Self::Target {
349 &mut self.events
350 }
351}
352
353/// [`Iterator`] over sent [`EventIds`](`EventId`) from a batch.
354pub struct SendBatchIds<E> {
355 last_count: usize,
356 event_count: usize,
357 _marker: PhantomData<E>,
358}
359
360impl<E: Event> Iterator for SendBatchIds<E> {
361 type Item = EventId<E>;
362
363 fn next(&mut self) -> Option<Self::Item> {
364 if self.last_count >= self.event_count {
365 return None;
366 }
367
368 let result = Some(EventId {
369 id: self.last_count,
370 caller: MaybeLocation::caller(),
371 _marker: PhantomData,
372 });
373
374 self.last_count += 1;
375
376 result
377 }
378}
379
380impl<E: Event> ExactSizeIterator for SendBatchIds<E> {
381 fn len(&self) -> usize {
382 self.event_count.saturating_sub(self.last_count)
383 }
384}
385
386#[cfg(test)]
387mod tests {
388 use crate::event::Events;
389 use bevy_ecs_macros::Event;
390
391 #[test]
392 fn iter_current_update_events_iterates_over_current_events() {
393 #[derive(Event, Clone)]
394 struct TestEvent;
395
396 let mut test_events = Events::<TestEvent>::default();
397
398 // Starting empty
399 assert_eq!(test_events.len(), 0);
400 assert_eq!(test_events.iter_current_update_events().count(), 0);
401 test_events.update();
402
403 // Sending one event
404 test_events.send(TestEvent);
405
406 assert_eq!(test_events.len(), 1);
407 assert_eq!(test_events.iter_current_update_events().count(), 1);
408 test_events.update();
409
410 // Sending two events on the next frame
411 test_events.send(TestEvent);
412 test_events.send(TestEvent);
413
414 assert_eq!(test_events.len(), 3); // Events are double-buffered, so we see 1 + 2 = 3
415 assert_eq!(test_events.iter_current_update_events().count(), 2);
416 test_events.update();
417
418 // Sending zero events
419 assert_eq!(test_events.len(), 2); // Events are double-buffered, so we see 2 + 0 = 2
420 assert_eq!(test_events.iter_current_update_events().count(), 0);
421 }
422}