Skip to content

Commit 609961e

Browse files
authored
Merge pull request #1 from Vurich/master
Add alloc_many method
2 parents 13de4c5 + 5d023eb commit 609961e

File tree

1 file changed

+68
-4
lines changed

1 file changed

+68
-4
lines changed

src/arena.rs

Lines changed: 68 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
44
use std::mem::size_of;
55
use std::cell::Cell;
6+
use std::borrow::Cow;
67

78
const ARENA_BLOCK: usize = 64 * 1024;
89

@@ -16,7 +17,7 @@ const ARENA_BLOCK: usize = 64 * 1024;
1617
pub struct Arena {
1718
store: Cell<Vec<Vec<u8>>>,
1819
ptr: Cell<*mut u8>,
19-
offset: Cell<usize>
20+
offset: Cell<usize>,
2021
}
2122

2223
/// A pointer to an uninitialized region of memory.
@@ -77,7 +78,51 @@ impl Arena {
7778
Arena {
7879
store: Cell::new(store),
7980
ptr: Cell::new(ptr),
80-
offset: Cell::new(0)
81+
offset: Cell::new(0),
82+
}
83+
}
84+
85+
/// Allocate many items at once, without reallocating
86+
#[inline]
87+
pub fn alloc_many<'input, 'output, T: Sized + Copy + 'input, V: Into<Cow<'input, [T]>>>(
88+
&'output self,
89+
vals: V,
90+
) -> &'output [T] {
91+
use std::{mem, ptr, slice};
92+
93+
let vals = vals.into();
94+
95+
if vals.as_ref().is_empty() {
96+
return &[];
97+
}
98+
99+
let len = vals.as_ref().len();
100+
let bytes = len * mem::size_of::<T>();
101+
102+
match vals {
103+
Cow::Owned(mut vec) => {
104+
let p = vec.as_mut_ptr();
105+
let cap = vec.capacity();
106+
107+
mem::forget(vec);
108+
109+
let out = self.alloc_vec(unsafe {
110+
Vec::from_raw_parts(
111+
p as _,
112+
len * mem::size_of::<T>(),
113+
cap * mem::size_of::<T>(),
114+
)
115+
});
116+
117+
unsafe { slice::from_raw_parts(out as _, len) }
118+
}
119+
Cow::Borrowed(slice) => {
120+
let ptr = self.require(bytes);
121+
122+
unsafe { ptr::copy_nonoverlapping(slice.as_ptr() as _, ptr, bytes) };
123+
124+
unsafe { slice::from_raw_parts(ptr as _, len) }
125+
}
81126
}
82127
}
83128

@@ -251,6 +296,17 @@ mod test {
251296
assert_eq!(arena.store.get_mut().len(), 1);
252297
}
253298

299+
#[test]
300+
fn allocate_some_vecs() {
301+
let arena = Arena::new();
302+
303+
let vecs = vec![vec![1u64, 2, 3, 4], vec![7; ARENA_BLOCK * 2], vec![]];
304+
305+
for vec in vecs {
306+
assert_eq!(arena.alloc_many(vec.clone()), &vec[..]);
307+
}
308+
}
309+
254310
#[test]
255311
fn allocate_huge_heap() {
256312
let arena = Arena::new();
@@ -272,7 +328,10 @@ mod test {
272328
assert_eq!(arena.store.get_mut().len(), 2);
273329

274330
// Second page is appropriately large
275-
assert_eq!(arena.store.get_mut()[1].capacity(), size_of::<usize>() * 1024 * 1024);
331+
assert_eq!(
332+
arena.store.get_mut()[1].capacity(),
333+
size_of::<usize>() * 1024 * 1024
334+
);
276335
}
277336

278337
#[test]
@@ -312,6 +371,11 @@ mod test {
312371
let allocated = unsafe { ::std::slice::from_raw_parts(ptr, 12) };
313372

314373
assert_eq!(arena.offset.get(), 16);
315-
assert_eq!(allocated, &[b'a', b'b', b'c', b'd', b'e', b'f', b'g', b'h', b'i', b'j', b'k', 0]);
374+
assert_eq!(
375+
allocated,
376+
&[
377+
b'a', b'b', b'c', b'd', b'e', b'f', b'g', b'h', b'i', b'j', b'k', 0
378+
]
379+
);
316380
}
317381
}

0 commit comments

Comments
 (0)