Skip to content

Commit 8209bfe

Browse files
committed
[eclipse-iceoryx#139] Provide id tracker impl
1 parent 373a1f3 commit 8209bfe

File tree

7 files changed

+149
-29
lines changed

7 files changed

+149
-29
lines changed

iceoryx2-bb/lock-free/src/mpmc/bit_set.rs

+11-9
Original file line numberDiff line numberDiff line change
@@ -52,19 +52,20 @@ use iceoryx2_bb_elementary::{
5252

5353
use iceoryx2_bb_log::{fail, fatal_panic};
5454

55-
type BitsetElement = AtomicU8;
56-
const BITSET_ELEMENT_BITSIZE: usize = core::mem::size_of::<BitsetElement>() * 8;
57-
5855
/// This BitSet variant's data is stored in the heap.
59-
pub type BitSet = details::BitSet<OwningPointer<BitsetElement>>;
56+
pub type BitSet = details::BitSet<OwningPointer<details::BitsetElement>>;
6057
/// This BitSet variant can be stored inside shared memory.
61-
pub type RelocatableBitSet = details::BitSet<RelocatablePointer<BitsetElement>>;
58+
pub type RelocatableBitSet = details::BitSet<RelocatablePointer<details::BitsetElement>>;
6259

60+
#[doc(hidden)]
6361
pub mod details {
6462
use std::sync::atomic::AtomicUsize;
6563

6664
use super::*;
6765

66+
pub type BitsetElement = AtomicU8;
67+
const BITSET_ELEMENT_BITSIZE: usize = core::mem::size_of::<BitsetElement>() * 8;
68+
6869
#[derive(Debug)]
6970
#[repr(C)]
7071
pub struct BitSet<PointerType: PointerTrait<BitsetElement>> {
@@ -295,9 +296,9 @@ pub struct FixedSizeBitSet<const CAPACITY: usize> {
295296
bitset: RelocatableBitSet,
296297
// TODO: we waste here some memory since rust does us not allow to perform const operations
297298
// on generic parameters. Whenever this is supported, change this line into
298-
// data: [BitsetElement; Self::array_capacity(CAPACITY)]
299+
// data: [`details::BitsetElement; Self::array_capacity(CAPACITY)`]
299300
// For now we can live with it, since the bitsets are usually rather small
300-
data: [BitsetElement; CAPACITY],
301+
data: [details::BitsetElement; CAPACITY],
301302
}
302303

303304
unsafe impl<const CAPACITY: usize> Send for FixedSizeBitSet<CAPACITY> {}
@@ -309,10 +310,11 @@ impl<const CAPACITY: usize> Default for FixedSizeBitSet<CAPACITY> {
309310
bitset: unsafe {
310311
RelocatableBitSet::new(
311312
CAPACITY,
312-
align_to::<BitsetElement>(std::mem::size_of::<RelocatableBitSet>()) as _,
313+
align_to::<details::BitsetElement>(std::mem::size_of::<RelocatableBitSet>())
314+
as _,
313315
)
314316
},
315-
data: core::array::from_fn(|_| BitsetElement::new(0)),
317+
data: core::array::from_fn(|_| details::BitsetElement::new(0)),
316318
}
317319
}
318320
}

iceoryx2-cal/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,5 @@ ouroboros = { workspace = true }
3232

3333
[dev-dependencies]
3434
iceoryx2-pal-posix = { workspace = true }
35+
pin-init = { workspace = true }
3536
generic-tests = { workspace = true }

iceoryx2-cal/src/event/id_tracker/bitset.rs renamed to iceoryx2-cal/src/event/id_tracker/bit_set.rs

+8-4
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,25 @@
1010
//
1111
// SPDX-License-Identifier: Apache-2.0 OR MIT
1212

13-
use iceoryx2_bb_lock_free::mpmc::bit_set::RelocatableBitSet;
13+
use std::fmt::Debug;
14+
15+
use iceoryx2_bb_elementary::relocatable_ptr::PointerTrait;
16+
use iceoryx2_bb_lock_free::mpmc::bit_set::details::*;
1417
use iceoryx2_bb_log::fail;
1518

1619
use super::IdTracker;
1720
use crate::event::{NotifierNotifyError, TriggerId};
1821

19-
impl IdTracker for RelocatableBitSet {
22+
impl<PointerType: PointerTrait<BitsetElement> + Debug> IdTracker for BitSet<PointerType> {
2023
fn trigger_id_max(&self) -> TriggerId {
2124
TriggerId::new(self.capacity() as u64)
2225
}
2326

2427
fn add(&self, id: TriggerId) -> Result<(), NotifierNotifyError> {
25-
if self.trigger_id_max() >= id {
28+
if self.trigger_id_max() <= id {
2629
fail!(from self, with NotifierNotifyError::TriggerIdOutOfBounds,
27-
"Unable to set bit {:?} since it is out of bounds.", id);
30+
"Unable to set bit {:?} since it is out of bounds (max = {:?}).",
31+
id, self.trigger_id_max());
2832
}
2933
self.set(id.as_u64() as usize);
3034

iceoryx2-cal/src/event/id_tracker/mod.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,11 @@
1010
//
1111
// SPDX-License-Identifier: Apache-2.0 OR MIT
1212

13-
pub mod bitset;
14-
pub mod queue;
13+
pub mod bit_set;
1514

1615
use super::{NotifierNotifyError, TriggerId};
17-
use iceoryx2_bb_elementary::relocatable_container::RelocatableContainer;
1816

19-
pub trait IdTracker: RelocatableContainer {
17+
pub trait IdTracker: Send + Sync {
2018
fn trigger_id_max(&self) -> TriggerId;
2119
fn add(&self, id: TriggerId) -> Result<(), NotifierNotifyError>;
2220
fn acquire(&self) -> Option<TriggerId>;

iceoryx2-cal/src/event/id_tracker/queue.rs

-11
This file was deleted.

iceoryx2-cal/src/event/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ impl std::fmt::Display for ListenerCreateError {
8080

8181
impl std::error::Error for ListenerCreateError {}
8282

83-
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
83+
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
8484
pub struct TriggerId(u64);
8585

8686
impl TriggerId {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
// Copyright (c) 2024 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+
#[generic_tests::define]
14+
mod event_id_tracker {
15+
use std::collections::HashSet;
16+
17+
use iceoryx2_bb_lock_free::mpmc::bit_set::BitSet;
18+
use iceoryx2_bb_testing::assert_that;
19+
use iceoryx2_cal::event::{id_tracker::IdTracker, TriggerId};
20+
21+
trait NewSut {
22+
fn new_sut(capacity: usize) -> Self;
23+
}
24+
25+
impl NewSut for BitSet {
26+
fn new_sut(capacity: usize) -> Self {
27+
BitSet::new(capacity)
28+
}
29+
}
30+
#[test]
31+
fn max_trigger_id_must_be_at_least_capacity<Sut: IdTracker + NewSut>() {
32+
const CAPACITY: usize = 5234;
33+
34+
let sut = Sut::new_sut(CAPACITY);
35+
assert_that!(sut.trigger_id_max().as_u64(), ge CAPACITY as u64);
36+
}
37+
38+
#[test]
39+
fn add_and_acquire_works<Sut: IdTracker + NewSut>() {
40+
const CAPACITY: usize = 1234;
41+
42+
let sut = Sut::new_sut(CAPACITY);
43+
44+
assert_that!(sut.acquire(), eq None);
45+
for i in 0..CAPACITY {
46+
let id = TriggerId::new(i as u64);
47+
assert_that!(sut.add(id), is_ok);
48+
assert_that!(sut.acquire(), eq Some(id));
49+
assert_that!(sut.acquire(), is_none);
50+
}
51+
}
52+
53+
#[test]
54+
fn add_until_full_and_then_acquire_works<Sut: IdTracker + NewSut>() {
55+
const CAPACITY: usize = 1234;
56+
57+
let sut = Sut::new_sut(CAPACITY);
58+
59+
for i in 0..CAPACITY {
60+
let id = TriggerId::new((i as u64).min(sut.trigger_id_max().as_u64()));
61+
assert_that!(sut.add(id), is_ok);
62+
}
63+
64+
let mut ids = HashSet::new();
65+
for _ in 0..CAPACITY {
66+
let result = sut.acquire().unwrap();
67+
assert_that!(result, le sut.trigger_id_max());
68+
assert_that!(ids.insert(result), eq true);
69+
}
70+
71+
assert_that!(sut.acquire(), is_none);
72+
}
73+
74+
#[test]
75+
fn add_and_acquire_all_works<Sut: IdTracker + NewSut>() {
76+
const CAPACITY: usize = 3234;
77+
78+
let sut = Sut::new_sut(CAPACITY);
79+
80+
for i in 0..CAPACITY {
81+
let id = TriggerId::new((i as u64).min(sut.trigger_id_max().as_u64()));
82+
assert_that!(sut.add(id), is_ok);
83+
}
84+
85+
let mut ids = HashSet::new();
86+
sut.acquire_all(|id| {
87+
assert_that!(id, le sut.trigger_id_max());
88+
assert_that!(ids.insert(id), eq true);
89+
});
90+
91+
let mut callback_called = false;
92+
sut.acquire_all(|_| callback_called = true);
93+
assert_that!(callback_called, eq false);
94+
95+
assert_that!(ids, len CAPACITY);
96+
}
97+
98+
#[test]
99+
fn add_acquire_and_acquire_all_works<Sut: IdTracker + NewSut>() {
100+
const CAPACITY: usize = 234;
101+
102+
let sut = Sut::new_sut(CAPACITY);
103+
104+
for i in 0..CAPACITY {
105+
let id = TriggerId::new((i as u64).min(sut.trigger_id_max().as_u64()));
106+
assert_that!(sut.add(id), is_ok);
107+
}
108+
109+
let mut ids = HashSet::new();
110+
for _ in 0..CAPACITY / 2 {
111+
let result = sut.acquire().unwrap();
112+
assert_that!(result, le sut.trigger_id_max());
113+
assert_that!(ids.insert(result), eq true);
114+
}
115+
116+
sut.acquire_all(|id| {
117+
assert_that!(id, le sut.trigger_id_max());
118+
assert_that!(ids.insert(id), eq true);
119+
});
120+
121+
assert_that!(ids, len CAPACITY);
122+
}
123+
124+
#[instantiate_tests(<BitSet>)]
125+
mod bitset {}
126+
}

0 commit comments

Comments
 (0)