iceoryx2_ffi/api/
notifier.rs1#![allow(non_camel_case_types)]
14
15use crate::api::{
16 c_size_t, iox2_event_id_t, iox2_service_type_e, iox2_unique_notifier_id_h,
17 iox2_unique_notifier_id_t, AssertNonNullHandle, HandleToType, IntoCInt, IOX2_OK,
18};
19
20use iceoryx2::port::notifier::{Notifier, NotifierNotifyError};
21use iceoryx2::prelude::*;
22use iceoryx2_bb_elementary::static_assert::*;
23use iceoryx2_ffi_macros::iceoryx2_ffi;
24
25use core::ffi::c_int;
26use core::mem::ManuallyDrop;
27
28#[repr(C)]
31#[derive(Copy, Clone)]
32pub enum iox2_notifier_notify_error_e {
33 EVENT_ID_OUT_OF_BOUNDS = IOX2_OK as isize + 1,
34}
35
36impl IntoCInt for NotifierNotifyError {
37 fn into_c_int(self) -> c_int {
38 (match self {
39 NotifierNotifyError::EventIdOutOfBounds => {
40 iox2_notifier_notify_error_e::EVENT_ID_OUT_OF_BOUNDS
41 }
42 }) as c_int
43 }
44}
45
46pub(super) union NotifierUnion {
47 ipc: ManuallyDrop<Notifier<ipc::Service>>,
48 local: ManuallyDrop<Notifier<local::Service>>,
49}
50
51impl NotifierUnion {
52 pub(super) fn new_ipc(notifier: Notifier<ipc::Service>) -> Self {
53 Self {
54 ipc: ManuallyDrop::new(notifier),
55 }
56 }
57 pub(super) fn new_local(notifier: Notifier<local::Service>) -> Self {
58 Self {
59 local: ManuallyDrop::new(notifier),
60 }
61 }
62}
63
64#[repr(C)]
65#[repr(align(8))] pub struct iox2_notifier_storage_t {
67 internal: [u8; 1656], }
69
70#[repr(C)]
71#[iceoryx2_ffi(NotifierUnion)]
72pub struct iox2_notifier_t {
73 service_type: iox2_service_type_e,
74 value: iox2_notifier_storage_t,
75 deleter: fn(*mut iox2_notifier_t),
76}
77
78impl iox2_notifier_t {
79 pub(super) fn init(
80 &mut self,
81 service_type: iox2_service_type_e,
82 value: NotifierUnion,
83 deleter: fn(*mut iox2_notifier_t),
84 ) {
85 self.service_type = service_type;
86 self.value.init(value);
87 self.deleter = deleter;
88 }
89}
90
91pub struct iox2_notifier_h_t;
92pub type iox2_notifier_h = *mut iox2_notifier_h_t;
94pub type iox2_notifier_h_ref = *const iox2_notifier_h;
96
97impl AssertNonNullHandle for iox2_notifier_h {
98 fn assert_non_null(self) {
99 debug_assert!(!self.is_null());
100 }
101}
102
103impl AssertNonNullHandle for iox2_notifier_h_ref {
104 fn assert_non_null(self) {
105 debug_assert!(!self.is_null());
106 unsafe {
107 debug_assert!(!(*self).is_null());
108 }
109 }
110}
111
112impl HandleToType for iox2_notifier_h {
113 type Target = *mut iox2_notifier_t;
114
115 fn as_type(self) -> Self::Target {
116 self as *mut _ as _
117 }
118}
119
120impl HandleToType for iox2_notifier_h_ref {
121 type Target = *mut iox2_notifier_t;
122
123 fn as_type(self) -> Self::Target {
124 unsafe { *self as *mut _ as _ }
125 }
126}
127
128#[no_mangle]
141pub unsafe extern "C" fn iox2_notifier_id(
142 notifier_handle: iox2_notifier_h_ref,
143 id_struct_ptr: *mut iox2_unique_notifier_id_t,
144 id_handle_ptr: *mut iox2_unique_notifier_id_h,
145) {
146 notifier_handle.assert_non_null();
147 debug_assert!(!id_handle_ptr.is_null());
148
149 fn no_op(_: *mut iox2_unique_notifier_id_t) {}
150 let mut deleter: fn(*mut iox2_unique_notifier_id_t) = no_op;
151 let mut storage_ptr = id_struct_ptr;
152 if id_struct_ptr.is_null() {
153 deleter = iox2_unique_notifier_id_t::dealloc;
154 storage_ptr = iox2_unique_notifier_id_t::alloc();
155 }
156 debug_assert!(!storage_ptr.is_null());
157
158 let notifier = &mut *notifier_handle.as_type();
159
160 let id = match notifier.service_type {
161 iox2_service_type_e::IPC => notifier.value.as_mut().ipc.id(),
162 iox2_service_type_e::LOCAL => notifier.value.as_mut().local.id(),
163 };
164
165 (*storage_ptr).init(id, deleter);
166 *id_handle_ptr = (*storage_ptr).as_handle();
167}
168
169#[no_mangle]
184pub unsafe extern "C" fn iox2_notifier_notify(
185 notifier_handle: iox2_notifier_h_ref,
186 number_of_notified_listener_ptr: *mut c_size_t,
187) -> c_int {
188 notifier_handle.assert_non_null();
189
190 let notifier = &mut *notifier_handle.as_type();
191
192 let notify_result = match notifier.service_type {
193 iox2_service_type_e::IPC => notifier.value.as_mut().ipc.notify(),
194 iox2_service_type_e::LOCAL => notifier.value.as_mut().local.notify(),
195 };
196
197 match notify_result {
198 Ok(count) => {
199 if !number_of_notified_listener_ptr.is_null() {
200 *number_of_notified_listener_ptr = count;
201 }
202 }
203 Err(error) => {
204 return error.into_c_int();
205 }
206 }
207
208 IOX2_OK
209}
210
211#[no_mangle]
228pub unsafe extern "C" fn iox2_notifier_notify_with_custom_event_id(
229 notifier_handle: iox2_notifier_h_ref,
230 custom_event_id_ptr: *const iox2_event_id_t,
231 number_of_notified_listener_ptr: *mut c_size_t,
232) -> c_int {
233 notifier_handle.assert_non_null();
234 debug_assert!(!custom_event_id_ptr.is_null());
235
236 let event_id = (*custom_event_id_ptr).into();
237
238 let notifier = &mut *notifier_handle.as_type();
239 let notify_result = match notifier.service_type {
240 iox2_service_type_e::IPC => notifier
241 .value
242 .as_mut()
243 .ipc
244 .notify_with_custom_event_id(event_id),
245 iox2_service_type_e::LOCAL => notifier
246 .value
247 .as_mut()
248 .local
249 .notify_with_custom_event_id(event_id),
250 };
251
252 match notify_result {
253 Ok(count) => {
254 if !number_of_notified_listener_ptr.is_null() {
255 *number_of_notified_listener_ptr = count;
256 }
257 }
258 Err(error) => {
259 return error.into_c_int();
260 }
261 }
262
263 IOX2_OK
264}
265
266#[no_mangle]
278pub unsafe extern "C" fn iox2_notifier_drop(notifier_handle: iox2_notifier_h) {
279 debug_assert!(!notifier_handle.is_null());
280
281 let notifier = &mut *notifier_handle.as_type();
282
283 match notifier.service_type {
284 iox2_service_type_e::IPC => {
285 ManuallyDrop::drop(&mut notifier.value.as_mut().ipc);
286 }
287 iox2_service_type_e::LOCAL => {
288 ManuallyDrop::drop(&mut notifier.value.as_mut().local);
289 }
290 }
291 (notifier.deleter)(notifier);
292}
293
294