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}