embassy_time_queue_utils/
queue_generic.rs1use core::cmp::{Ordering, min};
6use core::task::Waker;
7
8use heapless::Vec;
9
10#[derive(Debug)]
11struct Timer {
12 at: u64,
13 waker: Waker,
14}
15
16impl PartialEq for Timer {
17 fn eq(&self, other: &Self) -> bool {
18 self.at == other.at
19 }
20}
21
22impl Eq for Timer {}
23
24impl PartialOrd for Timer {
25 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
26 self.at.partial_cmp(&other.at)
27 }
28}
29
30impl Ord for Timer {
31 fn cmp(&self, other: &Self) -> Ordering {
32 self.at.cmp(&other.at)
33 }
34}
35
36#[derive(Debug)]
38pub struct ConstGenericQueue<const QUEUE_SIZE: usize> {
39 queue: Vec<Timer, QUEUE_SIZE>,
40}
41
42impl<const QUEUE_SIZE: usize> ConstGenericQueue<QUEUE_SIZE> {
43 pub const fn new() -> Self {
45 Self { queue: Vec::new() }
46 }
47
48 pub fn schedule_wake(&mut self, at: u64, waker: &Waker) -> bool {
53 self.queue
54 .iter_mut()
55 .find(|timer| timer.waker.will_wake(waker))
56 .map(|timer| {
57 if timer.at > at {
58 timer.at = at;
59 true
60 } else {
61 false
62 }
63 })
64 .unwrap_or_else(|| {
65 let mut timer = Timer {
66 waker: waker.clone(),
67 at,
68 };
69
70 loop {
71 match self.queue.push(timer) {
72 Ok(()) => break,
73 Err(e) => timer = e,
74 }
75
76 self.queue.pop().unwrap().waker.wake();
77 }
78
79 true
80 })
81 }
82
83 pub fn next_expiration(&mut self, now: u64) -> u64 {
85 let mut next_alarm = u64::MAX;
86
87 let mut i = 0;
88 while i < self.queue.len() {
89 let timer = &self.queue[i];
90 if timer.at <= now {
91 let timer = self.queue.swap_remove(i);
92 timer.waker.wake();
93 } else {
94 next_alarm = min(next_alarm, timer.at);
95 i += 1;
96 }
97 }
98
99 next_alarm
100 }
101}
102
103#[cfg(feature = "generic-queue-8")]
104const QUEUE_SIZE: usize = 8;
105#[cfg(feature = "generic-queue-16")]
106const QUEUE_SIZE: usize = 16;
107#[cfg(feature = "generic-queue-32")]
108const QUEUE_SIZE: usize = 32;
109#[cfg(feature = "generic-queue-64")]
110const QUEUE_SIZE: usize = 64;
111#[cfg(feature = "generic-queue-128")]
112const QUEUE_SIZE: usize = 128;
113#[cfg(not(any(
114 feature = "generic-queue-8",
115 feature = "generic-queue-16",
116 feature = "generic-queue-32",
117 feature = "generic-queue-64",
118 feature = "generic-queue-128"
119)))]
120const QUEUE_SIZE: usize = 64;
121
122#[derive(Debug)]
124pub struct Queue {
125 queue: ConstGenericQueue<QUEUE_SIZE>,
126}
127
128impl Queue {
129 pub const fn new() -> Self {
131 Self {
132 queue: ConstGenericQueue::new(),
133 }
134 }
135
136 pub fn schedule_wake(&mut self, at: u64, waker: &Waker) -> bool {
141 self.queue.schedule_wake(at, waker)
142 }
143
144 pub fn next_expiration(&mut self, now: u64) -> u64 {
146 self.queue.next_expiration(now)
147 }
148}