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}