a3s_lane/
priority_queue.rs1use crate::Priority;
10use std::cmp::Ordering;
11use std::collections::BinaryHeap;
12
13#[derive(Debug)]
15pub struct PriorityItem<T> {
16 priority: Priority,
17 sequence: u64,
18 value: T,
19}
20
21impl<T> PriorityItem<T> {
22 pub fn priority(&self) -> Priority {
24 self.priority
25 }
26
27 pub fn sequence(&self) -> u64 {
29 self.sequence
30 }
31
32 pub fn value(&self) -> &T {
34 &self.value
35 }
36
37 pub fn value_mut(&mut self) -> &mut T {
39 &mut self.value
40 }
41
42 pub fn into_value(self) -> T {
44 self.value
45 }
46}
47
48impl<T> PartialEq for PriorityItem<T> {
49 fn eq(&self, other: &Self) -> bool {
50 self.priority == other.priority && self.sequence == other.sequence
51 }
52}
53
54impl<T> Eq for PriorityItem<T> {}
55
56impl<T> Ord for PriorityItem<T> {
57 fn cmp(&self, other: &Self) -> Ordering {
58 other
61 .priority
62 .cmp(&self.priority)
63 .then_with(|| other.sequence.cmp(&self.sequence))
64 }
65}
66
67impl<T> PartialOrd for PriorityItem<T> {
68 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
69 Some(self.cmp(other))
70 }
71}
72
73#[derive(Debug)]
78pub struct PriorityQueue<T> {
79 entries: BinaryHeap<PriorityItem<T>>,
80 next_sequence: u64,
81}
82
83impl<T> Default for PriorityQueue<T> {
84 fn default() -> Self {
85 Self::new()
86 }
87}
88
89impl<T> PriorityQueue<T> {
90 pub fn new() -> Self {
92 Self {
93 entries: BinaryHeap::new(),
94 next_sequence: 0,
95 }
96 }
97
98 pub fn len(&self) -> usize {
100 self.entries.len()
101 }
102
103 pub fn is_empty(&self) -> bool {
105 self.entries.is_empty()
106 }
107
108 pub fn push(&mut self, priority: Priority, value: T) -> u64 {
110 self.ensure_sequence_capacity();
111 self.next_sequence += 1;
112 let sequence = self.next_sequence;
113 self.entries.push(PriorityItem {
114 priority,
115 sequence,
116 value,
117 });
118 sequence
119 }
120
121 pub fn pop(&mut self) -> Option<PriorityItem<T>> {
123 self.entries.pop()
124 }
125
126 pub fn restore(&mut self, item: PriorityItem<T>) {
130 self.next_sequence = self.next_sequence.max(item.sequence);
131 self.entries.push(item);
132 }
133
134 pub fn ordered(&self) -> Vec<&PriorityItem<T>> {
136 let mut entries = self.entries.iter().collect::<Vec<_>>();
137 entries.sort_by(|left, right| {
138 left.priority
139 .cmp(&right.priority)
140 .then_with(|| left.sequence.cmp(&right.sequence))
141 });
142 entries
143 }
144
145 pub fn clear(&mut self) {
147 self.entries.clear();
148 self.next_sequence = 0;
149 }
150
151 fn ensure_sequence_capacity(&mut self) {
152 if self.next_sequence != u64::MAX {
153 return;
154 }
155
156 let mut entries = self.entries.drain().collect::<Vec<_>>();
159 entries.sort_by_key(|entry| entry.sequence);
160 for (index, entry) in entries.iter_mut().enumerate() {
161 entry.sequence = index as u64 + 1;
162 }
163 self.next_sequence = entries.len() as u64;
164 self.entries.extend(entries);
165 }
166}
167
168#[cfg(test)]
169mod tests {
170 use super::*;
171
172 #[test]
173 fn lower_priority_runs_first_and_equal_priority_is_fifo() {
174 let mut queue = PriorityQueue::new();
175 queue.push(5, "background");
176 queue.push(1, "first user");
177 queue.push(1, "second user");
178 queue.push(3, "continuation");
179
180 let drained =
181 std::iter::from_fn(|| queue.pop().map(PriorityItem::into_value)).collect::<Vec<_>>();
182
183 assert_eq!(
184 drained,
185 ["first user", "second user", "continuation", "background"]
186 );
187 }
188
189 #[test]
190 fn restore_preserves_original_fifo_position() {
191 let mut queue = PriorityQueue::new();
192 queue.push(1, "first");
193 queue.push(1, "second");
194
195 let first = queue.pop().unwrap();
196 queue.push(1, "third");
197 queue.restore(first);
198
199 let drained =
200 std::iter::from_fn(|| queue.pop().map(PriorityItem::into_value)).collect::<Vec<_>>();
201 assert_eq!(drained, ["first", "second", "third"]);
202 }
203
204 #[test]
205 fn ordered_matches_claim_order_without_mutating_the_queue() {
206 let mut queue = PriorityQueue::new();
207 queue.push(4, "later");
208 queue.push(0, "first");
209 queue.push(4, "last");
210
211 let ordered = queue
212 .ordered()
213 .into_iter()
214 .map(|entry| *entry.value())
215 .collect::<Vec<_>>();
216
217 assert_eq!(ordered, ["first", "later", "last"]);
218 assert_eq!(queue.len(), 3);
219 }
220
221 #[test]
222 fn clear_resets_pending_values_and_sequence() {
223 let mut queue = PriorityQueue::new();
224 assert_eq!(queue.push(1, "old"), 1);
225 queue.clear();
226
227 assert!(queue.is_empty());
228 assert_eq!(queue.push(1, "new"), 1);
229 }
230}