diff options
-rw-r--r-- | libanalysis/src/arena.rs | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/libanalysis/src/arena.rs b/libanalysis/src/arena.rs new file mode 100644 index 000000000..fc0c25c54 --- /dev/null +++ b/libanalysis/src/arena.rs | |||
@@ -0,0 +1,42 @@ | |||
1 | use parking_lot::RwLock; | ||
2 | |||
3 | const CHUNK_LEN: usize = 16; | ||
4 | |||
5 | pub struct Arena<T> { | ||
6 | chunks: RwLock<Vec<Vec<T>>>, | ||
7 | } | ||
8 | |||
9 | impl<T> Arena<T> { | ||
10 | pub fn new(&self) -> Arena<T> { | ||
11 | Arena { | ||
12 | chunks: RwLock::new(vec![Vec::with_capacity(CHUNK_LEN)]), | ||
13 | } | ||
14 | } | ||
15 | |||
16 | pub fn push(&self, value: T) -> usize { | ||
17 | let mut guard = self.chunks.write(); | ||
18 | let mut idx = (guard.len() - 1) * CHUNK_LEN; | ||
19 | let chunk = { | ||
20 | if guard.last().unwrap().len() == CHUNK_LEN { | ||
21 | guard.push(Vec::with_capacity(CHUNK_LEN)); | ||
22 | } | ||
23 | guard.last_mut().unwrap() | ||
24 | }; | ||
25 | assert!(chunk.len() < chunk.capacity()); | ||
26 | idx += chunk.len(); | ||
27 | chunk.push(value); | ||
28 | idx | ||
29 | } | ||
30 | |||
31 | pub fn get(&self, idx: usize) -> &T { | ||
32 | let chunk_idx = idx / CHUNK_LEN; | ||
33 | let chunk_off = idx - chunk_idx * CHUNK_LEN; | ||
34 | let guard = self.chunks.read(); | ||
35 | let value = &guard[chunk_idx][chunk_off]; | ||
36 | unsafe { | ||
37 | // We are careful to not move values in chunks, | ||
38 | // so this hopefully is safe | ||
39 | ::std::mem::transmute::<&T, &T>(value) | ||
40 | } | ||
41 | } | ||
42 | } | ||