zenoh_shm/api/protocol_implementations/posix/
posix_shm_provider_backend_talc.rs1use std::{
16 alloc::Layout,
17 ptr::NonNull,
18 slice,
19 sync::{Arc, Mutex},
20};
21
22use talc::{ErrOnOom, Talc};
23use zenoh_core::{zlock, Resolvable, Wait};
24use zenoh_result::ZResult;
25
26use super::posix_shm_segment::PosixShmSegment;
27use crate::api::{
28 common::{types::ProtocolID, with_id::WithProtocolID},
29 protocol_implementations::posix::protocol_id::POSIX_PROTOCOL_ID,
30 provider::{
31 chunk::ChunkDescriptor,
32 memory_layout::MemoryLayout,
33 shm_provider_backend::ShmProviderBackend,
34 types::{AllocAlignment, ChunkAllocResult, ZAllocError, ZLayoutError},
35 },
36};
37
38#[zenoh_macros::unstable_doc]
40pub struct PosixShmProviderBackendTalcBuilder<Layout> {
41 layout: Layout,
42}
43
44#[zenoh_macros::unstable_doc]
45impl<Layout> Resolvable for PosixShmProviderBackendTalcBuilder<Layout> {
46 type To = ZResult<PosixShmProviderBackendTalc>;
47}
48
49#[zenoh_macros::unstable_doc]
50impl<Layout: TryInto<MemoryLayout>> Wait for PosixShmProviderBackendTalcBuilder<Layout>
51where
52 Layout::Error: Into<ZLayoutError>,
53{
54 fn wait(self) -> <Self as Resolvable>::To {
55 PosixShmProviderBackendTalc::new(&self.layout.try_into().map_err(Into::into)?)
56 }
57}
58
59#[zenoh_macros::unstable_doc]
64pub struct PosixShmProviderBackendTalc {
65 segment: Arc<PosixShmSegment>,
66 talc: Mutex<Talc<ErrOnOom>>,
67 alignment: AllocAlignment,
68}
69
70impl PosixShmProviderBackendTalc {
71 #[zenoh_macros::unstable_doc]
73 pub fn builder<Layout>(layout: Layout) -> PosixShmProviderBackendTalcBuilder<Layout> {
74 PosixShmProviderBackendTalcBuilder { layout }
75 }
76
77 fn new(layout: &MemoryLayout) -> ZResult<Self> {
78 let segment = Arc::new(PosixShmSegment::create(layout.size())?);
79
80 let real_size = segment.segment.elem_count().get();
83 let ptr = unsafe { segment.segment.elem_mut(0) };
84
85 let mut talc = Talc::new(ErrOnOom);
86
87 unsafe {
88 talc.claim(slice::from_raw_parts_mut(ptr, real_size).into())
89 .map_err(|_| "Error initializing Talc backend!")?;
90 }
91
92 tracing::trace!(
93 "Created PosixShmProviderBackendTalc id {}, layout {:?}",
94 segment.segment.id(),
95 layout
96 );
97
98 Ok(Self {
99 segment,
100 talc: Mutex::new(talc),
101 alignment: layout.alignment(),
102 })
103 }
104}
105
106impl WithProtocolID for PosixShmProviderBackendTalc {
107 fn id(&self) -> ProtocolID {
108 POSIX_PROTOCOL_ID
109 }
110}
111
112impl ShmProviderBackend for PosixShmProviderBackendTalc {
113 fn alloc(&self, layout: &MemoryLayout) -> ChunkAllocResult {
114 tracing::trace!("PosixShmProviderBackendTalc::alloc({:?})", layout);
115
116 let alloc_layout = unsafe {
117 Layout::from_size_align_unchecked(
118 layout.size().get(),
119 layout.alignment().get_alignment_value().get(),
120 )
121 };
122
123 let alloc = {
124 let mut lock = zlock!(self.talc);
125 unsafe { lock.malloc(alloc_layout) }
126 };
127
128 match alloc {
129 Ok(buf) => Ok(self.segment.clone().allocated_chunk(buf, layout)),
130 Err(_) => Err(ZAllocError::OutOfMemory),
131 }
132 }
133
134 fn free(&self, chunk: &ChunkDescriptor) {
135 let alloc_layout = unsafe {
136 Layout::from_size_align_unchecked(
137 chunk.len.get(),
138 self.alignment.get_alignment_value().get(),
139 )
140 };
141
142 let ptr = unsafe { self.segment.segment.elem_mut(chunk.chunk) };
143
144 unsafe { zlock!(self.talc).free(NonNull::new_unchecked(ptr), alloc_layout) };
145 }
146
147 fn defragment(&self) -> usize {
148 0
149 }
150
151 fn available(&self) -> usize {
152 0
153 }
154
155 fn layout_for(&self, layout: MemoryLayout) -> Result<MemoryLayout, ZLayoutError> {
156 layout.extend(self.alignment)
157 }
158}