Create TracingId type
The TracingId is used as a wrapper for the pointer to allow implementing Send and Sync traits. The pointer is used only as an ID and is never dereferenced, therefore, it is safe.
This commit is contained in:
parent
cf03fe1b48
commit
2b4f9753d4
|
|
@ -12,5 +12,8 @@ pub use rclcpp_tracepoints::*;
|
|||
mod r2r_tracepoints;
|
||||
pub use r2r_tracepoints::*;
|
||||
|
||||
mod tracing_id;
|
||||
pub use tracing_id::TracingId;
|
||||
|
||||
mod macros;
|
||||
use macros::tracepoint_fn;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use crate::tracepoint_fn;
|
||||
use crate::{tracepoint_fn, TracingId};
|
||||
use r2r_rcl::{rcl_node_t, rcl_service_t, rcl_subscription_t, rcl_timer_t};
|
||||
|
||||
#[cfg(feature = "tracing")]
|
||||
|
|
@ -104,18 +104,18 @@ pub fn trace_service_callback_added(service: *const rcl_service_t, callback_id:
|
|||
/// Tracepoint to allow associating the timer callback identified by `callback_id` with its `rcl_timer_t` handle.
|
||||
///
|
||||
/// Tracepoint: `ros2::rclcpp_timer_callback_added`
|
||||
pub fn trace_timer_callback_added(timer: *const rcl_timer_t, callback_id: usize) {
|
||||
pub fn trace_timer_callback_added(timer: TracingId<rcl_timer_t>, callback_id: usize) {
|
||||
unsafe {
|
||||
tp::ros_trace_rclcpp_timer_callback_added(timer.cast(), c_void!(callback_id));
|
||||
tp::ros_trace_rclcpp_timer_callback_added(timer.c_void(), c_void!(callback_id));
|
||||
}
|
||||
}
|
||||
|
||||
/// Tracepoint to allow associating the `timer` with a `node`.
|
||||
///
|
||||
/// Tracepoint: `ros2::rclcpp_timer_link_node`
|
||||
pub fn trace_timer_link_node(timer: *const rcl_timer_t, node: *const rcl_node_t) {
|
||||
pub fn trace_timer_link_node(timer: TracingId<rcl_timer_t>, node: TracingId<rcl_node_t>) {
|
||||
unsafe {
|
||||
tp::ros_trace_rclcpp_timer_link_node(timer.cast(), node.cast());
|
||||
tp::ros_trace_rclcpp_timer_link_node(timer.c_void(), node.c_void());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,77 @@
|
|||
/// Unique identifier for tracing purposes
|
||||
#[derive(Debug)]
|
||||
pub struct TracingId<T> {
|
||||
/// Pointer to the object used as a unique ID.
|
||||
/// Safety: Do NOT dereference the pointer.
|
||||
#[cfg(feature = "tracing")]
|
||||
id: *const T,
|
||||
|
||||
/// Marker for the type. Needed when `tracing` feature is disabled.
|
||||
#[cfg(not(feature = "tracing"))]
|
||||
_marker: std::marker::PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T> TracingId<T> {
|
||||
/// Creates new `TracingId` from the pointer.
|
||||
///
|
||||
/// # Safety
|
||||
/// The pointer is used as a unique ID so users must ensure that they never create `TracingId`
|
||||
/// with same address for different objects.
|
||||
///
|
||||
/// The pointer does not need to point to valid memory.
|
||||
pub const unsafe fn new(_id: *const T) -> Self {
|
||||
Self {
|
||||
#[cfg(feature = "tracing")]
|
||||
id: _id,
|
||||
#[cfg(not(feature = "tracing"))]
|
||||
_marker: std::marker::PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
/// Erase the generic type of the ID.
|
||||
#[must_use]
|
||||
pub fn forget_type(self) -> TracingId<std::ffi::c_void> {
|
||||
#[cfg(not(feature = "tracing"))]
|
||||
unsafe {
|
||||
// Safety: The ID cannot be obtained back without the `tracing` feature.
|
||||
TracingId::new(std::ptr::null())
|
||||
}
|
||||
#[cfg(feature = "tracing")]
|
||||
unsafe {
|
||||
// Safety: self contains valid ID.
|
||||
TracingId::new(self.c_void())
|
||||
}
|
||||
}
|
||||
|
||||
/// Obtain the address representing the ID.
|
||||
///
|
||||
/// # Safety
|
||||
/// Do NOT dereference the pointer.
|
||||
#[cfg(feature = "tracing")]
|
||||
pub(crate) const unsafe fn c_void(self) -> *const std::ffi::c_void {
|
||||
self.id.cast::<std::ffi::c_void>()
|
||||
}
|
||||
}
|
||||
|
||||
/// Deriving Clone for `TracingId` would only derive it only conditionally based on whether the
|
||||
/// `T` is `Clone` or not. But TracingId is independent of T.
|
||||
impl<T> Clone for TracingId<T> {
|
||||
fn clone(&self) -> Self {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
/// Deriving Copy for `TracingId` would only derive it only conditionally based on whether the
|
||||
/// `T` is `Copy` or not. But TracingId is independent of T.
|
||||
impl<T> Copy for TracingId<T> {}
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// The address is never dereferenced and is used only as a unique ID so it is safe to send to another thread.
|
||||
unsafe impl<T> Send for TracingId<T> {}
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// The `TracingId` does not allow interior mutability because the pointer is never dereferenced.
|
||||
/// It is safe to use across multiple threads.
|
||||
unsafe impl<T> Sync for TracingId<T> {}
|
||||
Loading…
Reference in New Issue