Skip to content

Commit a6b5b48

Browse files
Plumbing for dynamic publishers
Signed-off-by: Luca Della Vedova <[email protected]>
1 parent 9ab136b commit a6b5b48

File tree

2 files changed

+67
-64
lines changed

2 files changed

+67
-64
lines changed

rclrs/src/dynamic_message/dynamic_publisher.rs

Lines changed: 33 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
use std::ffi::CStr;
21
use std::ffi::CString;
32
use std::sync::{Arc, Mutex};
43

@@ -9,7 +8,7 @@ use super::{
98
use crate::error::{RclrsError, ToResult};
109
use crate::qos::QoSProfile;
1110
use crate::rcl_bindings::*;
12-
use crate::NodeHandle;
11+
use crate::{ENTITY_LIFECYCLE_MUTEX, PublisherHandle, NodeHandle};
1312

1413
/// Struct for sending messages of type `T`.
1514
///
@@ -22,24 +21,13 @@ use crate::NodeHandle;
2221
///
2322
/// [1]: crate::spin
2423
pub struct DynamicPublisher {
25-
rcl_publisher_mtx: Mutex<rcl_publisher_t>,
26-
node_handle: Arc<NodeHandle>,
24+
handle: PublisherHandle,
2725
metadata: DynamicMessageMetadata,
2826
// This is the regular type support library, not the introspection one.
2927
#[allow(dead_code)]
3028
type_support_library: Arc<libloading::Library>,
3129
}
3230

33-
impl Drop for DynamicPublisher {
34-
fn drop(&mut self) {
35-
let mut rcl_node = self.node_handle.rcl_node.lock().unwrap();
36-
unsafe {
37-
// SAFETY: No preconditions for this function (besides the arguments being valid).
38-
rcl_publisher_fini(self.rcl_publisher_mtx.get_mut().unwrap(), &mut *rcl_node);
39-
}
40-
}
41-
}
42-
4331
// SAFETY: The functions accessing this type, including drop(), shouldn't care about the thread
4432
// they are running in. Therefore, this type can be safely sent to another thread.
4533
// unsafe impl Send for DynamicPublisher {}
@@ -52,7 +40,7 @@ impl DynamicPublisher {
5240
///
5341
/// Node and namespace changes are always applied _before_ topic remapping.
5442
pub(crate) fn new(
55-
node_handle: &Arc<NodeHandle>,
43+
node_handle: Arc<NodeHandle>,
5644
topic: &str,
5745
topic_type: MessageTypeName,
5846
qos: QoSProfile,
@@ -81,30 +69,36 @@ impl DynamicPublisher {
8169
err,
8270
s: topic.into(),
8371
})?;
84-
let rcl_node = node_handle.rcl_node.lock().unwrap();
8572

8673
// SAFETY: No preconditions for this function.
8774
let mut publisher_options = unsafe { rcl_publisher_get_default_options() };
8875
publisher_options.qos = qos.into();
89-
unsafe {
90-
// SAFETY: The rcl_publisher is zero-initialized as expected by this function.
91-
// The rcl_node is kept alive because it is co-owned by the subscription.
92-
// The topic name and the options are copied by this function, so they can be dropped
93-
// afterwards.
94-
// TODO: type support?
95-
rcl_publisher_init(
96-
&mut rcl_publisher,
97-
&*rcl_node,
98-
type_support_ptr,
99-
topic_c_string.as_ptr(),
100-
&publisher_options,
101-
)
102-
.ok()?;
76+
77+
{
78+
let rcl_node = node_handle.rcl_node.lock().unwrap();
79+
let _lifecycle_lock = ENTITY_LIFECYCLE_MUTEX.lock().unwrap();
80+
unsafe {
81+
// SAFETY: The rcl_publisher is zero-initialized as expected by this function.
82+
// The rcl_node is kept alive because it is co-owned by the subscription.
83+
// The topic name and the options are copied by this function, so they can be dropped
84+
// afterwards.
85+
// TODO: type support?
86+
rcl_publisher_init(
87+
&mut rcl_publisher,
88+
&*rcl_node,
89+
type_support_ptr,
90+
topic_c_string.as_ptr(),
91+
&publisher_options,
92+
)
93+
.ok()?;
94+
}
10395
}
10496

10597
Ok(Self {
106-
rcl_publisher_mtx: Mutex::new(rcl_publisher),
107-
node_handle: node_handle.clone(),
98+
handle: PublisherHandle {
99+
rcl_publisher: Mutex::new(rcl_publisher),
100+
node_handle,
101+
},
108102
metadata,
109103
type_support_library,
110104
})
@@ -115,15 +109,12 @@ impl DynamicPublisher {
115109
/// This returns the topic name after remapping, so it is not necessarily the
116110
/// topic name which was used when creating the publisher.
117111
pub fn topic_name(&self) -> String {
118-
// SAFETY: No preconditions for the functions called.
119-
// The unsafe variables created get converted to safe types before being returned
120-
unsafe {
121-
let raw_topic_pointer =
122-
rcl_publisher_get_topic_name(&*self.rcl_publisher_mtx.lock().unwrap());
123-
CStr::from_ptr(raw_topic_pointer)
124-
.to_string_lossy()
125-
.into_owned()
126-
}
112+
self.handle.topic_name()
113+
}
114+
115+
/// Returns the number of subscriptions of the publisher.
116+
pub fn get_subscription_count(&self) -> Result<usize, RclrsError> {
117+
self.handle.get_subscription_count()
127118
}
128119

129120
/// Publishes a message.
@@ -135,7 +126,7 @@ impl DynamicPublisher {
135126
if message.metadata.message_type != self.metadata.message_type {
136127
return Err(DynamicMessageError::MessageTypeMismatch.into());
137128
}
138-
let rcl_publisher = &mut *self.rcl_publisher_mtx.lock().unwrap();
129+
let rcl_publisher = &mut *self.handle.rcl_publisher.lock().unwrap();
139130
unsafe {
140131
// SAFETY: The message type is guaranteed to match the publisher type by the type system.
141132
// The message does not need to be valid beyond the duration of this function call.

rclrs/src/publisher.rs

Lines changed: 34 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@ unsafe impl Send for rcl_publisher_t {}
2626
/// [dropped after][1] the `rcl_publisher_t`.
2727
///
2828
/// [1]: <https://doc.rust-lang.org/reference/destructors.html>
29-
struct PublisherHandle {
30-
rcl_publisher: Mutex<rcl_publisher_t>,
31-
node_handle: Arc<NodeHandle>,
29+
pub(crate) struct PublisherHandle {
30+
pub(crate) rcl_publisher: Mutex<rcl_publisher_t>,
31+
pub(crate) node_handle: Arc<NodeHandle>,
3232
}
3333

3434
impl Drop for PublisherHandle {
@@ -43,6 +43,35 @@ impl Drop for PublisherHandle {
4343
}
4444
}
4545

46+
// Functions shared between normal and dynamic publishers
47+
impl PublisherHandle {
48+
pub(crate) fn topic_name(&self) -> String {
49+
// SAFETY: No preconditions for the functions called.
50+
// The unsafe variables created get converted to safe types before being returned
51+
unsafe {
52+
let raw_topic_pointer =
53+
rcl_publisher_get_topic_name(&*self.rcl_publisher.lock().unwrap());
54+
CStr::from_ptr(raw_topic_pointer)
55+
.to_string_lossy()
56+
.into_owned()
57+
}
58+
}
59+
60+
/// Returns the number of subscriptions of the publisher.
61+
pub(crate) fn get_subscription_count(&self) -> Result<usize, RclrsError> {
62+
let mut subscription_count = 0;
63+
// SAFETY: No preconditions for the function called.
64+
unsafe {
65+
rcl_publisher_get_subscription_count(
66+
&*self.rcl_publisher.lock().unwrap(),
67+
&mut subscription_count,
68+
)
69+
.ok()?
70+
};
71+
Ok(subscription_count)
72+
}
73+
}
74+
4675
/// Struct for sending messages of type `T`.
4776
///
4877
/// Create a publisher using [`Node::create_publisher`][1].
@@ -152,29 +181,12 @@ where
152181
/// This returns the topic name after remapping, so it is not necessarily the
153182
/// topic name which was used when creating the publisher.
154183
pub fn topic_name(&self) -> String {
155-
// SAFETY: No preconditions for the functions called.
156-
// The unsafe variables created get converted to safe types before being returned
157-
unsafe {
158-
let raw_topic_pointer =
159-
rcl_publisher_get_topic_name(&*self.handle.rcl_publisher.lock().unwrap());
160-
CStr::from_ptr(raw_topic_pointer)
161-
.to_string_lossy()
162-
.into_owned()
163-
}
184+
self.handle.topic_name()
164185
}
165186

166187
/// Returns the number of subscriptions of the publisher.
167188
pub fn get_subscription_count(&self) -> Result<usize, RclrsError> {
168-
let mut subscription_count = 0;
169-
// SAFETY: No preconditions for the function called.
170-
unsafe {
171-
rcl_publisher_get_subscription_count(
172-
&*self.handle.rcl_publisher.lock().unwrap(),
173-
&mut subscription_count,
174-
)
175-
.ok()?
176-
};
177-
Ok(subscription_count)
189+
self.handle.get_subscription_count()
178190
}
179191

180192
/// Publishes a message.

0 commit comments

Comments
 (0)