@@ -26,6 +26,9 @@ use std::vec::Vec;
26
26
mod exclusivity_guard;
27
27
use exclusivity_guard:: * ;
28
28
29
+ mod guard_condition;
30
+ use guard_condition:: * ;
31
+
29
32
/// A struct for waiting on subscriptions and other waitable entities to become ready.
30
33
pub struct WaitSet {
31
34
rcl_wait_set : rcl_wait_set_t ,
@@ -36,6 +39,8 @@ pub struct WaitSet {
36
39
// even in the error case.
37
40
subscriptions : Vec < ExclusivityGuard < Arc < dyn SubscriptionBase > > > ,
38
41
clients : Vec < ExclusivityGuard < Arc < dyn ClientBase > > > ,
42
+ // The guard conditions that are currently registered in the wait set.
43
+ guard_conditions : Vec < ExclusivityGuard < Arc < Mutex < GuardCondition > > > > ,
39
44
services : Vec < ExclusivityGuard < Arc < dyn ServiceBase > > > ,
40
45
}
41
46
@@ -45,6 +50,8 @@ pub struct ReadyEntities {
45
50
pub subscriptions : Vec < Arc < dyn SubscriptionBase > > ,
46
51
/// A list of clients that have potentially received responses.
47
52
pub clients : Vec < Arc < dyn ClientBase > > ,
53
+ /// A list of guard conditions that have potentially been triggered.
54
+ pub guard_conditions : Vec < Arc < Mutex < GuardCondition > > > ,
48
55
/// A list of services that have potentially received requests.
49
56
pub services : Vec < Arc < dyn ServiceBase > > ,
50
57
}
@@ -96,6 +103,7 @@ impl WaitSet {
96
103
rcl_wait_set,
97
104
_rcl_context_mtx : context. rcl_context_mtx . clone ( ) ,
98
105
subscriptions : Vec :: new ( ) ,
106
+ guard_conditions : Vec :: new ( ) ,
99
107
clients : Vec :: new ( ) ,
100
108
services : Vec :: new ( ) ,
101
109
} )
@@ -107,6 +115,7 @@ impl WaitSet {
107
115
/// [`WaitSet::new`].
108
116
pub fn clear ( & mut self ) {
109
117
self . subscriptions . clear ( ) ;
118
+ self . guard_conditions . clear ( ) ;
110
119
self . clients . clear ( ) ;
111
120
self . services . clear ( ) ;
112
121
// This cannot fail – the rcl_wait_set_clear function only checks that the input handle is
@@ -150,6 +159,38 @@ impl WaitSet {
150
159
Ok ( ( ) )
151
160
}
152
161
162
+ /// Adds a guard condition to the wait set.
163
+ ///
164
+ /// # Errors
165
+ /// - If the guard condition was already added to this wait set or another one,
166
+ /// [`AlreadyAddedToWaitSet`][1] will be returned
167
+ /// - If the number of guard condition in the wait set is larger than the
168
+ /// capacity set in [`WaitSet::new`], [`WaitSetFull`][2] will be returned
169
+ ///
170
+ /// [1]: crate::RclrsError
171
+ /// [2]: crate::RclReturnCode
172
+ pub fn add_guard_condition (
173
+ & mut self ,
174
+ guard_condition : Arc < Mutex < GuardCondition > > ,
175
+ ) -> Result < ( ) , RclrsError > {
176
+ let exclusive_guard_condition = ExclusivityGuard :: new (
177
+ Arc :: clone ( & guard_condition) ,
178
+ Arc :: clone ( & guard_condition. lock ( ) . unwrap ( ) . in_use_by_wait_set ) ,
179
+ ) ?;
180
+
181
+ unsafe {
182
+ // SAFETY: Safe if the wait set and guard condition are initialized
183
+ rcl_wait_set_add_guard_condition (
184
+ & mut self . rcl_wait_set ,
185
+ & * guard_condition. lock ( ) . unwrap ( ) . lock ( ) ,
186
+ std:: ptr:: null_mut ( ) ,
187
+ )
188
+ . ok ( ) ?;
189
+ }
190
+ self . guard_conditions . push ( exclusive_guard_condition) ;
191
+ Ok ( ( ) )
192
+ }
193
+
153
194
/// Adds a client to the wait set.
154
195
///
155
196
/// # Errors
@@ -252,6 +293,7 @@ impl WaitSet {
252
293
unsafe { rcl_wait ( & mut self . rcl_wait_set , timeout_ns) } . ok ( ) ?;
253
294
let mut ready_entities = ReadyEntities {
254
295
subscriptions : Vec :: new ( ) ,
296
+ guard_conditions : Vec :: new ( ) ,
255
297
clients : Vec :: new ( ) ,
256
298
services : Vec :: new ( ) ,
257
299
} ;
@@ -266,6 +308,19 @@ impl WaitSet {
266
308
. push ( Arc :: clone ( & subscription. waitable ) ) ;
267
309
}
268
310
}
311
+
312
+ for ( i, guard_condition) in self . guard_conditions . iter ( ) . enumerate ( ) {
313
+ // SAFETY: The `guard_conditions` entry is an array of pointers, and this dereferencing is
314
+ // equivalent to
315
+ // https://github.com/ros2/rcl/blob/35a31b00a12f259d492bf53c0701003bd7f1745c/rcl/include/rcl/wait.h#L419
316
+ let wait_set_entry = unsafe { * self . rcl_wait_set . guard_conditions . add ( i) } ;
317
+ if !wait_set_entry. is_null ( ) {
318
+ ready_entities
319
+ . guard_conditions
320
+ . push ( Arc :: clone ( & guard_condition. waitable ) ) ;
321
+ }
322
+ }
323
+
269
324
for ( i, client) in self . clients . iter ( ) . enumerate ( ) {
270
325
// SAFETY: The `clients` entry is an array of pointers, and this dereferencing is
271
326
// equivalent to
0 commit comments