subms_arena_allocator/features/
aligned.rs1use std::alloc::{Layout, alloc, dealloc};
14use std::slice;
15
16use crate::align_up;
17
18pub struct AlignedBump {
20 ptr: *mut u8,
21 layout: Layout,
22 cursor: usize,
23}
24
25impl AlignedBump {
26 pub fn with_capacity(capacity: usize) -> Self {
30 let capacity = capacity.max(64);
31 let layout = Layout::from_size_align(capacity, 64).expect("layout");
34 let ptr = unsafe { alloc(layout) };
35 assert!(!ptr.is_null(), "OOM allocating aligned arena chunk");
36 Self {
37 ptr,
38 layout,
39 cursor: 0,
40 }
41 }
42
43 pub fn alloc_aligned(&mut self, size: usize, align: usize) -> &mut [u8] {
46 let cursor = self.cursor;
47 let cap = self.layout.size();
48 match self.try_alloc_aligned(size, align) {
49 Some(s) => s,
50 None => panic!(
51 "AlignedBump out of capacity: cursor={cursor} cap={cap} size={size} align={align}",
52 ),
53 }
54 }
55
56 pub fn try_alloc_aligned(&mut self, size: usize, align: usize) -> Option<&mut [u8]> {
58 assert!(
59 align.is_power_of_two(),
60 "align must be power of two: {align}"
61 );
62 let base = self.ptr as usize;
63 let aligned = align_up(base + self.cursor, align) - base;
64 let end = aligned.checked_add(size)?;
65 if end > self.layout.size() {
66 return None;
67 }
68 self.cursor = end;
69 unsafe {
70 let p = self.ptr.add(aligned);
71 Some(slice::from_raw_parts_mut(p, size))
72 }
73 }
74
75 pub fn reset(&mut self) {
77 self.cursor = 0;
78 }
79
80 pub fn capacity(&self) -> usize {
82 self.layout.size()
83 }
84
85 pub fn used(&self) -> usize {
87 self.cursor
88 }
89}
90
91impl Drop for AlignedBump {
92 fn drop(&mut self) {
93 unsafe { dealloc(self.ptr, self.layout) };
94 }
95}
96
97#[cfg(test)]
98#[path = "aligned_tests.rs"]
99mod tests;