1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#[derive(Clone, Copy, Debug)]
pub struct GenerationalId {
id: usize,
generation: usize,
}
struct GenerationalCell<T> {
generation: usize,
state: T,
}
pub(crate) struct GenerationalStorage<T> {
vec: Vec<Option<GenerationalCell<T>>>,
free_indices: Vec<(usize, usize)>,
}
impl<T> GenerationalStorage<T> {
pub fn new() -> GenerationalStorage<T> {
GenerationalStorage {
vec: Vec::with_capacity(1000),
free_indices: Vec::with_capacity(100),
}
}
pub fn push(&mut self, data: T) -> GenerationalId {
let generation;
if let Some((free_id, old_generation)) = self.free_indices.pop() {
assert!(self.vec[free_id].is_none());
generation = old_generation + 1;
self.vec[free_id] = Some(GenerationalCell {
state: data,
generation,
});
} else {
generation = 0;
self.vec.push(Some(GenerationalCell {
state: data,
generation,
}));
}
GenerationalId {
id: self.vec.len() - 1,
generation,
}
}
pub fn get(&self, id: GenerationalId) -> Option<&T> {
if id.id > self.vec.len() {
return None;
}
if self.vec[id.id].is_none() {
return None;
}
let cell = self.vec[id.id].as_ref().unwrap();
if cell.generation != id.generation {
return None;
}
Some(&cell.state)
}
pub fn get_mut(&mut self, id: GenerationalId) -> Option<&mut T> {
if id.id > self.vec.len() {
return None;
}
if self.vec[id.id].is_none() {
return None;
}
let cell = self.vec[id.id].as_mut().unwrap();
if cell.generation != id.generation {
return None;
}
Some(&mut cell.state)
}
pub fn retain<F>(&mut self, mut f: F)
where
F: FnMut(&mut T) -> bool,
{
for (id, cell) in self.vec.iter_mut().enumerate() {
if cell.is_none() {
continue;
}
let c = cell.as_mut().unwrap();
let pred = f(&mut c.state);
let old_generation = c.generation;
if !pred {
self.free_indices.push((id, old_generation));
*cell = None;
}
}
}
pub fn count(&self) -> usize {
self.vec.iter().filter(|c| c.is_some()).count()
}
pub fn clear(&mut self) {
self.vec.clear();
self.free_indices.clear();
}
pub fn free(&mut self, id: GenerationalId) {
if let Some(cell) = &self.vec[id.id] {
if cell.generation != id.generation {
return;
}
}
self.free_indices.push((id.id, id.generation));
self.vec[id.id] = None;
}
pub(crate) fn allocated_memory(&self) -> usize {
self.vec.capacity() * std::mem::size_of::<GenerationalCell<T>>()
}
}