unros_core/utils.rs
1//! Several utilities that complement the Unros framework.
2
3use std::{
4 ops::{Deref, DerefMut},
5 sync::OnceLock,
6};
7
8use crossbeam::queue::ArrayQueue;
9
10// pub struct TimeVec<T, F = Box<dyn Fn(&VecDeque<T>) -> T + Send>> {
11// vec: VecDeque<T>,
12// head_time: Instant,
13// duration: Duration,
14// max_length: usize,
15// default: F,
16// }
17
18// impl<T, F: FnMut(&VecDeque<T>) -> T + Send> TimeVec<T, F> {
19// #[must_use]
20// pub fn new(max_length: usize, duration: Duration, mut default: F) -> Self {
21// let mut vec = VecDeque::with_capacity(max_length);
22// for _ in 0..max_length {
23// vec.push_back(default(&vec));
24// }
25// Self {
26// vec,
27// head_time: Instant::now(),
28// duration,
29// max_length,
30// default,
31// }
32// }
33
34// #[must_use]
35// pub fn new_default(
36// max_length: usize,
37// duration: Duration,
38// ) -> TimeVec<T, Box<dyn Fn(&VecDeque<T>) -> T + Send>>
39// where
40// T: Default,
41// {
42// TimeVec::new(max_length, duration, Box::new(|_| Default::default()))
43// }
44
45// fn update(&mut self) {
46// let single_duration = self.duration.div_f32(self.max_length as f32);
47// let elapsed = self.head_time.elapsed();
48// let mut lag = elapsed.div_duration_f32(single_duration) as usize;
49// lag = lag.min(self.max_length);
50// self.vec.drain(0..lag);
51// for _ in 0..lag {
52// self.vec.push_back((self.default)(&self.vec));
53// }
54// if lag > 0 {
55// self.head_time += elapsed;
56// }
57// }
58
59// pub fn peek(&mut self) -> &mut T {
60// self.update();
61// self.vec.back_mut().unwrap()
62// }
63
64// fn get_index(&mut self, instant: Instant) -> Option<usize> {
65// self.update();
66// let prelapsed = self.head_time.checked_duration_since(instant)?;
67// let single_duration = self.duration.div_f32(self.max_length as f32);
68// let i = prelapsed.div_duration_f32(single_duration) as usize;
69// if i >= self.max_length {
70// None
71// } else {
72// Some(self.max_length - i - 1)
73// }
74// }
75
76// pub fn get(&mut self, instant: Instant) -> Option<&mut T> {
77// let i = self.get_index(instant)?;
78// self.vec.get_mut(i)
79// }
80
81// pub fn get_pair(&mut self, instant: Instant) -> Option<(&mut T, &mut T)> {
82// let i = self.get_index(instant)?;
83// if i >= self.max_length - 1 {
84// None
85// } else {
86// let mut iter = self.vec.range_mut(i..=i + 1);
87// let a = iter.next().unwrap();
88// let b = iter.next().unwrap();
89// Some((a, b))
90// }
91// }
92
93// pub fn get_head_time(&mut self) -> Instant {
94// self.update();
95// self.head_time
96// }
97
98// pub fn get_vec(&mut self) -> BorrowedVecDeque<T, F> {
99// self.update();
100// BorrowedVecDeque(self)
101// }
102// }
103
104// pub struct BorrowedVecDeque<'a, T, F: FnMut(&VecDeque<T>) -> T>(&'a mut TimeVec<T, F>);
105
106// impl<'a, T, F: FnMut(&VecDeque<T>) -> T> Deref for BorrowedVecDeque<'a, T, F> {
107// type Target = VecDeque<T>;
108
109// fn deref(&self) -> &Self::Target {
110// &self.0.vec
111// }
112// }
113
114// impl<'a, T, F: FnMut(&VecDeque<T>) -> T> DerefMut for BorrowedVecDeque<'a, T, F> {
115// fn deref_mut(&mut self) -> &mut Self::Target {
116// &mut self.0.vec
117// }
118// }
119
120// impl<'a, T, F: FnMut(&VecDeque<T>) -> T> Drop for BorrowedVecDeque<'a, T, F> {
121// fn drop(&mut self) {
122// match self.0.vec.len().cmp(&self.0.max_length) {
123// Ordering::Less => {
124// for _ in 0..(self.0.max_length - self.0.vec.len()) {
125// self.0.vec.push_back((self.0.default)(&self.0.vec));
126// }
127// }
128
129// Ordering::Equal => {}
130// Ordering::Greater => {
131// self.0.vec.drain(0..self.0.vec.len() - self.0.max_length);
132// }
133// }
134// }
135// }
136
137/// A concurrent queue for storing a pool of resources.
138pub struct ResourceQueue<T> {
139 queue: OnceLock<ArrayQueue<T>>,
140 max_length: usize,
141 default: fn() -> T,
142}
143
144impl<T> ResourceQueue<T> {
145 /// Create a new queue where elements can be generated by the given function pointer.
146 pub const fn new(max_length: usize, default: fn() -> T) -> Self {
147 Self {
148 queue: OnceLock::new(),
149 max_length,
150 default,
151 }
152 }
153
154 /// Gets any available resource.
155 pub fn get(&self) -> ResourceGuard<T> {
156 let inner = self
157 .queue
158 .get_or_init(|| ArrayQueue::new(self.max_length))
159 .pop()
160 .unwrap_or_else(self.default);
161 ResourceGuard {
162 inner: Some(inner),
163 queue: self,
164 }
165 }
166
167 /// Manually sets a resource into this queue.
168 ///
169 /// You only need to call this if you want to add elements into this queue since
170 /// `ResourceGuard` calls this automatically.
171 ///
172 /// If you set more values than this queue can hold, the oldest resource is dropped.
173 pub fn set(&self, value: T) {
174 self.queue
175 .get_or_init(|| ArrayQueue::new(self.max_length))
176 .force_push(value);
177 }
178}
179
180/// An RAII Guard around a resource.
181///
182/// When this is dropped, the resource will be returned to the `ResourceQueue`.
183pub struct ResourceGuard<'a, T> {
184 inner: Option<T>,
185 queue: &'a ResourceQueue<T>,
186}
187
188impl<'a, T> ResourceGuard<'a, T> {
189 /// Unwraps this object, returning the resource instead of returning it to the
190 /// `ResourceQueue`.
191 ///
192 /// If the queue is lacking a resource, a new one will be generated.
193 pub fn do_not_return(mut this: Self) -> T {
194 this.inner.take().unwrap()
195 }
196}
197
198impl<'a, T> Deref for ResourceGuard<'a, T> {
199 type Target = T;
200
201 fn deref(&self) -> &Self::Target {
202 self.inner.as_ref().unwrap()
203 }
204}
205
206impl<'a, T> DerefMut for ResourceGuard<'a, T> {
207 fn deref_mut(&mut self) -> &mut Self::Target {
208 self.inner.as_mut().unwrap()
209 }
210}
211
212impl<'a, T> Drop for ResourceGuard<'a, T> {
213 fn drop(&mut self) {
214 if let Some(inner) = self.inner.take() {
215 self.queue.queue.get().unwrap().force_push(inner);
216 }
217 }
218}