Skip to content

Commit 7d540c2

Browse files
committed
Implement timers for Workers
Signed-off-by: Michael X. Grey <[email protected]>
1 parent 5cf50fd commit 7d540c2

File tree

4 files changed

+81
-20
lines changed

4 files changed

+81
-20
lines changed

rclrs/src/node.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -241,15 +241,15 @@ impl NodeState {
241241
//
242242
// TODO(@mxgrey): Write some usage examples.
243243
pub fn create_worker<'a, Payload>(
244-
&self,
244+
self: &Arc<Self>,
245245
options: impl IntoWorkerOptions<Payload>,
246246
) -> Worker<Payload>
247247
where
248248
Payload: 'static + Send + Sync,
249249
{
250250
let options = options.into_worker_options();
251251
let commands = self.commands.create_worker_commands(Box::new(options.payload));
252-
WorkerState::create(Arc::clone(&self.handle), commands)
252+
WorkerState::create(Arc::clone(self), commands)
253253
}
254254

255255
/// Creates a [`Client`][1].
@@ -571,7 +571,7 @@ impl NodeState {
571571

572572
/// Create a [`Timer`] whose callback will be triggered once after the period
573573
/// of the timer has elapsed. After that you will need to use
574-
/// [`Timer::set_callback`] or a related method or else nothing will happen
574+
/// [`Timer::set_repeating`] or [`Timer::set_oneshot`] or else nothing will happen
575575
/// the following times that the `Timer` elapses.
576576
///
577577
/// See also:

rclrs/src/timer.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -359,7 +359,7 @@ impl<Payload: 'static + Send + Sync> TimerState<Worker<Payload>> {
359359
&self,
360360
f: impl IntoWorkerTimerRepeatingCallback<Worker<Payload>, Args>,
361361
) -> Option<AnyTimerCallback<Worker<Payload>>> {
362-
self.set_callback(f.into_timer_repeating_callback())
362+
self.set_callback(f.into_worker_timer_repeating_callback())
363363
}
364364

365365
/// Set a one-shot callback for the worker timer.
@@ -376,7 +376,7 @@ impl<Payload: 'static + Send + Sync> TimerState<Worker<Payload>> {
376376
&self,
377377
f: impl IntoWorkerTimerOneshotCallback<Worker<Payload>, Args>,
378378
) -> Option<AnyTimerCallback<Worker<Payload>>> {
379-
self.set_callback(f.into_timer_oneshot_callback())
379+
self.set_callback(f.into_worker_timer_oneshot_callback())
380380
}
381381
}
382382

rclrs/src/timer/into_worker_timer_callback.rs

+10-10
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@ use std::sync::Arc;
44
/// This trait is used to create timer callbacks for repeating timers in a Worker.
55
pub trait IntoWorkerTimerRepeatingCallback<Scope: WorkScope, Args>: 'static + Send {
66
/// Convert a suitable object into a repeating timer callback for a worker scope
7-
fn into_timer_repeating_callback(self) -> AnyTimerCallback<Scope>;
7+
fn into_worker_timer_repeating_callback(self) -> AnyTimerCallback<Scope>;
88
}
99

