Skip to content

Commit

Permalink
[#224] Introduce RawMemory testing helper; address review findings
Browse files Browse the repository at this point in the history
  • Loading branch information
elfenpiff committed Jun 6, 2024
1 parent 220b2b6 commit 4233ef5
Show file tree
Hide file tree
Showing 9 changed files with 167 additions and 75 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/build-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,8 @@ jobs:
- uses: vmactions/freebsd-vm@v1
with:
release: ${{ matrix.freebsd_version }}
mem: 8192
copyback: false
run: |
./internal/scripts/ci_prepare_freebsd.sh
export PATH=$PATH:$HOME/.cargo/bin
Expand Down
2 changes: 1 addition & 1 deletion examples/rust/complex_data_types/complex_data_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {

while let Iox2Event::Tick = Iox2::wait(CYCLE_TIME) {
// ComplexDataType as a size of over 30MB, we need to perform a placement new
// otherwise we will encounter a StackOverflow.
// otherwise we will encounter a stack overflow in debug builds.
// Therefore, we acquire an uninitialized sample, use the PlacementDefault
// trait to initialize ComplexDataType in place and then populate it with data.
let mut sample = publisher.loan_uninit()?;
Expand Down
15 changes: 3 additions & 12 deletions iceoryx2-bb/container/tests/byte_string_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,13 @@

mod fixed_size_byte_string {
use std::{
alloc::{alloc, dealloc, Layout},
hash::{Hash, Hasher},
mem::size_of,
ops::DerefMut,
};

use iceoryx2_bb_container::byte_string::*;
use iceoryx2_bb_elementary::placement_default::PlacementDefault;
use iceoryx2_bb_testing::assert_that;
use iceoryx2_bb_testing::{assert_that, memory::RawMemory};
use std::collections::hash_map::DefaultHasher;

const SUT_CAPACITY: usize = 129;
Expand Down Expand Up @@ -506,18 +504,11 @@ mod fixed_size_byte_string {

#[test]
fn placement_default_works() {
let layout = Layout::new::<Sut>();
let memory = unsafe { alloc(layout) } as *mut Sut;
for i in 0..size_of::<Sut>() {
unsafe { (memory as *mut u8).add(i).write(0xff) };
}
unsafe { Sut::placement_default(memory) };
let sut = unsafe { &mut (*memory) };
let mut sut = RawMemory::<Sut>::new_filled(0xff);
unsafe { Sut::placement_default(sut.as_mut_ptr()) };
assert_that!(sut, len 0);

assert_that!(sut.push_bytes(b"hello"), is_ok);
assert_that!(sut.as_bytes(), eq b"hello");

unsafe { dealloc(memory.cast(), layout) };
}
}
18 changes: 3 additions & 15 deletions iceoryx2-bb/container/tests/queue_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,11 @@
// SPDX-License-Identifier: Apache-2.0 OR MIT

mod queue {
use std::{
alloc::{alloc, dealloc, Layout},
mem::size_of,
};

use iceoryx2_bb_container::queue::*;
use iceoryx2_bb_elementary::{
bump_allocator::BumpAllocator, placement_default::PlacementDefault,
};
use iceoryx2_bb_testing::{assert_that, lifetime_tracker::LifetimeTracker};
use iceoryx2_bb_testing::{assert_that, lifetime_tracker::LifetimeTracker, memory::RawMemory};

const SUT_CAPACITY: usize = 128;
type Sut = FixedSizeQueue<usize, SUT_CAPACITY>;
Expand Down Expand Up @@ -302,21 +297,14 @@ mod queue {
#[test]
fn placement_default_works() {
type Sut = FixedSizeQueue<usize, SUT_CAPACITY>;
let layout = Layout::new::<Sut>();
let memory = unsafe { alloc(layout) } as *mut Sut;
for i in 0..size_of::<Sut>() {
unsafe { (memory as *mut u8).add(i).write(0xff) };
}
unsafe { Sut::placement_default(memory) };
let mut sut = RawMemory::<Sut>::new_filled(0xff);
unsafe { Sut::placement_default(sut.as_mut_ptr()) };

let sut = unsafe { &mut (*memory) };
assert_that!(sut, len 0);
assert_that!(sut.push(123), eq true);
assert_that!(sut.push(456), eq true);

assert_that!(sut.pop(), eq Some(123));
assert_that!(sut.pop(), eq Some(456));

unsafe { dealloc(memory.cast(), layout) };
}
}
15 changes: 3 additions & 12 deletions iceoryx2-bb/container/tests/vec_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,13 @@
//
// SPDX-License-Identifier: Apache-2.0 OR MIT

use std::alloc::{alloc, dealloc, Layout};
use std::mem::size_of;

use iceoryx2_bb_container::vec::*;
use iceoryx2_bb_elementary::bump_allocator::BumpAllocator;
use iceoryx2_bb_elementary::placement_default::PlacementDefault;
use iceoryx2_bb_elementary::relocatable_container::RelocatableContainer;
use iceoryx2_bb_testing::assert_that;
use iceoryx2_bb_testing::lifetime_tracker::LifetimeTracker;
use iceoryx2_bb_testing::memory::RawMemory;

const SUT_CAPACITY: usize = 128;
type Sut = FixedSizeVec<usize, SUT_CAPACITY>;
Expand Down Expand Up @@ -251,20 +249,13 @@ fn fixed_size_vec_pop_releases_ownership() {
#[test]
fn placement_default_works() {
type Sut = FixedSizeVec<usize, SUT_CAPACITY>;
let layout = Layout::new::<Sut>();
let memory = unsafe { alloc(layout) } as *mut Sut;
for i in 0..size_of::<Sut>() {
unsafe { (memory as *mut u8).add(i).write(0xff) };
}
unsafe { Sut::placement_default(memory) };
let mut sut = RawMemory::<Sut>::new_filled(0xff);
unsafe { Sut::placement_default(sut.as_mut_ptr()) };

let sut = unsafe { &mut (*memory) };
assert_that!(sut, len 0);
assert_that!(sut.push(123), eq true);
assert_that!(sut.push(456), eq true);

assert_that!(sut.pop(), eq Some(456));
assert_that!(sut.pop(), eq Some(123));

unsafe { dealloc(memory.cast(), layout) };
}
53 changes: 19 additions & 34 deletions iceoryx2-bb/derive-macros/tests/placement_default_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,11 @@

#[cfg(test)]
mod placement_new {
use std::{
alloc::{alloc, dealloc, Layout},
sync::atomic::{AtomicU64, AtomicUsize, Ordering},
};
use std::sync::atomic::{AtomicU64, AtomicUsize, Ordering};

use iceoryx2_bb_derive_macros::PlacementDefault;
use iceoryx2_bb_elementary::placement_default::PlacementDefault;
use iceoryx2_bb_testing::assert_that;
use iceoryx2_bb_testing::{assert_that, memory::RawMemory};

static DEFAULT_CTOR_COUNT: AtomicUsize = AtomicUsize::new(0);
static FUU_VALUE: AtomicU64 = AtomicU64::new(0);
Expand Down Expand Up @@ -81,15 +78,12 @@ mod placement_new {
FUU_VALUE.store(123, Ordering::Relaxed);
BAR_VALUE.store(456, Ordering::Relaxed);

let layout = Layout::new::<NamedTestStruct>();
let memory = unsafe { alloc(layout) } as *mut NamedTestStruct;
unsafe { NamedTestStruct::placement_default(memory) };
let memory = RawMemory::<NamedTestStruct>::new_zeroed();
unsafe { NamedTestStruct::placement_default(memory.as_mut_ptr()) };

assert_that!(DEFAULT_CTOR_COUNT.load(Ordering::Relaxed), eq 3);
assert_that!(unsafe{ &*memory }.value2.0, eq FUU_VALUE.load(Ordering::Relaxed));
assert_that!(unsafe{ &*memory }.value3.value, eq BAR_VALUE.load(Ordering::Relaxed));

unsafe { dealloc(memory.cast(), layout) };
assert_that!(memory.value2.0, eq FUU_VALUE.load(Ordering::Relaxed));
assert_that!(memory.value3.value, eq BAR_VALUE.load(Ordering::Relaxed));
}

#[test]
Expand All @@ -98,16 +92,13 @@ mod placement_new {
FUU_VALUE.store(789, Ordering::Relaxed);
BAR_VALUE.store(1337, Ordering::Relaxed);

let layout = Layout::new::<UnnamedTestStruct>();
let memory = unsafe { alloc(layout) } as *mut UnnamedTestStruct;
unsafe { UnnamedTestStruct::placement_default(memory) };
let memory = RawMemory::<UnnamedTestStruct>::new_zeroed();
unsafe { UnnamedTestStruct::placement_default(memory.as_mut_ptr()) };

assert_that!(DEFAULT_CTOR_COUNT.load(Ordering::Relaxed), eq 6);
assert_that!(unsafe{ &*memory }.0.0, eq FUU_VALUE.load(Ordering::Relaxed));
assert_that!(unsafe{ &*memory }.1.value, eq BAR_VALUE.load(Ordering::Relaxed));
assert_that!(unsafe{ &*memory }.2.value, eq BAR_VALUE.load(Ordering::Relaxed));

unsafe { dealloc(memory.cast(), layout) };
assert_that!(memory.0.0, eq FUU_VALUE.load(Ordering::Relaxed));
assert_that!(memory.1.value, eq BAR_VALUE.load(Ordering::Relaxed));
assert_that!(memory.2.value, eq BAR_VALUE.load(Ordering::Relaxed));
}

#[test]
Expand All @@ -117,15 +108,12 @@ mod placement_new {
FUU_VALUE.store(4711, Ordering::Relaxed);
BAR_VALUE.store(247, Ordering::Relaxed);

let layout = Layout::new::<SutType>();
let memory = unsafe { alloc(layout) } as *mut SutType;
unsafe { SutType::placement_default(memory) };
let memory = RawMemory::<SutType>::new_zeroed();
unsafe { SutType::placement_default(memory.as_mut_ptr()) };

assert_that!(DEFAULT_CTOR_COUNT.load(Ordering::Relaxed), eq 2);
assert_that!(unsafe{ &*memory }.value1.0, eq FUU_VALUE.load(Ordering::Relaxed));
assert_that!(unsafe{ &*memory }.value2.value, eq BAR_VALUE.load(Ordering::Relaxed));

unsafe { dealloc(memory.cast(), layout) };
assert_that!(memory.value1.0, eq FUU_VALUE.load(Ordering::Relaxed));
assert_that!(memory.value2.value, eq BAR_VALUE.load(Ordering::Relaxed));
}

#[test]
Expand All @@ -135,14 +123,11 @@ mod placement_new {
FUU_VALUE.store(895711, Ordering::Relaxed);
BAR_VALUE.store(89547, Ordering::Relaxed);

let layout = Layout::new::<SutType>();
let memory = unsafe { alloc(layout) } as *mut SutType;
unsafe { SutType::placement_default(memory) };
let memory = RawMemory::<SutType>::new_zeroed();
unsafe { SutType::placement_default(memory.as_mut_ptr()) };

assert_that!(DEFAULT_CTOR_COUNT.load(Ordering::Relaxed), eq 2);
assert_that!(unsafe{ &*memory }.0.0, eq FUU_VALUE.load(Ordering::Relaxed));
assert_that!(unsafe{ &*memory }.1.value, eq BAR_VALUE.load(Ordering::Relaxed));

unsafe { dealloc(memory.cast(), layout) };
assert_that!(memory.0.0, eq FUU_VALUE.load(Ordering::Relaxed));
assert_that!(memory.1.value, eq BAR_VALUE.load(Ordering::Relaxed));
}
}
56 changes: 55 additions & 1 deletion iceoryx2-bb/elementary/src/placement_default.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
//! Trait to perform placement new construction on a given pointer via [`Default::default()`].
//! See [`PlacementDefault`] for example.
use std::mem::MaybeUninit;

use iceoryx2_pal_concurrency_sync::iox_atomic::*;

/// A trait that allows types to perform a placement new based on their
Expand Down Expand Up @@ -98,6 +100,15 @@ Impl!(IoxAtomicI64);
Impl!(IoxAtomicIsize);
Impl!(IoxAtomicUsize);

impl<T: PlacementDefault> PlacementDefault for [T] {
unsafe fn placement_default(ptr: *mut Self) {
let ptr = ptr as *mut [MaybeUninit<T>];
for i in (*ptr).iter_mut() {
PlacementDefault::placement_default(i.as_mut_ptr());
}
}
}

impl<T: PlacementDefault, const CAPACITY: usize> PlacementDefault for [T; CAPACITY] {
unsafe fn placement_default(ptr: *mut Self) {
for i in 0..CAPACITY {
Expand All @@ -106,13 +117,56 @@ impl<T: PlacementDefault, const CAPACITY: usize> PlacementDefault for [T; CAPACI
}
}

impl<T: PlacementDefault> PlacementDefault for (T,) {
impl<T1: PlacementDefault> PlacementDefault for (T1,) {
unsafe fn placement_default(ptr: *mut Self) {
let ptr = core::ptr::addr_of_mut!((*ptr).0);
PlacementDefault::placement_default(ptr)
}
}

impl<T1: PlacementDefault, T2: PlacementDefault> PlacementDefault for (T1, T2) {
unsafe fn placement_default(ptr: *mut Self) {
let elem = core::ptr::addr_of_mut!((*ptr).0);
PlacementDefault::placement_default(elem);

let elem = core::ptr::addr_of_mut!((*ptr).1);
PlacementDefault::placement_default(elem)
}
}

impl<T1: PlacementDefault, T2: PlacementDefault, T3: PlacementDefault> PlacementDefault
for (T1, T2, T3)
{
unsafe fn placement_default(ptr: *mut Self) {
let elem = core::ptr::addr_of_mut!((*ptr).0);
PlacementDefault::placement_default(elem);

let elem = core::ptr::addr_of_mut!((*ptr).1);
PlacementDefault::placement_default(elem);

let elem = core::ptr::addr_of_mut!((*ptr).2);
PlacementDefault::placement_default(elem)
}
}

impl<T1: PlacementDefault, T2: PlacementDefault, T3: PlacementDefault, T4: PlacementDefault>
PlacementDefault for (T1, T2, T3, T4)
{
unsafe fn placement_default(ptr: *mut Self) {
let elem = core::ptr::addr_of_mut!((*ptr).0);
PlacementDefault::placement_default(elem);

let elem = core::ptr::addr_of_mut!((*ptr).1);
PlacementDefault::placement_default(elem);

let elem = core::ptr::addr_of_mut!((*ptr).2);
PlacementDefault::placement_default(elem);

let elem = core::ptr::addr_of_mut!((*ptr).3);
PlacementDefault::placement_default(elem)
}
}

impl<T> PlacementDefault for Option<T> {
unsafe fn placement_default(ptr: *mut Self) {
ptr.write(None)
Expand Down
1 change: 1 addition & 0 deletions iceoryx2-bb/testing/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#[macro_use]
pub mod assert;
pub mod lifetime_tracker;
pub mod memory;
pub mod watchdog;

#[macro_export(local_inner_macros)]
Expand Down
Loading

0 comments on commit 4233ef5

Please sign in to comment.