pub struct ReactionCtx<'a, 'x> { /* private fields */ }Expand description
The context in which a reaction executes. Its API allows mutating the event queue of the scheduler. Only the interactions declared at assembly time are allowed.
Implementations§
Source§impl<'a, 'x> ReactionCtx<'a, 'x>
impl<'a, 'x> ReactionCtx<'a, 'x>
Sourcepub fn get_start_time(&self) -> Instant
pub fn get_start_time(&self) -> Instant
Returns the start time of the execution of this program.
This is a logical instant with microstep zero.
Sourcepub fn get_physical_time(&self) -> Instant
pub fn get_physical_time(&self) -> Instant
Returns the current physical time.
Repeated invocation of this method may produce different values, although Instant is monotonic. The physical time is necessarily greater than the logical time.
Sourcepub fn get_logical_time(&self) -> Instant
pub fn get_logical_time(&self) -> Instant
Returns the current logical time.
Logical time is frozen during the execution of a reaction. Repeated invocation of this method will always produce the same value.
Sourcepub fn get_tag(&self) -> EventTag
pub fn get_tag(&self) -> EventTag
Returns the tag at which the reaction executes.
Repeated invocation of this method will always produce the same value.
Sourcepub fn is_shutdown(&self) -> bool
pub fn is_shutdown(&self) -> bool
Returns whether this tag is the shutdown tag of the application. If so, it’s necessarily the very last invocation of the current reaction (on a given reactor instance).
Repeated invocation of this method will always produce the same value.
Sourcepub fn get_elapsed_logical_time(&self) -> Duration
pub fn get_elapsed_logical_time(&self) -> Duration
Returns the amount of logical time elapsed since the start of the program. This does not take microsteps into account.
Sourcepub fn get_elapsed_physical_time(&self) -> Duration
pub fn get_elapsed_physical_time(&self) -> Duration
Returns the amount of physical time elapsed since the start of the program.
Since this uses Self::get_physical_time, be aware that this function’s result may change over time.
Sourcepub fn num_workers(&self) -> usize
pub fn num_workers(&self) -> usize
Returns the number of active workers in the execution of a reactor program.
Return values:
1if threading is not enabled.- If threading is enabled and a number of workers was specified, it returns that number.
- And if the number of workers was left unspecified, the return value might vary.
Sourcepub fn get<T: Copy>(&self, container: &impl ReactionTrigger<T>) -> Option<T>
pub fn get<T: Copy>(&self, container: &impl ReactionTrigger<T>) -> Option<T>
Returns the current value of a port or action at this logical time. If the value is absent, Option::None is returned. This is the case if the action or port is not present (Self::is_present), or if no value was scheduled (action values are optional, see Self::schedule_with_v).
The value is copied out. See also Self::use_ref if this is to be avoided.
§Examples
if let Some(value) = ctx.get(port) {
// branch is taken if the port is set
}Sourcepub fn get_ref<'q, T>(
&self,
container: &'q impl ReactionTriggerWithRefAccess<T>,
) -> Option<&'q T>
pub fn get_ref<'q, T>( &self, container: &'q impl ReactionTriggerWithRefAccess<T>, ) -> Option<&'q T>
Returns a reference to the current value of a port or action at this logical time. If the value is absent, Option::None is returned. This is the case if the action or port is not present (Self::is_present), or if no value was scheduled (action values are optional, see Self::schedule_with_v).
This does not require the value to be Copy, however, the implementation
of this method currently may require unsafe code. The method is therefore
not offered when compiling with the no-unsafe feature.
§Examples
if let Some(value) = ctx.get_ref(port) {
// value is a ref to the internal value
}Sourcepub fn use_ref<T, O>(
&self,
container: &impl ReactionTrigger<T>,
action: impl FnOnce(Option<&T>) -> O,
) -> O
pub fn use_ref<T, O>( &self, container: &impl ReactionTrigger<T>, action: impl FnOnce(Option<&T>) -> O, ) -> O
Executes the provided closure on the value of the port or action. The value is fetched by reference and not copied.
§Examples
let len = ctx.use_ref(port, |str| str.map(String::len).unwrap_or(0));
// equivalent to
let len = ctx.use_ref_opt(port, String::len).unwrap_or(0);
if let Some(str) = ctx.use_ref_opt(port, Clone::clone) {
// only entered if the port value is present, so no need to check is_present
}See also the similar Self::use_ref_opt.
Sourcepub fn use_ref_opt<T, O>(
&self,
container: &impl ReactionTrigger<T>,
action: impl FnOnce(&T) -> O,
) -> Option<O>
pub fn use_ref_opt<T, O>( &self, container: &impl ReactionTrigger<T>, action: impl FnOnce(&T) -> O, ) -> Option<O>
Executes the provided closure on the value of the port, only if it is present. The value is fetched by reference and not copied.
See also the similar Self::use_ref.
Sourcepub fn set<T>(&mut self, port: &mut Port<T>, value: T)where
T: Sync,
pub fn set<T>(&mut self, port: &mut Port<T>, value: T)where
T: Sync,
Sets the value of the given port.
The change is visible at the same logical time, i.e. the value propagates immediately. This may hence schedule more reactions that should execute at the same logical time.
Sourcepub fn set_opt<T>(&mut self, port: &mut Port<T>, value: Option<T>)where
T: Sync,
pub fn set_opt<T>(&mut self, port: &mut Port<T>, value: Option<T>)where
T: Sync,
Sets the value of the given port, if the given value is Some.
Otherwise the port is not set and no reactions are triggered.
The change is visible at the same logical time, i.e. the value propagates immediately. This may hence schedule more reactions that should execute at the same logical time.
ctx.set_opt(sink, ctx.get(source));
// equivalent to
if let Some(value) = ctx.get(source) {
ctx.set(sink, value);
}Sourcepub fn is_present<T>(&self, action: &impl ReactionTrigger<T>) -> bool
pub fn is_present<T>(&self, action: &impl ReactionTrigger<T>) -> bool
Returns true if the given action was triggered at the current logical time.
If so, then it may, but must not, present a value (Self::get).
Sourcepub fn schedule<T: Sync>(
&mut self,
action: &mut impl SchedulableAsAction<T>,
offset: Offset,
)
pub fn schedule<T: Sync>( &mut self, action: &mut impl SchedulableAsAction<T>, offset: Offset, )
Schedule an action to trigger at some point in the future. The action will trigger after its own implicit time delay, plus an optional additional time delay (see Offset). This delay is added to the current logical (resp. physical) time for logical (resp. physical) actions.
This is like Self::schedule_with_v, where the value is None.
§Examples
ctx.schedule(action, Asap); // will be executed one microstep from now (+ own delay)
ctx.schedule(action, after!(2 ms)); // will be executed 2 milliseconds from now (+ own delay)
ctx.schedule(action, After(delay!(2 ms))); // equivalent to the previous
ctx.schedule(action, After(Duration::from_millis(2))); // equivalent to the previousSourcepub fn schedule_with_v<T: Sync>(
&mut self,
action: &mut impl SchedulableAsAction<T>,
value: Option<T>,
offset: Offset,
)
pub fn schedule_with_v<T: Sync>( &mut self, action: &mut impl SchedulableAsAction<T>, value: Option<T>, offset: Offset, )
Schedule an action to trigger at some point in the future,
The action will carry the given value at the time it
is triggered, unless it is overwritten by another call
to this method. The value can be cleared by using None
as a value. Note that even if the value is absent, the
action will still be present at the time it is triggered
(see Self::is_present).
The action will trigger after its own implicit time delay, plus an optional additional time delay (see Offset). This delay is added to the current logical (resp. physical) time for logical (resp. physical) actions.
§Examples
// will be executed 2 milliseconds (+ own delay) from now with that value.
ctx.schedule_with_v(action, Some("value"), after!(2 msec));
// will be executed one microstep from now, with no value
ctx.schedule_with_v(action, None, Asap);
// that's equivalent to
ctx.schedule(action, Asap);Sourcepub fn spawn_physical_thread<F, R>(&mut self, f: F) -> JoinHandle<R>
pub fn spawn_physical_thread<F, R>(&mut self, f: F) -> JoinHandle<R>
Spawn a new thread that can use a AsyncCtx to push asynchronous events to the reaction queue. This is only useful with physical actions.
Since the thread is allowed to keep references into the internals of the scheduler, it is joined when the scheduler shuts down. This means the scheduler will wait for the thread to finish its task. For that reason, the thread’s closure should not execute an infinite loop, it should at least check that the scheduler has not been terminated by polling AsyncCtx::was_terminated.
§Example
fn some_reaction(ctx: &mut ReactionCtx, phys_action: &PhysicalActionRef<u32>) {
let phys_action = phys_action.clone(); // clone to move it into other thread
ctx.spawn_physical_thread(move |link| {
std::thread::sleep(Duration::from_millis(200));
// This will push an event whose tag is the
// current physical time at the point of this
// statement.
link.schedule_physical_with_v(&phys_action, Some(123), Asap).unwrap();
});
}Sourcepub fn request_stop(&mut self, offset: Offset)
pub fn request_stop(&mut self, offset: Offset)
Request that the application shutdown, possibly with
a particular offset. Just like for actions, even a zero
offset will only trigger the special shutdown trigger
at the earliest one microstep after the current tag.
// trigger shutdown on the next microstep
ctx.request_stop(Asap);
// trigger shutdown in *at most* 1 msec (in logical time).
// If in the meantime, another `request_stop` call schedules
// shutdown for an earlier tag, that one will be honored instead.
ctx.request_stop(after!(1 msec));