1
1
use crate :: { clock:: Clock , context:: Context , error:: RclrsError , rcl_bindings:: * , to_rclrs_result} ;
2
+ // TODO: fix me when the callback type is properly defined.
2
3
// use std::fmt::Debug;
3
4
use std:: sync:: { atomic:: AtomicBool , Arc , Mutex } ;
4
5
6
+ /// Type alias for the `Timer` callback.
5
7
pub type TimerCallback = Box < dyn Fn ( i64 ) + Send + Sync > ;
6
8
9
+ /// Struct for executing periodic events.
10
+ ///
11
+ /// The execution of the callbacks is tied to [`spin_once`][1] or [`spin`][2] on the timers's node.
12
+ ///
13
+ /// Timer can be created via [`Node::create_timer()`][3], this is to ensure that [`Node`][4]s can
14
+ /// track all the timers that have been created. However, a user of a `Timer` can also
15
+ /// use it standalone.
16
+ ///
17
+ /// [1]: crate::spin_once
18
+ /// [2]: crate::spin
19
+ /// [3]: crate::Node::create_timer
20
+ /// [4]: crate::Node
21
+ // TODO: callback type prevents us from making the Timer implement the Debug trait.
7
22
// #[derive(Debug)]
8
23
pub struct Timer {
9
24
pub ( crate ) rcl_timer : Arc < Mutex < rcl_timer_t > > ,
25
+ /// The callback function that runs when the timer is due.
10
26
callback : Option < TimerCallback > ,
11
27
pub ( crate ) in_use_by_wait_set : Arc < AtomicBool > ,
12
28
}
13
29
14
30
impl Timer {
15
- /// Creates a new timer (constructor)
16
- pub fn new ( clock : & Clock , context : & Context , period : i64 ) -> Result < Timer , RclrsError > {
17
- Self :: new_with_callback ( clock, context, period, None )
18
- }
19
-
20
- pub fn new_with_callback (
31
+ /// Creates a new timer.
32
+ pub fn new (
21
33
clock : & Clock ,
22
34
context : & Context ,
23
35
period : i64 ,
@@ -97,6 +109,7 @@ impl Timer {
97
109
to_rclrs_result ( time_until_next_call_result) . map ( |_| time_value_ns)
98
110
}
99
111
112
+ /// Resets the timer.
100
113
pub fn reset ( & self ) -> Result < ( ) , RclrsError > {
101
114
let mut rcl_timer = self . rcl_timer . lock ( ) . unwrap ( ) ;
102
115
to_rclrs_result ( unsafe { rcl_timer_reset ( & mut * rcl_timer) } )
@@ -119,7 +132,7 @@ impl Timer {
119
132
to_rclrs_result ( is_ready_result) . map ( |_| is_ready)
120
133
}
121
134
122
- pub fn execute ( & self ) -> Result < ( ) , RclrsError > {
135
+ pub ( crate ) fn execute ( & self ) -> Result < ( ) , RclrsError > {
123
136
if self . is_ready ( ) ? {
124
137
let time_since_last_call = self . time_since_last_call ( ) ?;
125
138
self . call ( ) ?;
@@ -157,6 +170,10 @@ mod tests {
157
170
use super :: * ;
158
171
use std:: { thread, time} ;
159
172
173
+ fn create_dummy_callback ( ) -> Option < TimerCallback > {
174
+ Some ( Box :: new ( move |_| { } ) )
175
+ }
176
+
160
177
#[ test]
161
178
fn traits ( ) {
162
179
use crate :: test_helpers:: * ;
@@ -170,8 +187,7 @@ mod tests {
170
187
let clock = Clock :: system ( ) ;
171
188
let context = Context :: new ( vec ! [ ] ) . unwrap ( ) ;
172
189
let period: i64 = 1e6 as i64 ; // 1 milliseconds.
173
-
174
- let dut = Timer :: new ( & clock, & context, period) ;
190
+ let dut = Timer :: new ( & clock, & context, period, create_dummy_callback ( ) ) ;
175
191
assert ! ( dut. is_ok( ) ) ;
176
192
}
177
193
@@ -180,8 +196,7 @@ mod tests {
180
196
let clock = Clock :: steady ( ) ;
181
197
let context = Context :: new ( vec ! [ ] ) . unwrap ( ) ;
182
198
let period: i64 = 1e6 as i64 ; // 1 milliseconds.
183
-
184
- let dut = Timer :: new ( & clock, & context, period) ;
199
+ let dut = Timer :: new ( & clock, & context, period, create_dummy_callback ( ) ) ;
185
200
assert ! ( dut. is_ok( ) ) ;
186
201
}
187
202
@@ -195,11 +210,9 @@ mod tests {
195
210
source. set_ros_time_override ( set_time) ;
196
211
// Ros time is set, should return the value that was set
197
212
assert_eq ! ( clock. now( ) . nsec, set_time) ;
198
-
199
213
let context = Context :: new ( vec ! [ ] ) . unwrap ( ) ;
200
214
let period: i64 = 1e6 as i64 ; // 1 milliseconds..
201
-
202
- let dut = Timer :: new ( & clock, & context, period) ;
215
+ let dut = Timer :: new ( & clock, & context, period, create_dummy_callback ( ) ) ;
203
216
assert ! ( dut. is_ok( ) ) ;
204
217
}
205
218
@@ -208,8 +221,7 @@ mod tests {
208
221
let clock = Clock :: steady ( ) ;
209
222
let context = Context :: new ( vec ! [ ] ) . unwrap ( ) ;
210
223
let period: i64 = 1e6 as i64 ; // 1 milliseconds.
211
-
212
- let dut = Timer :: new ( & clock, & context, period) ;
224
+ let dut = Timer :: new ( & clock, & context, period, create_dummy_callback ( ) ) ;
213
225
assert ! ( dut. is_ok( ) ) ;
214
226
let dut = dut. unwrap ( ) ;
215
227
let period_result = dut. get_timer_period_ns ( ) ;
@@ -223,8 +235,7 @@ mod tests {
223
235
let clock = Clock :: steady ( ) ;
224
236
let context = Context :: new ( vec ! [ ] ) . unwrap ( ) ;
225
237
let period: i64 = 1e6 as i64 ; // 1 milliseconds.
226
-
227
- let dut = Timer :: new ( & clock, & context, period) ;
238
+ let dut = Timer :: new ( & clock, & context, period, create_dummy_callback ( ) ) ;
228
239
assert ! ( dut. is_ok( ) ) ;
229
240
let dut = dut. unwrap ( ) ;
230
241
assert ! ( dut. is_canceled( ) . is_ok( ) ) ;
@@ -241,8 +252,7 @@ mod tests {
241
252
let context = Context :: new ( vec ! [ ] ) . unwrap ( ) ;
242
253
let period_ns: i64 = 2e6 as i64 ; // 2 milliseconds.
243
254
let sleep_period_ms = time:: Duration :: from_millis ( 1 ) ;
244
-
245
- let dut = Timer :: new ( & clock, & context, period_ns) ;
255
+ let dut = Timer :: new ( & clock, & context, period_ns, create_dummy_callback ( ) ) ;
246
256
assert ! ( dut. is_ok( ) ) ;
247
257
let dut = dut. unwrap ( ) ;
248
258
thread:: sleep ( sleep_period_ms) ;
@@ -261,7 +271,7 @@ mod tests {
261
271
let clock = Clock :: steady ( ) ;
262
272
let context = Context :: new ( vec ! [ ] ) . unwrap ( ) ;
263
273
let period_ns: i64 = 2e6 as i64 ; // 2 milliseconds.
264
- let dut = Timer :: new ( & clock, & context, period_ns) ;
274
+ let dut = Timer :: new ( & clock, & context, period_ns, create_dummy_callback ( ) ) ;
265
275
assert ! ( dut. is_ok( ) ) ;
266
276
let dut = dut. unwrap ( ) ;
267
277
let time_until_next_call = dut. time_until_next_call ( ) ;
@@ -280,7 +290,7 @@ mod tests {
280
290
let clock = Clock :: steady ( ) ;
281
291
let context = Context :: new ( vec ! [ ] ) . unwrap ( ) ;
282
292
let period_ns: i64 = 2e6 as i64 ; // 2 milliseconds.
283
- let dut = Timer :: new ( & clock, & context, period_ns) . unwrap ( ) ;
293
+ let dut = Timer :: new ( & clock, & context, period_ns, create_dummy_callback ( ) ) . unwrap ( ) ;
284
294
let elapsed = period_ns - dut. time_until_next_call ( ) . unwrap ( ) ;
285
295
assert ! ( elapsed < tolerance, "elapsed before reset: {}" , elapsed) ;
286
296
thread:: sleep ( time:: Duration :: from_millis ( 1 ) ) ;
@@ -295,21 +305,17 @@ mod tests {
295
305
let clock = Clock :: steady ( ) ;
296
306
let context = Context :: new ( vec ! [ ] ) . unwrap ( ) ;
297
307
let period_ns: i64 = 1e6 as i64 ; // 1 millisecond.
298
- let dut = Timer :: new ( & clock, & context, period_ns) . unwrap ( ) ;
308
+ let dut = Timer :: new ( & clock, & context, period_ns, create_dummy_callback ( ) ) . unwrap ( ) ;
299
309
let elapsed = period_ns - dut. time_until_next_call ( ) . unwrap ( ) ;
300
310
assert ! ( elapsed < tolerance, "elapsed before reset: {}" , elapsed) ;
301
-
302
311
thread:: sleep ( time:: Duration :: from_micros ( 1500 ) ) ;
303
-
304
312
let elapsed = period_ns - dut. time_until_next_call ( ) . unwrap ( ) ;
305
313
assert ! (
306
314
elapsed > 1500000i64 ,
307
315
"time_until_next_call before call: {}" ,
308
316
elapsed
309
317
) ;
310
-
311
318
assert ! ( dut. call( ) . is_ok( ) ) ;
312
-
313
319
let elapsed = dut. time_until_next_call ( ) . unwrap ( ) ;
314
320
assert ! (
315
321
elapsed < 500000i64 ,
@@ -323,27 +329,24 @@ mod tests {
323
329
let clock = Clock :: steady ( ) ;
324
330
let context = Context :: new ( vec ! [ ] ) . unwrap ( ) ;
325
331
let period_ns: i64 = 1e6 as i64 ; // 1 millisecond.
326
- let dut = Timer :: new ( & clock, & context, period_ns) . unwrap ( ) ;
327
-
332
+ let dut = Timer :: new ( & clock, & context, period_ns, create_dummy_callback ( ) ) . unwrap ( ) ;
328
333
let is_ready = dut. is_ready ( ) ;
329
334
assert ! ( is_ready. is_ok( ) ) ;
330
335
assert ! ( !is_ready. unwrap( ) ) ;
331
-
332
336
thread:: sleep ( time:: Duration :: from_micros ( 1100 ) ) ;
333
-
334
337
let is_ready = dut. is_ready ( ) ;
335
338
assert ! ( is_ready. is_ok( ) ) ;
336
339
assert ! ( is_ready. unwrap( ) ) ;
337
340
}
338
341
339
342
#[ test]
340
- fn test_callback_wip ( ) {
343
+ fn test_callback ( ) {
341
344
let clock = Clock :: steady ( ) ;
342
345
let context = Context :: new ( vec ! [ ] ) . unwrap ( ) ;
343
346
let period_ns: i64 = 1e6 as i64 ; // 1 millisecond.
344
347
let foo = Arc :: new ( Mutex :: new ( 0i64 ) ) ;
345
348
let foo_callback = foo. clone ( ) ;
346
- let dut = Timer :: new_with_callback (
349
+ let dut = Timer :: new (
347
350
& clock,
348
351
& context,
349
352
period_ns,
@@ -361,7 +364,7 @@ mod tests {
361
364
let period_ns: i64 = 1e6 as i64 ; // 1 millisecond.
362
365
let foo = Arc :: new ( Mutex :: new ( 0i64 ) ) ;
363
366
let foo_callback = foo. clone ( ) ;
364
- let dut = Timer :: new_with_callback (
367
+ let dut = Timer :: new (
365
368
& clock,
366
369
& context,
367
370
period_ns,
@@ -379,7 +382,7 @@ mod tests {
379
382
let period_ns: i64 = 1e6 as i64 ; // 1 millisecond.
380
383
let foo = Arc :: new ( Mutex :: new ( 0i64 ) ) ;
381
384
let foo_callback = foo. clone ( ) ;
382
- let dut = Timer :: new_with_callback (
385
+ let dut = Timer :: new (
383
386
& clock,
384
387
& context,
385
388
period_ns,
0 commit comments