@@ -86,26 +86,50 @@ impl<Scope: WorkScope> TimerState<Scope> {
8686 pub fn get_timer_period ( & self ) -> Result < Duration , RclrsError > {
8787 let mut timer_period_ns = 0 ;
8888 unsafe {
89+ // SAFETY: The unwrap is safe here since we never use the rcl_timer
90+ // in a way that could panic while the mutex is locked.
8991 let rcl_timer = self . handle . rcl_timer . lock ( ) . unwrap ( ) ;
92+
93+ // SAFETY: The rcl_timer is kept valid by the TimerState. This C
94+ // function call is thread-safe and only requires a valid rcl_timer
95+ // to be passed in.
9096 rcl_timer_get_period ( & * rcl_timer, & mut timer_period_ns)
9197 }
9298 . ok ( ) ?;
9399
94100 rcl_duration ( timer_period_ns)
95101 }
96102
97- /// Cancels the timer, stopping the execution of the callback
103+ /// Cancels the timer, stopping the execution of the callback.
104+ ///
105+ /// [`TimerState::is_ready`] will always return false while the timer is in
106+ /// a cancelled state. [`TimerState::reset`] can be used to revert the timer
107+ /// out of the cancelled state.
98108 pub fn cancel ( & self ) -> Result < ( ) , RclrsError > {
99- let mut rcl_timer = self . handle . rcl_timer . lock ( ) . unwrap ( ) ;
100- let cancel_result = unsafe { rcl_timer_cancel ( & mut * rcl_timer) } . ok ( ) ?;
109+ let cancel_result = unsafe {
110+ // SAFETY: The unwrap is safe here since we never use the rcl_timer
111+ // in a way that could panic while the mutex is locked.
112+ let mut rcl_timer = self . handle . rcl_timer . lock ( ) . unwrap ( ) ;
113+
114+ // SAFETY: The rcl_timer is kept valid by the TimerState. This C
115+ // function call is thread-safe and only requires a valid rcl_timer
116+ // to be passed in.
117+ rcl_timer_cancel ( & mut * rcl_timer)
118+ } . ok ( ) ?;
101119 Ok ( cancel_result)
102120 }
103121
104122 /// Checks whether the timer is canceled or not
105123 pub fn is_canceled ( & self ) -> Result < bool , RclrsError > {
106124 let mut is_canceled = false ;
107125 unsafe {
126+ // SAFETY: The unwrap is safe here since we never use the rcl_timer
127+ // in a way that could panic while the mutex is locked.
108128 let rcl_timer = self . handle . rcl_timer . lock ( ) . unwrap ( ) ;
129+
130+ // SAFETY: The rcl_timer is kept valid by the TimerState. This C
131+ // function call is thread-safe and only requires a valid rcl_timer
132+ // to be passed in.
109133 rcl_timer_is_canceled ( & * rcl_timer, & mut is_canceled)
110134 }
111135 . ok ( ) ?;
@@ -128,7 +152,13 @@ impl<Scope: WorkScope> TimerState<Scope> {
128152 pub fn time_since_last_call ( & self ) -> Result < Duration , RclrsError > {
129153 let mut time_value_ns: i64 = 0 ;
130154 unsafe {
155+ // SAFETY: The unwrap is safe here since we never use the rcl_timer
156+ // in a way that could panic while the mutex is locked.
131157 let rcl_timer = self . handle . rcl_timer . lock ( ) . unwrap ( ) ;
158+
159+ // SAFETY: The rcl_timer is kept valid by the TimerState. This C
160+ // function call is thread-safe and only requires a valid rcl_timer
161+ // to be passed in.
132162 rcl_timer_get_time_since_last_call ( & * rcl_timer, & mut time_value_ns)
133163 }
134164 . ok ( ) ?;
@@ -140,7 +170,13 @@ impl<Scope: WorkScope> TimerState<Scope> {
140170 pub fn time_until_next_call ( & self ) -> Result < Duration , RclrsError > {
141171 let mut time_value_ns: i64 = 0 ;
142172 unsafe {
173+ // SAFETY: The unwrap is safe here since we never use the rcl_timer
174+ // in a way that could panic while the mutex is locked.
143175 let rcl_timer = self . handle . rcl_timer . lock ( ) . unwrap ( ) ;
176+
177+ // SAFETY: The rcl_timer is kept valid by the TimerState. This C
178+ // function call is thread-safe and only requires a valid rcl_timer
179+ // to be passed in.
144180 rcl_timer_get_time_until_next_call ( & * rcl_timer, & mut time_value_ns)
145181 }
146182 . ok ( ) ?;
@@ -149,9 +185,20 @@ impl<Scope: WorkScope> TimerState<Scope> {
149185 }
150186
151187 /// Resets the timer.
188+ ///
189+ /// For all timers it will reset the last call time to now. For cancelled
190+ /// timers it will revert the timer to no longer being cancelled.
152191 pub fn reset ( & self ) -> Result < ( ) , RclrsError > {
192+ // SAFETY: The unwrap is safe here since we never use the rcl_timer
193+ // in a way that could panic while the mutex is locked.
153194 let mut rcl_timer = self . handle . rcl_timer . lock ( ) . unwrap ( ) ;
154- unsafe { rcl_timer_reset ( & mut * rcl_timer) } . ok ( )
195+
196+ unsafe {
197+ // SAFETY: The rcl_timer is kept valid by the TimerState. This C
198+ // function call is thread-safe and only requires a valid rcl_timer
199+ // to be passed in.
200+ rcl_timer_reset ( & mut * rcl_timer)
201+ } . ok ( )
155202 }
156203
157204 /// Checks if the timer is ready (not canceled)
@@ -215,8 +262,10 @@ impl<Scope: WorkScope> TimerState<Scope> {
215262 let rcl_timer_callback: rcl_timer_callback_t = None ;
216263
217264 let rcl_timer = Arc :: new ( Mutex :: new (
218- // SAFETY: Zero-initializing a timer is always safe
219- unsafe { rcl_get_zero_initialized_timer ( ) } ,
265+ unsafe {
266+ // SAFETY: Zero-initializing a timer is always safe
267+ rcl_get_zero_initialized_timer ( )
268+ } ,
220269 ) ) ;
221270
222271 unsafe {
@@ -340,8 +389,16 @@ impl<Scope: WorkScope> TimerState<Scope> {
340389 /// in the [`Timer`] struct. This means there are no side-effects to this
341390 /// except to keep track of when the timer has been called.
342391 fn rcl_call ( & self ) -> Result < ( ) , RclrsError > {
392+ // SAFETY: The unwrap is safe here since we never use the rcl_timer
393+ // in a way that could panic while the mutex is locked.
343394 let mut rcl_timer = self . handle . rcl_timer . lock ( ) . unwrap ( ) ;
344- unsafe { rcl_timer_call ( & mut * rcl_timer) } . ok ( )
395+
396+ unsafe {
397+ // SAFETY: The rcl_timer is kept valid by the TimerState. This C
398+ // function call is thread-safe and only requires a valid rcl_timer
399+ // to be passed in.
400+ rcl_timer_call ( & mut * rcl_timer)
401+ } . ok ( )
345402 }
346403
347404 /// Used by [`Timer::execute`] to restore the state of the callback if and
@@ -469,15 +526,17 @@ pub(crate) struct TimerHandle {
469526impl Drop for TimerHandle {
470527 fn drop ( & mut self ) {
471528 let _lifecycle = ENTITY_LIFECYCLE_MUTEX . lock ( ) . unwrap ( ) ;
472- // SAFETY: The lifecycle mutex is locked and the clock for the timer
473- // must still be valid because TimerHandle keeps it alive.
474- unsafe { rcl_timer_fini ( & mut * self . rcl_timer . lock ( ) . unwrap ( ) ) } ;
529+ unsafe {
530+ // SAFETY: The lifecycle mutex is locked and the clock for the timer
531+ // must still be valid because TimerHandle keeps it alive.
532+ rcl_timer_fini ( & mut * self . rcl_timer . lock ( ) . unwrap ( ) )
533+ } ;
475534 }
476535}
477536
478537// SAFETY: The functions accessing this type, including drop(), shouldn't care about the thread
479538// they are running in. Therefore, this type can be safely sent to another thread.
480- unsafe impl Send for rcl_timer_t { }
539+ impl Send for rcl_timer_t { }
481540
482541#[ cfg( test) ]
483542mod tests {
@@ -759,8 +818,8 @@ mod tests {
759818 handle : Arc :: clone ( & timer. handle ) ,
760819 } ;
761820
762- // SAFETY: Node timers expect a payload of ()
763821 unsafe {
822+ // SAFETY: Node timers expect a payload of ()
764823 executable. execute ( & mut ( ) ) . unwrap ( ) ;
765824 }
766825 assert ! ( !executed. load( Ordering :: Acquire ) ) ;
@@ -790,8 +849,8 @@ mod tests {
790849
791850 thread:: sleep ( Duration :: from_millis ( 2 ) ) ;
792851
793- // SAFETY: Node timers expect a payload of ()
794852 unsafe {
853+ // SAFETY: Node timers expect a payload of ()
795854 executable. execute ( & mut ( ) ) . unwrap ( ) ;
796855 }
797856 assert ! ( executed. load( Ordering :: Acquire ) ) ;
0 commit comments