Skip to content

Commit 2e2dce0

Browse files
committed
Timers have a dependency on Node when using NodeTime
Signed-off-by: Michael X. Grey <[email protected]>
1 parent 2780db7 commit 2e2dce0

File tree

4 files changed

+41
-13
lines changed

4 files changed

+41
-13
lines changed

rclrs/src/node.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1005,7 +1005,7 @@ impl NodeState {
10051005
/// [2]: crate::Time
10061006
/// [3]: std::sync::Weak
10071007
pub fn create_timer_repeating<'a, Args>(
1008-
&self,
1008+
self: &Arc<Self>,
10091009
options: impl IntoTimerOptions<'a>,
10101010
callback: impl IntoNodeTimerRepeatingCallback<Args>,
10111011
) -> Result<Timer, RclrsError> {
@@ -1060,7 +1060,7 @@ impl NodeState {
10601060
/// [2]: crate::Time
10611061
/// [3]: std::sync::Weak
10621062
pub fn create_timer_oneshot<'a, Args>(
1063-
&self,
1063+
self: &Arc<Self>,
10641064
options: impl IntoTimerOptions<'a>,
10651065
callback: impl IntoNodeTimerOneshotCallback<Args>,
10661066
) -> Result<Timer, RclrsError> {
@@ -1075,7 +1075,7 @@ impl NodeState {
10751075
/// * [`Self::create_timer_repeating`]
10761076
/// * [`Self::create_timer_oneshot`]
10771077
pub fn create_timer_inert<'a>(
1078-
&self,
1078+
self: &Arc<Self>,
10791079
options: impl IntoTimerOptions<'a>,
10801080
) -> Result<Timer, RclrsError> {
10811081
self.create_timer(options, AnyTimerCallback::Inert)
@@ -1088,18 +1088,20 @@ impl NodeState {
10881088
/// * [`Self::create_timer_oneshot`]
10891089
/// * [`Self::create_timer_inert`]
10901090
fn create_timer<'a>(
1091-
&self,
1091+
self: &Arc<Self>,
10921092
options: impl IntoTimerOptions<'a>,
10931093
callback: AnyTimerCallback<Node>,
10941094
) -> Result<Timer, RclrsError> {
10951095
let options = options.into_timer_options();
10961096
let clock = options.clock.as_clock(self);
1097+
let node = options.clock.is_node_time().then(|| Arc::clone(self));
10971098
TimerState::create(
10981099
options.period,
10991100
clock,
11001101
callback,
11011102
self.commands.async_worker_commands(),
11021103
&self.handle.context_handle,
1104+
node,
11031105
)
11041106
}
11051107

rclrs/src/timer.rs

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,9 @@ pub struct TimerState<Scope: WorkScope> {
7878
/// before we can get the lifecycle handle.
7979
#[allow(unused)]
8080
lifecycle: Mutex<Option<WaitableLifecycle>>,
81+
/// We optionally hold onto a live node if the timer is depending on node time.
82+
#[allow(unused)]
83+
node: Option<Node>,
8184
_ignore: std::marker::PhantomData<Scope>,
8285
}
8386

@@ -115,7 +118,8 @@ impl<Scope: WorkScope> TimerState<Scope> {
115118
// function call is thread-safe and only requires a valid rcl_timer
116119
// to be passed in.
117120
rcl_timer_cancel(&mut *rcl_timer)
118-
}.ok()?;
121+
}
122+
.ok()?;
119123
Ok(cancel_result)
120124
}
121125

@@ -198,7 +202,8 @@ impl<Scope: WorkScope> TimerState<Scope> {
198202
// function call is thread-safe and only requires a valid rcl_timer
199203
// to be passed in.
200204
rcl_timer_reset(&mut *rcl_timer)
201-
}.ok()
205+
}
206+
.ok()
202207
}
203208

204209
/// Checks if the timer is ready (not canceled)
@@ -257,18 +262,17 @@ impl<Scope: WorkScope> TimerState<Scope> {
257262
callback: AnyTimerCallback<Scope>,
258263
commands: &Arc<WorkerCommands>,
259264
context: &ContextHandle,
265+
node: Option<Node>,
260266
) -> Result<Arc<Self>, RclrsError> {
261267
let period = period.as_nanos() as i64;
262268

263269
// Callbacks will be handled at the rclrs layer.
264270
let rcl_timer_callback: rcl_timer_callback_t = None;
265271

266-
let rcl_timer = Arc::new(Mutex::new(
267-
unsafe {
268-
// SAFETY: Zero-initializing a timer is always safe
269-
rcl_get_zero_initialized_timer()
270-
},
271-
));
272+
let rcl_timer = Arc::new(Mutex::new(unsafe {
273+
// SAFETY: Zero-initializing a timer is always safe
274+
rcl_get_zero_initialized_timer()
275+
}));
272276

273277
unsafe {
274278
let mut rcl_clock = clock.get_rcl_clock().lock().unwrap();
@@ -321,6 +325,7 @@ impl<Scope: WorkScope> TimerState<Scope> {
321325
callback: Mutex::new(Some(callback)),
322326
last_elapse: Mutex::new(Duration::ZERO),
323327
lifecycle: Mutex::default(),
328+
node,
324329
_ignore: Default::default(),
325330
});
326331

@@ -400,7 +405,8 @@ impl<Scope: WorkScope> TimerState<Scope> {
400405
// function call is thread-safe and only requires a valid rcl_timer
401406
// to be passed in.
402407
rcl_timer_call(&mut *rcl_timer)
403-
}.ok()
408+
}
409+
.ok()
404410
}
405411

