Skip to content

Commit

Permalink
[eclipse-iceoryx#497] Implementing resizable shared memory
Browse files Browse the repository at this point in the history
  • Loading branch information
elfenpiff committed Nov 6, 2024
1 parent 662e21d commit d95a220
Show file tree
Hide file tree
Showing 3 changed files with 186 additions and 47 deletions.
3 changes: 3 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions iceoryx2-fal/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,6 @@ version = { workspace = true }
[dependencies]
iceoryx2-cal = { workspace = true }
iceoryx2-bb-system-types = { workspace = true }
iceoryx2-bb-elementary = { workspace = true }
iceoryx2-bb-log = { workspace = true }
iceoryx2-pal-concurrency-sync = { workspace = true }
227 changes: 180 additions & 47 deletions iceoryx2-fal/src/resizable_shared_memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,93 +11,221 @@
// SPDX-License-Identifier: Apache-2.0 OR MIT

use std::alloc::Layout;
use std::collections::VecDeque;
use std::fmt::Debug;
use std::time::Duration;

use iceoryx2_bb_elementary::CallbackProgression;
use iceoryx2_bb_log::fail;
use iceoryx2_bb_system_types::file_name::FileName;
use iceoryx2_cal::shared_memory::{SharedMemory, SharedMemoryCreateError, SharedMemoryOpenError};
use iceoryx2_cal::named_concept::*;
use iceoryx2_cal::shared_memory::{
SharedMemory, SharedMemoryBuilder, SharedMemoryCreateError, SharedMemoryOpenError, ShmPointer,
};
use iceoryx2_cal::shm_allocator::pool_allocator::PoolAllocator;
use iceoryx2_cal::shm_allocator::ShmAllocator;
use iceoryx2_cal::shm_allocator::{PointerOffset, ShmAllocationError};

#[derive(Debug)]
pub struct UniqueIndexVector<T: Debug> {
data: Vec<T>,
idx_to_data: Vec<usize>,
current_idx: usize,
}

impl<T: Debug> UniqueIndexVector<T> {
pub fn new() -> Self {
Self {
data: vec![],
idx_to_data: vec![],
current_idx: 0,
}
}

pub fn push(&mut self, value: T) -> usize {
todo!()
}

pub fn write_at(&mut self, value: T, index: usize) {}

pub fn remove(&mut self, index: usize) {}

pub fn get(&self, index: usize) -> &T {
todo!()
}

pub fn get_mut(&mut self, index: usize) -> &mut T {
todo!()
}
}

impl<T: Debug, const N: usize> From<[T; N]> for UniqueIndexVector<T> {
fn from(value: [T; N]) -> Self {
todo!()
}
}

pub struct DynamicPointerOffset {
value: u64,
}

impl DynamicPointerOffset {
pub fn offset(&self) -> PointerOffset {
todo!()
}

pub fn segment_id(&self) -> u8 {
todo!()
}

pub fn has_segment_update(&self) -> u8 {
todo!()
}
}

#[derive(Default)]
pub enum AllocationStrategy {
#[default]
PowerOfTwo,
BestFit,
Static,
}

pub struct ResizableSharedMemoryBuilder {}
#[derive(Debug)]
pub struct ResizableSharedMemoryBuilder<T: SharedMemory<PoolAllocator>>
where
T::Builder: Debug,
{
builder: T::Builder,
bucket_layout_hint: Layout,
number_of_buckets_hint: usize,
}

impl ResizableSharedMemoryBuilder {
/// Defines the prefix that the concept will use.
fn prefix(self, value: &FileName) -> Self {
todo!()
impl<T: SharedMemory<PoolAllocator>> ResizableSharedMemoryBuilder<T>
where
T::Builder: Debug,
{
pub fn new(name: &FileName) -> Self {
Self {
builder: T::Builder::new(name),
bucket_layout_hint: Layout::new::<u8>(),
number_of_buckets_hint: 1,
}
}

/// Defines the suffix that the concept will use.
fn suffix(self, value: &FileName) -> Self {
todo!()
pub fn config(mut self, config: &T::Configuration) -> Self {
self.builder = self.builder.config(config);
self
}

/// Defines if a newly created [`SharedMemory`] owns the underlying resources
fn has_ownership(self, value: bool) -> Self {
todo!()
pub fn has_ownership(mut self, value: bool) -> Self {
self.builder = self.builder.has_ownership(value);
self
}

fn bucket_layout_hint(self, layout: Layout) -> Self {
todo!()
pub fn bucket_layout_hint(mut self, layout: Layout) -> Self {
self.bucket_layout_hint = layout;
self
}

fn number_of_buckets_hint(self, value: usize) -> Self {
todo!()
pub fn number_of_buckets_hint(mut self, value: usize) -> Self {
self.number_of_buckets_hint = value.max(1);
self
}

/// The timeout defines how long the [`SharedMemoryBuilder`] should wait for
/// [`SharedMemoryBuilder::create()`] to finialize
/// the initialization. This is required when the [`SharedMemory`] is created and initialized
/// concurrently from another process. By default it is set to [`Duration::ZERO`] for no
/// timeout.
fn timeout(self, value: Duration) -> Self {
todo!()
pub fn timeout(mut self, value: Duration) -> Self {
self.builder = self.builder.timeout(value);
self
}

/// Creates new [`SharedMemory`]. If it already exists the method will fail.
fn create<T: SharedMemory<PoolAllocator>>(
self,
) -> Result<ResizableSharedMemory<T>, SharedMemoryCreateError> {
todo!()
pub fn create(self) -> Result<ResizableSharedMemory<T>, SharedMemoryCreateError> {
let initial_size = self.number_of_buckets_hint * self.bucket_layout_hint.size();
let initial_allocator_config = iceoryx2_cal::shm_allocator::pool_allocator::Config {
bucket_layout: self.bucket_layout_hint,
};

let origin = format!("{:?}", self);
let shm = fail!(from origin, when self
.builder
.size(initial_size)
.create(&initial_allocator_config),
"Unable to create ResizableSharedMemory since the underlying shared memory could not be created.");

Ok(ResizableSharedMemory {
shared_memory_vec: UniqueIndexVector::from([shm]),
current_idx: 0,
number_of_buckets: self.number_of_buckets_hint,
bucket_layout: self.bucket_layout_hint,
})
}

/// Opens already existing [`SharedMemory`]. If it does not exist or the initialization is not
/// yet finished the method will fail.
fn open<T: SharedMemory<PoolAllocator>>(
self,
) -> Result<ResizableSharedMemory<T>, SharedMemoryOpenError> {
pub fn open(self) -> Result<ResizableSharedMemoryView<T>, SharedMemoryOpenError> {
let origin = format!("{:?}", self);
let shm = fail!(from origin, when self
.builder
.open(),
"Unable to open ResizableSharedMemoryView since the underlying shared memory could not be opened.");

Ok(ResizableSharedMemoryView {
shared_memory_vec: UniqueIndexVector::from([shm]),
})
}
}

pub struct ResizableSharedMemoryView<T: SharedMemory<PoolAllocator>> {
shared_memory_vec: UniqueIndexVector<T>,
}

impl<T: SharedMemory<PoolAllocator>> ResizableSharedMemoryView<T> {
fn translate_offset(&self, offset: DynamicPointerOffset) -> usize {
// updates and remaps shared memories
//
todo!()
}
}

pub struct ResizableSharedMemory<T: SharedMemory<PoolAllocator>> {
shared_memory_vec: VecDeque<T>,
shared_memory_vec: UniqueIndexVector<T>,
current_idx: u8,
number_of_buckets: usize,
bucket_layout: Layout,
}

impl<T: SharedMemory<PoolAllocator>> ResizableSharedMemory<T> {
/// Returns the size of the shared memory.
fn size(&self) -> usize {
fn name(&self) -> &FileName {
todo!()
}

/// Returns the max supported alignment.
fn max_alignment(&self) -> usize;
unsafe fn remove(
name: &FileName,
config: &T::Configuration,
) -> Result<bool, NamedConceptRemoveError> {
todo!()
}

/// Returns the start address of the shared memory. Used by the [`ShmPointer`] to calculate
/// the actual memory position.
fn payload_start_address(&self) -> usize;
fn does_exist(
name: &FileName,
config: &T::Configuration,
) -> Result<bool, NamedConceptDoesExistError> {
todo!()
}

fn list<F: FnMut(&FileName) -> CallbackProgression>(
config: &T::Configuration,
callback: F,
) -> Result<(), NamedConceptListError> {
todo!()
}

/// Allocates memory. The alignment in the layout must be smaller or equal
/// [`SharedMemory::max_alignment()`] otherwise the method will fail.
fn allocate(&self, layout: std::alloc::Layout) -> Result<ShmPointer, ShmAllocationError>;
fn allocate(&self, layout: std::alloc::Layout) -> Result<ShmPointer, ShmAllocationError> {
todo!()
}

/// Release previously allocated memory
///
Expand All @@ -106,25 +234,30 @@ impl<T: SharedMemory<PoolAllocator>> ResizableSharedMemory<T> {
/// * the offset must be acquired with [`SharedMemory::allocate()`] - extracted from the
/// [`ShmPointer`]
/// * the layout must be identical to the one used in [`SharedMemory::allocate()`]
unsafe fn deallocate(&self, offset: PointerOffset, layout: std::alloc::Layout);
unsafe fn deallocate(&self, offset: PointerOffset, layout: std::alloc::Layout) {
todo!()
}

/// Returns if the [`SharedMemory`] supports persistency, meaning that the underlying OS
/// resource remain even when every [`SharedMemory`] instance in every process was removed.
fn does_support_persistency() -> bool;
fn does_support_persistency() -> bool {
todo!()
}

/// Returns true if the [`SharedMemory`] holds the ownership, otherwise false
fn has_ownership(&self) -> bool;
fn has_ownership(&self) -> bool {
todo!()
}

/// Acquires the ownership of the [`SharedMemory`]. When the object goes out of scope the
/// underlying resources will be removed.
fn acquire_ownership(&self);
fn acquire_ownership(&self) {
todo!()
}

/// Releases the ownership of the [`SharedMemory`] meaning when it goes out of scope the
/// underlying resource will not be removed.
fn release_ownership(&self);

/// The default suffix of every shared memory
fn default_suffix() -> FileName {
unsafe { FileName::new_unchecked(b".shm") }
fn release_ownership(&self) {
todo!()
}
}

0 comments on commit d95a220

Please sign in to comment.