1010
impl<Scope: WorkScope, Func> IntoWorkerTimerRepeatingCallback<Scope, ()> for Func
1111
where
1212
Func: FnMut() + 'static + Send,
1313
{
14-
fn into_timer_repeating_callback(mut self) -> AnyTimerCallback<Scope> {
14+
fn into_worker_timer_repeating_callback(mut self) -> AnyTimerCallback<Scope> {
1515
AnyTimerCallback::Repeating(Box::new(move |_, _| self())).into()
1616
}
1717
}
@@ -20,7 +20,7 @@ impl<Scope: WorkScope, Func> IntoWorkerTimerRepeatingCallback<Scope, (Scope::Pay
2020
where
2121
Func: FnMut(&mut Scope::Payload) + 'static + Send,
2222
{
23-
fn into_timer_repeating_callback(mut self) -> AnyTimerCallback<Scope> {
23+
fn into_worker_timer_repeating_callback(mut self) -> AnyTimerCallback<Scope> {
2424
AnyTimerCallback::Repeating(Box::new(move |payload, _| self(payload))).into()
2525
}
2626
}
@@ -29,7 +29,7 @@ impl<Scope: WorkScope, Func> IntoWorkerTimerRepeatingCallback<Scope, (Scope::Pay
2929
where
3030
Func: FnMut(&mut Scope::Payload, &Arc<TimerState<Scope>>) + 'static + Send,
3131
{
32-
fn into_timer_repeating_callback(self) -> AnyTimerCallback<Scope> {
32+
fn into_worker_timer_repeating_callback(self) -> AnyTimerCallback<Scope> {
3333
AnyTimerCallback::Repeating(Box::new(self)).into()
3434
}
3535
}
@@ -38,22 +38,22 @@ impl<Scope: WorkScope, Func> IntoWorkerTimerRepeatingCallback<Scope, (Scope::Pay
3838
where
3939
Func: FnMut(&mut Scope::Payload, Time) + 'static + Send,
4040
{
41-
fn into_timer_repeating_callback(mut self) -> AnyTimerCallback<Scope> {
41+
fn into_worker_timer_repeating_callback(mut self) -> AnyTimerCallback<Scope> {
4242
AnyTimerCallback::Repeating(Box::new(move |payload, t| self(payload, t.handle.clock.now()))).into()
4343
}
4444
}
4545

4646
/// This trait is used to create timer callbacks for one-shot timers in a Worker.
4747
pub trait IntoWorkerTimerOneshotCallback<Scope: WorkScope, Args>: 'static + Send {
4848
/// Convert a suitable object into a one-shot timer callback for a worker scope
49-
fn into_timer_oneshot_callback(self) -> AnyTimerCallback<Scope>;
49+
fn into_worker_timer_oneshot_callback(self) -> AnyTimerCallback<Scope>;
5050
}
5151

5252
impl<Scope: WorkScope, Func> IntoWorkerTimerOneshotCallback<Scope, ()> for Func
5353
where
5454
Func: FnOnce() + 'static + Send,
5555
{
56-
fn into_timer_oneshot_callback(self) -> AnyTimerCallback<Scope> {
56+
fn into_worker_timer_oneshot_callback(self) -> AnyTimerCallback<Scope> {
5757
AnyTimerCallback::OneShot(Box::new(move |_, _| self())).into()
5858
}
5959
}
@@ -62,7 +62,7 @@ impl<Scope: WorkScope, Func> IntoWorkerTimerOneshotCallback<Scope, (Scope::Paylo
6262
where
6363
Func: FnOnce(&mut Scope::Payload) + 'static + Send,
6464
{
65-
fn into_timer_oneshot_callback(self) -> AnyTimerCallback<Scope> {
65+
fn into_worker_timer_oneshot_callback(self) -> AnyTimerCallback<Scope> {
6666
AnyTimerCallback::OneShot(Box::new(move |payload, _| self(payload))).into()
6767
}
6868
}
@@ -71,7 +71,7 @@ impl<Scope: WorkScope, Func> IntoWorkerTimerOneshotCallback<Scope, (Scope::Paylo
7171
where
7272
Func: FnOnce(&mut Scope::Payload, &Arc<TimerState<Scope>>) + 'static + Send,
7373
{
74-
fn into_timer_oneshot_callback(self) -> AnyTimerCallback<Scope> {
74+
fn into_worker_timer_oneshot_callback(self) -> AnyTimerCallback<Scope> {
7575
AnyTimerCallback::OneShot(Box::new(self)).into()
7676
}
7777
}
@@ -80,7 +80,7 @@ impl<Scope: WorkScope, Func> IntoWorkerTimerOneshotCallback<Scope, (Scope::Paylo
8080
where
8181
Func: FnMut(&mut Scope::Payload, Time) + 'static + Send,
8282
{
83-
fn into_timer_oneshot_callback(mut self) -> AnyTimerCallback<Scope> {
83+
fn into_worker_timer_oneshot_callback(mut self) -> AnyTimerCallback<Scope> {
8484
AnyTimerCallback::OneShot(Box::new(move |payload, t| self(payload, t.handle.clock.now()))).into()
8585
}
8686
}

rclrs/src/worker.rs

+66-5
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@ use rosidl_runtime_rs::{Message, Service as IdlService};
22
use std::{any::Any, sync::{Arc, Mutex, Weak}};
33
use futures::channel::oneshot;
44
use crate::{
5-
WorkerCommands, NodeHandle, ToLogParams, Promise, log_fatal,
5+
WorkerCommands, ToLogParams, Promise, log_fatal,
66
IntoWorkerSubscriptionCallback, IntoWorkerServiceCallback,
77
WorkerSubscription, SubscriptionState, WorkerService, ServiceState,
88
SubscriptionOptions, ServiceOptions, RclrsError, Node,
9+
IntoWorkerTimerRepeatingCallback, IntoWorkerTimerOneshotCallback,
10+
IntoTimerOptions, AnyTimerCallback, WorkerTimer, TimerState,
911
};
1012

1113
/// A worker that carries a payload and synchronizes callbacks for subscriptions
@@ -33,7 +35,7 @@ pub type Worker<Payload> = Arc<WorkerState<Payload>>;
3335
/// [1]: std::sync::Weak
3436
pub struct WorkerState<Payload> {
3537
/// The node that this worker is associated with
36-
node: Arc<NodeHandle>,
38+
node: Node,
3739
/// The commands to communicate with the runtime of the worker
3840
commands: Arc<WorkerCommands>,
3941
_ignore: std::marker::PhantomData<Payload>,
@@ -159,7 +161,7 @@ impl<Payload: 'static + Send + Sync> WorkerState<Payload> {
159161
SubscriptionState::<T, Worker<Payload>>::create(
160162
options,
161163
callback.into_worker_subscription_callback(),
162-
&self.node,
164+
self.node.handle(),
163165
&self.commands,
164166
)
165167
}
@@ -176,16 +178,75 @@ impl<Payload: 'static + Send + Sync> WorkerState<Payload> {
176178
ServiceState::<T, Worker<Payload>>::create(
177179
options,
178180
callback.into_worker_service_callback(),
179-
&self.node,
181+
self.node.handle(),
180182
&self.commands,
181183
)
182184
}
183185

186+
/// Create a [`WorkerTimer`] with a repeating callback.
187+
///
188+
/// See also:
189+
/// * [`Self::create_timer_oneshot`]
190+
/// * [`Self::create_timer_inert`]
191+
pub fn create_timer_repeating<'a, Args>(
192+
&self,
193+
options: impl IntoTimerOptions<'a>,
194+
callback: impl IntoWorkerTimerRepeatingCallback<Worker<Payload>, Args>,
195+
) -> Result<WorkerTimer<Payload>, RclrsError> {
196+
self.create_timer(options, callback.into_worker_timer_repeating_callback())
197+
}
198+
199+
/// Create a [`WorkerTimer`] whose callback will be triggered once after the
200+
/// period of the timer has elapsed. After that you will need to use
201+
/// [`WorkerTimer::set_worker_oneshot`] or [`WorkerTimer::set_worker_repeating`]
202+
/// or else nothing will happen the following times that the `Timer` elapses.
203+
///
204+
/// See also:
205+
/// * [`Self::create_timer_repeating`]
206+
/// * [`Self::create_time_inert`]
207+
pub fn create_timer_oneshot<'a, Args>(
208+
&self,
209+
options: impl IntoTimerOptions<'a>,
210+
callback: impl IntoWorkerTimerOneshotCallback<Worker<Payload>, Args>,
211+
) -> Result<WorkerTimer<Payload>, RclrsError> {
212+
self.create_timer(options, callback.into_worker_timer_oneshot_callback())
213+
}
214+
215+
/// Create a [`WorkerTimer`] without a callback. Nothing will happen when this
216+
/// `WorkerTimer` elapses until you use [`WorkerTimer::set_worker_repeating`]
217+
/// or [`WorkerTimer::set_worker_oneshot`].
218+
///
219+
/// See also:
220+
/// * [`Self::create_timer_repeating`]
221+
/// * [`Self::create_timer_oneshot`]
222+
pub fn create_timer_inert<'a>(
223+
&self,
224+
options: impl IntoTimerOptions<'a>,
225+
) -> Result<WorkerTimer<Payload>, RclrsError> {
226+
self.create_timer(options, AnyTimerCallback::Inert)
227+
}
228+
229+
fn create_timer<'a>(
230+
&self,
231+
options: impl IntoTimerOptions<'a>,
232+
callback: AnyTimerCallback<Worker<Payload>>,
233+
) -> Result<WorkerTimer<Payload>, RclrsError> {
234+
let options = options.into_timer_options();
235+
let clock = options.clock.as_clock(&*self.node);
236+
TimerState::create(
237+
options.period,
238+
clock,
239+
callback,
240+
&self.commands,
241+
&self.node.handle().context_handle,
242+
)
243+
}
244+
184245
/// Used by [`Node`][crate::Node] to create a `WorkerState`. Users should
185246
/// call [`Node::create_worker`][crate::NodeState::create_worker] instead of
186247
/// this.
187248
pub(crate) fn create(
188-
node: Arc<NodeHandle>,
249+
node: Node,
189250
commands: Arc<WorkerCommands>,
190251
) -> Arc<Self> {
191252
Arc::new(Self { node, commands, _ignore: Default::default() })

0 commit comments

Comments
 (0)