406412
/// Used by [`Timer::execute`] to restore the state of the callback if and
@@ -570,6 +576,7 @@ mod tests {
570576
(|| {}).into_node_timer_repeating_callback(),
571577
executor.commands().async_worker_commands(),
572578
&executor.commands().context().handle,
579+
None,
573580
);
574581
assert!(result.is_ok());
575582
}
@@ -583,6 +590,7 @@ mod tests {
583590
(|| {}).into_node_timer_repeating_callback(),
584591
executor.commands().async_worker_commands(),
585592
&executor.commands().context().handle,
593+
None,
586594
);
587595
assert!(result.is_ok());
588596
}
@@ -605,6 +613,7 @@ mod tests {
605613
(|| {}).into_node_timer_repeating_callback(),
606614
executor.commands().async_worker_commands(),
607615
&executor.commands().context().handle,
616+
None,
608617
);
609618
assert!(result.is_ok());
610619
}
@@ -621,6 +630,7 @@ mod tests {
621630
(|| {}).into_node_timer_repeating_callback(),
622631
executor.commands().async_worker_commands(),
623632
&executor.commands().context().handle,
633+
None,
624634
);
625635

626636
let timer = result.unwrap();
@@ -638,6 +648,7 @@ mod tests {
638648
(|| {}).into_node_timer_repeating_callback(),
639649
executor.commands().async_worker_commands(),
640650
&executor.commands().context().handle,
651+
None,
641652
);
642653

643654
let timer = result.unwrap();
@@ -656,6 +667,7 @@ mod tests {
656667
(|| {}).into_node_timer_repeating_callback(),
657668
executor.commands().async_worker_commands(),
658669
&executor.commands().context().handle,
670+
None,
659671
);
660672
let timer = result.unwrap();
661673

@@ -682,6 +694,7 @@ mod tests {
682694
(|| {}).into_node_timer_repeating_callback(),
683695
executor.commands().async_worker_commands(),
684696
&executor.commands().context().handle,
697+
None,
685698
);
686699
let timer = result.unwrap();
687700

@@ -704,6 +717,7 @@ mod tests {
704717
(|| {}).into_node_timer_repeating_callback(),
705718
executor.commands().async_worker_commands(),
706719
&executor.commands().context().handle,
720+
None,
707721
)
708722
.unwrap();
709723

@@ -735,6 +749,7 @@ mod tests {
735749
(|| {}).into_node_timer_repeating_callback(),
736750
executor.commands().async_worker_commands(),
737751
&executor.commands().context().handle,
752+
None,
738753
)
739754
.unwrap();
740755

@@ -766,6 +781,7 @@ mod tests {
766781
(|| {}).into_node_timer_repeating_callback(),
767782
executor.commands().async_worker_commands(),
768783
&executor.commands().context().handle,
784+
None,
769785
)
770786
.unwrap();
771787

@@ -791,6 +807,7 @@ mod tests {
791807
create_timer_callback_for_testing(initial_time, Arc::clone(&executed)),
792808
executor.commands().async_worker_commands(),
793809
&executor.commands().context().handle,
810+
None,
794811
)
795812
.unwrap();
796813

@@ -812,6 +829,7 @@ mod tests {
812829
create_timer_callback_for_testing(initial_time, Arc::clone(&executed)),
813830
executor.commands().async_worker_commands(),
814831
&executor.commands().context().handle,
832+
None,
815833
)
816834
.unwrap();
817835

@@ -841,6 +859,7 @@ mod tests {
841859
create_timer_callback_for_testing(initial_time, Arc::clone(&executed)),
842860
executor.commands().async_worker_commands(),
843861
&executor.commands().context().handle,
862+
None,
844863
)
845864
.unwrap();
846865

rclrs/src/timer/timer_options.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,11 @@ pub enum TimerClock<'a> {
7777
}
7878

7979
impl TimerClock<'_> {
80+
/// Check if node time has been selected for the timer's clock.
81+
pub fn is_node_time(&self) -> bool {
82+
matches!(self, Self::NodeTime)
83+
}
84+
8085
pub(crate) fn as_clock(&self, node: &NodeState) -> Clock {
8186
match self {
8287
TimerClock::SteadyTime => Clock::steady(),

rclrs/src/worker.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -547,12 +547,14 @@ impl<Payload: 'static + Send + Sync> WorkerState<Payload> {
547547
) -> Result<WorkerTimer<Payload>, RclrsError> {
548548
let options = options.into_timer_options();
549549
let clock = options.clock.as_clock(&*self.node);
550+
let node = options.clock.is_node_time().then(|| Arc::clone(&self.node));
550551
TimerState::create(
551552
options.period,
552553
clock,
553554
callback,
554555
&self.commands,
555556
&self.node.handle().context_handle,
557+
node,
556558
)
557559
}
558560

0 commit comments

Comments
 (0)