Skip to content

Commit

Permalink
Merge pull request #527 from elfenpiff/iox2-525-resizable-shm-support
Browse files Browse the repository at this point in the history
[#525] resizable shm support
  • Loading branch information
elfenpiff authored Dec 4, 2024
2 parents 417196f + 47b476d commit 0ad8d53
Show file tree
Hide file tree
Showing 26 changed files with 852 additions and 313 deletions.
22 changes: 11 additions & 11 deletions benchmarks/queue/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,36 +22,36 @@ const ITERATIONS: u64 = 10000000;

trait PushPop: Send + Sync {
fn push(&self, value: usize);
fn pop(&self) -> Option<usize>;
fn pop(&self) -> bool;
}

impl<const CAPACITY: usize> PushPop for Queue<usize, CAPACITY> {
fn push(&self, value: usize) {
unsafe { self.push(&value) };
}

fn pop(&self) -> Option<usize> {
unsafe { self.pop() }
fn pop(&self) -> bool {
unsafe { self.pop().is_some() }
}
}

impl<const CAPACITY: usize> PushPop for FixedSizeIndexQueue<CAPACITY> {
fn push(&self, value: usize) {
unsafe { self.push(value) };
unsafe { self.push(value as u64) };
}

fn pop(&self) -> Option<usize> {
unsafe { self.pop() }
fn pop(&self) -> bool {
unsafe { self.pop().is_some() }
}
}

impl<const CAPACITY: usize> PushPop for FixedSizeSafelyOverflowingIndexQueue<CAPACITY> {
fn push(&self, value: usize) {
unsafe { self.push(value) };
unsafe { self.push(value as u64) };
}

fn pop(&self) -> Option<usize> {
unsafe { self.pop() }
fn pop(&self) -> bool {
unsafe { self.pop().is_some() }
}
}

Expand All @@ -78,7 +78,7 @@ fn perform_benchmark<Q: PushPop>(

for _ in 0..args.iterations {
queue_a2b.push(0);
while queue_b2a.pop().is_none() {}
while !queue_b2a.pop() {}
}
});

Expand All @@ -90,7 +90,7 @@ fn perform_benchmark<Q: PushPop>(
start_benchmark_barrier.wait();

for _ in 0..args.iterations {
while queue_a2b.pop().is_none() {}
while !queue_a2b.pop() {}

queue_b2a.push(0);
}
Expand Down
17 changes: 7 additions & 10 deletions iceoryx2-bb/container/src/queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -333,8 +333,8 @@ pub mod details {
debug_assert!(
self.is_initialized
.load(std::sync::atomic::Ordering::Relaxed),
"From: {}, Undefined behavior - the object was not initialized with 'init' before.",
source
"From: MetaQueue<{}>::{}, Undefined behavior - the object was not initialized with 'init' before.",
std::any::type_name::<T>(), source
);
}

Expand Down Expand Up @@ -363,7 +363,7 @@ pub mod details {
}

pub(crate) unsafe fn peek_mut_impl(&mut self) -> Option<&mut T> {
self.verify_init(&format!("Queue<{}>::pop()", std::any::type_name::<T>()));
self.verify_init("peek_mut()");

if self.is_empty() {
return None;
Expand All @@ -375,7 +375,7 @@ pub mod details {
}

pub(crate) unsafe fn peek_impl(&self) -> Option<&T> {
self.verify_init(&format!("Queue<{}>::pop()", std::any::type_name::<T>()));
self.verify_init("peek()");

if self.is_empty() {
return None;
Expand All @@ -387,7 +387,7 @@ pub mod details {
}

pub(crate) unsafe fn pop_impl(&mut self) -> Option<T> {
self.verify_init(&format!("Queue<{}>::pop()", std::any::type_name::<T>()));
self.verify_init("pop()");

if self.is_empty() {
return None;
Expand All @@ -403,7 +403,7 @@ pub mod details {
}

pub(crate) unsafe fn push_impl(&mut self, value: T) -> bool {
self.verify_init(&format!("Queue<{}>::push()", std::any::type_name::<T>()));
self.verify_init("push()");

if self.len == self.capacity {
return false;
Expand All @@ -414,10 +414,7 @@ pub mod details {
}

pub(crate) unsafe fn push_with_overflow_impl(&mut self, value: T) -> Option<T> {
self.verify_init(&format!(
"Queue<{}>::push_with_overflow()",
std::any::type_name::<T>()
));
self.verify_init("push_with_overflow()");

let overridden_value = if self.len() == self.capacity() {
self.pop_impl()
Expand Down
26 changes: 26 additions & 0 deletions iceoryx2-bb/container/src/slotmap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ const INVALID: usize = usize::MAX;

#[doc(hidden)]
pub mod details {
use iceoryx2_pal_concurrency_sync::iox_atomic::IoxAtomicBool;

use super::*;

/// The iterator of a [`SlotMap`], [`RelocatableSlotMap`] or [`FixedSizeSlotMap`].
Expand Down Expand Up @@ -123,10 +125,21 @@ pub mod details {
data: MetaVec<Option<T>, Ptr>,
data_next_free_index: MetaQueue<usize, Ptr>,
idx_to_data_free_list_head: usize,
is_initialized: IoxAtomicBool,
len: usize,
}

impl<T, Ptr: GenericPointer> MetaSlotMap<T, Ptr> {
#[inline(always)]
fn verify_init(&self, source: &str) {
debug_assert!(
self.is_initialized
.load(std::sync::atomic::Ordering::Relaxed),
"From: MetaSlotMap<{}>::{}, Undefined behavior - the object was not initialized with 'init' before.",
std::any::type_name::<T>(), source
);
}

fn next_available_key_after(&self, start: SlotMapKey) -> Option<(SlotMapKey, &T)> {
let idx_to_data = &self.idx_to_data;

Expand Down Expand Up @@ -160,17 +173,20 @@ pub mod details {
}

pub(crate) unsafe fn iter_impl(&self) -> Iter<T, Ptr> {
self.verify_init("iter()");
Iter {
slotmap: self,
key: SlotMapKey(0),
}
}

pub(crate) unsafe fn contains_impl(&self, key: SlotMapKey) -> bool {
self.verify_init("contains()");
self.idx_to_data[key.0] != INVALID
}

pub(crate) unsafe fn get_impl(&self, key: SlotMapKey) -> Option<&T> {
self.verify_init("get()");
match self.idx_to_data[key.0] {
INVALID => None,
n => Some(self.data[n].as_ref().expect(
Expand All @@ -180,6 +196,7 @@ pub mod details {
}

pub(crate) unsafe fn get_mut_impl(&mut self, key: SlotMapKey) -> Option<&mut T> {
self.verify_init("get_mut()");
match self.idx_to_data[key.0] {
INVALID => None,
n => Some(self.data[n].as_mut().expect(
Expand Down Expand Up @@ -233,6 +250,7 @@ pub mod details {
}

pub(crate) unsafe fn insert_impl(&mut self, value: T) -> Option<SlotMapKey> {
self.verify_init("insert()");
self.acquire_next_free_index().map(|key| {
let key = SlotMapKey(key);
self.store_value(key, value);
Expand All @@ -241,11 +259,13 @@ pub mod details {
}

pub(crate) unsafe fn insert_at_impl(&mut self, key: SlotMapKey, value: T) -> bool {
self.verify_init("insert_at()");
self.claim_index(key.value());
self.store_value(key, value)
}

pub(crate) unsafe fn store_value(&mut self, key: SlotMapKey, value: T) -> bool {
self.verify_init("store()");
if key.0 > self.capacity_impl() {
return false;
}
Expand All @@ -264,6 +284,7 @@ pub mod details {
}

pub(crate) unsafe fn remove_impl(&mut self, key: SlotMapKey) -> bool {
self.verify_init("remove()");
if key.0 > self.idx_to_data.len() {
return false;
}
Expand All @@ -283,6 +304,7 @@ pub mod details {
}

pub(crate) unsafe fn next_free_key_impl(&self) -> Option<SlotMapKey> {
self.verify_init("next_free_key()");
if self.idx_to_data_free_list_head == INVALID {
return None;
}
Expand Down Expand Up @@ -316,6 +338,7 @@ pub mod details {
idx_to_data_free_list: RelocatableVec::new_uninit(capacity),
data: RelocatableVec::new_uninit(capacity),
data_next_free_index: RelocatableQueue::new_uninit(capacity),
is_initialized: IoxAtomicBool::new(false),
}
}

Expand All @@ -338,6 +361,8 @@ pub mod details {
"{msg} since the underlying data_next_free_index queue could not be initialized.");

self.initialize_data_structures();
self.is_initialized
.store(true, std::sync::atomic::Ordering::Relaxed);
Ok(())
}

Expand All @@ -356,6 +381,7 @@ pub mod details {
idx_to_data_free_list: MetaVec::new(capacity),
data: MetaVec::new(capacity),
data_next_free_index: MetaQueue::new(capacity),
is_initialized: IoxAtomicBool::new(true),
};
unsafe { new_self.initialize_data_structures() };
new_self
Expand Down
12 changes: 6 additions & 6 deletions iceoryx2-bb/container/src/vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,14 +181,14 @@ pub mod details {
type Target = [T];

fn deref(&self) -> &Self::Target {
self.verify_init(&format!("Vec<{}>::push()", std::any::type_name::<T>()));
self.verify_init("deref()");
unsafe { core::slice::from_raw_parts((*self.data_ptr.as_ptr()).as_ptr(), self.len) }
}
}

impl<T, Ptr: GenericPointer> DerefMut for MetaVec<T, Ptr> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.verify_init(&format!("Vec<{}>::push()", std::any::type_name::<T>()));
self.verify_init("deref_mut()");
unsafe {
core::slice::from_raw_parts_mut(
(*self.data_ptr.as_mut_ptr()).as_mut_ptr(),
Expand Down Expand Up @@ -222,8 +222,8 @@ pub mod details {
debug_assert!(
self.is_initialized
.load(std::sync::atomic::Ordering::Relaxed),
"From: {}, Undefined behavior - the object was not initialized with 'init' before.",
source
"From: MetaVec<{}>::{}, Undefined behavior - the object was not initialized with 'init' before.",
core::any::type_name::<T>(), source
);
}

Expand Down Expand Up @@ -252,7 +252,7 @@ pub mod details {
return false;
}

self.verify_init(&format!("Vec<{}>::push()", std::any::type_name::<T>()));
self.verify_init("push()");
self.push_unchecked(value);
true
}
Expand Down Expand Up @@ -303,7 +303,7 @@ pub mod details {
return None;
}

self.verify_init(&format!("Vec<{}>::pop()", std::any::type_name::<T>()));
self.verify_init("pop()");
Some(self.pop_unchecked())
}

Expand Down
8 changes: 4 additions & 4 deletions iceoryx2-bb/lock-free/src/mpmc/bit_set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ pub mod details {
fn verify_init(&self, source: &str) {
debug_assert!(
self.is_memory_initialized.load(Ordering::Relaxed),
"Undefined behavior when calling \"{}\" and the object is not initialized.",
"Undefined behavior when calling BitSet::{} and the object is not initialized.",
source
);
}
Expand Down Expand Up @@ -242,7 +242,7 @@ pub mod details {
/// If the bit was successfully set it returns true, if the bit was already set it
/// returns false.
pub fn set(&self, id: usize) -> bool {
self.verify_init("set");
self.verify_init("set()");
debug_assert!(
id < self.capacity,
"This should never happen. Out of bounds access with index {}.",
Expand All @@ -255,7 +255,7 @@ pub mod details {
/// Resets the next set bit and returns the bit index. If no bit was set it returns
/// [`None`].
pub fn reset_next(&self) -> Option<usize> {
self.verify_init("reset_next");
self.verify_init("reset_next()");

let current_position = self.reset_position.load(Ordering::Relaxed);
for pos in (current_position..self.capacity).chain(0..current_position) {
Expand All @@ -271,7 +271,7 @@ pub mod details {
/// Reset every set bit in the BitSet and call the provided callback for every bit that
/// was set. This is the most efficient way to acquire all bits that were set.
pub fn reset_all<F: FnMut(usize)>(&self, mut callback: F) {
self.verify_init("reset_all");
self.verify_init("reset_all()");

for i in 0..self.array_capacity {
let value = unsafe { (*self.data_ptr.as_ptr().add(i)).swap(0, Ordering::Relaxed) };
Expand Down
Loading

0 comments on commit 0ad8d53

Please sign in to comment.