Skip to main content

iceoryx2_cal/shm_allocator/
mod.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
13pub mod bump_allocator;
14pub mod pointer_offset;
15pub mod pool_allocator;
16
17use core::{alloc::Layout, fmt::Debug, ptr::NonNull};
18
19use iceoryx2_bb_elementary::enum_gen;
20pub use iceoryx2_bb_elementary_traits::allocator::AllocationError;
21use iceoryx2_bb_elementary_traits::allocator::BaseAllocator;
22pub use pointer_offset::*;
23use serde::{Deserialize, Serialize};
24
25/// Trait that identifies a configuration of a [`ShmAllocator`].
26pub trait ShmAllocatorConfig: Copy + Default + Debug + Send {}
27
28enum_gen! {
29/// Describes the errors that can occur when [`ShmAllocator::allocate()`] is called.
30    ShmAllocationError
31  entry:
32    ExceedsMaxSupportedAlignment
33  mapping:
34    AllocationError
35}
36
37/// Describes generically an [`AllocationStrategy`], meaning how the memory is increased when the
38/// available memory is insufficient.
39#[derive(Clone, Copy, Eq, PartialEq, Debug, Default, Serialize, Deserialize)]
40pub enum AllocationStrategy {
41    /// Increases the memory so that it perfectly fits the new size requirements. This may lead
42    /// to a lot of reallocations but has the benefit that no byte is wasted.
43    BestFit,
44    /// Increases the memory by rounding the increased memory size up to the next power of two.
45    /// Reduces reallocations a lot at the cost of increased memory usage.
46    PowerOfTwo,
47    /// The memory is not increased. This may lead to an out-of-memory error when allocating.
48    #[default]
49    Static,
50}
51
52/// Describes error that may occur when a [`ShmAllocator`] is initialized.
53#[derive(Clone, Copy, Eq, PartialEq, Debug)]
54pub enum ShmAllocatorInitError {
55    /// The [`SharedMemory`](crate::shared_memory::SharedMemory) max supported alignment does not
56    /// satisfy the required alignment of the [`ShmAllocator`].
57    MaxSupportedMemoryAlignmentInsufficient,
58    /// The [`ShmAllocator`] requires more memory to initialize than available.
59    AllocationFailed,
60}
61
62impl core::fmt::Display for ShmAllocatorInitError {
63    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
64        write!(f, "ShmAllocatorInitError::{self:?}")
65    }
66}
67
68impl core::error::Error for ShmAllocatorInitError {}
69
70/// Returned by [`ShmAllocator::resize_hint()`] and [`ShmAllocator::initial_setup_hint()`].
71/// It contains a payload size and [`ShmAllocator`] configuration suggestion for the given
72/// parameters.
73pub struct SharedMemorySetupHint<Config: ShmAllocatorConfig> {
74    /// The payload size of the [`SharedMemory`](crate::shared_memory::SharedMemory)
75    pub payload_size: usize,
76    /// The [`ShmAllocatorConfig`] that shall be used for the
77    /// [`SharedMemory`](crate::shared_memory::SharedMemory)
78    pub config: Config,
79}
80
81/// Every allocator implementation must be relocatable. The allocator itself must be stored either
82/// in the same shared memory segment or in a separate shared memory segment of a different type
83/// but accessible by all participating processes.
84pub trait ShmAllocator: Debug + Send + Sync + 'static {
85    type Configuration: ShmAllocatorConfig;
86    /// Suggest a new payload size by considering the current allocation state in combination with
87    /// a provided [`AllocationStrategy`] and a `layout` that shall be allocatable.
88    fn resize_hint(
89        &self,
90        layout: Layout,
91        strategy: AllocationStrategy,
92    ) -> SharedMemorySetupHint<Self::Configuration>;
93
94    /// Suggest a managed payload size under a provided configuration assuming that at most
95    /// `max_number_of_chunks` of memory are in use in parallel.
96    fn initial_setup_hint(
97        max_chunk_layout: Layout,
98        max_number_of_chunks: usize,
99    ) -> SharedMemorySetupHint<Self::Configuration>;
100
101    /// Returns the required memory size of the additional dynamic part of the allocator that is
102    /// allocated in [`ShmAllocator::init()`].
103    fn management_size(memory_size: usize, config: &Self::Configuration) -> usize;
104
105    /// Creates a new uninitialized shared memory allocator.
106    ///
107    /// # Safety
108    ///
109    /// * the method [`ShmAllocator::init()`] must be called before any other method is called
110    ///
111    unsafe fn new_uninit(
112        max_supported_alignment_by_memory: usize,
113        managed_memory: NonNull<[u8]>,
114        config: &Self::Configuration,
115    ) -> Self;
116
117    /// Initializes the shared memory allocator.
118    ///
119    /// # Safety
120    ///
121    /// * must be called only once
122    /// * must be called before any other method is called
123    ///
124    unsafe fn init<Allocator: BaseAllocator>(
125        &mut self,
126        mgmt_allocator: &Allocator,
127    ) -> Result<(), ShmAllocatorInitError>;
128
129    /// Returns the unique id of the allocator. It is inequal to any other
130    /// [`ShmAllocator::unique_id()`]
131    fn unique_id() -> u8;
132
133    /// Returns the max supported alignment by the allocator.
134    fn max_alignment(&self) -> usize;
135
136    /// Returns the offset to the beginning of the allocator payload. The smallest offset a user
137    /// can allocate.
138    fn relative_start_address(&self) -> usize;
139
140    /// Allocates memory and returns the pointer offset.
141    ///
142    /// # Safety
143    ///
144    /// * [`ShmAllocator::init()`] must have been called before using this method
145    ///
146    unsafe fn allocate(&self, layout: Layout) -> Result<PointerOffset, ShmAllocationError>;
147
148    /// Deallocates a previously allocated pointer offset
149    ///
150    /// # Safety
151    ///
152    /// * the provided distance must have been allocated before with the same layout
153    /// * [`ShmAllocator::init()`] must have been called before using this method
154    ///
155    unsafe fn deallocate(&self, distance: PointerOffset, layout: Layout);
156}