aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2018-08-10 19:13:46 +0100
committerAleksey Kladov <[email protected]>2018-08-10 19:13:46 +0100
commit3fff5e94ebf772f8485aaa2bda2ea36be766fdb3 (patch)
tree8eb533e24f7664209f301ebc72af877ec5593711
parent120789804d5483f14c9682b2b777adf6d2992547 (diff)
Add arena
-rw-r--r--libanalysis/src/arena.rs42
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 @@
1use parking_lot::RwLock;
2
3const CHUNK_LEN: usize = 16;
4
5pub struct Arena<T> {
6 chunks: RwLock<Vec<Vec<T>>>,
7}
8
9impl<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}