des_sim/execution/strategy/continue_strategy/
limit_discard.rs1use crate::execution::phase::UncheckedActiveExecutor;
10use crate::execution::strategy::{ContinueStrategy, ContinuousStrategyResult};
11use crate::modeling::model::Model;
12
13#[derive(Clone)]
21pub struct LimitDiscardStrategy {
22 limit_micro_step_count: u64,
23}
24
25impl<E, M: Model<E>, RunnerError> ContinueStrategy<E, M, RunnerError> for LimitDiscardStrategy {
26 type Err = RunnerError;
27
28 fn handle_micro_step_continue(
30 &mut self,
31 model: &M,
32 unchecked: UncheckedActiveExecutor<E, M>,
33 ) -> ContinuousStrategyResult<E, M, Self::Err> {
34 let current_micro_step = unchecked.current_micro_step();
35
36 if current_micro_step.value() < self.limit_micro_step_count {
38 return Ok(unchecked.into_active_executor());
39 }
40
41 let mut next_active = unchecked.into_active_executor();
43 next_active.discard_remain_micro_step(model);
45 Ok(next_active)
46 }
47}
48
49impl LimitDiscardStrategy {
50 pub fn new(limit_micro_step_count: u64) -> Self {
55 LimitDiscardStrategy {
56 limit_micro_step_count,
57 }
58 }
59}
60
61#[cfg(test)]
62mod tests {
63 use super::*;
64 use crate::context::{ActiveExecutorContext, EventContext};
65 use crate::event_scheduler::EventScheduler;
66 use crate::modeling::event::Event;
67 use crate::modeling::hook::instance::HookDelegate;
68 use crate::primitive::time::{MicroStep, MicroStepStatus, TickStatus};
69 use crate::source_handler::SourceHandler;
70 use std::convert::Infallible;
71
72 #[derive(Debug, PartialEq, Eq, Clone, Copy)]
73 enum TestEvent {}
74
75 struct TestModel;
76
77 impl Model<TestEvent> for TestModel {
78 fn handle_event(
79 &mut self,
80 _context: &mut EventContext<TestEvent, Self>,
81 _event: &Event<TestEvent>,
82 ) {
83 }
84 }
85
86 fn create_unchecked_executor(
88 micro_step_val: u64,
89 ) -> UncheckedActiveExecutor<TestEvent, TestModel> {
90 let active_context = ActiveExecutorContext {
91 current_tick_status: TickStatus::initialize(),
92 next_micro_step_status: MicroStepStatus::new(MicroStep::new(micro_step_val + 1)),
93 hook_delegate: HookDelegate::new(),
94 source_handler: SourceHandler::new(),
95 event_scheduler: EventScheduler::new(),
96 };
97 UncheckedActiveExecutor::new(active_context, MicroStep::new(micro_step_val))
98 }
99
100 #[test]
101 fn test_limit_discard_strategy_under_limit() {
102 let model = TestModel;
103 let mut strategy = LimitDiscardStrategy::new(5);
104
105 let unchecked = create_unchecked_executor(4);
107 let result: ContinuousStrategyResult<TestEvent, TestModel, Infallible> =
108 strategy.handle_micro_step_continue(&model, unchecked);
109
110 assert!(
112 result.is_ok(),
113 "Strategy failed to continue when under limit."
114 );
115 }
116
117 #[test]
118 fn test_limit_discard_strategy_reach_limit() {
119 let model = TestModel;
120 let mut strategy = LimitDiscardStrategy::new(5);
121
122 let unchecked = create_unchecked_executor(5);
124 let result: ContinuousStrategyResult<TestEvent, TestModel, Infallible> =
125 strategy.handle_micro_step_continue(&model, unchecked);
126
127 assert!(
130 result.is_ok(),
131 "Strategy failed to continue after reaching limit."
132 );
133 }
134}