iceoryx2_bb_memory/
bump_allocator.rs1use core::{fmt::Display, ptr::NonNull};
19
20use iceoryx2_bb_concurrency::atomic::AtomicUsize;
21use iceoryx2_bb_concurrency::atomic::Ordering;
22use iceoryx2_bb_elementary::math::align;
23use iceoryx2_log::fail;
24
25pub use iceoryx2_bb_elementary_traits::allocator::{AllocationError, BaseAllocator};
26
27#[derive(Debug)]
28pub struct BumpAllocator {
29 pub(crate) start: usize,
30 size: usize,
31 current_position: AtomicUsize,
32}
33
34impl Display for BumpAllocator {
35 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
36 write!(
37 f,
38 "BumpAllocator {{ start: {}, size: {}, current_position: {} }}",
39 self.start,
40 self.size,
41 self.current_position
42 .load(core::sync::atomic::Ordering::Relaxed)
43 )
44 }
45}
46
47impl BumpAllocator {
48 pub fn new(ptr: NonNull<u8>, size: usize) -> Self {
49 Self {
50 start: ptr.as_ptr() as usize,
51 size,
52 current_position: AtomicUsize::new(0),
53 }
54 }
55
56 pub fn start_address(&self) -> usize {
57 self.start
58 }
59
60 pub fn used_space(&self) -> usize {
61 self.current_position.load(Ordering::Relaxed)
62 }
63
64 pub fn free_space(&self) -> usize {
65 self.size - self.used_space()
66 }
67
68 pub fn total_space(&self) -> usize {
69 self.size
70 }
71}
72
73impl BaseAllocator for BumpAllocator {
74 fn allocate(&self, layout: core::alloc::Layout) -> Result<NonNull<[u8]>, AllocationError> {
75 let msg = "Unable to allocate chunk with";
76 let mut aligned_position;
77
78 if layout.size() == 0 {
79 fail!(from self, with AllocationError::SizeIsZero,
80 "{} {:?} since the requested size was zero.", msg, layout);
81 }
82
83 let mut current_position = self
84 .current_position
85 .load(core::sync::atomic::Ordering::Relaxed);
86 loop {
87 aligned_position = align(self.start + current_position, layout.align()) - self.start;
88 if aligned_position + layout.size() > self.size {
89 fail!(from self, with AllocationError::OutOfMemory,
90 "{} {:?} since there is not enough memory available.", msg, layout);
91 }
92
93 match self.current_position.compare_exchange_weak(
94 current_position,
95 aligned_position + layout.size(),
96 core::sync::atomic::Ordering::Relaxed,
97 core::sync::atomic::Ordering::Relaxed,
98 ) {
99 Ok(_) => break,
100 Err(v) => current_position = v,
101 }
102 }
103
104 Ok(unsafe {
105 NonNull::new_unchecked(core::ptr::slice_from_raw_parts_mut(
106 (self.start + aligned_position) as *mut u8,
107 layout.size(),
108 ))
109 })
110 }
111
112 unsafe fn deallocate(&self, _ptr: NonNull<u8>, _layout: core::alloc::Layout) {
113 self.current_position
114 .store(0, core::sync::atomic::Ordering::Relaxed);
115 }
116}