1#![deny(
2 anonymous_parameters,
5 bare_trait_objects,
6 box_pointers,
7 elided_lifetimes_in_paths,
8 missing_copy_implementations,
9 missing_debug_implementations,
10 missing_docs,
11 single_use_lifetimes,
12 trivial_casts,
13 trivial_numeric_casts,
14 unreachable_pub,
15 unsafe_code,
16 unstable_features,
17 unused_extern_crates,
18 unused_import_braces,
19 unused_qualifications,
20 unused_results,
21 variant_size_differences,
22 warnings, clippy::all,
25 clippy::pedantic,
27 clippy::cargo,
29)]
30#![allow(
31 clippy::blanket_clippy_restriction_lints, clippy::implicit_return, clippy::module_name_repetitions, clippy::multiple_crate_versions, clippy::panic_in_result_fn,
37 clippy::shadow_same, clippy::shadow_reuse, clippy::exhaustive_enums,
40 clippy::exhaustive_structs,
41 clippy::indexing_slicing,
42 clippy::separated_literal_suffix, clippy::single_char_lifetime_names,
44)]
45
46use std::collections::vec_deque::{Iter, IterMut};
48use std::collections::{BTreeMap, VecDeque};
49use std::sync::atomic::{AtomicUsize, Ordering};
50use std::time::{Duration, SystemTime, UNIX_EPOCH};
51
52#[must_use]
57pub fn now() -> u64 {
58 u64::try_from(
59 SystemTime::now()
60 .duration_since(UNIX_EPOCH)
61 .expect("1970-01-01 00:00:00 UTC was {} seconds ago!")
62 .as_nanos(),
63 )
64 .unwrap_or(u64::MAX)
65}
66
67#[must_use]
69pub fn get_timeout_time(dur: Duration) -> u64 {
70 u64::try_from(dur.as_nanos())
71 .map(|d| d.saturating_add(now()))
72 .unwrap_or(u64::MAX)
73}
74
75#[derive(Debug, Eq, PartialEq)]
77pub struct TimerEntry<T> {
78 timestamp: u64,
79 inner: VecDeque<T>,
80}
81
82impl<'t, T> IntoIterator for &'t mut TimerEntry<T> {
83 type Item = &'t mut T;
84 type IntoIter = IterMut<'t, T>;
85
86 fn into_iter(self) -> Self::IntoIter {
87 self.iter_mut()
88 }
89}
90
91impl<'t, T> IntoIterator for &'t TimerEntry<T> {
92 type Item = &'t T;
93 type IntoIter = Iter<'t, T>;
94
95 fn into_iter(self) -> Self::IntoIter {
96 self.iter()
97 }
98}
99
100impl<T> TimerEntry<T> {
101 #[must_use]
103 pub fn new(timestamp: u64) -> Self {
104 TimerEntry {
105 timestamp,
106 inner: VecDeque::new(),
107 }
108 }
109
110 #[must_use]
112 pub fn len(&self) -> usize {
113 self.inner.len()
114 }
115
116 #[must_use]
118 pub fn is_empty(&self) -> bool {
119 self.inner.is_empty()
120 }
121
122 #[must_use]
124 pub fn get_timestamp(&self) -> u64 {
125 self.timestamp
126 }
127
128 pub fn pop_front(&mut self) -> Option<T> {
130 self.inner.pop_front()
131 }
132
133 pub fn push_back(&mut self, t: T) {
135 self.inner.push_back(t);
136 }
137
138 pub fn remove(&mut self, t: &T) -> Option<T>
143 where
144 T: Ord,
145 {
146 let index = self
147 .inner
148 .binary_search_by(|x| x.cmp(t))
149 .unwrap_or_else(|x| x);
150 self.inner.remove(index)
151 }
152
153 pub fn iter_mut(&mut self) -> IterMut<'_, T> {
155 self.inner.iter_mut()
156 }
157
158 #[must_use]
160 pub fn iter(&self) -> Iter<'_, T> {
161 self.inner.iter()
162 }
163}
164
165#[repr(C)]
167#[derive(Debug)]
168pub struct TimerList<T> {
169 inner: BTreeMap<u64, TimerEntry<T>>,
170 total: AtomicUsize,
171}
172
173impl<T: PartialEq> PartialEq<Self> for TimerList<T> {
174 fn eq(&self, other: &Self) -> bool {
175 self.inner.eq(&other.inner)
176 }
177}
178
179impl<T: Eq> Eq for TimerList<T> {}
180
181impl<T> Default for TimerList<T> {
182 fn default() -> Self {
183 TimerList {
184 inner: BTreeMap::default(),
185 total: AtomicUsize::new(0),
186 }
187 }
188}
189
190impl<'t, T> IntoIterator for &'t TimerList<T> {
191 type Item = (&'t u64, &'t TimerEntry<T>);
192 type IntoIter = std::collections::btree_map::Iter<'t, u64, TimerEntry<T>>;
193
194 fn into_iter(self) -> Self::IntoIter {
195 self.iter()
196 }
197}
198
199impl<T> TimerList<T> {
200 #[must_use]
202 pub fn len(&self) -> usize {
203 if self.inner.is_empty() {
204 return 0;
205 }
206 self.total.load(Ordering::Acquire)
207 }
208
209 #[must_use]
211 pub fn entry_len(&self) -> usize {
212 self.inner.len()
213 }
214
215 pub fn insert(&mut self, timestamp: u64, t: T) {
218 if let Some(entry) = self.inner.get_mut(×tamp) {
219 entry.push_back(t);
220 _ = self.total.fetch_add(1, Ordering::Release);
221 return;
222 }
223 let mut entry = TimerEntry::new(timestamp);
224 entry.push_back(t);
225 _ = self.total.fetch_add(1, Ordering::Release);
226 if let Some(mut entry) = self.inner.insert(timestamp, entry) {
227 while !entry.is_empty() {
229 if let Some(e) = entry.pop_front() {
230 self.insert(timestamp, e);
231 }
232 }
233 }
234 }
235
236 #[must_use]
238 pub fn front(&self) -> Option<(&u64, &TimerEntry<T>)> {
239 self.inner.first_key_value()
240 }
241
242 pub fn pop_front(&mut self) -> Option<(u64, TimerEntry<T>)> {
244 self.inner.pop_first().map(|(timestamp, entry)| {
245 _ = self.total.fetch_sub(entry.len(), Ordering::Release);
246 (timestamp, entry)
247 })
248 }
249
250 #[must_use]
252 pub fn is_empty(&self) -> bool {
253 self.len() == 0
254 }
255
256 pub fn remove_entry(&mut self, timestamp: &u64) -> Option<TimerEntry<T>> {
261 self.inner.remove(timestamp).map(|entry| {
262 _ = self.total.fetch_sub(entry.len(), Ordering::Release);
263 entry
264 })
265 }
266
267 pub fn remove(&mut self, timestamp: &u64, t: &T) -> Option<T>
272 where
273 T: Ord,
274 {
275 if let Some(entry) = self.inner.get_mut(timestamp) {
276 let val = entry.remove(t).map(|item| {
277 _ = self.total.fetch_sub(1, Ordering::Release);
278 item
279 });
280 if entry.is_empty() {
281 _ = self.remove_entry(timestamp);
282 }
283 return val;
284 }
285 None
286 }
287
288 pub fn iter(&self) -> std::collections::btree_map::Iter<'_, u64, TimerEntry<T>> {
290 self.inner.iter()
291 }
292}
293
294#[cfg(test)]
295mod tests {
296 use super::*;
297
298 #[test]
299 fn test() {
300 assert!(now() > 0);
301 }
302
303 #[test]
304 fn timer_list() {
305 let mut list = TimerList::default();
306 assert_eq!(list.entry_len(), 0);
307 list.insert(1, String::from("data is 1"));
308 list.insert(2, String::from("data is 2"));
309 list.insert(3, String::from("data is 3"));
310 assert_eq!(list.entry_len(), 3);
311
312 let mut entry = list.pop_front().unwrap().1;
313 assert_eq!(entry.len(), 1);
314 let string = entry.pop_front().unwrap();
315 assert_eq!(string, String::from("data is 1"));
316 assert_eq!(entry.len(), 0);
317 }
318}