Skip to content

Commit 2ee4d7a

Browse files
authored
Make all the things Send, and messages Sync as well (#171)
This is required to make multithreading work. For instance, calling publish() on a separate thread doesn't work without these impls.
1 parent 583cb47 commit 2ee4d7a

File tree

7 files changed

+32
-6
lines changed

7 files changed

+32
-6
lines changed

rclrs/src/context.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ impl Drop for rcl_context_t {
2424
}
2525
}
2626

27+
// SAFETY: The functions accessing this type, including drop(), shouldn't care about the thread
28+
// they are running in. Therefore, this type can be safely sent to another thread.
29+
unsafe impl Send for rcl_context_t {}
30+
2731
/// Shared state between nodes and similar entities.
2832
///
2933
/// It is possible, but not usually necessary, to have several contexts in an application.

rclrs/src/node/mod.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ impl Drop for rcl_node_t {
2424
}
2525
}
2626

27+
// SAFETY: The functions accessing this type, including drop(), shouldn't care about the thread
28+
// they are running in. Therefore, this type can be safely sent to another thread.
29+
unsafe impl Send for rcl_node_t {}
30+
2731
/// A processing unit that can communicate with other nodes.
2832
///
2933
/// Nodes are a core concept in ROS 2. Refer to the official ["Understanding ROS 2 nodes"][1]
@@ -263,7 +267,7 @@ impl Node {
263267
) -> Result<Arc<Subscription<T>>, RclrsError>
264268
where
265269
T: Message,
266-
F: FnMut(T) + 'static,
270+
F: FnMut(T) + 'static + Send,
267271
{
268272
let subscription = Arc::new(Subscription::<T>::new(self, topic, qos, callback)?);
269273
self.subscriptions

rclrs/src/node/publisher.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ use parking_lot::{Mutex, MutexGuard};
1212

1313
use rosidl_runtime_rs::{Message, RmwMessage};
1414

15+
// SAFETY: The functions accessing this type, including drop(), shouldn't care about the thread
16+
// they are running in. Therefore, this type can be safely sent to another thread.
17+
unsafe impl Send for rcl_publisher_t {}
18+
1519
pub(crate) struct PublisherHandle {
1620
handle: Mutex<rcl_publisher_t>,
1721
node_handle: Arc<Mutex<rcl_node_t>>,

rclrs/src/node/subscription.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ use rosidl_runtime_rs::{Message, RmwMessage};
1313

1414
use parking_lot::{Mutex, MutexGuard};
1515

16+
// SAFETY: The functions accessing this type, including drop(), shouldn't care about the thread
17+
// they are running in. Therefore, this type can be safely sent to another thread.
18+
unsafe impl Send for rcl_subscription_t {}
19+
1620
/// Internal struct used by subscriptions.
1721
pub struct SubscriptionHandle {
1822
handle: Mutex<rcl_subscription_t>,
@@ -37,7 +41,7 @@ impl Drop for SubscriptionHandle {
3741
}
3842

3943
/// Trait to be implemented by concrete [`Subscription`]s.
40-
pub trait SubscriptionBase {
44+
pub trait SubscriptionBase: Send + Sync {
4145
/// Internal function to get a reference to the `rcl` handle.
4246
fn handle(&self) -> &SubscriptionHandle;
4347
/// Tries to take a new message and run the callback with it.
@@ -61,7 +65,7 @@ where
6165
{
6266
pub(crate) handle: Arc<SubscriptionHandle>,
6367
/// The callback function that runs when a message was received.
64-
pub callback: Mutex<Box<dyn FnMut(T) + 'static>>,
68+
pub callback: Mutex<Box<dyn FnMut(T) + 'static + Send>>,
6569
message: PhantomData<T>,
6670
}
6771

@@ -81,7 +85,7 @@ where
8185
) -> Result<Self, RclrsError>
8286
where
8387
T: Message,
84-
F: FnMut(T) + 'static,
88+
F: FnMut(T) + 'static + Send,
8589
{
8690
// SAFETY: Getting a zero-initialized value is always safe.
8791
let mut subscription_handle = unsafe { rcl_get_zero_initialized_subscription() };

rosidl_runtime_rs/src/sequence.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,11 @@ impl<T: SequenceAlloc + PartialOrd> PartialOrd for Sequence<T> {
235235
}
236236
}
237237

238+
// SAFETY: A sequence is a simple data structure, and therefore not thread-specific.
239+
unsafe impl<T: Send + SequenceAlloc> Send for Sequence<T> {}
240+
// SAFETY: A sequence does not have interior mutability, so it can be shared.
241+
unsafe impl<T: Sync + SequenceAlloc> Sync for Sequence<T> {}
242+
238243
impl<T> Sequence<T>
239244
where
240245
T: SequenceAlloc,

rosidl_runtime_rs/src/string.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,11 @@ macro_rules! string_impl {
213213
}
214214
}
215215

216+
// SAFETY: A string is a simple data structure, and therefore not thread-specific.
217+
unsafe impl Send for $string {}
218+
// SAFETY: A string does not have interior mutability, so it can be shared.
219+
unsafe impl Sync for $string {}
220+
216221
impl SequenceAlloc for $string {
217222
fn sequence_init(seq: &mut Sequence<Self>, size: libc::size_t) -> bool {
218223
// SAFETY: There are no special preconditions to the sequence_init function.

rosidl_runtime_rs/src/traits.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ pub trait SequenceAlloc: Sized {
3737
/// used by user code.
3838
///
3939
/// User code never needs to call this trait's method, much less implement this trait.
40-
pub trait RmwMessage: Clone + Debug + Default {
40+
pub trait RmwMessage: Clone + Debug + Default + Send + Sync {
4141
/// Get a pointer to the correct `rosidl_message_type_support_t` structure.
4242
fn get_type_support() -> libc::uintptr_t;
4343
}
@@ -126,7 +126,7 @@ pub trait RmwMessage: Clone + Debug + Default {
126126
/// problem, since nothing is allocated this way.
127127
/// The `Drop` impl for any sequence or string will call `fini()`.
128128
129-
pub trait Message: Clone + Debug + Default + 'static {
129+
pub trait Message: Clone + Debug + Default + 'static + Send + Sync {
130130
/// The corresponding RMW-native message type.
131131
type RmwMsg: RmwMessage;
132132

0 commit comments

Comments
 (0)