1use std::collections::VecDeque;
2
3#[derive(Debug, Clone)]
4pub struct PullTimer<T>(VecDeque<(u32, T)>);
5
6impl<T> PullTimer<T> {
7 pub fn new() -> PullTimer<T> {
8 PullTimer(VecDeque::new())
9 }
10
11 pub fn next_in(&self) -> Option<u32> {
12 self.0.front().map(|&(deadline, _)| deadline)
13 }
14
15 pub fn update(&mut self, elapsed: u32) {
16 let mut remaining = elapsed;
17 for (delta, _) in &mut self.0 {
18 let temp = *delta;
19 *delta = delta.saturating_sub(elapsed);
20 remaining = remaining.saturating_sub(temp);
21
22 if remaining == 0 {
23 break;
24 }
25 }
26 }
27
28 pub fn add(&mut self, deadline: u32, event: T) {
29 let mut sum = 0;
30 let mut insertion_point = 0;
31
32 for (index, &(delta, _)) in self.0.iter().enumerate() {
33 if sum + delta > deadline {
34 break;
35 }
36 insertion_point = index + 1;
37 sum += delta;
38 }
39
40 let insertion_delta = deadline - sum;
41
42 if let Some((delta, _)) = &mut self.0.get_mut(insertion_point) {
43 *delta = delta.saturating_sub(insertion_delta);
44 }
45
46 self.0.insert(insertion_point, (insertion_delta, event));
47 }
48
49 pub fn remove(&mut self, event: T) -> Option<u32>
50 where
51 T: PartialEq,
52 {
53 let mut sum = 0;
54 let mut target = None;
55
56 for (index, &(delta, ref element)) in self.0.iter().enumerate() {
57 sum += delta;
58 if *element == event {
59 target = Some(index);
60 break;
61 }
62 }
63
64 let index = target?;
65 let (delta, _) = self.0.remove(index)?;
66
67 if let Some((next_delta, _)) = self.0.get_mut(index) {
68 *next_delta += delta;
69 }
70
71 Some(sum)
72 }
73
74 pub fn poll(&mut self) -> Option<T> {
75 let &(delta, _) = self.0.front()?;
76
77 if delta == 0 {
78 self.0.pop_front().map(|(_, event)| event)
79 } else {
80 None
81 }
82 }
83}
84
85#[cfg(test)]
86mod tests {
87 use super::*;
88
89 #[test]
90 fn timer_preserves_fifo_order() {
91 let mut timer = PullTimer::new();
92
93 timer.add(0, "testing");
94 timer.add(0, "one two three");
95
96 assert_eq!(timer.poll(), Some("testing"));
97 assert_eq!(timer.poll(), Some("one two three"));
98 assert_eq!(timer.poll(), None);
99 }
100
101 #[test]
102 fn timer_fires_in_order() {
103 let mut timer = PullTimer::new();
104
105 timer.add(4, "test");
106 timer.add(3, "a");
107 timer.add(2, "is");
108 timer.add(1, "this");
109
110 timer.update(4);
111
112 assert_eq!(timer.poll(), Some("this"));
113 assert_eq!(timer.poll(), Some("is"));
114 assert_eq!(timer.poll(), Some("a"));
115 assert_eq!(timer.poll(), Some("test"));
116 assert_eq!(timer.poll(), None);
117 }
118
119 #[test]
120 fn timer_fires_in_time() {
121 let mut timer = PullTimer::new();
122
123 timer.add(40, 40);
124 timer.add(20, 20);
125 timer.add(0, 0);
126 timer.add(30, 30);
127 timer.add(10, 10);
128
129 for i in 0..=41 {
130 if let Some(value) = timer.poll() {
131 assert_eq!(value, i);
132 }
133 timer.update(1);
134 }
135 }
136
137 #[test]
138 fn timer_next_in() {
139 let mut timer = PullTimer::new();
140
141 timer.add(0, "hi");
142 timer.add(20, "!");
143 timer.add(10, "there");
144
145 assert_eq!(timer.next_in(), Some(0));
146 assert_eq!(timer.poll(), Some("hi"));
147
148 assert_eq!(timer.next_in(), Some(10));
149
150 timer.update(10);
151 assert_eq!(timer.next_in(), Some(0));
152 assert_eq!(timer.poll(), Some("there"));
153
154 timer.update(3);
155 assert_eq!(timer.next_in(), Some(7));
156 }
157
158 #[test]
159 fn timer_remove() {
160 let mut timer = PullTimer::new();
161
162 timer.add(100, "boom!");
163 timer.update(50);
164 assert_eq!(timer.remove("boom!"), Some(50));
165 assert_eq!(timer.next_in(), None);
166 }
167
168 #[test]
169 fn timer_fires_after_remove() {
170 let mut timer = PullTimer::new();
171
172 timer.add(30, 30);
173 timer.add(20, 20);
174 timer.add(40, 40);
175 timer.add(10, 10);
176 timer.add(50, 50);
177
178 assert_eq!(timer.remove(50), Some(50));
179 assert_eq!(timer.remove(10), Some(10));
180
181 for i in 0..=41 {
182 if let Some(value) = timer.poll() {
183 assert_eq!(value, i);
184 }
185 timer.update(1);
186 }
187 }
188}