@@ -2,23 +2,24 @@ use crate::{
22 clock:: Clock , context:: Context , error:: RclrsError , rcl_bindings:: * , to_rclrs_result
33} ;
44// use std::fmt::Debug;
5- use std:: sync:: { Arc , Mutex } ;
5+ use std:: sync:: { atomic :: AtomicBool , Arc , Mutex } ;
66
7- pub type TimerCallback = Box < dyn FnMut ( i64 ) + Send + Sync > ;
7+ pub type TimerCallback = Box < dyn Fn ( i64 ) + Send + Sync > ;
88
99// #[derive(Debug)]
1010pub struct Timer {
11- rcl_timer : Arc < Mutex < rcl_timer_t > > ,
11+ pub ( crate ) rcl_timer : Arc < Mutex < rcl_timer_t > > ,
1212 callback : Option < TimerCallback > ,
13+ pub ( crate ) in_use_by_wait_set : Arc < AtomicBool > ,
1314}
1415
1516impl Timer {
1617 /// Creates a new timer (constructor)
1718 pub fn new ( clock : & Clock , context : & Context , period : i64 ) -> Result < Timer , RclrsError > {
18- Self :: with_callback ( clock, context, period, None )
19+ Self :: new_with_callback ( clock, context, period, None )
1920 }
2021
21- pub fn with_callback ( clock : & Clock , context : & Context , period : i64 , callback : Option < TimerCallback > ) -> Result < Timer , RclrsError > {
22+ pub fn new_with_callback ( clock : & Clock , context : & Context , period : i64 , callback : Option < TimerCallback > ) -> Result < Timer , RclrsError > {
2223 let mut rcl_timer;
2324 let timer_init_result = unsafe {
2425 // SAFETY: Getting a default value is always safe.
@@ -43,6 +44,7 @@ impl Timer {
4344 Timer {
4445 rcl_timer : Arc :: new ( Mutex :: new ( rcl_timer) ) ,
4546 callback,
47+ in_use_by_wait_set : Arc :: new ( AtomicBool :: new ( false ) ) ,
4648 }
4749 } )
4850 }
@@ -114,8 +116,7 @@ impl Timer {
114116 } )
115117 }
116118
117- /// Resets the timer, setting the last call time to now
118- pub fn reset ( & mut self ) -> Result < ( ) , RclrsError >
119+ pub fn reset ( & self ) -> Result < ( ) , RclrsError >
119120 {
120121 let mut rcl_timer = self . rcl_timer . lock ( ) . unwrap ( ) ;
121122 to_rclrs_result ( unsafe { rcl_timer_reset ( & mut * rcl_timer) } )
@@ -144,7 +145,20 @@ impl Timer {
144145 is_ready
145146 } )
146147 }
147- // handle() -> RCLC Timer Type
148+
149+ pub ( crate ) fn execute ( & self ) -> Result < ( ) , RclrsError >
150+ {
151+ if self . is_ready ( ) ?
152+ {
153+ let time_since_last_call = self . time_since_last_call ( ) ?;
154+ self . call ( ) ?;
155+ if let Some ( ref callback) = self . callback
156+ {
157+ callback ( time_since_last_call) ;
158+ }
159+ }
160+ Ok ( ( ) )
161+ }
148162}
149163
150164/// 'Drop' trait implementation to be able to release the resources
@@ -158,6 +172,12 @@ impl Drop for rcl_timer_t {
158172 }
159173}
160174
175+ impl PartialEq for Timer {
176+ fn eq ( & self , other : & Self ) -> bool {
177+ Arc :: ptr_eq ( & self . rcl_timer , & other. rcl_timer )
178+ }
179+ }
180+
161181// SAFETY: The functions accessing this type, including drop(), shouldn't care about the thread
162182// they are running in. Therefore, this type can be safely sent to another thread.
163183unsafe impl Send for rcl_timer_t { }
@@ -282,7 +302,7 @@ mod tests {
282302 let clock = Clock :: steady ( ) ;
283303 let context = Context :: new ( vec ! [ ] ) . unwrap ( ) ;
284304 let period_ns: i64 = 2e6 as i64 ; // 2 milliseconds.
285- let mut dut = Timer :: new ( & clock, & context, period_ns) . unwrap ( ) ;
305+ let dut = Timer :: new ( & clock, & context, period_ns) . unwrap ( ) ;
286306 let elapsed = period_ns - dut. time_until_next_call ( ) . unwrap ( ) ;
287307 assert ! ( elapsed < tolerance , "elapsed before reset: {}" , elapsed) ;
288308 thread:: sleep ( time:: Duration :: from_millis ( 1 ) ) ;
@@ -297,7 +317,7 @@ mod tests {
297317 let clock = Clock :: steady ( ) ;
298318 let context = Context :: new ( vec ! [ ] ) . unwrap ( ) ;
299319 let period_ns: i64 = 1e6 as i64 ; // 1 millisecond.
300- let mut dut = Timer :: new ( & clock, & context, period_ns) . unwrap ( ) ;
320+ let dut = Timer :: new ( & clock, & context, period_ns) . unwrap ( ) ;
301321 let elapsed = period_ns - dut. time_until_next_call ( ) . unwrap ( ) ;
302322 assert ! ( elapsed < tolerance , "elapsed before reset: {}" , elapsed) ;
303323
@@ -337,8 +357,35 @@ mod tests {
337357 let period_ns: i64 = 1e6 as i64 ; // 1 millisecond.
338358 let foo = Arc :: new ( Mutex :: new ( 0i64 ) ) ;
339359 let foo_callback = foo. clone ( ) ;
340- let dut = Timer :: with_callback ( & clock, & context, period_ns, Some ( Box :: new ( move |x| * foo_callback. lock ( ) . unwrap ( ) = x ) ) ) . unwrap ( ) ;
360+ let dut = Timer :: new_with_callback ( & clock, & context, period_ns, Some ( Box :: new ( move |x| * foo_callback. lock ( ) . unwrap ( ) = x ) ) ) . unwrap ( ) ;
341361 dut. callback . unwrap ( ) ( 123 ) ;
342362 assert_eq ! ( * foo. lock( ) . unwrap( ) , 123 ) ;
343363 }
364+
365+ #[ test]
366+ fn test_execute_when_is_not_ready ( ) {
367+ let clock = Clock :: steady ( ) ;
368+ let context = Context :: new ( vec ! [ ] ) . unwrap ( ) ;
369+ let period_ns: i64 = 1e6 as i64 ; // 1 millisecond.
370+ let foo = Arc :: new ( Mutex :: new ( 0i64 ) ) ;
371+ let foo_callback = foo. clone ( ) ;
372+ let dut = Timer :: new_with_callback ( & clock, & context, period_ns, Some ( Box :: new ( move |x| * foo_callback. lock ( ) . unwrap ( ) = x ) ) ) . unwrap ( ) ;
373+ assert ! ( dut. execute( ) . is_ok( ) ) ;
374+ assert_eq ! ( * foo. lock( ) . unwrap( ) , 0i64 ) ;
375+ }
376+
377+ #[ test]
378+ fn test_execute_when_is_ready ( ) {
379+ let clock = Clock :: steady ( ) ;
380+ let context = Context :: new ( vec ! [ ] ) . unwrap ( ) ;
381+ let period_ns: i64 = 1e6 as i64 ; // 1 millisecond.
382+ let foo = Arc :: new ( Mutex :: new ( 0i64 ) ) ;
383+ let foo_callback = foo. clone ( ) ;
384+ let dut = Timer :: new_with_callback ( & clock, & context, period_ns, Some ( Box :: new ( move |x| * foo_callback. lock ( ) . unwrap ( ) = x ) ) ) . unwrap ( ) ;
385+ thread:: sleep ( time:: Duration :: from_micros ( 1500 ) ) ;
386+ assert ! ( dut. execute( ) . is_ok( ) ) ;
387+ let x = * foo. lock ( ) . unwrap ( ) ;
388+ assert ! ( x > 1500000i64 ) ;
389+ assert ! ( x < 1600000i64 ) ;
390+ }
344391}
0 commit comments