zenoh_shm/posix_shm/
array.rs1use std::{marker::PhantomData, mem::size_of, num::NonZeroUsize};
16
17use num_traits::{AsPrimitive, PrimInt, Unsigned};
18use stabby::IStable;
19use zenoh_result::{bail, ZResult};
20
21use super::segment::Segment;
22use crate::shm;
23
24#[derive(Debug)]
26pub struct ArrayInSHM<ID, Elem, ElemIndex>
27where
28 rand::distributions::Standard: rand::distributions::Distribution<ID>,
29 ID: shm::SegmentID,
30{
31 inner: Segment<ID>,
32 _phantom: PhantomData<(Elem, ElemIndex)>,
33}
34
35unsafe impl<ID, Elem: Sync, ElemIndex> Sync for ArrayInSHM<ID, Elem, ElemIndex>
36where
37 rand::distributions::Standard: rand::distributions::Distribution<ID>,
38 ID: shm::SegmentID,
39{
40}
41unsafe impl<ID, Elem: Send, ElemIndex> Send for ArrayInSHM<ID, Elem, ElemIndex>
42where
43 rand::distributions::Standard: rand::distributions::Distribution<ID>,
44 ID: shm::SegmentID,
45{
46}
47
48impl<ID, Elem, ElemIndex> ArrayInSHM<ID, Elem, ElemIndex>
49where
50 rand::distributions::Standard: rand::distributions::Distribution<ID>,
51 ID: shm::SegmentID,
52 ElemIndex: Unsigned + PrimInt + 'static + AsPrimitive<usize>,
53 Elem: IStable<ContainsIndirections = stabby::abi::B0>,
54 isize: AsPrimitive<ElemIndex>,
55{
56 const _S: () = if size_of::<Elem>() == 0 {
58 panic!("Elem is a ZST. ZSTs are not allowed as ArrayInSHM generic");
59 };
60
61 pub fn create(elem_count: NonZeroUsize) -> ZResult<Self> {
62 let max: usize = ElemIndex::max_value().as_();
63 if elem_count.get() - 1 > max {
64 bail!("Unable to create SHM array segment of {elem_count} elements: out of range for ElemIndex!")
65 }
66
67 let alloc_size = NonZeroUsize::try_from(elem_count.get() * size_of::<Elem>())?;
68 let inner = Segment::create(alloc_size)?;
69 Ok(Self {
70 inner,
71 _phantom: PhantomData,
72 })
73 }
74
75 pub fn open(id: ID) -> ZResult<Self> {
76 let inner = Segment::open(id)?;
77 Ok(Self {
78 inner,
79 _phantom: PhantomData,
80 })
81 }
82
83 pub fn id(&self) -> ID {
84 self.inner.id()
85 }
86
87 pub fn elem_count(&self) -> NonZeroUsize {
88 let max: usize = ElemIndex::max_value().as_();
89 let actual = self.inner.len().get() / size_of::<Elem>();
90 unsafe { NonZeroUsize::new_unchecked(std::cmp::min(max.saturating_add(1), actual)) }
91 }
92
93 pub unsafe fn elem(&self, index: ElemIndex) -> *const Elem {
97 #[cfg(feature = "test")]
98 assert!(self.inner.len().get() > index.as_() * size_of::<Elem>());
99 (self.inner.as_ptr() as *const Elem).add(index.as_())
100 }
101
102 pub unsafe fn elem_mut(&self, index: ElemIndex) -> *mut Elem {
106 #[cfg(feature = "test")]
107 assert!(self.inner.len().get() > index.as_() * size_of::<Elem>());
108 (self.inner.as_ptr() as *mut Elem).add(index.as_())
109 }
110
111 pub unsafe fn index(&self, elem: *const Elem) -> ElemIndex {
115 let index = elem.offset_from(self.inner.as_ptr() as *const Elem);
116 #[cfg(feature = "test")]
117 {
118 assert!(index >= 0);
119 assert!(self.inner.len().get() > index as usize * size_of::<Elem>());
120 }
121 index.as_()
122 }
123}