zencan_node/
priority_queue.rs1use core::{cell::RefCell, mem::MaybeUninit};
3
4use critical_section::Mutex;
5
6#[derive(Clone, Copy, Debug)]
7struct Prio<T: Copy>(u32, MaybeUninit<T>);
8
9impl<T: Copy> Prio<T> {
10 const EMPTY: Prio<T> = Prio(1 << 31, MaybeUninit::uninit());
11
12 pub fn new(prio: u32, value: T) -> Self {
13 let prio = prio & 0x7FFFFFFF;
14 Self(prio, MaybeUninit::new(value))
15 }
16
17 pub fn is_empty(&self) -> bool {
18 self.0 & (1 << 31) != 0
19 }
20
21 pub fn prio(&self) -> Option<u32> {
22 if self.is_empty() {
23 None
24 } else {
25 Some(self.0)
26 }
27 }
28
29 pub fn value(&self) -> Option<T> {
30 if self.is_empty() {
31 None
32 } else {
33 Some(unsafe { self.1.assume_init() })
34 }
35 }
36
37 pub fn take(&mut self) -> Option<T> {
38 let value = self.value();
39 *self = Prio::EMPTY;
40 value
41 }
42}
43
44#[derive(Debug)]
46pub struct PriorityQueue<const N: usize, T: Copy> {
47 buffer: Mutex<RefCell<[Prio<T>; N]>>,
48}
49
50impl<const N: usize, T: Copy + Send> Default for PriorityQueue<N, T> {
51 fn default() -> Self {
52 Self::new()
53 }
54}
55
56impl<const N: usize, T> PriorityQueue<N, T>
57where
58 T: Copy + Send,
59{
60 pub const fn new() -> Self {
62 Self {
63 buffer: Mutex::new(RefCell::new([Prio::EMPTY; N])),
64 }
65 }
66
67 pub fn push(&self, prio: u32, item: T) -> Result<(), T> {
74 critical_section::with(|cs| {
75 let mut buffer = self.buffer.borrow_ref_mut(cs);
76 for loc in buffer.iter_mut() {
77 if loc.is_empty() {
78 *loc = Prio::new(prio, item);
79 return Ok(());
80 }
81 }
82
83 Err(item)
84 })
85 }
86
87 pub fn pop(&self) -> Option<T> {
91 critical_section::with(|cs| {
92 let mut min_prio = u32::MAX;
93 let mut selected_index = None;
94 let mut buffer = self.buffer.borrow_ref_mut(cs);
95 for (i, loc) in buffer.iter().enumerate() {
97 if let Some(prio) = loc.prio() {
98 if prio < min_prio {
99 min_prio = prio;
100 selected_index = Some(i);
101 }
102 }
103 }
104
105 selected_index.map(|i| buffer[i].take())?
106 })
107 }
108}
109
110#[cfg(test)]
111mod test {
112 use super::*;
113 #[test]
114 fn test_priority_queue() {
115 let queue: PriorityQueue<4, u8> = PriorityQueue::new();
116
117 queue.push(87, 2).unwrap();
118 queue.push(100, 3).unwrap();
119 queue.push(1, 0).unwrap();
120 queue.push(10, 1).unwrap();
121
122 assert_eq!(Err(12), queue.push(100, 12));
124
125 assert_eq!(Some(0), queue.pop());
126 assert_eq!(Some(1), queue.pop());
127 assert_eq!(Some(2), queue.pop());
128 assert_eq!(Some(3), queue.pop());
129 }
130}