1use crate::context::{EventContext, UserContext};
8use crate::execution::phase::MicroStepHandler;
9use crate::modeling::event::Event;
10use crate::modeling::hook::Hook;
11use crate::modeling::model::Model;
12use std::collections::VecDeque;
13
14pub struct EventPhase<E, M: Model<E>> {
20 context: EventContext<E, M>,
21 ready_events: VecDeque<Event<E>>,
22}
23
24impl<E, M: Model<E>> EventPhase<E, M> {
25 pub(crate) fn new(context: EventContext<E, M>, ready_events: VecDeque<Event<E>>) -> Self {
27 EventPhase {
28 context,
29 ready_events,
30 }
31 }
32
33 pub fn get_context(&mut self) -> &mut EventContext<E, M> {
35 &mut self.context
36 }
37
38 pub fn complete_event_phase(self, model: &M) -> MicroStepHandler<EventContext<E, M>> {
42 self.context.hook().after_event_phase(
43 model,
44 self.context.current_tick(),
45 self.context.current_micro_step(),
46 );
47
48 MicroStepHandler::new(self.context)
49 }
50
51 pub fn take_one(&mut self) -> Option<Event<E>> {
53 self.ready_events.pop_front()
54 }
55
56 pub fn take_one_if<F>(&mut self, predicate: F) -> Option<Event<E>>
58 where
59 F: FnOnce(&Event<E>) -> bool,
60 {
61 self.ready_events.pop_front_if(|e| predicate(e))
64 }
65
66 pub fn take_front_if<F>(&mut self, predicate: F) -> Option<Event<E>>
68 where
69 F: FnOnce(&Event<E>) -> bool,
70 {
71 if self.ready_events.front().is_some_and(predicate) {
72 self.ready_events.pop_front()
73 } else {
74 None
75 }
76 }
77
78 pub fn take_all(&mut self) -> VecDeque<Event<E>> {
80 std::mem::take(&mut self.ready_events)
81 }
82
83 pub fn take_all_if<F>(&mut self, predicate: F) -> VecDeque<Event<E>>
87 where
88 F: FnMut(&Event<E>) -> bool,
89 {
90 let all_events = std::mem::take(&mut self.ready_events);
91
92 let (taken, remaining): (VecDeque<_>, VecDeque<_>) =
93 all_events.into_iter().partition(predicate);
94
95 self.ready_events = remaining;
96
97 taken
98 }
99
100 pub fn handle_event(&mut self, model: &mut M, event: Event<E>) {
104 self.context.hook().before_event(
105 model,
106 self.context.current_tick(),
107 self.context.current_micro_step(),
108 &event,
109 );
110 model.handle_event(self.get_context(), &event);
111 self.context.hook().after_event(
112 model,
113 self.context.current_tick(),
114 self.context.current_micro_step(),
115 &event,
116 );
117 }
118
119 pub fn discard(&mut self, model: &M, event: Event<E>) {
123 self.context.hook().discard_event(
124 model,
125 self.context.current_tick(),
126 self.context.current_micro_step(),
127 &event,
128 );
129 }
130}
131
132#[cfg(test)]
133mod tests {
134 use super::*;
135 use crate::context::{EventContext, UserContext};
136 use crate::event_scheduler::EventScheduler;
137 use crate::modeling::event::{Event, EventPriority};
138 use crate::modeling::hook::instance::{HookDelegate, SharedHook};
139 use crate::modeling::model::Model;
140 use crate::primitive::id::EventId;
141 use crate::primitive::time::{Duration, MicroStep, MicroStepStatus, SimTime, TickStatus};
142 use crate::source_handler::{SourceHandler, SourceReadyEntry, SourceView};
143 use std::collections::VecDeque;
144 use std::rc::Rc;
145 use std::sync::Mutex;
146
147 #[derive(Debug, PartialEq, Eq, Clone, Copy)]
148 enum TestEvent {
149 A,
150 B,
151 C,
152 }
153
154 struct TestModel {
155 handled_events: Vec<TestEvent>,
156 }
157
158 impl Model<TestEvent> for TestModel {
159 fn handle_event(
160 &mut self,
161 _context: &mut EventContext<TestEvent, Self>,
162 event: &Event<TestEvent>,
163 ) {
164 self.handled_events.push(event.payload);
165 }
166 }
167
168 struct DiscardHook {
170 discarded_events: Rc<Mutex<Vec<TestEvent>>>,
171 }
172
173 impl Hook<TestEvent, TestModel> for DiscardHook {
174 fn before_simulation(&self, _model: &TestModel) {
175 }
177
178 fn after_simulation(&self, _model: &TestModel, _end_tick: SimTime) {
179 }
181
182 fn before_tick(
183 &self,
184 _model: &TestModel,
185 _current_tick: SimTime,
186 _skipped_duration: Duration,
187 ) {
188 }
190
191 fn after_tick(
192 &self,
193 _model: &TestModel,
194 _current_tick: SimTime,
195 _last_micro_step: MicroStep,
196 ) {
197 }
199
200 fn before_micro_step(
201 &self,
202 _model: &TestModel,
203 _current_tick: SimTime,
204 _current_micro_step: MicroStep,
205 ) {
206 }
208
209 fn after_micro_step(
210 &self,
211 _model: &TestModel,
212 _current_tick: SimTime,
213 _current_micro_step: MicroStep,
214 ) {
215 }
217
218 fn on_discard_remain_micro_step(
219 &self,
220 _model: &TestModel,
221 _current_tick: SimTime,
222 _first_discarded_micro_step: MicroStep,
223 _discarded_sources: &[SourceReadyEntry],
224 _discarded_events: &[Event<TestEvent>],
225 ) {
226 }
228
229 fn before_register_source(&self, _model: &TestModel, _name: &str) {
230 }
232
233 fn after_register_source(&self, _model: &TestModel, _name: &str) {
234 }
236
237 fn before_source_phase(
238 &self,
239 _model: &TestModel,
240 _current_tick: SimTime,
241 _current_micro_step: MicroStep,
242 ) {
243 }
245
246 fn before_source(
247 &self,
248 _model: &TestModel,
249 _current_tick: SimTime,
250 _current_micro_step: MicroStep,
251 _source_view: &SourceView,
252 ) {
253 }
255
256 fn after_source(
257 &self,
258 _model: &TestModel,
259 _current_tick: SimTime,
260 _current_micro_step: MicroStep,
261 _source_view: &SourceView,
262 _computed_next_fire: Option<SimTime>,
263 ) {
264 }
266
267 fn cancel_source(
268 &self,
269 _model: &TestModel,
270 _current_tick: SimTime,
271 _current_micro_step: MicroStep,
272 _scheduled_at: SimTime,
273 _source_view: &SourceView,
274 ) {
275 }
277
278 fn discard_source(
279 &self,
280 _model: &TestModel,
281 _current_tick: SimTime,
282 _current_micro_step: MicroStep,
283 _source_view: &SourceView,
284 ) {
285 }
287
288 fn after_source_phase(
289 &self,
290 _model: &TestModel,
291 _current_tick: SimTime,
292 _current_micro_step: MicroStep,
293 ) {
294 }
296
297 fn before_event_phase(
298 &self,
299 _model: &TestModel,
300 _current_tick: SimTime,
301 _current_micro_step: MicroStep,
302 ) {
303 }
305
306 fn before_event(
307 &self,
308 _model: &TestModel,
309 _current_tick: SimTime,
310 _current_micro_step: MicroStep,
311 _event: &Event<TestEvent>,
312 ) {
313 }
315
316 fn after_event(
317 &self,
318 _model: &TestModel,
319 _current_tick: SimTime,
320 _current_micro_step: MicroStep,
321 _event: &Event<TestEvent>,
322 ) {
323 }
325
326 fn cancel_event(
327 &self,
328 _model: &TestModel,
329 _current_tick: SimTime,
330 _current_micro_step: MicroStep,
331 _scheduled_at: SimTime,
332 _event: &Event<TestEvent>,
333 ) {
334 }
336
337 fn discard_event(
338 &self,
339 _model: &TestModel,
340 _current_tick: SimTime,
341 _current_micro_step: MicroStep,
342 event: &Event<TestEvent>,
343 ) {
344 self.discarded_events.lock().unwrap().push(event.payload);
345 }
346
347 fn after_event_phase(
348 &self,
349 _model: &TestModel,
350 _current_tick: SimTime,
351 _current_micro_step: MicroStep,
352 ) {
353 }
355 }
356
357 fn setup_event_phase() -> (EventPhase<TestEvent, TestModel>, TestModel) {
359 let model = TestModel {
360 handled_events: Vec::new(),
361 };
362 let event_context = EventContext {
363 current_tick_status: TickStatus::initialize(),
364 current_micro_step_status: MicroStepStatus::initialize(),
365 hook_delegate: HookDelegate::new(),
366 source_handler: SourceHandler::new(),
367 event_scheduler: EventScheduler::new(),
368 };
369
370 let mut ready_events = VecDeque::new();
371 ready_events.push_back(Event::new(
372 EventId::new(0),
373 EventPriority::minimum(),
374 TestEvent::A,
375 ));
376 ready_events.push_back(Event::new(
377 EventId::new(1),
378 EventPriority::minimum(),
379 TestEvent::B,
380 ));
381 ready_events.push_back(Event::new(
382 EventId::new(2),
383 EventPriority::minimum(),
384 TestEvent::C,
385 ));
386
387 (EventPhase::new(event_context, ready_events), model)
388 }
389
390 #[test]
391 fn test_new() {
392 let (event_phase, _) = setup_event_phase();
393 assert_eq!(event_phase.ready_events.len(), 3);
394 }
395
396 #[test]
397 fn test_get_context() {
398 let (mut event_phase, _) = setup_event_phase();
399 let context = event_phase.get_context();
400 assert_eq!(context.current_tick(), SimTime::zero());
401 }
402
403 #[test]
404 fn test_take_one() {
405 let (mut event_phase, _) = setup_event_phase();
406 let event = event_phase.take_one().unwrap();
407 assert_eq!(event.payload, TestEvent::A);
408 assert_eq!(event_phase.ready_events.len(), 2);
409 }
410
411 #[test]
412 fn test_take_one_if() {
413 let (mut event_phase_a, _) = setup_event_phase();
415 let event_a = event_phase_a
416 .take_one_if(|e| e.payload == TestEvent::A)
417 .unwrap();
418 assert_eq!(event_a.payload, TestEvent::A);
419 assert_eq!(event_phase_a.ready_events.len(), 2);
420 assert_eq!(
421 event_phase_a.ready_events.front().unwrap().payload,
422 TestEvent::B
423 );
424
425 let (mut event_phase_b, _) = setup_event_phase();
427 let event_b = event_phase_b.take_one_if(|_| false);
428 assert!(event_b.is_none());
429 assert_eq!(event_phase_b.ready_events.len(), 3);
430 }
431
432 #[test]
433 fn test_take_front_if() {
434 let (mut event_phase, _) = setup_event_phase();
435 let event_a = event_phase
436 .take_front_if(|e| e.payload == TestEvent::A)
437 .unwrap();
438 assert_eq!(event_a.payload, TestEvent::A);
439 assert_eq!(event_phase.ready_events.len(), 2);
440
441 let event_b = event_phase.take_front_if(|e| e.payload == TestEvent::A);
442 assert!(event_b.is_none());
443 assert_eq!(event_phase.ready_events.len(), 2);
444 }
445
446 #[test]
447 fn test_take_all() {
448 let (mut event_phase, _) = setup_event_phase();
449 let all_events = event_phase.take_all();
450 assert_eq!(all_events.len(), 3);
451 assert_eq!(event_phase.ready_events.len(), 0);
452 }
453
454 #[test]
455 fn test_take_all_if() {
456 let (mut event_phase, _) = setup_event_phase();
457 event_phase.ready_events.push_back(Event::new(
458 EventId::new(3),
459 EventPriority::minimum(),
460 TestEvent::A,
461 ));
462
463 let taken_events = event_phase.take_all_if(|e| e.payload == TestEvent::A);
464 assert_eq!(taken_events.len(), 2); assert_eq!(taken_events.front().unwrap().payload, TestEvent::A);
466 assert_eq!(taken_events.get(1).unwrap().payload, TestEvent::A);
467
468 assert_eq!(event_phase.ready_events.len(), 2);
469 assert_eq!(
470 event_phase.ready_events.front().unwrap().payload,
471 TestEvent::B
472 );
473 assert_eq!(
474 event_phase.ready_events.get(1).unwrap().payload,
475 TestEvent::C
476 );
477 }
478
479 #[test]
480 fn test_handle_event() {
481 let (mut event_phase, mut model) = setup_event_phase();
482 let event = Event::new(EventId::new(3), EventPriority::minimum(), TestEvent::A);
483 event_phase.handle_event(&mut model, event);
484 assert_eq!(model.handled_events.len(), 1);
485 assert_eq!(model.handled_events[0], TestEvent::A);
486 }
487
488 #[test]
489 fn test_discard() {
490 let (mut event_phase, model) = setup_event_phase();
491 let hook = SharedHook::new(DiscardHook {
492 discarded_events: Rc::new(Mutex::new(Vec::new())),
493 });
494 event_phase
495 .get_context()
496 .hook_delegate
497 .add_shared_hook(hook.clone());
498
499 let event = Event::new(EventId::new(3), EventPriority::minimum(), TestEvent::A);
500 event_phase.discard(&model, event);
501 assert_eq!(hook.get_ref().discarded_events.lock().unwrap().len(), 1);
502 assert_eq!(
503 hook.get_ref().discarded_events.lock().unwrap()[0],
504 TestEvent::A
505 );
506 }
507
508 #[test]
509 fn test_complete_event_phase() {
510 let (event_phase, model) = setup_event_phase();
511 let micro_step_handler = event_phase.complete_event_phase(&model);
512 assert_eq!(
513 micro_step_handler.ref_context().current_tick(),
514 SimTime::zero()
515 );
516 }
517}