1
1
use crate :: error:: { RclReturnCode , ToResult } ;
2
- use crate :: qos:: QoSProfile ;
3
- use crate :: Node ;
4
2
use crate :: { rcl_bindings:: * , RclrsError } ;
3
+ use crate :: { Node , QoSProfile , WaitSet , Waitable } ;
5
4
6
5
use std:: boxed:: Box ;
7
6
use std:: ffi:: CStr ;
@@ -11,25 +10,13 @@ use std::sync::Arc;
11
10
12
11
use rosidl_runtime_rs:: { Message , RmwMessage } ;
13
12
14
- use parking_lot:: { Mutex , MutexGuard } ;
13
+ use parking_lot:: Mutex ;
15
14
16
15
// SAFETY: The functions accessing this type, including drop(), shouldn't care about the thread
17
16
// they are running in. Therefore, this type can be safely sent to another thread.
18
17
unsafe impl Send for rcl_subscription_t { }
19
18
20
- /// Internal struct used by subscriptions.
21
- pub struct SubscriptionHandle {
22
- rcl_subscription_mtx : Mutex < rcl_subscription_t > ,
23
- rcl_node_mtx : Arc < Mutex < rcl_node_t > > ,
24
- }
25
-
26
- impl SubscriptionHandle {
27
- pub ( crate ) fn lock ( & self ) -> MutexGuard < rcl_subscription_t > {
28
- self . rcl_subscription_mtx . lock ( )
29
- }
30
- }
31
-
32
- impl Drop for SubscriptionHandle {
19
+ impl < T : Message > Drop for Subscription < T > {
33
20
fn drop ( & mut self ) {
34
21
let rcl_subscription = self . rcl_subscription_mtx . get_mut ( ) ;
35
22
let rcl_node = & mut * self . rcl_node_mtx . lock ( ) ;
@@ -40,14 +27,6 @@ impl Drop for SubscriptionHandle {
40
27
}
41
28
}
42
29
43
- /// Trait to be implemented by concrete [`Subscription`]s.
44
- pub trait SubscriptionBase : Send + Sync {
45
- /// Internal function to get a reference to the `rcl` handle.
46
- fn handle ( & self ) -> & SubscriptionHandle ;
47
- /// Tries to take a new message and run the callback with it.
48
- fn execute ( & self ) -> Result < ( ) , RclrsError > ;
49
- }
50
-
51
30
/// Struct for receiving messages of type `T`.
52
31
///
53
32
/// There can be multiple subscriptions for the same topic, in different nodes or the same node.
@@ -63,7 +42,8 @@ pub struct Subscription<T>
63
42
where
64
43
T : Message ,
65
44
{
66
- pub ( crate ) handle : Arc < SubscriptionHandle > ,
45
+ rcl_subscription_mtx : Mutex < rcl_subscription_t > ,
46
+ rcl_node_mtx : Arc < Mutex < rcl_node_t > > ,
67
47
/// The callback function that runs when a message was received.
68
48
pub callback : Mutex < Box < dyn FnMut ( T ) + ' static + Send > > ,
69
49
message : PhantomData < T > ,
@@ -113,13 +93,9 @@ where
113
93
. ok ( ) ?;
114
94
}
115
95
116
- let handle = Arc :: new ( SubscriptionHandle {
96
+ Ok ( Self {
117
97
rcl_subscription_mtx : Mutex :: new ( rcl_subscription) ,
118
98
rcl_node_mtx : node. rcl_node_mtx . clone ( ) ,
119
- } ) ;
120
-
121
- Ok ( Self {
122
- handle,
123
99
callback : Mutex :: new ( Box :: new ( callback) ) ,
124
100
message : PhantomData ,
125
101
} )
@@ -133,7 +109,8 @@ where
133
109
// SAFETY: No preconditions for the function used
134
110
// The unsafe variables get converted to safe types before being returned
135
111
unsafe {
136
- let raw_topic_pointer = rcl_subscription_get_topic_name ( & * self . handle . lock ( ) ) ;
112
+ let raw_topic_pointer =
113
+ rcl_subscription_get_topic_name ( & * self . rcl_subscription_mtx . lock ( ) ) ;
137
114
CStr :: from_ptr ( raw_topic_pointer)
138
115
. to_string_lossy ( )
139
116
. into_owned ( )
@@ -164,7 +141,7 @@ where
164
141
// ```
165
142
pub fn take ( & self ) -> Result < T , RclrsError > {
166
143
let mut rmw_message = <T as Message >:: RmwMsg :: default ( ) ;
167
- let rcl_subscription = & mut * self . handle . lock ( ) ;
144
+ let rcl_subscription = & mut * self . rcl_subscription_mtx . lock ( ) ;
168
145
let ret = unsafe {
169
146
// SAFETY: The first two pointers are valid/initialized, and do not need to be valid
170
147
// beyond the function call.
@@ -181,12 +158,22 @@ where
181
158
}
182
159
}
183
160
184
- impl < T > SubscriptionBase for Subscription < T >
161
+ impl < T > Waitable for Subscription < T >
185
162
where
186
163
T : Message ,
187
164
{
188
- fn handle ( & self ) -> & SubscriptionHandle {
189
- & self . handle
165
+ unsafe fn add_to_wait_set ( self : Arc < Self > , wait_set : & mut WaitSet ) -> Result < ( ) , RclrsError > {
166
+ // SAFETY: I'm not sure if it's required, but the subscription pointer will remain valid
167
+ // for as long as the wait set exists, because it's stored in self.subscriptions.
168
+ // Passing in a null pointer for the third argument is explicitly allowed.
169
+ rcl_wait_set_add_subscription (
170
+ & mut wait_set. rcl_wait_set ,
171
+ & * self . rcl_subscription_mtx . lock ( ) ,
172
+ std:: ptr:: null_mut ( ) ,
173
+ )
174
+ . ok ( ) ?;
175
+ wait_set. subscriptions . push ( self ) ;
176
+ Ok ( ( ) )
190
177
}
191
178
192
179
fn execute ( & self ) -> Result < ( ) , RclrsError > {
0 commit comments