iceoryx2_bb_elementary/allocator.rs
1// Copyright (c) 2023 Contributors to the Eclipse Foundation
2//
3// See the NOTICE file(s) distributed with this work for additional
4// information regarding copyright ownership.
5//
6// This program and the accompanying materials are made available under the
7// terms of the Apache Software License 2.0 which is available at
8// https://www.apache.org/licenses/LICENSE-2.0, or the MIT license
9// which is available at https://opensource.org/licenses/MIT.
10//
11// SPDX-License-Identifier: Apache-2.0 OR MIT
12
13//! Contains the traits [`BaseAllocator`] which contains the most basic functionality an allocator
14//! requires and [`Allocator`] with more advanced allocation features.
15
16pub use std::{alloc::Layout, ptr::NonNull};
17
18/// Failures caused by [`BaseAllocator::allocate()`] or [`BaseAllocator::allocate_zeroed()`].
19#[derive(Debug, Clone, Copy, Eq, Hash, PartialEq)]
20pub enum AllocationError {
21 SizeIsZero,
22 SizeTooLarge,
23 AlignmentFailure,
24 OutOfMemory,
25 InternalError,
26}
27
28/// Failures caused by [`Allocator::grow()`] or [`Allocator::grow_zeroed()`].
29#[derive(Debug, PartialEq, Eq, Copy, Clone)]
30pub enum AllocationGrowError {
31 GrowWouldShrink,
32 SizeIsZero,
33 OutOfMemory,
34 AlignmentFailure,
35 InternalError,
36}
37
38/// Failures caused by [`Allocator::shrink()`].
39#[derive(Debug, PartialEq, Eq, Copy, Clone)]
40pub enum AllocationShrinkError {
41 ShrinkWouldGrow,
42 SizeIsZero,
43 AlignmentFailure,
44 InternalError,
45}
46
47/// The most minimalistic requirement for an allocator
48pub trait BaseAllocator {
49 /// Allocates a memory chunk with the properties provided in layout and either
50 /// returns a slice or an allocation error on failure.
51 fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocationError>;
52
53 /// Allocates a memory chunk with the properties provided in layout and zeroes the memory
54 /// On success it returns a slice or an allocation error on failure.
55 fn allocate_zeroed(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocationError> {
56 let memory = self.allocate(layout)?;
57 unsafe {
58 std::ptr::write_bytes(
59 memory.as_ref().as_ptr() as *mut u8,
60 0,
61 memory.as_ref().len(),
62 )
63 };
64 Ok(memory)
65 }
66
67 /// Releases an previously allocated chunk of memory.
68 ///
69 /// # Safety
70 ///
71 /// * `ptr` must be allocated previously with [`BaseAllocator::allocate()`] or
72 /// [`BaseAllocator::allocate_zeroed()`]
73 /// * `layout` must have the same value as in the allocation or, when the memory was
74 /// resized, the same value as it was resized to
75 ///
76 unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout);
77}
78
79/// Allocator with grow and shrink features.
80pub trait Allocator: BaseAllocator {
81 /// Increases the size of an previously allocated chunk of memory or allocates a new chunk
82 /// with the provided properties.
83 /// It returns a failure when the size decreases.
84 ///
85 /// # Safety
86 ///
87 /// * `ptr` must be allocated previously with [`BaseAllocator::allocate()`] or
88 /// [`BaseAllocator::allocate_zeroed()`]
89 /// * `old_layout` must have the same value as in the allocation or, when the memory was
90 /// resized, the same value as it was resized to
91 ///
92 unsafe fn grow(
93 &self,
94 ptr: NonNull<u8>,
95 old_layout: Layout,
96 new_layout: Layout,
97 ) -> Result<NonNull<[u8]>, AllocationGrowError>;
98
99 /// Increases the size of an previously allocated chunk of memory or allocates a new chunk
100 /// with the provided properties. If the chunk can be resized only the difference in size
101 /// will be zeroed.
102 /// It returns a failure when the size decreases.
103 ///
104 /// # Safety
105 ///
106 /// * `ptr` must be allocated previously with [`BaseAllocator::allocate()`] or
107 /// [`BaseAllocator::allocate_zeroed()`]
108 /// * `old_layout` must have the same value as in the allocation or, when the memory was
109 /// resized, the same value as it was resized to
110 ///
111 unsafe fn grow_zeroed(
112 &self,
113 ptr: NonNull<u8>,
114 old_layout: Layout,
115 new_layout: Layout,
116 ) -> Result<NonNull<[u8]>, AllocationGrowError> {
117 let memory = self.grow(ptr, old_layout, new_layout)?;
118 std::ptr::write_bytes(
119 memory.as_ref().as_ptr().add(old_layout.size()) as *mut u8,
120 0,
121 memory.as_ref().len() - old_layout.size(),
122 );
123 Ok(memory)
124 }
125
126 /// Decreases the size of an previously allocated chunk of memory. If the size increases it
127 /// fails.
128 ///
129 /// # Safety
130 ///
131 /// * `ptr` must be allocated previously with [`BaseAllocator::allocate()`] or
132 /// [`BaseAllocator::allocate_zeroed()`]
133 /// * `old_layout` must have the same value as in the allocation or, when the memory was
134 /// resized, the same value as it was resized to
135 ///
136 unsafe fn shrink(
137 &self,
138 ptr: NonNull<u8>,
139 old_layout: Layout,
140 new_layout: Layout,
141 ) -> Result<NonNull<[u8]>, AllocationShrinkError>;
142}