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}