diff --git a/iceoryx2-ffi/cxx/include/iox2/waitset.hpp b/iceoryx2-ffi/cxx/include/iox2/waitset.hpp index 2addf55b1..7b00c39cb 100644 --- a/iceoryx2-ffi/cxx/include/iox2/waitset.hpp +++ b/iceoryx2-ffi/cxx/include/iox2/waitset.hpp @@ -72,6 +72,9 @@ class WaitSetAttachmentId { /// Returns true if the deadline for the attachment corresponding to [`WaitSetGuard`] was missed. auto has_missed_deadline(const WaitSetGuard& guard) const -> bool; + /// Returns the a non-secure hash for the [`WaitSetAttachmentId`]. + auto hash() const -> std::size_t; + private: explicit WaitSetAttachmentId(iox2_waitset_attachment_id_h handle); template @@ -80,6 +83,8 @@ class WaitSetAttachmentId { friend auto operator==(const WaitSetAttachmentId&, const WaitSetAttachmentId&) -> bool; template friend auto operator<(const WaitSetAttachmentId&, const WaitSetAttachmentId&) -> bool; + template + friend auto operator<<(std::ostream& stream, const WaitSetAttachmentId& self) -> std::ostream&; void drop(); @@ -92,6 +97,9 @@ auto operator==(const WaitSetAttachmentId& lhs, const WaitSetAttachmentId& template auto operator<(const WaitSetAttachmentId& lhs, const WaitSetAttachmentId& rhs) -> bool; +template +auto operator<<(std::ostream& stream, const WaitSetAttachmentId& self) -> std::ostream&; + /// The [`WaitSet`] implements a reactor pattern and allows to wait on multiple events in one /// single call [`WaitSet::try_wait_and_process()`] until it wakes up or to run repeatedly with /// [`WaitSet::wait_and_process()`] until the a interrupt or termination signal was received or the user @@ -222,5 +230,4 @@ class WaitSetBuilder { iox2_waitset_builder_h m_handle; }; } // namespace iox2 - #endif diff --git a/iceoryx2-ffi/cxx/include/iox2/waitset_hash.hpp b/iceoryx2-ffi/cxx/include/iox2/waitset_hash.hpp new file mode 100644 index 000000000..1a3cbc87f --- /dev/null +++ b/iceoryx2-ffi/cxx/include/iox2/waitset_hash.hpp @@ -0,0 +1,32 @@ +// Copyright (c) 2024 Contributors to the Eclipse Foundation +// +// See the NOTICE file(s) distributed with this work for additional +// information regarding copyright ownership. +// +// This program and the accompanying materials are made available under the +// terms of the Apache Software License 2.0 which is available at +// https://www.apache.org/licenses/LICENSE-2.0, or the MIT license +// which is available at https://opensource.org/licenses/MIT. +// +// SPDX-License-Identifier: Apache-2.0 OR MIT + +#ifndef IOX2_WAITSET_HASH_HPP +#define IOX2_WAITSET_HASH_HPP + +#include "iox2/waitset.hpp" + +template <> +struct std::hash> { + auto operator()(const iox2::WaitSetAttachmentId& self) -> std::size_t { + return self.hash(); + } +}; + +template <> +struct std::hash> { + auto operator()(const iox2::WaitSetAttachmentId& self) -> std::size_t { + return self.hash(); + } +}; + +#endif diff --git a/iceoryx2-ffi/cxx/src/waitset.cpp b/iceoryx2-ffi/cxx/src/waitset.cpp index 6460cfb56..1452e988b 100644 --- a/iceoryx2-ffi/cxx/src/waitset.cpp +++ b/iceoryx2-ffi/cxx/src/waitset.cpp @@ -68,6 +68,14 @@ void WaitSetAttachmentId::drop() { } } +template +auto WaitSetAttachmentId::hash() const -> std::size_t { + auto len = iox2_waitset_attachment_id_debug_len(&m_handle); + std::string empty(len, '\0'); + iox2_waitset_attachment_id_debug(&m_handle, empty.data(), len); + return std::hash {}(empty); +} + template auto operator==(const WaitSetAttachmentId& lhs, const WaitSetAttachmentId& rhs) -> bool { return iox2_waitset_attachment_id_equal(&lhs.m_handle, &rhs.m_handle); @@ -78,6 +86,14 @@ auto operator<(const WaitSetAttachmentId& lhs, const WaitSetAttachmentId& return iox2_waitset_attachment_id_less(&lhs.m_handle, &rhs.m_handle); } +template +auto operator<<(std::ostream& stream, const WaitSetAttachmentId& self) -> std::ostream& { + auto len = iox2_waitset_attachment_id_debug_len(&self.m_handle); + std::string empty(len, '\0'); + iox2_waitset_attachment_id_debug(&self.m_handle, empty.data(), len); + stream << empty; + return stream; +} //////////////////////////// // END: WaitSetAttachmentId @@ -328,4 +344,7 @@ template auto operator<(const WaitSetAttachmentId& lhs, const WaitSetAttachmentId& rhs) -> bool; template auto operator<(const WaitSetAttachmentId& lhs, const WaitSetAttachmentId& rhs) -> bool; +template auto operator<<(std::ostream& stream, const WaitSetAttachmentId& self) -> std::ostream&; +template auto operator<<(std::ostream& stream, const WaitSetAttachmentId& self) -> std::ostream&; + } // namespace iox2 diff --git a/iceoryx2-ffi/ffi/src/api/waitset_attachment_id.rs b/iceoryx2-ffi/ffi/src/api/waitset_attachment_id.rs index 8f3147b29..8d03383da 100644 --- a/iceoryx2-ffi/ffi/src/api/waitset_attachment_id.rs +++ b/iceoryx2-ffi/ffi/src/api/waitset_attachment_id.rs @@ -12,7 +12,8 @@ #![allow(non_camel_case_types)] -use std::mem::ManuallyDrop; +use crate::c_size_t; +use std::{ffi::c_char, mem::ManuallyDrop}; use iceoryx2::{ prelude::WaitSetAttachmentId, @@ -303,4 +304,61 @@ pub unsafe extern "C" fn iox2_waitset_attachment_id_from_guard( *attachment_id_handle_ptr = (*attachment_id_struct_ptr).as_handle(); } + +/// Stores the debug output in the provided `debug_output` variable that must provide enough +/// memory to store the content. The content length can be acquired with +/// [`iox2_waitset_attachment_id_debug_len()`] +/// +/// # Safety +/// * `handle` must be valid and non-null. +/// * `debug_output` must be valid and provide enough memory +/// * `debug_len` the provided memory length of `debug_output` +#[no_mangle] +pub unsafe extern "C" fn iox2_waitset_attachment_id_debug( + handle: iox2_waitset_attachment_id_h_ref, + debug_output: *mut c_char, + debug_len: c_size_t, +) -> bool { + handle.assert_non_null(); + debug_assert!(!debug_output.is_null()); + + let attachment_id = &mut *handle.as_type(); + + let raw_str = match attachment_id.service_type { + iox2_service_type_e::IPC => format!("{:?}\0", *attachment_id.value.as_mut().ipc), + iox2_service_type_e::LOCAL => format!("{:?}\0", *attachment_id.value.as_mut().local), + }; + + if debug_len < raw_str.len() { + return false; + } + + std::ptr::copy_nonoverlapping( + raw_str.as_bytes().as_ptr().cast(), + debug_output, + raw_str.len(), + ); + + true +} + +/// Returns the length of the debug output. Shall be used before calling +/// [`iox2_waitset_attachment_id_debug()`] to acquire enough memory to store the output. +/// +/// # Safety +/// * `handle` must be valid and non-null. +#[no_mangle] +pub unsafe extern "C" fn iox2_waitset_attachment_id_debug_len( + handle: iox2_waitset_attachment_id_h_ref, +) -> c_size_t { + handle.assert_non_null(); + + let attachment_id = &mut *handle.as_type(); + + match attachment_id.service_type { + iox2_service_type_e::IPC => format!("{:?}\0", *attachment_id.value.as_mut().ipc).len(), + iox2_service_type_e::LOCAL => format!("{:?}\0", *attachment_id.value.as_mut().local).len(), + } +} + // END C API diff --git a/iceoryx2/src/port/waitset.rs b/iceoryx2/src/port/waitset.rs index 74f0a1e97..44f864731 100644 --- a/iceoryx2/src/port/waitset.rs +++ b/iceoryx2/src/port/waitset.rs @@ -274,12 +274,23 @@ enum AttachmentIdType { } /// Represents an attachment to the [`WaitSet`] -#[derive(Debug, Clone, Copy)] +#[derive(Clone, Copy)] pub struct WaitSetAttachmentId { attachment_type: AttachmentIdType, _data: PhantomData, } +impl Debug for WaitSetAttachmentId { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, + "WaitSetAttachmentId<{}> {{ attachment_type: {:?} }}", + core::any::type_name::(), + self.attachment_type + ) + } +} + impl WaitSetAttachmentId { /// Creates an [`WaitSetAttachmentId`] from a [`WaitSetGuard`] that was returned via /// [`WaitSet::attach_interval()`], [`WaitSet::attach_notification()`] or