shape_runtime/simulation/
event_scheduler.rs1use std::cmp::{Ordering, Reverse};
7use std::collections::BinaryHeap;
8
9#[derive(Debug, Clone)]
11pub struct ScheduledEvent {
12 pub time: i64,
14 pub event_type: u32,
16 pub payload: u64,
18 sequence: u64,
20}
21
22impl ScheduledEvent {
23 pub fn new(time: i64, event_type: u32, payload: u64, sequence: u64) -> Self {
25 Self {
26 time,
27 event_type,
28 payload,
29 sequence,
30 }
31 }
32}
33
34impl PartialEq for ScheduledEvent {
36 fn eq(&self, other: &Self) -> bool {
37 self.time == other.time && self.sequence == other.sequence
38 }
39}
40
41impl Eq for ScheduledEvent {}
42
43impl PartialOrd for ScheduledEvent {
44 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
45 Some(self.cmp(other))
46 }
47}
48
49impl Ord for ScheduledEvent {
50 fn cmp(&self, other: &Self) -> Ordering {
51 match self.time.cmp(&other.time) {
54 Ordering::Equal => self.sequence.cmp(&other.sequence),
55 ord => ord,
56 }
57 }
58}
59
60#[derive(Debug)]
65pub struct EventQueue {
66 heap: BinaryHeap<Reverse<ScheduledEvent>>,
68 sequence: u64,
70}
71
72impl EventQueue {
73 pub fn new() -> Self {
75 Self {
76 heap: BinaryHeap::new(),
77 sequence: 0,
78 }
79 }
80
81 pub fn with_capacity(capacity: usize) -> Self {
83 Self {
84 heap: BinaryHeap::with_capacity(capacity),
85 sequence: 0,
86 }
87 }
88
89 pub fn schedule(&mut self, time: i64, event_type: u32, payload: u64) {
96 let event = ScheduledEvent::new(time, event_type, payload, self.sequence);
97 self.sequence += 1;
98 self.heap.push(Reverse(event));
99 }
100
101 pub fn pop_due(&mut self, current_time: i64) -> Option<ScheduledEvent> {
105 if let Some(Reverse(event)) = self.heap.peek() {
106 if event.time <= current_time {
107 return self.heap.pop().map(|r| r.0);
108 }
109 }
110 None
111 }
112
113 pub fn peek(&self) -> Option<&ScheduledEvent> {
115 self.heap.peek().map(|r| &r.0)
116 }
117
118 pub fn has_due_events(&self, current_time: i64) -> bool {
120 self.peek().is_some_and(|e| e.time <= current_time)
121 }
122
123 pub fn len(&self) -> usize {
125 self.heap.len()
126 }
127
128 pub fn is_empty(&self) -> bool {
130 self.heap.is_empty()
131 }
132
133 pub fn clear(&mut self) {
135 self.heap.clear();
136 self.sequence = 0;
137 }
138
139 pub fn drain_due(&mut self, current_time: i64) -> Vec<ScheduledEvent> {
141 let mut events = Vec::new();
142 while let Some(event) = self.pop_due(current_time) {
143 events.push(event);
144 }
145 events
146 }
147}
148
149impl Default for EventQueue {
150 fn default() -> Self {
151 Self::new()
152 }
153}
154
155#[cfg(test)]
156mod tests {
157 use super::*;
158
159 #[test]
160 fn test_event_queue_basic() {
161 let mut queue = EventQueue::new();
162
163 queue.schedule(1000, 1, 0);
164 queue.schedule(500, 2, 0);
165 queue.schedule(1500, 3, 0);
166
167 assert_eq!(queue.len(), 3);
168
169 let event = queue.pop_due(1000).unwrap();
171 assert_eq!(event.time, 500);
172 assert_eq!(event.event_type, 2);
173
174 let event = queue.pop_due(1000).unwrap();
176 assert_eq!(event.time, 1000);
177 assert_eq!(event.event_type, 1);
178
179 assert!(queue.pop_due(1000).is_none());
181
182 let event = queue.pop_due(1500).unwrap();
184 assert_eq!(event.time, 1500);
185 assert_eq!(event.event_type, 3);
186
187 assert!(queue.is_empty());
188 }
189
190 #[test]
191 fn test_event_ordering_same_time() {
192 let mut queue = EventQueue::new();
193
194 queue.schedule(1000, 1, 0);
196 queue.schedule(1000, 2, 0);
197 queue.schedule(1000, 3, 0);
198
199 let e1 = queue.pop_due(1000).unwrap();
201 let e2 = queue.pop_due(1000).unwrap();
202 let e3 = queue.pop_due(1000).unwrap();
203
204 assert_eq!(e1.event_type, 1);
205 assert_eq!(e2.event_type, 2);
206 assert_eq!(e3.event_type, 3);
207 }
208}