rafx_base/slab/
raw_slab.rs1use std::prelude::v1::*;
2
3use super::SlabIndexT;
4use std::hash::{Hash, Hasher};
5use std::marker::PhantomData;
6
7pub struct RawSlabKey<T: Sized> {
9 index: SlabIndexT,
11
12 phantom_data: PhantomData<T>,
13}
14
15impl<T: Sized> Clone for RawSlabKey<T> {
16 fn clone(&self) -> RawSlabKey<T> {
17 RawSlabKey {
18 index: self.index,
19 phantom_data: Default::default(),
20 }
21 }
22}
23
24impl<T: Sized> Copy for RawSlabKey<T> {}
25
26impl<T: Sized> PartialEq for RawSlabKey<T> {
27 fn eq(
28 &self,
29 other: &Self,
30 ) -> bool {
31 self.index == other.index
32 }
33}
34
35impl<T: Sized> Eq for RawSlabKey<T> {}
36
37impl<T: Sized> Hash for RawSlabKey<T> {
38 fn hash<H: Hasher>(
39 &self,
40 state: &mut H,
41 ) {
42 self.index.hash(state);
43 }
44}
45
46impl<T: Sized> std::fmt::Debug for RawSlabKey<T> {
47 fn fmt(
48 &self,
49 f: &mut std::fmt::Formatter<'_>,
50 ) -> std::fmt::Result {
51 f.debug_struct("RawSlabKey")
52 .field("index", &self.index)
53 .finish()
54 }
55}
56
57impl<T: Sized> RawSlabKey<T> {
58 pub fn new(index: SlabIndexT) -> Self {
59 RawSlabKey {
60 index,
61 phantom_data: PhantomData,
62 }
63 }
64
65 pub fn index(self) -> SlabIndexT {
66 self.index
67 }
68}
69
70pub struct RawSlab<T> {
73 storage: Vec<Option<T>>,
75
76 free_list: Vec<SlabIndexT>,
78}
79
80impl<T> Default for RawSlab<T> {
81 fn default() -> Self {
82 Self::with_capacity(32)
83 }
84}
85
86impl<T> RawSlab<T> {
87 pub fn new() -> Self {
89 Default::default()
90 }
91
92 pub fn clear(&mut self) {
93 self.storage.clear();
94 self.free_list.clear();
95 }
96
97 pub fn with_capacity(capacity: SlabIndexT) -> Self {
99 let mut storage = Vec::with_capacity(capacity as usize);
100 let mut free_list = Vec::with_capacity(capacity as usize);
101
102 for index in (0..capacity).rev() {
104 storage.push(None);
105 free_list.push(index);
106 }
107
108 RawSlab { storage, free_list }
109 }
110
111 pub fn allocate(
115 &mut self,
116 value: T,
117 ) -> RawSlabKey<T> {
118 let index = self.free_list.pop();
119
120 if let Some(index) = index {
121 assert!(self.storage[index as usize].is_none());
123 self.storage[index as usize] = Some(value);
124 RawSlabKey::new(index)
125 } else {
126 let index = self.storage.len() as SlabIndexT;
127 self.storage.push(Some(value));
128
129 RawSlabKey::new(index)
130 }
131 }
132
133 pub fn allocate_with_key<F: FnMut(RawSlabKey<T>) -> T>(
134 &mut self,
135 mut f: F,
136 ) -> RawSlabKey<T> {
137 let index = self.free_list.pop();
138
139 if let Some(index) = index {
140 assert!(self.storage[index as usize].is_none());
142 let slab_key = RawSlabKey::new(index);
143 let value = (f)(slab_key);
144 self.storage[index as usize] = Some(value);
145 slab_key
146 } else {
147 let index = self.storage.len() as SlabIndexT;
148 let slab_key = RawSlabKey::new(index);
149 let value = (f)(slab_key);
150 self.storage.push(Some(value));
151 slab_key
152 }
153 }
154
155 pub fn free(
157 &mut self,
158 slab_key: RawSlabKey<T>,
159 ) {
160 assert!(
161 self.storage[slab_key.index as usize].is_some(),
162 "tried to free a none value"
163 );
164 self.storage[slab_key.index as usize] = None;
165 self.free_list.push(slab_key.index);
166 }
167
168 pub fn exists(
170 &self,
171 slab_key: RawSlabKey<T>,
172 ) -> bool {
173 self.storage[slab_key.index as usize].is_some()
174 }
175
176 pub fn get(
178 &self,
179 slab_key: RawSlabKey<T>,
180 ) -> Option<&T> {
181 self.storage[slab_key.index as usize].as_ref()
184 }
185
186 pub fn get_mut(
188 &mut self,
189 slab_key: RawSlabKey<T>,
190 ) -> Option<&mut T> {
191 self.storage[slab_key.index as usize].as_mut()
194 }
195
196 pub fn iter(&self) -> impl Iterator<Item = (RawSlabKey<T>, &T)> {
198 self.storage
199 .iter()
200 .enumerate()
201 .filter(|(_, value)| value.is_some())
202 .map(|(index, value)| (RawSlabKey::new(index as u32), value.as_ref().unwrap()))
203 }
204
205 pub fn iter_mut(&mut self) -> impl Iterator<Item = (RawSlabKey<T>, &mut T)> {
207 self.storage
208 .iter_mut()
209 .enumerate()
210 .filter(|(_, value)| value.is_some())
211 .map(|(index, value)| (RawSlabKey::new(index as u32), value.as_mut().unwrap()))
212 }
213
214 pub fn allocated_count(&self) -> usize {
216 self.storage.len() - self.free_list.len()
217 }
218
219 pub fn storage_size(&self) -> usize {
220 self.storage.len()
221 }
222}
223
224#[cfg(test)]
225mod tests {
226 use super::*;
227
228 struct TestStruct {
229 value: u32,
230 }
231
232 impl TestStruct {
233 fn new(value: u32) -> Self {
234 TestStruct { value }
235 }
236 }
237
238 #[test]
240 fn test_allocate_deallocate_one() {
241 let mut pool = RawSlab::<TestStruct>::new();
242 let value = TestStruct::new(123);
243 let key = pool.allocate(value);
244
245 assert_eq!(1, pool.allocated_count());
246 pool.free(key);
247 assert_eq!(0, pool.allocated_count());
248 }
249
250 #[test]
251 #[should_panic(expected = "tried to free a none value")]
252 fn test_double_free() {
253 let mut pool = RawSlab::<TestStruct>::new();
254 let value = TestStruct::new(123);
255 let key = pool.allocate(value);
256
257 assert_eq!(1, pool.allocated_count());
258 pool.free(key);
259 assert_eq!(0, pool.allocated_count());
260 pool.free(key);
261 }
262
263 #[test]
265 fn test_allocate_deallocate_fifo() {
266 let mut pool = RawSlab::<TestStruct>::new();
267 let mut keys = vec![];
268
269 for i in 0..1000 {
270 let value = TestStruct::new(i);
271 let key = pool.allocate(value);
272 keys.push(key);
273 }
274
275 assert_eq!(1000, pool.allocated_count());
276
277 for k in keys {
278 pool.free(k);
279 }
280
281 assert_eq!(0, pool.allocated_count());
282 }
283
284 #[test]
285 fn test_allocate_deallocate_lifo() {
286 let mut pool = RawSlab::<TestStruct>::new();
287 let mut keys = vec![];
288
289 for i in 0..1000 {
290 let value = TestStruct::new(i);
291 let key = pool.allocate(value);
292 keys.push(key);
293 }
294
295 assert_eq!(1000, pool.allocated_count());
296
297 for i in (0..keys.len()).rev() {
298 pool.free(keys[i]);
299 }
300
301 assert_eq!(0, pool.allocated_count());
302 }
303
304 #[test]
305 fn test_get_success() {
306 let mut pool = RawSlab::<TestStruct>::new();
307 let mut keys = vec![];
308
309 for i in 0..10 {
310 let value = TestStruct::new(i);
311 let key = pool.allocate(value);
312 keys.push(key);
313 }
314
315 assert_eq!(10, pool.allocated_count());
316 assert_eq!(5, pool.get(keys[5]).unwrap().value);
317 }
318
319 #[test]
320 fn test_get_fail_out_of_range() {
321 let mut pool = RawSlab::<TestStruct>::new();
322 let value = TestStruct::new(123);
323 let key = pool.allocate(value);
324 assert_eq!(1, pool.allocated_count());
325
326 assert!(pool.get(key).is_some());
327
328 pool.free(key);
329 assert_eq!(0, pool.allocated_count());
330
331 assert!(pool.get(key).is_none());
332 }
333
334 #[test]
335 fn test_get_mut_success() {
336 let mut pool = RawSlab::<TestStruct>::new();
337 let mut keys = vec![];
338
339 for i in 0..10 {
340 let value = TestStruct::new(i);
341 let key = pool.allocate(value);
342 keys.push(key);
343 }
344
345 assert_eq!(10, pool.allocated_count());
346 assert_eq!(5, pool.get_mut(keys[5]).unwrap().value);
347 }
348
349 #[test]
350 fn test_get_mut_fail_out_of_range() {
351 let mut pool = RawSlab::<TestStruct>::new();
352 let value = TestStruct::new(123);
353 let key = pool.allocate(value);
354 assert_eq!(1, pool.allocated_count());
355
356 assert!(pool.get_mut(key).is_some());
357
358 pool.free(key);
359 assert_eq!(0, pool.allocated_count());
360
361 assert!(pool.get_mut(key).is_none());
362 }
363}