gen_vec/exposed/index_allocator.rs
1use std::
2{
3 vec,
4 vec::Vec,
5 collections::VecDeque,
6 iter,
7 slice
8};
9use crate::Index;
10
11#[cfg(feature = "serde")]
12use serde::{Serialize, Deserialize};
13
14/// An allocated index of a `IndexAllocator`
15#[derive(Debug)]
16#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
17struct AllocatedIndex
18{
19 is_free: bool,
20 generation: usize
21}
22
23/// Allocates and deallocates indices for a `ExposedGenVec`
24#[derive(Default, Debug)]
25#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
26pub struct IndexAllocator
27{
28 free_indices: VecDeque<usize>,
29 active_indices: Vec<AllocatedIndex>
30}
31
32impl IndexAllocator
33{
34 /// Returns a new empty `IndexAllocator`
35 ///
36 /// # Examples
37 ///
38 /// ```
39 /// use gen_vec::exposed::IndexAllocator;
40 /// let mut allocator: IndexAllocator = IndexAllocator::new();
41 /// ```
42 pub fn new() -> IndexAllocator
43 {
44 IndexAllocator
45 {
46 free_indices: VecDeque::new(),
47 active_indices: Vec::new()
48 }
49 }
50
51 /// Returns a `IndexAllocator` with initial capacity of `capacity`
52 ///
53 /// Allows the `IndexAllocator` to hold `capacity` elements before
54 /// allocating more space
55 ///
56 /// # Examples
57 ///
58 /// ```
59 /// use gen_vec::exposed::IndexAllocator;
60 /// let mut allocator: IndexAllocator = IndexAllocator::with_capacity(5);
61 /// ```
62 pub fn with_capacity(capacity: usize) -> IndexAllocator
63 {
64 IndexAllocator
65 {
66 free_indices: VecDeque::with_capacity(capacity),
67 active_indices: Vec::with_capacity(capacity)
68 }
69 }
70
71 /// Allocates and returns a new `Index`
72 ///
73 /// Activates a freed index if there are any, otherwise creates
74 /// and adds a new index to `active_indices`
75 ///
76 /// # Examples
77 ///
78 /// ```
79 /// use gen_vec::Index;
80 /// use gen_vec::exposed::IndexAllocator;
81 ///
82 /// let mut allocator: IndexAllocator = IndexAllocator::new();
83 /// let index: Index = allocator.allocate();
84 /// ```
85 pub fn allocate(&mut self) -> Index
86 {
87 match self.free_indices.pop_front()
88 {
89 Some(index) =>
90 {
91 match self.active_indices.get_mut(index)
92 {
93 Some(AllocatedIndex{ is_free, generation }) if *is_free =>
94 {
95 *is_free = false;
96 *generation += 1;
97 Index { index: index, generation: *generation }
98 },
99 // Try again if the free index was invalid
100 _ => self.allocate()
101 }
102 },
103 _ =>
104 {
105 self.active_indices.push(AllocatedIndex{ is_free: false, generation: 0 });
106 Index{ index: self.active_indices.len().saturating_sub(1), generation: 0 }
107 }
108 }
109 }
110
111 /// Frees `index` if it hasn't been already.
112 ///
113 /// Afterwards, `index` is added to the pool of free indices
114 /// available for reuse
115 ///
116 /// # Examples
117 ///
118 /// ```
119 /// use gen_vec::Index;
120 /// use gen_vec::exposed::IndexAllocator;
121 ///
122 /// let mut allocator: IndexAllocator = IndexAllocator::new();
123 /// let index: Index = allocator.allocate();
124 /// allocator.deallocate(index);
125 /// ```
126 pub fn deallocate(&mut self, index: Index)
127 {
128 if self.is_active(index)
129 {
130 self.active_indices[index.index].is_free = true;
131 self.free_indices.push_back(index.index);
132 }
133 }
134
135 /// Frees all active indices and adds them to the pool of free indices
136 ///
137 /// # Examples
138 ///
139 /// ```
140 /// use gen_vec::exposed::IndexAllocator;
141 /// use gen_vec::Index;
142 ///
143 /// let mut allocator: IndexAllocator = IndexAllocator::new();
144 /// for _ in 0..10
145 /// {
146 /// allocator.allocate();
147 /// }
148 /// assert_eq!(allocator.num_active(), 10);
149 /// assert_eq!(allocator.num_free(), 0);
150 ///
151 /// allocator.deallocate_all();
152 /// assert_eq!(allocator.num_active(), 0);
153 /// assert_eq!(allocator.num_free(), 10);
154 /// ```
155 pub fn deallocate_all(&mut self)
156 {
157 for (index, alloc_index) in self.active_indices.iter_mut().enumerate()
158 {
159 alloc_index.is_free = true;
160 self.free_indices.push_back(index);
161 }
162 }
163
164 /// Reserved capacity within the `IndexAllocator`
165 ///
166 /// # Examples
167 ///
168 /// ```
169 /// use gen_vec::exposed::IndexAllocator;
170 ///
171 /// let mut allocator: IndexAllocator = IndexAllocator::with_capacity(5);
172 /// assert_eq!(allocator.capacity(), 5);
173 /// ```
174 pub fn capacity(&self) -> usize
175 {
176 self.active_indices.capacity()
177 }
178
179 /// Reserves extra space for *at least* `additional` more elements
180 ///
181 /// More space may be allocated to avoid frequent re-allocations
182 /// (as per the specifications of std::vec::Vec)
183 ///
184 /// # Examples
185 ///
186 /// ```
187 /// use gen_vec::Index;
188 /// use gen_vec::exposed::IndexAllocator;
189 ///
190 /// let mut allocator: IndexAllocator = IndexAllocator::new();
191 /// let index: Index = allocator.allocate();
192 /// allocator.reserve(4);
193 /// assert!(allocator.capacity() >= 4);
194 /// ```
195 pub fn reserve(&mut self, additional: usize)
196 {
197 if additional > 0
198 {
199 self.active_indices.reserve(additional);
200 self.free_indices.reserve(additional);
201
202 if self.active_indices.len() > 0
203 {
204 let last_index = self.active_indices.len().saturating_sub(1);
205 // Add all new reserved
206 for i in last_index..(last_index+additional)
207 {
208 self.free_indices.push_back(i);
209 self.active_indices.push(AllocatedIndex{ is_free: true, generation: 0 });
210 }
211 }
212 }
213 }
214
215 /// Returns if `index` is still active and hasn't been deallocated
216 ///
217 /// # Examples
218 ///
219 /// ```
220 /// use gen_vec::Index;
221 /// use gen_vec::exposed::IndexAllocator;
222 ///
223 /// let mut allocator: IndexAllocator = IndexAllocator::new();
224 /// let index: Index = allocator.allocate();
225 /// assert!(allocator.is_active(index));
226 /// allocator.deallocate(index);
227 /// assert!(!allocator.is_active(index));
228 /// ```
229 pub fn is_active(&self, index: Index) -> bool
230 {
231 match self.active_indices.get(index.index)
232 {
233 Some(AllocatedIndex{ is_free, generation }) => *generation == index.generation && !*is_free,
234 _ => false
235 }
236 }
237
238 /// Returns the number of free indices waiting to be allocated and reused
239 ///
240 /// # Examples
241 ///
242 /// ```
243 /// use gen_vec::Index;
244 /// use gen_vec::exposed::IndexAllocator;
245 ///
246 /// let mut allocator: IndexAllocator = IndexAllocator::new();
247 /// assert_eq!(allocator.num_free(), 0);
248 ///
249 /// let index: Index = allocator.allocate();
250 ///
251 /// allocator.deallocate(index);
252 /// assert_eq!(allocator.num_free(), 1);
253 ///
254 /// let index: Index = allocator.allocate();
255 /// assert_eq!(allocator.num_free(), 0);
256 /// ```
257 pub fn num_free(&self) -> usize
258 {
259 self.free_indices.len()
260 }
261
262 /// Returns the number of active indices
263 ///
264 /// # Examples
265 ///
266 /// ```
267 /// use gen_vec::Index;
268 /// use gen_vec::exposed::IndexAllocator;
269 ///
270 /// let mut allocator: IndexAllocator = IndexAllocator::new();
271 /// assert_eq!(allocator.num_active(), 0);
272 ///
273 /// let index: Index = allocator.allocate();
274 /// assert_eq!(allocator.num_active(), 1);
275 ///
276 /// allocator.deallocate(index);
277 /// assert_eq!(allocator.num_active(), 0);
278 /// ```
279 pub fn num_active(&self) -> usize
280 {
281 self.active_indices.len().saturating_sub(self.free_indices.len())
282 }
283
284 /// Returns an iterator over an immutable `IndexAllocator`
285 /// Each step returns an `Index`
286 ///
287 /// # Examples
288 ///
289 /// ```
290 /// use gen_vec::Index;
291 /// use gen_vec::exposed::IndexAllocator;
292 ///
293 /// let mut allocator: IndexAllocator = IndexAllocator::new();
294 /// allocator.allocate();
295 /// allocator.allocate();
296 ///
297 /// for index in allocator
298 /// {
299 /// println!("{:?}", index);
300 /// }
301 /// ```
302 pub fn iter(&self) -> Iter
303 {
304 Iter
305 {
306 internal: self.active_indices.iter().enumerate()
307 }
308 }
309}
310
311/// Struct for consuming a `IndexAllocator` into an iterator
312#[derive(Debug)]
313pub struct IntoIter
314{
315 internal: iter::Enumerate<vec::IntoIter<AllocatedIndex>>
316}
317
318impl Iterator for IntoIter
319{
320 type Item = Index;
321
322 fn next(&mut self) -> Option<Self::Item>
323 {
324 loop
325 {
326 match self.internal.next()
327 {
328 Some((index, allocated_index)) if !allocated_index.is_free => return Some(Index { index, generation: allocated_index.generation }),
329 Some((_, _)) => continue,
330 _ => return None
331 }
332 }
333 }
334}
335
336impl IntoIterator for IndexAllocator
337{
338 type Item = Index;
339 type IntoIter = IntoIter;
340
341 fn into_iter(self) -> Self::IntoIter
342 {
343 IntoIter
344 {
345 internal: self.active_indices.into_iter().enumerate()
346 }
347 }
348}
349
350/// Struct for creating an iterator over an immutable `IndexAllocator` reference
351#[derive(Debug)]
352pub struct Iter<'a>
353{
354 internal: iter::Enumerate<slice::Iter<'a, AllocatedIndex>>
355}
356
357impl<'a> Iterator for Iter<'a>
358{
359 type Item = Index;
360
361 fn next(&mut self) -> Option<Self::Item>
362 {
363 loop
364 {
365 loop
366 {
367 match self.internal.next()
368 {
369 Some((index, allocated_index)) if !allocated_index.is_free => return Some(Index { index, generation: allocated_index.generation }),
370 Some((_, _)) => continue,
371 _ => return None
372 }
373 }
374 }
375 }
376}
377
378impl<'a> IntoIterator for &'a IndexAllocator
379{
380 type Item = Index;
381 type IntoIter = Iter<'a>;
382
383 fn into_iter(self) -> Self::IntoIter
384 {
385 self.iter()
386 }
387}
388
389#[cfg(test)]
390mod allocator_tests
391{
392 use crate::exposed::*;
393 use crate::Index;
394
395 #[test]
396 fn allocate()
397 {
398 let mut allocator = IndexAllocator::new();
399 let index = allocator.allocate();
400 assert_eq!(index.index, 0);
401 assert_eq!(index.generation, 0);
402
403 let index = allocator.allocate();
404 assert_eq!(index.index, 1);
405 assert_eq!(index.generation, 0);
406 }
407
408 #[test]
409 fn deallocate()
410 {
411 let mut allocator = IndexAllocator::new();
412 let index = allocator.allocate();
413 allocator.allocate();
414
415 allocator.deallocate(index);
416
417 let index = allocator.allocate();
418 assert_eq!(index.index, 0);
419 assert_eq!(index.generation, 1);
420 }
421
422 #[test]
423 fn deallocate_all()
424 {
425 let mut allocator: IndexAllocator = IndexAllocator::new();
426 for _ in 0..10
427 {
428 allocator.allocate();
429 }
430 assert_eq!(allocator.num_active(), 10);
431 assert_eq!(allocator.num_free(), 0);
432
433 allocator.deallocate_all();
434 assert_eq!(allocator.num_active(), 0);
435 assert_eq!(allocator.num_free(), 10);
436 }
437
438 #[test]
439 fn capacity()
440 {
441 let mut allocator = IndexAllocator::new();
442 assert_eq!(allocator.capacity(), 0);
443 allocator.allocate();
444 assert!(allocator.capacity() >= 1);
445
446 allocator = IndexAllocator::with_capacity(3);
447 assert!(allocator.capacity() >= 3);
448 allocator.allocate();
449 allocator.allocate();
450
451 allocator.reserve(4);
452 assert!(allocator.capacity() >= 5);
453 }
454
455 #[test]
456 fn active()
457 {
458 let mut allocator = IndexAllocator::new();
459 let index = allocator.allocate();
460 allocator.allocate();
461 assert_eq!(allocator.num_active(), 2);
462 assert_eq!(allocator.num_free(), 0);
463 assert!(allocator.is_active(index));
464 allocator.deallocate(index);
465 assert!(!allocator.is_active(index));
466 assert_eq!(allocator.num_active(), 1);
467 assert_eq!(allocator.num_free(), 1);
468 }
469
470 #[test]
471 fn iter()
472 {
473 let mut allocator = IndexAllocator::new();
474 allocator.allocate();
475 allocator.allocate();
476 let i = allocator.allocate();
477 allocator.deallocate(i);
478
479 let mut iter = allocator.iter();
480 assert_eq!(iter.next(), Some(Index { index: 0, generation: 0 }));
481 assert_eq!(iter.next(), Some(Index { index: 1, generation: 0}));
482 assert_eq!(iter.next(), None);
483 }
484}