diff --git a/crates.js b/crates.js index db66e183..9a3fb548 100644 --- a/crates.js +++ b/crates.js @@ -1 +1 @@ -window.ALL_CRATES = ["reactor_rt","vecmap"]; \ No newline at end of file +window.ALL_CRATES = ["reactor_rt"]; \ No newline at end of file diff --git a/help.html b/help.html index 6b9661a8..d68b81d1 100644 --- a/help.html +++ b/help.html @@ -1 +1,2 @@ -
Redirecting to ../../reactor_rt/prelude/struct.LogicalAction.html...
- +Redirecting to ../../reactor_rt/struct.LogicalAction.html...
+ \ No newline at end of file diff --git a/reactor_rt/actions/struct.PhysicalActionRef.html b/reactor_rt/actions/struct.PhysicalActionRef.html index d092c6f2..6994fca0 100644 --- a/reactor_rt/actions/struct.PhysicalActionRef.html +++ b/reactor_rt/actions/struct.PhysicalActionRef.html @@ -1,11 +1,11 @@ - +Redirecting to ../../reactor_rt/prelude/struct.PhysicalActionRef.html...
- +Redirecting to ../../reactor_rt/struct.PhysicalActionRef.html...
+ \ No newline at end of file diff --git a/reactor_rt/all.html b/reactor_rt/all.html index d4ff1531..71f0cca1 100644 --- a/reactor_rt/all.html +++ b/reactor_rt/all.html @@ -1 +1,2 @@ -pub enum PortKind {
+PortKind in reactor_rt::assembly - Rust
+ Enum reactor_rt::assembly::PortKind
source · pub enum PortKind {
Input,
Output,
ChildInputReference,
ChildOutputReference,
}
Expand description
Kind of a port.
-Variants§
Trait Implementations§
source§impl PartialEq<PortKind> for PortKind
source§impl Copy for PortKind
source§impl Eq for PortKind
source§impl StructuralEq for PortKind
source§impl StructuralPartialEq for PortKind
Auto Trait Implementations§
§impl RefUnwindSafe for PortKind
§impl Send for PortKind
§impl Sync for PortKind
§impl Unpin for PortKind
§impl UnwindSafe for PortKind
Blanket Implementations§
source§impl<Q, K> Equivalent<K> for Qwhere
- Q: Eq + ?Sized,
- K: Borrow<Q> + ?Sized,
source§fn equivalent(&self, key: &K) -> bool
Compare self to key
and return true
if they are equal.source§impl<T, U> Into<U> for Twhere
- U: From<T>,
Variants§
Trait Implementations§
source§impl PartialEq for PortKind
source§impl Copy for PortKind
source§impl Eq for PortKind
source§impl StructuralEq for PortKind
source§impl StructuralPartialEq for PortKind
Auto Trait Implementations§
§impl RefUnwindSafe for PortKind
§impl Send for PortKind
§impl Sync for PortKind
§impl Unpin for PortKind
§impl UnwindSafe for PortKind
Blanket Implementations§
source§impl<T> BorrowMut<T> for Twhere
+ T: ?Sized,
source§fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more§impl<Q, K> Equivalent<K> for Q
§fn equivalent(&self, key: &K) -> bool
Checks if this value is equivalent to the given key. Read more§impl<Q, K> Equivalent<K> for Q
§fn equivalent(&self, key: &K) -> bool
Compare self to key
and return true
if they are equal.
\ No newline at end of file
+From<T> for U
chooses to do.
+
Module containing the API to initialize a reactor program.
-Module containing the API to initialize a reactor program.
+pub use crate::triggers::TriggerLike;
pub struct AssemblyCtx<'x, S>where
- S: ReactorInitializer,{ /* private fields */ }
Helper struct to assemble reactors during initialization. +
pub struct AssemblyCtx<'x, S>where
+ S: ReactorInitializer,{ /* private fields */ }
Helper struct to assemble reactors during initialization. One assembly context is used per reactor, they can’t be shared.
-top level function
-Innermost function.
-Assembles a child reactor and makes it available in +) -> AssemblyResult<AssemblyIntermediate<'x, S>>
Assembles a child reactor and makes it available in the scope of a function.
-Assembles a bank of children reactor and makes it + F: FnOnce(Self, &mut Vec<Sub>) -> AssemblyResult<AssemblyIntermediate<'x, S>>, + A: Fn(usize) -> Sub::Params,
Assembles a bank of children reactor and makes it available in the scope of a function.
-From<T> for U
chooses to do.
+pub struct AssemblyError(_);
An error occurring during initialization of the reactor program. +
pub struct AssemblyError(/* private fields */);
An error occurring during initialization of the reactor program. Should never occur unless the graph is built by hand, and not by a Lingua Franca compiler.
-From<T> for U
chooses to do.
+pub struct AssemblyIntermediate<'x, S>(_, _)
+AssemblyIntermediate in reactor_rt::assembly - Rust
+ Struct reactor_rt::assembly::AssemblyIntermediate
source · pub struct AssemblyIntermediate<'x, S>(/* private fields */)
where
- S: ReactorInitializer;
Expand description
Intermediate result of assembly.
-Auto Trait Implementations§
§impl<'x, S> !RefUnwindSafe for AssemblyIntermediate<'x, S>
§impl<'x, S> !Send for AssemblyIntermediate<'x, S>
§impl<'x, S> !Sync for AssemblyIntermediate<'x, S>
§impl<'x, S> Unpin for AssemblyIntermediate<'x, S>where
- S: Unpin,
§impl<'x, S> !UnwindSafe for AssemblyIntermediate<'x, S>
Blanket Implementations§
source§impl<T, U> Into<U> for Twhere
- U: From<T>,
const: unstable · source§fn into(self) -> U
Calls U::from(self)
.
+ S: ReactorInitializer;Expand description
Intermediate result of assembly.
+Auto Trait Implementations§
§impl<'x, S> !RefUnwindSafe for AssemblyIntermediate<'x, S>
§impl<'x, S> !Send for AssemblyIntermediate<'x, S>
§impl<'x, S> !Sync for AssemblyIntermediate<'x, S>
§impl<'x, S> Unpin for AssemblyIntermediate<'x, S>where
+ S: Unpin,
§impl<'x, S> !UnwindSafe for AssemblyIntermediate<'x, S>
Blanket Implementations§
source§impl<T> BorrowMut<T> for Twhere
+ T: ?Sized,
source§fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more
\ No newline at end of file
+From<T> for U
chooses to do.
+
pub struct ComponentCreator<'a, 'x, S: ReactorInitializer> { /* private fields */ }
Creates the components of a reactor.
-pub struct ComponentCreator<'a, 'x, S: ReactorInitializer> { /* private fields */ }
Creates the components of a reactor.
+From<T> for U
chooses to do.
+pub struct DependencyDeclarator<'a, 'x, S: ReactorInitializer> { /* private fields */ }
Declares dependencies between components and reactions.
-pub struct DependencyDeclarator<'a, 'x, S: ReactorInitializer> { /* private fields */ }
Declares dependencies between components and reactions.
+Bind two ports together.
-Bind two ports together.
+Bind the ports of the upstream to those of the downstream, + upstream: impl Iterator<Item = &'a mut Port<T>>, + downstream: impl Iterator<Item = &'a mut Port<T>> +) -> AssemblyResult<()>
Bind the ports of the upstream to those of the downstream, as if zipping both iterators. todo this will just throw away bindings if both iterators are not of the same size normally this should be reported by LFC as a warning, maybe we should implement the same thing here
-From<T> for U
chooses to do.
+pub struct FinishedReactor<'x, S>(_, _)
+FinishedReactor in reactor_rt::assembly - Rust
+ Struct reactor_rt::assembly::FinishedReactor
source · pub struct FinishedReactor<'x, S>(/* private fields */)
where
- S: ReactorInitializer;
Expand description
Final result of the assembly of a reactor.
-Auto Trait Implementations§
§impl<'x, S> !RefUnwindSafe for FinishedReactor<'x, S>
§impl<'x, S> !Send for FinishedReactor<'x, S>
§impl<'x, S> !Sync for FinishedReactor<'x, S>
§impl<'x, S> Unpin for FinishedReactor<'x, S>where
- S: Unpin,
§impl<'x, S> !UnwindSafe for FinishedReactor<'x, S>
Blanket Implementations§
source§impl<T, U> Into<U> for Twhere
- U: From<T>,
const: unstable · source§fn into(self) -> U
Calls U::from(self)
.
+ S: ReactorInitializer;Expand description
Final result of the assembly of a reactor.
+Auto Trait Implementations§
§impl<'x, S> !RefUnwindSafe for FinishedReactor<'x, S>
§impl<'x, S> !Send for FinishedReactor<'x, S>
§impl<'x, S> !Sync for FinishedReactor<'x, S>
§impl<'x, S> Unpin for FinishedReactor<'x, S>where
+ S: Unpin,
§impl<'x, S> !UnwindSafe for FinishedReactor<'x, S>
Blanket Implementations§
source§impl<T> BorrowMut<T> for Twhere
+ T: ?Sized,
source§fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more
\ No newline at end of file
+From<T> for U
chooses to do.
+
pub struct GlobalReactionId(_);
Global identifier for a reaction.
-source
. Read moreself
and other
values to be equal, and is used
-by ==
.self
and other
) and is used by the <=
-operator. Read morekey
and return true
if they are equal.Calls U::from(self)
.
pub struct GlobalReactionId(/* private fields */);
Global identifier for a reaction.
+source
. Read moreself
and other
values to be equal, and is used
+by ==
.self
and other
) and is used by the <=
+operator. Read morekey
and return true
if they are equal.From<T> for U
chooses to do.
+pub struct TriggerId(_);
The ID of a trigger component.
-self
and other
) and is used by the <=
-operator. Read morekey
and return true
if they are equal.pub struct TriggerId(/* private fields */);
The ID of a trigger component.
+self
and other
) and is used by the <=
+operator. Read morekey
and return true
if they are equal.From<T> for U
chooses to do.
+pub trait ReactorInitializer: ReactorBehavior {
+ReactorInitializer in reactor_rt::assembly - Rust
+ Trait reactor_rt::assembly::ReactorInitializer
source · pub trait ReactorInitializer: ReactorBehavior {
type Wrapped;
type Params;
@@ -9,7 +10,7 @@
args: Self::Params,
assembler: AssemblyCtx<'_, Self>
) -> AssemblyResult<FinishedReactor<'_, Self>>
- where Self: Sized;
+ where Self: Sized;
}
Expand description
Wrapper around the user struct for safe dispatch.
Fields are
@@ -17,15 +18,15 @@
- ctor parameters of the reactor, and
- every logical action and port declared by the reactor.
-Required Associated Types§
Required Associated Types§
Required Associated Constants§
sourceconst MAX_REACTION_ID: LocalReactionId
Exclusive maximum value of the local_rid
parameter of [ReactorBehavior.react].
-Required Methods§
Required Associated Constants§
sourceconst MAX_REACTION_ID: LocalReactionId
Exclusive maximum value of the local_rid
parameter of [ReactorBehavior.react].
+Required Methods§
sourcefn assemble(
args: Self::Params,
assembler: AssemblyCtx<'_, Self>
-) -> AssemblyResult<FinishedReactor<'_, Self>>where
- Self: Sized,
Assemble this reactor. This initializes state variables,
+) -> AssemblyResult<FinishedReactor<'_, Self>>
where
+ Self: Sized,Assemble this reactor. This initializes state variables,
produces internal components, assembles children reactor
instances, and declares dependencies between them.
-Implementors§
\ No newline at end of file
+
pub type AssemblyResult<T = ()> = Result<T, AssemblyError>;
pub type AssemblyResult<T = ()> = Result<T, AssemblyError>;
enum AssemblyResult<T = ()> {
+ Ok(T),
+ Err(AssemblyError),
+}
pub enum Offset {
+Offset in reactor_rt - Rust
+ Enum reactor_rt::Offset
source · pub enum Offset {
After(Duration),
Asap,
}
Expand description
An offset from the current event.
-This is to be used with ReactionCtx::schedule.
-Variants§
§After(Duration)
Specify that the trigger will fire at least after
+
This is to be used with ReactionCtx::schedule.
+Variants§
§After(Duration)
Specify that the trigger will fire at least after
the provided duration.
If the duration is zero (eg Asap), it does not
mean that the trigger will fire right away. For actions, the
@@ -21,21 +22,23 @@
is applied. This is equivalent to
assert_eq!(Asap, After(Duration::ZERO));
-Trait Implementations§
source§impl PartialEq<Offset> for Offset
source§impl Copy for Offset
source§impl Eq for Offset
Auto Trait Implementations§
§impl RefUnwindSafe for Offset
§impl Send for Offset
§impl Sync for Offset
§impl Unpin for Offset
§impl UnwindSafe for Offset
Blanket Implementations§
source§impl<Q, K> Equivalent<K> for Qwhere
- Q: Eq + ?Sized,
- K: Borrow<Q> + ?Sized,
source§fn equivalent(&self, key: &K) -> bool
Compare self to key
and return true
if they are equal.source§impl<T, U> Into<U> for Twhere
- U: From<T>,
Trait Implementations§
source§impl PartialEq for Offset
source§impl Copy for Offset
source§impl Eq for Offset
Auto Trait Implementations§
§impl RefUnwindSafe for Offset
§impl Send for Offset
§impl Sync for Offset
§impl Unpin for Offset
§impl UnwindSafe for Offset
Blanket Implementations§
source§impl<T> BorrowMut<T> for Twhere
+ T: ?Sized,
source§fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more§impl<Q, K> Equivalent<K> for Q
§fn equivalent(&self, key: &K) -> bool
Checks if this value is equivalent to the given key. Read more§impl<Q, K> Equivalent<K> for Q
§fn equivalent(&self, key: &K) -> bool
Compare self to key
and return true
if they are equal.
\ No newline at end of file
+From<T> for U
chooses to do.
+
pub enum TimeUnit {
+TimeUnit in reactor_rt - Rust
+ Enum reactor_rt::TimeUnit
source · pub enum TimeUnit {
NANO,
MICRO,
MILLI,
@@ -7,15 +8,15 @@
HOUR,
DAY,
}
Expand description
A unit of time, used in LF.
-Variants§
Implementations§
Trait Implementations§
Auto Trait Implementations§
§impl RefUnwindSafe for TimeUnit
§impl Send for TimeUnit
§impl Sync for TimeUnit
§impl Unpin for TimeUnit
§impl UnwindSafe for TimeUnit
Blanket Implementations§
source§impl<T, U> Into<U> for Twhere
- U: From<T>,
Variants§
Implementations§
Trait Implementations§
Auto Trait Implementations§
§impl RefUnwindSafe for TimeUnit
§impl Send for TimeUnit
§impl Sync for TimeUnit
§impl Unpin for TimeUnit
§impl UnwindSafe for TimeUnit
Blanket Implementations§
source§impl<T> BorrowMut<T> for Twhere
+ T: ?Sized,
source§fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more
\ No newline at end of file
+From<T> for U
chooses to do.
+
pub fn try_parse_duration(t: &str) -> Result<Duration, String>
Parse a duration from a string. This is used for CLI +
pub fn try_parse_duration(t: &str) -> Result<Duration, String>
Parse a duration from a string. This is used for CLI
parameter parsing in programs generated by LFC, specifically,
to parse main parameters with time
type, and scheduler
options with time type.
use reactor_rt::try_parse_duration;
use std::time::Duration;
-assert_eq!(try_parse_duration("3 ms"), Ok(Duration::from_millis(3)));
-assert_eq!(try_parse_duration("3ms"), Ok(Duration::from_millis(3)));
-assert_eq!(try_parse_duration("5us"), Ok(Duration::from_micros(5)));
-assert_eq!(try_parse_duration("30ns"), Ok(Duration::from_nanos(30)));
-assert_eq!(try_parse_duration("30nsec"), Ok(Duration::from_nanos(30)));
-assert_eq!(try_parse_duration("30secs"), Ok(Duration::from_secs(30)));
+assert_eq!(try_parse_duration("3 ms"), Ok(Duration::from_millis(3)));
+assert_eq!(try_parse_duration("3ms"), Ok(Duration::from_millis(3)));
+assert_eq!(try_parse_duration("5us"), Ok(Duration::from_micros(5)));
+assert_eq!(try_parse_duration("30ns"), Ok(Duration::from_nanos(30)));
+assert_eq!(try_parse_duration("30nsec"), Ok(Duration::from_nanos(30)));
+assert_eq!(try_parse_duration("30secs"), Ok(Duration::from_secs(30)));
// unit is not required for zero
-assert_eq!(try_parse_duration("0"), Ok(Duration::from_secs(0)));
+assert_eq!(try_parse_duration("0"), Ok(Duration::from_secs(0)));
-assert_eq!(try_parse_duration(""), Err("cannot parse empty string".into()));
-assert_eq!(try_parse_duration("30"), Err("time unit required".into()));
-assert_eq!(try_parse_duration("30000000000000000000000ns"), Err("number too large to fit in target type".into()));
+assert_eq!(try_parse_duration(""), Err("cannot parse empty string".into()));
+assert_eq!(try_parse_duration("30"), Err("time unit required".into()));
+assert_eq!(try_parse_duration("30000000000000000000000ns"), Err("number too large to fit in target type".into()));
The runtime library for reactor programs generated by LFC, +
The runtime library for reactor programs generated by LFC, the Lingua Franca compiler.
Most of this crate consists of types that are manipulated only by the generated code. User-written Rust code mostly -interacts with the type ReactionCtx, which is the entry +interacts with the type ReactionCtx, which is the entry point for user documentation.
Crate-level features include:
no-unsafe
: disable optimisations that use unsafe code in this runtime.
Just provided for comparison, should probably be removed (unsafe code is fine).assert_eq!
with the
-syntax of tag.Duration
type to represent a span of time, typically used for system
timeouts.Duration
.Duration
.T
.
@@ -47,11 +49,11 @@
Only the interactions declared at assembly time
are allowed.time
type, and scheduler
-options with time type.macro_rules! after { +after in reactor_rt - Rust +Macro reactor_rt::
source ·after macro_rules! after { ($amount:tt $unit:tt) => { ... }; -}Expand description
\ No newline at end of file +Shorthand for using After together with delay.
+}Expand description
Shorthand for using After together with [delay].
-use std::time::Duration; use reactor_rt::{after, Offset::After}; assert_eq!(after!(10 ns), After(Duration::from_nanos(10))); assert_eq!(after!(2 min), After(Duration::from_secs(120)));
macro_rules! assert_tag_is { +assert_tag_is in reactor_rt - Rust +\ No newline at end of file + Macro reactor_rt::
source ·assert_tag_is macro_rules! assert_tag_is { ($ctx:tt, T0) => { ... }; ($ctx:tt, (T0, $microstep:expr)) => { ... }; ($ctx:tt, T0 + $amount:tt $unit:ident) => { ... }; ($ctx:tt, (T0 + $amount:tt $unit:ident, $microstep:expr)) => { ... }; }Expand description
Convenient macro to assert equality of the current tag. This is just shorthand for using
+syntax of [tag].assert_eq!
with the -syntax of tag.-assert_tag_is!(ctx, T0 + 20 ms); @@ -15,4 +16,4 @@ assert_tag_is!(ctx, (T0, 1)); assert_tag_is!(ctx, (T0 + 3 sec, 1)); assert_tag_is!(ctx, (T0 + 3 sec, foo.i));
macro_rules! delay { +delay in reactor_rt - Rust + -Macro reactor_rt::
source ·delay macro_rules! delay { (0) => { ... }; ($amount:tt ns) => { ... }; ($amount:tt nsec) => { ... }; @@ -48,4 +49,4 @@ assert_eq!(delay!(2 h), delay!(2 hours)); assert_eq!(delay!(1 week), delay!(7 days));
macro_rules! tag { +tag in reactor_rt - Rust +Macro reactor_rt::
source ·tag macro_rules! tag { (T0) => { ... }; (T0, $microstep:expr) => { ... }; (T0 + $amount:tt $unit:ident) => { ... }; (T0 + $amount:tt $unit:ident, $microstep:expr) => { ... }; -}Expand description
\ No newline at end of file +Convenient macro to create a tag. +}
Expand description
Convenient macro to create a tag. This is just a shorthand for using the constructor together -with the syntax of delay.
+with the syntax of [delay].-use reactor_rt::{tag, delay}; @@ -15,4 +16,4 @@ // with a microstep: tag!(T0, 1); tag!(T0 + 3 sec, 1);
Redirecting to ../../reactor_rt/prelude/struct.Multiport.html...
- +Redirecting to ../../reactor_rt/struct.Multiport.html...
+ \ No newline at end of file diff --git a/reactor_rt/ports/struct.Port.html b/reactor_rt/ports/struct.Port.html index 811a544e..47a95863 100644 --- a/reactor_rt/ports/struct.Port.html +++ b/reactor_rt/ports/struct.Port.html @@ -1,11 +1,11 @@ - +Redirecting to ../../reactor_rt/prelude/struct.Port.html...
- +Redirecting to ../../reactor_rt/struct.Port.html...
+ \ No newline at end of file diff --git a/reactor_rt/prelude/index.html b/reactor_rt/prelude/index.html index fb5badce..3ccee636 100644 --- a/reactor_rt/prelude/index.html +++ b/reactor_rt/prelude/index.html @@ -1,22 +1,12 @@ -The prelude that is imported at the top of reactor files +
The prelude that is imported at the top of reactor files generated by LFC.
-pub use crate::Offset::*;
pub use crate::AsyncCtx;
pub use crate::EventTag;
pub use crate::LogicalAction;
pub use crate::Multiport;
pub use crate::PhysicalActionRef;
pub use crate::Port;
pub use crate::ReactionCtx;
pub use crate::Timer;
pub use crate::Offset::*;
assert_eq!
with the
-syntax of tag.Duration
type to represent a span of time, typically used for system
-timeouts.Duration
.T
.
-Ports reify the data inputs and outputs of a reactor.Duration
type to represent a span of time, typically used for system
+timeouts.Duration
.{= () =}
.
-It is not camel-case as it is actually a primitive type.macro_rules! after { +after in reactor_rt::prelude - Rust +Macro reactor_rt::
source ·prelude:: after macro_rules! after { ($amount:tt $unit:tt) => { ... }; -}Expand description
\ No newline at end of file +Shorthand for using After together with delay.
+}Expand description
Shorthand for using After together with [delay].
-use std::time::Duration; use reactor_rt::{after, Offset::After}; assert_eq!(after!(10 ns), After(Duration::from_nanos(10))); assert_eq!(after!(2 min), After(Duration::from_secs(120)));
macro_rules! assert_tag_is { +assert_tag_is in reactor_rt::prelude - Rust +\ No newline at end of file + Macro reactor_rt::
source ·prelude:: assert_tag_is macro_rules! assert_tag_is { ($ctx:tt, T0) => { ... }; ($ctx:tt, (T0, $microstep:expr)) => { ... }; ($ctx:tt, T0 + $amount:tt $unit:ident) => { ... }; ($ctx:tt, (T0 + $amount:tt $unit:ident, $microstep:expr)) => { ... }; }Expand description
Convenient macro to assert equality of the current tag. This is just shorthand for using
+syntax of [tag].assert_eq!
with the -syntax of tag.-assert_tag_is!(ctx, T0 + 20 ms); @@ -15,4 +16,4 @@ assert_tag_is!(ctx, (T0, 1)); assert_tag_is!(ctx, (T0 + 3 sec, 1)); assert_tag_is!(ctx, (T0 + 3 sec, foo.i));
macro_rules! delay { +delay in reactor_rt::prelude - Rust + -Macro reactor_rt::
source ·prelude:: delay macro_rules! delay { (0) => { ... }; ($amount:tt ns) => { ... }; ($amount:tt nsec) => { ... }; @@ -48,4 +49,4 @@ assert_eq!(delay!(2 h), delay!(2 hours)); assert_eq!(delay!(1 week), delay!(7 days));
macro_rules! tag { +tag in reactor_rt::prelude - Rust +Macro reactor_rt::
source ·prelude:: tag macro_rules! tag { (T0) => { ... }; (T0, $microstep:expr) => { ... }; (T0 + $amount:tt $unit:ident) => { ... }; (T0 + $amount:tt $unit:ident, $microstep:expr) => { ... }; -}Expand description
\ No newline at end of file +Convenient macro to create a tag. +}
Expand description
Convenient macro to create a tag. This is just a shorthand for using the constructor together -with the syntax of delay.
+with the syntax of [delay].-use reactor_rt::{tag, delay}; @@ -15,4 +16,4 @@ // with a microstep: tag!(T0, 1); tag!(T0 + 3 sec, 1);
pub struct AsyncCtx { /* private fields */ }
A type that can affect the logical event queue to implement -asynchronous physical actions. This is a “link” to the event -system, from the outside world.
- -Returns true if the scheduler has been shutdown. When -that’s true, calls to other methods of this type will -fail with [SendError].
-Request that the application shutdown, possibly with -a particular offset from the current physical time.
-This may fail if this is called while the scheduler -has already been shutdown. An Ok result is also not -a guarantee that the event will be processed: the -scheduler may be in the process of shutting down, -or its shutdown might be programmed for a logical -time which precedes the current physical time.
-Schedule an action to run after its own implicit time delay -plus an optional additional time delay. These delays are in -logical time.
-Note that this locks the action.
-This may fail if this is called while the scheduler -has already been shutdown. An Ok result is also not -a guarantee that the event will be processed: the -scheduler may be in the process of shutting down, -or its shutdown might be programmed for a logical -time which precedes the current physical time.
-Schedule an action to run after its own implicit time delay -plus an optional additional time delay. These delays are in -logical time.
-Note that this locks the action.
-This may fail if this is called while the scheduler -has already been shutdown. An Ok result is also not -a guarantee that the event will be processed: the -scheduler may be in the process of shutting down, -or its shutdown might be programmed for a logical -time which precedes the current physical time.
-pub struct Duration { /* private fields */ }
A Duration
type to represent a span of time, typically used for system
+
pub struct Duration { /* private fields */ }
A Duration
type to represent a span of time, typically used for system
timeouts.
Each Duration
is composed of a whole number of seconds and a fractional part
represented in nanoseconds. If the underlying system does not support
nanosecond-level precision, APIs binding a system timeout will typically round up
the number of nanoseconds.
Duration
s implement many common traits, including Add
, Sub
, and other
-ops
traits. It implements Default
by returning a zero-length Duration
.
Duration
s implement many common traits, including Add
, Sub
, and other
+ops
traits. It implements Default
by returning a zero-length Duration
.
use std::time::Duration;
@@ -24,38 +25,38 @@ Format
program output may appear in contexts that cannot rely on full Unicode
compatibility, you may wish to format Duration
objects yourself or use a
crate to do so.
-
duration_constants
)The duration of one second.
+duration_constants
)The duration of one second.
#![feature(duration_constants)]
use std::time::Duration;
assert_eq!(Duration::SECOND, Duration::from_secs(1));
duration_constants
)The duration of one millisecond.
+duration_constants
)The duration of one millisecond.
#![feature(duration_constants)]
use std::time::Duration;
assert_eq!(Duration::MILLISECOND, Duration::from_millis(1));
duration_constants
)The duration of one microsecond.
+duration_constants
)The duration of one microsecond.
#![feature(duration_constants)]
use std::time::Duration;
assert_eq!(Duration::MICROSECOND, Duration::from_micros(1));
duration_constants
)The duration of one nanosecond.
+duration_constants
)The duration of one nanosecond.
#![feature(duration_constants)]
use std::time::Duration;
assert_eq!(Duration::NANOSECOND, Duration::from_nanos(1));
A duration of zero time.
use std::time::Duration;
let duration = Duration::ZERO;
assert!(duration.is_zero());
assert_eq!(duration.as_nanos(), 0);
The maximum duration.
+The maximum duration.
May vary by platform as necessary. Must be able to contain the difference between
two instances of Instant
or two instances of SystemTime
.
This constraint gives it a value of about 584,942,417,355 years in practice,
@@ -64,7 +65,7 @@
use std::time::Duration;
assert_eq!(Duration::MAX, Duration::new(u64::MAX, 1_000_000_000 - 1));
Creates a new Duration
from the specified number of whole seconds and
+
Creates a new Duration
from the specified number of whole seconds and
additional nanoseconds.
If the number of nanoseconds is greater than 1 billion (the number of nanoseconds in a second), then it will carry over into the seconds provided.
@@ -75,7 +76,7 @@use std::time::Duration;
let five_seconds = Duration::new(5, 0);
Creates a new Duration
from the specified number of whole seconds.
Creates a new Duration
from the specified number of milliseconds.
Creates a new Duration
from the specified number of microseconds.
Creates a new Duration
from the specified number of nanoseconds.
Returns true if this Duration
spans no time.
Returns the number of whole seconds contained by this Duration
.
Returns the number of whole seconds contained by this Duration
.
The returned value does not include the fractional (nanosecond) part of the
duration, which can be obtained using subsec_nanos
.
To determine the total number of seconds represented by the Duration
including the fractional part, use as_secs_f64
or as_secs_f32
Returns the fractional part of this Duration
, in whole milliseconds.
Returns the fractional part of this Duration
, in whole milliseconds.
This method does not return the length of the duration when represented by milliseconds. The returned number always represents a fractional portion of a second (i.e., it is less than one thousand).
@@ -139,7 +140,7 @@Returns the fractional part of this Duration
, in whole microseconds.
Returns the fractional part of this Duration
, in whole microseconds.
This method does not return the length of the duration when represented by microseconds. The returned number always represents a fractional portion of a second (i.e., it is less than one million).
@@ -149,7 +150,7 @@Returns the fractional part of this Duration
, in nanoseconds.
Returns the fractional part of this Duration
, in nanoseconds.
This method does not return the length of the duration when represented by nanoseconds. The returned number always represents a fractional portion of a second (i.e., it is less than one billion).
@@ -159,77 +160,86 @@Returns the total number of whole milliseconds contained by this Duration
.
Returns the total number of whole milliseconds contained by this Duration
.
use std::time::Duration;
let duration = Duration::new(5, 730023852);
assert_eq!(duration.as_millis(), 5730);
Returns the total number of whole microseconds contained by this Duration
.
Returns the total number of whole microseconds contained by this Duration
.
use std::time::Duration;
let duration = Duration::new(5, 730023852);
assert_eq!(duration.as_micros(), 5730023);
Returns the total number of nanoseconds contained by this Duration
.
Returns the total number of nanoseconds contained by this Duration
.
use std::time::Duration;
let duration = Duration::new(5, 730023852);
assert_eq!(duration.as_nanos(), 5730023852);
Checked Duration
addition. Computes self + other
, returning None
-if overflow occurred.
duration_abs_diff
)Computes the absolute difference between self
and other
.
Basic usage:
+#![feature(duration_abs_diff)]
+use std::time::Duration;
+
+assert_eq!(Duration::new(100, 0).abs_diff(Duration::new(80, 0)), Duration::new(20, 0));
+assert_eq!(Duration::new(100, 400_000_000).abs_diff(Duration::new(110, 0)), Duration::new(9, 600_000_000));
Checked Duration
addition. Computes self + other
, returning None
+if overflow occurred.
Basic usage:
+use std::time::Duration;
assert_eq!(Duration::new(0, 0).checked_add(Duration::new(0, 1)), Some(Duration::new(0, 1)));
assert_eq!(Duration::new(1, 0).checked_add(Duration::new(u64::MAX, 0)), None);
Saturating Duration
addition. Computes self + other
, returning Duration::MAX
+
Saturating Duration
addition. Computes self + other
, returning Duration::MAX
if overflow occurred.
#![feature(duration_constants)]
use std::time::Duration;
assert_eq!(Duration::new(0, 0).saturating_add(Duration::new(0, 1)), Duration::new(0, 1));
assert_eq!(Duration::new(1, 0).saturating_add(Duration::new(u64::MAX, 0)), Duration::MAX);
Checked Duration
subtraction. Computes self - other
, returning None
+
Checked Duration
subtraction. Computes self - other
, returning None
if the result would be negative or if overflow occurred.
Basic usage:
use std::time::Duration;
assert_eq!(Duration::new(0, 1).checked_sub(Duration::new(0, 0)), Some(Duration::new(0, 1)));
assert_eq!(Duration::new(0, 0).checked_sub(Duration::new(0, 1)), None);
Saturating Duration
subtraction. Computes self - other
, returning Duration::ZERO
+
Saturating Duration
subtraction. Computes self - other
, returning Duration::ZERO
if the result would be negative or if overflow occurred.
use std::time::Duration;
assert_eq!(Duration::new(0, 1).saturating_sub(Duration::new(0, 0)), Duration::new(0, 1));
assert_eq!(Duration::new(0, 0).saturating_sub(Duration::new(0, 1)), Duration::ZERO);
Saturating Duration
multiplication. Computes self * other
, returning
+
Saturating Duration
multiplication. Computes self * other
, returning
Duration::MAX
if overflow occurred.
#![feature(duration_constants)]
use std::time::Duration;
assert_eq!(Duration::new(0, 500_000_001).saturating_mul(2), Duration::new(1, 2));
assert_eq!(Duration::new(u64::MAX - 1, 0).saturating_mul(2), Duration::MAX);
Checked Duration
division. Computes self / other
, returning None
+
Checked Duration
division. Computes self / other
, returning None
if other == 0
.
Basic usage:
use std::time::Duration;
@@ -237,25 +247,25 @@ Examples
assert_eq!(Duration::new(2, 0).checked_div(2), Some(Duration::new(1, 0)));
assert_eq!(Duration::new(1, 0).checked_div(2), Some(Duration::new(0, 500_000_000)));
assert_eq!(Duration::new(2, 0).checked_div(0), None);
Returns the number of seconds contained by this Duration
as f64
.
Returns the number of seconds contained by this Duration
as f32
.
Creates a new Duration
from the specified number of seconds represented
+
Creates a new Duration
from the specified number of seconds represented
as f64
.
This constructor will panic if secs
is negative, overflows Duration
or not finite.
use std::time::Duration;
let res = Duration::from_secs_f64(0.0);
@@ -274,11 +284,11 @@ Examples
// conversion uses rounding
let res = Duration::from_secs_f64(0.999e-9);
assert_eq!(res, Duration::new(0, 1));
Creates a new Duration
from the specified number of seconds represented
+
Creates a new Duration
from the specified number of seconds represented
as f32
.
This constructor will panic if secs
is negative, overflows Duration
or not finite.
use std::time::Duration;
let res = Duration::from_secs_f32(0.0);
@@ -297,37 +307,37 @@ Examples
// conversion uses rounding
let res = Duration::from_secs_f32(0.999e-9);
assert_eq!(res, Duration::new(0, 1));
Multiplies Duration
by f64
.
Multiplies Duration
by f64
.
This method will panic if result is negative, overflows Duration
or not finite.
use std::time::Duration;
let dur = Duration::new(2, 700_000_000);
assert_eq!(dur.mul_f64(3.14), Duration::new(8, 478_000_000));
assert_eq!(dur.mul_f64(3.14e5), Duration::new(847_800, 0));
Multiplies Duration
by f32
.
Multiplies Duration
by f32
.
This method will panic if result is negative, overflows Duration
or not finite.
use std::time::Duration;
let dur = Duration::new(2, 700_000_000);
assert_eq!(dur.mul_f32(3.14), Duration::new(8, 478_000_641));
assert_eq!(dur.mul_f32(3.14e5), Duration::new(847800, 0));
Divide Duration
by f64
.
Divide Duration
by f64
.
This method will panic if result is negative, overflows Duration
or not finite.
use std::time::Duration;
let dur = Duration::new(2, 700_000_000);
assert_eq!(dur.div_f64(3.14), Duration::new(0, 859_872_611));
assert_eq!(dur.div_f64(3.14e5), Duration::new(0, 8_599));
Divide Duration
by f32
.
Divide Duration
by f32
.
This method will panic if result is negative, overflows Duration
or not finite.
use std::time::Duration;
let dur = Duration::new(2, 700_000_000);
@@ -335,25 +345,25 @@ Examples
// different from 0.859_872_611
assert_eq!(dur.div_f32(3.14), Duration::new(0, 859_872_580));
assert_eq!(dur.div_f32(3.14e5), Duration::new(0, 8_599));
div_duration
)Divide Duration
by Duration
and return f64
.
div_duration
)Divide Duration
by Duration
and return f64
.
#![feature(div_duration)]
use std::time::Duration;
let dur1 = Duration::new(2, 700_000_000);
let dur2 = Duration::new(5, 400_000_000);
assert_eq!(dur1.div_duration_f64(dur2), 0.5);
div_duration
)Divide Duration
by Duration
and return f32
.
div_duration
)Divide Duration
by Duration
and return f32
.
#![feature(div_duration)]
use std::time::Duration;
let dur1 = Duration::new(2, 700_000_000);
let dur2 = Duration::new(5, 400_000_000);
assert_eq!(dur1.div_duration_f32(dur2), 0.5);
The checked version of from_secs_f32
.
The checked version of from_secs_f32
.
This constructor will return an Err
if secs
is negative, overflows Duration
or not finite.
use std::time::Duration;
let res = Duration::try_from_secs_f32(0.0);
@@ -400,9 +410,9 @@ Examples
let val = f32::from_bits(0x3F806000);
let res = Duration::try_from_secs_f32(val);
assert_eq!(res, Ok(Duration::new(1, 2_929_688)));
The checked version of from_secs_f64
.
The checked version of from_secs_f64
.
This constructor will return an Err
if secs
is negative, overflows Duration
or not finite.
use std::time::Duration;
let res = Duration::try_from_secs_f64(0.0);
@@ -457,36 +467,40 @@ Examples
let val = f64::from_bits(0x3_FF00_C000_0000_000);
let res = Duration::try_from_secs_f64(val);
assert_eq!(res, Ok(Duration::new(1, 2_929_688)));
+=
operation. Read more+=
operation. Read more/=
operation. Read more*=
operation. Read moreself
and other
) and is used by the <=
-operator. Read more-=
operation. Read more-=
operation. Read morekey
and return true
if they are equal.+=
operation. Read more+=
operation. Read more/=
operation. Read more*=
operation. Read moreself
and other
) and is used by the <=
+operator. Read more-=
operation. Read more-=
operation. Read morekey
and return true
if they are equal.From<T> for U
chooses to do.
+pub struct EventTag {
- pub offset_from_t0: Duration,
- pub microstep: MicroStep,
-}
The tag of an event.
-Tags correspond to a point on the logical timeline, and also -implement superdense time, which means an -infinite sequence of tags may be processed for any logical -instant. The label on this sequence is called the microstep -of the tag.
-Use the tag! macro to create this struct with -convenient syntax.
-offset_from_t0: Duration
The time offset from the origin of the logical timeline. -Knowing the start time of the application is necessary to -convert this to an absolute Instant (see Self::to_logical_time).
-microstep: MicroStep
The microstep of this tag.
-Returns the logical instant for this tag, using the
-initial time t0
.
Returns the amount of time elapsed since the start -of the app.
- -assert_eq!(tag1.duration_since_start(), tag1.to_logical_time(t0) - t0)
self
and other
) and is used by the <=
-operator. Read morekey
and return true
if they are equal.pub struct Instant(_);
A measurement of a monotonically nondecreasing clock. +
pub struct Instant(/* private fields */);
A measurement of a monotonically nondecreasing clock.
Opaque and useful only with Duration
.
Instants are always guaranteed, barring platform bugs, to be no less than any previously measured instant when created, and are often useful for tasks such as measuring @@ -7,7 +8,9 @@ words, each tick of the underlying clock might not be the same length (e.g. some seconds may be longer than others). An instant may jump forwards or experience time dilation (slow down or speed up), but it will never go -backwards.
+backwards. +As part of this non-guarantee it is also not specified whether system suspends count as +elapsed time or not. The behavior varies across platforms and rust versions.Instants are opaque types that can only be compared to one another. There is no method to get “the number of seconds” from an instant. Instead, it only allows measuring the duration between two instants (or comparing two @@ -24,8 +27,8 @@ // we sleep for 2 seconds sleep(Duration::new(2, 0)); - // it prints '2' - println!("{}", now.elapsed().as_secs()); + // it prints '2' + println!("{}", now.elapsed().as_secs()); }
An Instant
is a wrapper around system-specific types and it may behave
@@ -37,17 +40,17 @@
The following system calls are currently being used by now()
to find out
+
The following system calls are currently being used by now()
to find out
the current time:
Platform | System call |
---|---|
SGX | insecure_time usercall. More information on timekeeping in SGX |
UNIX | clock_gettime (Monotonic Clock) |
Darwin | mach_absolute_time |
Darwin | clock_gettime (Monotonic Clock) |
VXWorks | clock_gettime (Monotonic Clock) |
SOLID | get_tim |
WASI | __wasi_clock_time_get (Monotonic Clock) |
WASI | __wasi_clock_time_get (Monotonic Clock) |
Windows | QueryPerformanceCounter |
Instant
s are subtracted in the wrong order.
This workaround obscures programming errors where earlier and later instants are accidentally swapped. For this reason future rust versions may reintroduce panics.
-Returns an instant corresponding to “now”.
use std::time::Instant;
let now = Instant::now();
Returns the amount of time elapsed from another instant to this one, +
Returns the amount of time elapsed from another instant to this one, or zero duration if that instant is later than this one.
Previous rust versions panicked when earlier
was later than self
. Currently this
@@ -84,9 +87,9 @@
Returns the amount of time elapsed from another instant to this one, +println!("{:?}", new_now.duration_since(now)); +println!("{:?}", now.duration_since(new_now)); // 0ns
Returns the amount of time elapsed from another instant to this one, or None if that instant is later than this one.
Due to monotonicity bugs, even under correct logical ordering of the passed Instant
s,
this method can return None
.
Returns the amount of time elapsed from another instant to this one, +println!("{:?}", new_now.checked_duration_since(now)); +println!("{:?}", now.checked_duration_since(new_now)); // None
Returns the amount of time elapsed from another instant to this one, or zero duration if that instant is later than this one.
use std::time::{Duration, Instant};
@@ -108,9 +111,9 @@ Examples
let now = Instant::now();
sleep(Duration::new(1, 0));
let new_now = Instant::now();
-println!("{:?}", new_now.saturating_duration_since(now));
-println!("{:?}", now.saturating_duration_since(new_now)); // 0ns
Returns the amount of time elapsed since this instant.
+println!("{:?}", new_now.saturating_duration_since(now)); +println!("{:?}", now.saturating_duration_since(new_now)); // 0nsReturns the amount of time elapsed since this instant.
Previous rust versions panicked when the current time was earlier than self. Currently this method returns a Duration of zero in that case. Future versions may reintroduce the panic. @@ -123,43 +126,47 @@
Returns Some(t)
where t
is the time self + duration
if t
can be represented as
+
Returns Some(t)
where t
is the time self + duration
if t
can be represented as
Instant
(which means it’s inside the bounds of the underlying data structure), None
otherwise.
Returns Some(t)
where t
is the time self - duration
if t
can be represented as
+
Returns Some(t)
where t
is the time self - duration
if t
can be represented as
Instant
(which means it’s inside the bounds of the underlying data structure), None
otherwise.
+=
operation. Read moreself
and other
) and is used by the <=
-operator. Read more+=
operation. Read moreself
and other
) and is used by the <=
+operator. Read moreReturns the amount of time elapsed from another instant to this one, or zero duration if that instant is later than this one.
-Previous rust versions panicked when other
was later than self
. Currently this
method saturates. Future versions may reintroduce the panic in some circumstances.
See Monotonicity.
-=
operation. Read morekey
and return true
if they are equal.-=
operation. Read morekey
and return true
if they are equal.From<T> for U
chooses to do.
+pub struct LogicalAction<T: Sync>(_);
A logical action.
-pub struct Multiport<T: Sync> { /* private fields */ }
A multiport is a vector of independent ports (its channels) -Multiports have special Lingua Franca syntax, similar to reactor banks.
-Iterate over the multiport and return mutable references to individual channels.
-Iterate over the channels of this multiport. Returns read-only -references to individual ports.
-Iterate over only those channels that are set (have a value). -Returns a tuple with their index (not necessarily contiguous).
-Iterate over only those channels that are set (have a value). -The returned ports are not necessarily contiguous. See -Self::enumerate_set to get access to their index.
-Iterate over only those channels that are set (have a value), -and return a copy of the value. -The returned ports are not necessarily contiguous. See -Self::enumerate_values to get access to their index.
-Iterate over only those ports that are set (have a value), -and return a reference to the value. -The returned ports are not necessarily contiguous. See -Self::enumerate_values to get access to their index.
-Iterate over only those channels that are set (have a value), -yielding a tuple with their index in the bank and a copy of the value.
-Iterate over only those channels that are set (have a value), -yielding a tuple with their index in the bank and a reference to the value.
-pub struct PhysicalActionRef<T: Sync>(_);
A reference to a physical action. This thing is cloneable -and can be sent to async threads. The contained action -reference is unique and protected by a lock. All operations -on the action are
- -source
. Read morepub struct Port<T: Sync> { /* private fields */ }
Represents a port, which carries values of type T
.
-Ports reify the data inputs and outputs of a reactor.
They may be bound to another port, in which case the -upstream port forwards all values to the output port -(logically instantaneously). A port may have only one -upstream binding.
-Output ports may also be explicitly set -within a reaction, in which case they may not have an -upstream port binding.
-Those structural constraints are trusted to have been -verified by the code generator. If necessary we may be -able to add conditional compilation flags that enable -runtime checks.
-pub struct ReactionCtx<'a, 'x> { /* private fields */ }
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.
-Returns the start time of the execution of this program.
-This is a logical instant with microstep zero.
-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.
-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.
-Returns the tag at which the reaction executes.
-Repeated invocation of this method will always produce -the same value.
-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.
-Returns the amount of logical time elapsed since the -start of the program. This does not take microsteps -into account.
-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.
-Returns the number of active workers in the execution of -a reactor program.
-Return values:
-1
if threading is not enabled.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.
-if let Some(value) = ctx.get(port) {
- // branch is taken if the port is set
-}
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.
if let Some(value) = ctx.get_ref(port) {
- // value is a ref to the internal value
-}
Executes the provided closure on the value of the port -or action. The value is fetched by reference and not -copied.
-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.
-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.
-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.
-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);
-}
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).
-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.
-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 previous
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.
-// 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);
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.
-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();
- });
-}
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));
pub struct Timer {
- pub offset: Duration,
- pub period: Duration,
- /* private fields */
-}
A timer is conceptually a logical action that may re-schedule -itself periodically.
-For periodic timers, a reaction is synthesized which reschedules -the timer.
-offset: Duration
Minimal duration after the start of the program after -which the timer starts to trigger.
-period: Duration
Period between events emitted by this timer. A period -of zero means that the timer will trigger exactly once -after the specified offset.
-pub type unit = ();
Alias for the unit type, so that it can be written without quotes in LF. +
pub type unit = ();
Alias for the unit type, so that it can be written without quotes in LF.
Otherwise it needs to be written {= () =}
.
It is not camel-case as it is actually a primitive type.
Redirecting to ../../../reactor_rt/prelude/struct.AsyncCtx.html...
- +Redirecting to ../../../reactor_rt/struct.AsyncCtx.html...
+ \ No newline at end of file diff --git a/reactor_rt/scheduler/context/struct.ReactionCtx.html b/reactor_rt/scheduler/context/struct.ReactionCtx.html index bde46e02..005fda69 100644 --- a/reactor_rt/scheduler/context/struct.ReactionCtx.html +++ b/reactor_rt/scheduler/context/struct.ReactionCtx.html @@ -1,11 +1,11 @@ - +Redirecting to ../../../reactor_rt/prelude/struct.ReactionCtx.html...
- +Redirecting to ../../../reactor_rt/struct.ReactionCtx.html...
+ \ No newline at end of file diff --git a/reactor_rt/scheduler/events/struct.EventTag.html b/reactor_rt/scheduler/events/struct.EventTag.html index 21b28b0f..1159f3c4 100644 --- a/reactor_rt/scheduler/events/struct.EventTag.html +++ b/reactor_rt/scheduler/events/struct.EventTag.html @@ -1,11 +1,11 @@ - +Redirecting to ../../../reactor_rt/prelude/struct.EventTag.html...
- +Redirecting to ../../../reactor_rt/struct.EventTag.html...
+ \ No newline at end of file diff --git a/reactor_rt/struct.AsyncCtx.html b/reactor_rt/struct.AsyncCtx.html index fa224c05..0caba0ee 100644 --- a/reactor_rt/struct.AsyncCtx.html +++ b/reactor_rt/struct.AsyncCtx.html @@ -1,11 +1,12 @@ -pub struct AsyncCtx { /* private fields */ }
A type that can affect the logical event queue to implement +
pub struct AsyncCtx { /* private fields */ }
A type that can affect the logical event queue to implement asynchronous physical actions. This is a “link” to the event system, from the outside world.
- -Returns true if the scheduler has been shutdown. When +
+Returns true if the scheduler has been shutdown. When that’s true, calls to other methods of this type will fail with [SendError].
-Request that the application shutdown, possibly with +
Request that the application shutdown, possibly with a particular offset from the current physical time.
This may fail if this is called while the scheduler has already been shutdown. An Ok result is also not @@ -13,11 +14,11 @@ scheduler may be in the process of shutting down, or its shutdown might be programmed for a logical time which precedes the current physical time.
-Schedule an action to run after its own implicit time delay +) -> Result<(), SendError<Option<T>>>
Schedule an action to run after its own implicit time delay plus an optional additional time delay. These delays are in logical time.
Note that this locks the action.
@@ -27,12 +28,12 @@ scheduler may be in the process of shutting down, or its shutdown might be programmed for a logical time which precedes the current physical time. -Schedule an action to run after its own implicit time delay +) -> Result<(), SendError<Option<T>>>
Schedule an action to run after its own implicit time delay plus an optional additional time delay. These delays are in logical time.
Note that this locks the action.
@@ -42,15 +43,15 @@ scheduler may be in the process of shutting down, or its shutdown might be programmed for a logical time which precedes the current physical time. -From<T> for U
chooses to do.
+pub struct Duration { /* private fields */ }
A Duration
type to represent a span of time, typically used for system
+
pub struct Duration { /* private fields */ }
A Duration
type to represent a span of time, typically used for system
timeouts.
Each Duration
is composed of a whole number of seconds and a fractional part
represented in nanoseconds. If the underlying system does not support
nanosecond-level precision, APIs binding a system timeout will typically round up
the number of nanoseconds.
Duration
s implement many common traits, including Add
, Sub
, and other
-ops
traits. It implements Default
by returning a zero-length Duration
.
Duration
s implement many common traits, including Add
, Sub
, and other
+ops
traits. It implements Default
by returning a zero-length Duration
.
use std::time::Duration;
@@ -24,38 +25,38 @@ Format
program output may appear in contexts that cannot rely on full Unicode
compatibility, you may wish to format Duration
objects yourself or use a
crate to do so.
-
duration_constants
)The duration of one second.
+duration_constants
)The duration of one second.
#![feature(duration_constants)]
use std::time::Duration;
assert_eq!(Duration::SECOND, Duration::from_secs(1));
duration_constants
)The duration of one millisecond.
+duration_constants
)The duration of one millisecond.
#![feature(duration_constants)]
use std::time::Duration;
assert_eq!(Duration::MILLISECOND, Duration::from_millis(1));
duration_constants
)The duration of one microsecond.
+duration_constants
)The duration of one microsecond.
#![feature(duration_constants)]
use std::time::Duration;
assert_eq!(Duration::MICROSECOND, Duration::from_micros(1));
duration_constants
)The duration of one nanosecond.
+duration_constants
)The duration of one nanosecond.
#![feature(duration_constants)]
use std::time::Duration;
assert_eq!(Duration::NANOSECOND, Duration::from_nanos(1));
A duration of zero time.
use std::time::Duration;
let duration = Duration::ZERO;
assert!(duration.is_zero());
assert_eq!(duration.as_nanos(), 0);
The maximum duration.
+The maximum duration.
May vary by platform as necessary. Must be able to contain the difference between
two instances of Instant
or two instances of SystemTime
.
This constraint gives it a value of about 584,942,417,355 years in practice,
@@ -64,7 +65,7 @@
use std::time::Duration;
assert_eq!(Duration::MAX, Duration::new(u64::MAX, 1_000_000_000 - 1));
Creates a new Duration
from the specified number of whole seconds and
+
Creates a new Duration
from the specified number of whole seconds and
additional nanoseconds.
If the number of nanoseconds is greater than 1 billion (the number of nanoseconds in a second), then it will carry over into the seconds provided.
@@ -75,7 +76,7 @@use std::time::Duration;
let five_seconds = Duration::new(5, 0);
Creates a new Duration
from the specified number of whole seconds.
Creates a new Duration
from the specified number of milliseconds.
Creates a new Duration
from the specified number of microseconds.
Creates a new Duration
from the specified number of nanoseconds.
Returns true if this Duration
spans no time.
Returns the number of whole seconds contained by this Duration
.
Returns the number of whole seconds contained by this Duration
.
The returned value does not include the fractional (nanosecond) part of the
duration, which can be obtained using subsec_nanos
.
To determine the total number of seconds represented by the Duration
including the fractional part, use as_secs_f64
or as_secs_f32
Returns the fractional part of this Duration
, in whole milliseconds.
Returns the fractional part of this Duration
, in whole milliseconds.
This method does not return the length of the duration when represented by milliseconds. The returned number always represents a fractional portion of a second (i.e., it is less than one thousand).
@@ -139,7 +140,7 @@Returns the fractional part of this Duration
, in whole microseconds.
Returns the fractional part of this Duration
, in whole microseconds.
This method does not return the length of the duration when represented by microseconds. The returned number always represents a fractional portion of a second (i.e., it is less than one million).
@@ -149,7 +150,7 @@Returns the fractional part of this Duration
, in nanoseconds.
Returns the fractional part of this Duration
, in nanoseconds.
This method does not return the length of the duration when represented by nanoseconds. The returned number always represents a fractional portion of a second (i.e., it is less than one billion).
@@ -159,77 +160,86 @@Returns the total number of whole milliseconds contained by this Duration
.
Returns the total number of whole milliseconds contained by this Duration
.
use std::time::Duration;
let duration = Duration::new(5, 730023852);
assert_eq!(duration.as_millis(), 5730);
Returns the total number of whole microseconds contained by this Duration
.
Returns the total number of whole microseconds contained by this Duration
.
use std::time::Duration;
let duration = Duration::new(5, 730023852);
assert_eq!(duration.as_micros(), 5730023);
Returns the total number of nanoseconds contained by this Duration
.
Returns the total number of nanoseconds contained by this Duration
.
use std::time::Duration;
let duration = Duration::new(5, 730023852);
assert_eq!(duration.as_nanos(), 5730023852);
Checked Duration
addition. Computes self + other
, returning None
-if overflow occurred.
duration_abs_diff
)Computes the absolute difference between self
and other
.
Basic usage:
+#![feature(duration_abs_diff)]
+use std::time::Duration;
+
+assert_eq!(Duration::new(100, 0).abs_diff(Duration::new(80, 0)), Duration::new(20, 0));
+assert_eq!(Duration::new(100, 400_000_000).abs_diff(Duration::new(110, 0)), Duration::new(9, 600_000_000));
Checked Duration
addition. Computes self + other
, returning None
+if overflow occurred.
Basic usage:
+use std::time::Duration;
assert_eq!(Duration::new(0, 0).checked_add(Duration::new(0, 1)), Some(Duration::new(0, 1)));
assert_eq!(Duration::new(1, 0).checked_add(Duration::new(u64::MAX, 0)), None);
Saturating Duration
addition. Computes self + other
, returning Duration::MAX
+
Saturating Duration
addition. Computes self + other
, returning Duration::MAX
if overflow occurred.
#![feature(duration_constants)]
use std::time::Duration;
assert_eq!(Duration::new(0, 0).saturating_add(Duration::new(0, 1)), Duration::new(0, 1));
assert_eq!(Duration::new(1, 0).saturating_add(Duration::new(u64::MAX, 0)), Duration::MAX);
Checked Duration
subtraction. Computes self - other
, returning None
+
Checked Duration
subtraction. Computes self - other
, returning None
if the result would be negative or if overflow occurred.
Basic usage:
use std::time::Duration;
assert_eq!(Duration::new(0, 1).checked_sub(Duration::new(0, 0)), Some(Duration::new(0, 1)));
assert_eq!(Duration::new(0, 0).checked_sub(Duration::new(0, 1)), None);
Saturating Duration
subtraction. Computes self - other
, returning Duration::ZERO
+
Saturating Duration
subtraction. Computes self - other
, returning Duration::ZERO
if the result would be negative or if overflow occurred.
use std::time::Duration;
assert_eq!(Duration::new(0, 1).saturating_sub(Duration::new(0, 0)), Duration::new(0, 1));
assert_eq!(Duration::new(0, 0).saturating_sub(Duration::new(0, 1)), Duration::ZERO);
Saturating Duration
multiplication. Computes self * other
, returning
+
Saturating Duration
multiplication. Computes self * other
, returning
Duration::MAX
if overflow occurred.
#![feature(duration_constants)]
use std::time::Duration;
assert_eq!(Duration::new(0, 500_000_001).saturating_mul(2), Duration::new(1, 2));
assert_eq!(Duration::new(u64::MAX - 1, 0).saturating_mul(2), Duration::MAX);
Checked Duration
division. Computes self / other
, returning None
+
Checked Duration
division. Computes self / other
, returning None
if other == 0
.
Basic usage:
use std::time::Duration;
@@ -237,25 +247,25 @@ Examples
assert_eq!(Duration::new(2, 0).checked_div(2), Some(Duration::new(1, 0)));
assert_eq!(Duration::new(1, 0).checked_div(2), Some(Duration::new(0, 500_000_000)));
assert_eq!(Duration::new(2, 0).checked_div(0), None);
Returns the number of seconds contained by this Duration
as f64
.
Returns the number of seconds contained by this Duration
as f32
.
Creates a new Duration
from the specified number of seconds represented
+
Creates a new Duration
from the specified number of seconds represented
as f64
.
This constructor will panic if secs
is negative, overflows Duration
or not finite.
use std::time::Duration;
let res = Duration::from_secs_f64(0.0);
@@ -274,11 +284,11 @@ Examples
// conversion uses rounding
let res = Duration::from_secs_f64(0.999e-9);
assert_eq!(res, Duration::new(0, 1));
Creates a new Duration
from the specified number of seconds represented
+
Creates a new Duration
from the specified number of seconds represented
as f32
.
This constructor will panic if secs
is negative, overflows Duration
or not finite.
use std::time::Duration;
let res = Duration::from_secs_f32(0.0);
@@ -297,37 +307,37 @@ Examples
// conversion uses rounding
let res = Duration::from_secs_f32(0.999e-9);
assert_eq!(res, Duration::new(0, 1));
Multiplies Duration
by f64
.
Multiplies Duration
by f64
.
This method will panic if result is negative, overflows Duration
or not finite.
use std::time::Duration;
let dur = Duration::new(2, 700_000_000);
assert_eq!(dur.mul_f64(3.14), Duration::new(8, 478_000_000));
assert_eq!(dur.mul_f64(3.14e5), Duration::new(847_800, 0));
Multiplies Duration
by f32
.
Multiplies Duration
by f32
.
This method will panic if result is negative, overflows Duration
or not finite.
use std::time::Duration;
let dur = Duration::new(2, 700_000_000);
assert_eq!(dur.mul_f32(3.14), Duration::new(8, 478_000_641));
assert_eq!(dur.mul_f32(3.14e5), Duration::new(847800, 0));
Divide Duration
by f64
.
Divide Duration
by f64
.
This method will panic if result is negative, overflows Duration
or not finite.
use std::time::Duration;
let dur = Duration::new(2, 700_000_000);
assert_eq!(dur.div_f64(3.14), Duration::new(0, 859_872_611));
assert_eq!(dur.div_f64(3.14e5), Duration::new(0, 8_599));
Divide Duration
by f32
.
Divide Duration
by f32
.
This method will panic if result is negative, overflows Duration
or not finite.
use std::time::Duration;
let dur = Duration::new(2, 700_000_000);
@@ -335,25 +345,25 @@ Examples
// different from 0.859_872_611
assert_eq!(dur.div_f32(3.14), Duration::new(0, 859_872_580));
assert_eq!(dur.div_f32(3.14e5), Duration::new(0, 8_599));
div_duration
)Divide Duration
by Duration
and return f64
.
div_duration
)Divide Duration
by Duration
and return f64
.
#![feature(div_duration)]
use std::time::Duration;
let dur1 = Duration::new(2, 700_000_000);
let dur2 = Duration::new(5, 400_000_000);
assert_eq!(dur1.div_duration_f64(dur2), 0.5);
div_duration
)Divide Duration
by Duration
and return f32
.
div_duration
)Divide Duration
by Duration
and return f32
.
#![feature(div_duration)]
use std::time::Duration;
let dur1 = Duration::new(2, 700_000_000);
let dur2 = Duration::new(5, 400_000_000);
assert_eq!(dur1.div_duration_f32(dur2), 0.5);
The checked version of from_secs_f32
.
The checked version of from_secs_f32
.
This constructor will return an Err
if secs
is negative, overflows Duration
or not finite.
use std::time::Duration;
let res = Duration::try_from_secs_f32(0.0);
@@ -400,9 +410,9 @@ Examples
let val = f32::from_bits(0x3F806000);
let res = Duration::try_from_secs_f32(val);
assert_eq!(res, Ok(Duration::new(1, 2_929_688)));
The checked version of from_secs_f64
.
The checked version of from_secs_f64
.
This constructor will return an Err
if secs
is negative, overflows Duration
or not finite.
use std::time::Duration;
let res = Duration::try_from_secs_f64(0.0);
@@ -457,36 +467,40 @@ Examples
let val = f64::from_bits(0x3_FF00_C000_0000_000);
let res = Duration::try_from_secs_f64(val);
assert_eq!(res, Ok(Duration::new(1, 2_929_688)));
+=
operation. Read more+=
operation. Read more/=
operation. Read more*=
operation. Read moreself
and other
) and is used by the <=
-operator. Read more-=
operation. Read more-=
operation. Read morekey
and return true
if they are equal.+=
operation. Read more+=
operation. Read more/=
operation. Read more*=
operation. Read moreself
and other
) and is used by the <=
+operator. Read more-=
operation. Read more-=
operation. Read morekey
and return true
if they are equal.From<T> for U
chooses to do.
+pub struct EventTag {
+EventTag in reactor_rt - Rust
+ Struct reactor_rt::EventTag
source · pub struct EventTag {
pub offset_from_t0: Duration,
pub microstep: MicroStep,
}
Expand description
The tag of an event.
@@ -9,42 +10,46 @@
of the tag.
Use the tag! macro to create this struct with
convenient syntax.
-Fields§
§offset_from_t0: Duration
The time offset from the origin of the logical timeline.
+
Fields§
§offset_from_t0: Duration
The time offset from the origin of the logical timeline.
Knowing the start time of the application is necessary to
-convert this to an absolute Instant (see Self::to_logical_time).
-§microstep: MicroStep
The microstep of this tag.
-Implementations§
source§impl EventTag
sourcepub fn to_logical_time(&self, t0: Instant) -> Instant
Returns the logical instant for this tag, using the
+convert this to an absolute Instant (see Self::to_logical_time).
+§microstep: MicroStep
The microstep of this tag.
+Implementations§
source§impl EventTag
sourcepub fn to_logical_time(&self, t0: Instant) -> Instant
Returns the logical instant for this tag, using the
initial time t0
.
-sourcepub fn duration_since_start(&self) -> Duration
Returns the amount of time elapsed since the start
+
sourcepub fn duration_since_start(&self) -> Duration
Returns the amount of time elapsed since the start
of the app.
assert_eq!(tag1.duration_since_start(), tag1.to_logical_time(t0) - t0)
-Trait Implementations§
source§impl Ord for EventTag
1.21.0 · source§fn max(self, other: Self) -> Selfwhere
- Self: Sized,
Compares and returns the maximum of two values. Read moresource§impl PartialEq<EventTag> for EventTag
source§impl PartialOrd<EventTag> for EventTag
1.0.0 · source§fn le(&self, other: &Rhs) -> bool
This method tests less than or equal to (for self
and other
) and is used by the <=
-operator. Read moresource§impl Copy for EventTag
source§impl Eq for EventTag
source§impl StructuralEq for EventTag
source§impl StructuralPartialEq for EventTag
Auto Trait Implementations§
§impl RefUnwindSafe for EventTag
§impl Send for EventTag
§impl Sync for EventTag
§impl Unpin for EventTag
§impl UnwindSafe for EventTag
Blanket Implementations§
source§impl<Q, K> Equivalent<K> for Qwhere
- Q: Eq + ?Sized,
- K: Borrow<Q> + ?Sized,
source§fn equivalent(&self, key: &K) -> bool
Compare self to key
and return true
if they are equal.Trait Implementations§
source§impl Ord for EventTag
1.21.0 · source§fn max(self, other: Self) -> Selfwhere
+ Self: Sized,
Compares and returns the maximum of two values. Read moresource§impl PartialEq for EventTag
source§impl PartialOrd for EventTag
1.0.0 · source§fn le(&self, other: &Rhs) -> bool
This method tests less than or equal to (for self
and other
) and is used by the <=
+operator. Read moresource§impl Copy for EventTag
source§impl Eq for EventTag
source§impl StructuralEq for EventTag
source§impl StructuralPartialEq for EventTag
Auto Trait Implementations§
§impl RefUnwindSafe for EventTag
§impl Send for EventTag
§impl Sync for EventTag
§impl Unpin for EventTag
§impl UnwindSafe for EventTag
Blanket Implementations§
source§impl<T> BorrowMut<T> for Twhere
+ T: ?Sized,
source§fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more§impl<Q, K> Comparable<K> for Q
§impl<Q, K> Equivalent<K> for Q
§fn equivalent(&self, key: &K) -> bool
Checks if this value is equivalent to the given key. Read more§impl<Q, K> Equivalent<K> for Q
§fn equivalent(&self, key: &K) -> bool
Compare self to key
and return true
if they are equal.source§impl<N> NodeTrait for Nwhere
- N: Copy + Ord + Hash,
\ No newline at end of file
+From<T> for U
chooses to do.
+source§impl<N> NodeTrait for N
pub struct GlobalReactionId(_);
Global identifier for a reaction.
-source
. Read moreself
and other
values to be equal, and is used
-by ==
.self
and other
) and is used by the <=
-operator. Read morekey
and return true
if they are equal.Calls U::from(self)
.
pub struct GlobalReactionId(/* private fields */);
Global identifier for a reaction.
+source
. Read moreself
and other
values to be equal, and is used
+by ==
.self
and other
) and is used by the <=
+operator. Read morekey
and return true
if they are equal.From<T> for U
chooses to do.
+pub struct Instant(_);
A measurement of a monotonically nondecreasing clock. +
pub struct Instant(/* private fields */);
A measurement of a monotonically nondecreasing clock.
Opaque and useful only with Duration
.
Instants are always guaranteed, barring platform bugs, to be no less than any previously measured instant when created, and are often useful for tasks such as measuring @@ -7,7 +8,9 @@ words, each tick of the underlying clock might not be the same length (e.g. some seconds may be longer than others). An instant may jump forwards or experience time dilation (slow down or speed up), but it will never go -backwards.
+backwards. +As part of this non-guarantee it is also not specified whether system suspends count as +elapsed time or not. The behavior varies across platforms and rust versions.Instants are opaque types that can only be compared to one another. There is no method to get “the number of seconds” from an instant. Instead, it only allows measuring the duration between two instants (or comparing two @@ -24,8 +27,8 @@ // we sleep for 2 seconds sleep(Duration::new(2, 0)); - // it prints '2' - println!("{}", now.elapsed().as_secs()); + // it prints '2' + println!("{}", now.elapsed().as_secs()); }
An Instant
is a wrapper around system-specific types and it may behave
@@ -37,17 +40,17 @@
The following system calls are currently being used by now()
to find out
+
The following system calls are currently being used by now()
to find out
the current time:
Platform | System call |
---|---|
SGX | insecure_time usercall. More information on timekeeping in SGX |
UNIX | clock_gettime (Monotonic Clock) |
Darwin | mach_absolute_time |
Darwin | clock_gettime (Monotonic Clock) |
VXWorks | clock_gettime (Monotonic Clock) |
SOLID | get_tim |
WASI | __wasi_clock_time_get (Monotonic Clock) |
WASI | __wasi_clock_time_get (Monotonic Clock) |
Windows | QueryPerformanceCounter |
Instant
s are subtracted in the wrong order.
This workaround obscures programming errors where earlier and later instants are accidentally swapped. For this reason future rust versions may reintroduce panics.
-Returns an instant corresponding to “now”.
use std::time::Instant;
let now = Instant::now();
Returns the amount of time elapsed from another instant to this one, +
Returns the amount of time elapsed from another instant to this one, or zero duration if that instant is later than this one.
Previous rust versions panicked when earlier
was later than self
. Currently this
@@ -84,9 +87,9 @@
Returns the amount of time elapsed from another instant to this one, +println!("{:?}", new_now.duration_since(now)); +println!("{:?}", now.duration_since(new_now)); // 0ns
Returns the amount of time elapsed from another instant to this one, or None if that instant is later than this one.
Due to monotonicity bugs, even under correct logical ordering of the passed Instant
s,
this method can return None
.
Returns the amount of time elapsed from another instant to this one, +println!("{:?}", new_now.checked_duration_since(now)); +println!("{:?}", now.checked_duration_since(new_now)); // None
Returns the amount of time elapsed from another instant to this one, or zero duration if that instant is later than this one.
use std::time::{Duration, Instant};
@@ -108,9 +111,9 @@ Examples
let now = Instant::now();
sleep(Duration::new(1, 0));
let new_now = Instant::now();
-println!("{:?}", new_now.saturating_duration_since(now));
-println!("{:?}", now.saturating_duration_since(new_now)); // 0ns
Returns the amount of time elapsed since this instant.
+println!("{:?}", new_now.saturating_duration_since(now)); +println!("{:?}", now.saturating_duration_since(new_now)); // 0nsReturns the amount of time elapsed since this instant.
Previous rust versions panicked when the current time was earlier than self. Currently this method returns a Duration of zero in that case. Future versions may reintroduce the panic. @@ -123,43 +126,47 @@
Returns Some(t)
where t
is the time self + duration
if t
can be represented as
+
Returns Some(t)
where t
is the time self + duration
if t
can be represented as
Instant
(which means it’s inside the bounds of the underlying data structure), None
otherwise.
Returns Some(t)
where t
is the time self - duration
if t
can be represented as
+
Returns Some(t)
where t
is the time self - duration
if t
can be represented as
Instant
(which means it’s inside the bounds of the underlying data structure), None
otherwise.
+=
operation. Read moreself
and other
) and is used by the <=
-operator. Read more+=
operation. Read moreself
and other
) and is used by the <=
+operator. Read moreReturns the amount of time elapsed from another instant to this one, or zero duration if that instant is later than this one.
-Previous rust versions panicked when other
was later than self
. Currently this
method saturates. Future versions may reintroduce the panic in some circumstances.
See Monotonicity.
-=
operation. Read morekey
and return true
if they are equal.-=
operation. Read morekey
and return true
if they are equal.From<T> for U
chooses to do.
+#[repr(transparent)]pub struct LocalReactionId(_);
ID of a reaction local to its containing reactor.
-source
. Read moreself
and other
values to be equal, and is used
-by ==
.self
and other
) and is used by the <=
-operator. Read morekey
and return true
if they are equal.pub struct LocalReactionId(/* private fields */);
ID of a reaction local to its containing reactor.
+source
. Read moreself
and other
values to be equal, and is used
+by ==
.self
and other
) and is used by the <=
+operator. Read morekey
and return true
if they are equal.From<T> for U
chooses to do.
+pub struct LogicalAction<T: Sync>(_);
A logical action.
-pub struct LogicalAction<T: Sync>(/* private fields */);
A logical action.
+From<T> for U
chooses to do.
+pub struct MicroStep(_);
Type of the microsteps of an EventTag.
-self
and other
) and is used by the <=
-operator. Read morekey
and return true
if they are equal.Calls U::from(self)
.
pub struct MicroStep(/* private fields */);
Type of the microsteps of an EventTag.
+self
and other
) and is used by the <=
+operator. Read morekey
and return true
if they are equal.From<T> for U
chooses to do.
+pub struct Multiport<T: Sync> { /* private fields */ }
A multiport is a vector of independent ports (its channels) +
pub struct Multiport<T: Sync> { /* private fields */ }
A multiport is a vector of independent ports (its channels) Multiports have special Lingua Franca syntax, similar to reactor banks.
-Iterate over the multiport and return mutable references to individual channels.
-Iterate over the channels of this multiport. Returns read-only +
Iterate over the multiport and return mutable references to individual channels.
+Iterate over the channels of this multiport. Returns read-only references to individual ports.
-Iterate over only those channels that are set (have a value). +
Iterate over only those channels that are set (have a value). Returns a tuple with their index (not necessarily contiguous).
-Iterate over only those channels that are set (have a value). +
Iterate over only those channels that are set (have a value). The returned ports are not necessarily contiguous. See -Self::enumerate_set to get access to their index.
-Iterate over only those channels that are set (have a value), +Self::enumerate_set to get access to their index.
+Iterate over only those channels that are set (have a value), and return a copy of the value. The returned ports are not necessarily contiguous. See -Self::enumerate_values to get access to their index.
-Iterate over only those ports that are set (have a value), +Self::enumerate_values to get access to their index.
+Iterate over only those ports that are set (have a value), and return a reference to the value. The returned ports are not necessarily contiguous. See -Self::enumerate_values to get access to their index.
-Iterate over only those channels that are set (have a value), +Self::enumerate_values to get access to their index.
+Iterate over only those channels that are set (have a value), yielding a tuple with their index in the bank and a copy of the value.
-Iterate over only those channels that are set (have a value), +
Iterate over only those channels that are set (have a value), yielding a tuple with their index in the bank and a reference to the value.
-From<T> for U
chooses to do.
+pub struct PhysicalAction<T: Sync>(_);
A physical action. Physical actions may only be used with -the API of AsyncCtx. -See ReactionCtx::spawn_physical_thread.
-Calls U::from(self)
.
pub struct PhysicalAction<T: Sync>(/* private fields */);
A physical action. Physical actions may only be used with +the API of AsyncCtx. +See ReactionCtx::spawn_physical_thread.
+From<T> for U
chooses to do.
+pub struct PhysicalActionRef<T: Sync>(_);
A reference to a physical action. This thing is cloneable +
pub struct PhysicalActionRef<T: Sync>(/* private fields */);
A reference to a physical action. This thing is cloneable and can be sent to async threads. The contained action reference is unique and protected by a lock. All operations on the action are
- -source
. Read moresource
. Read moreFrom<T> for U
chooses to do.
+pub struct Port<T: Sync> { /* private fields */ }
Represents a port, which carries values of type T
.
+
pub struct Port<T: Sync> { /* private fields */ }
Represents a port, which carries values of type T
.
Ports reify the data inputs and outputs of a reactor.
They may be bound to another port, in which case the upstream port forwards all values to the output port (logically instantaneously). A port may have only one upstream binding.
-Output ports may also be explicitly set +
Output ports may also be explicitly set within a reaction, in which case they may not have an upstream port binding.
Those structural constraints are trusted to have been verified by the code generator. If necessary we may be able to add conditional compilation flags that enable runtime checks.
-From<T> for U
chooses to do.
+pub struct ReactionCtx<'a, 'x> { /* private fields */ }
The context in which a reaction executes. Its API +
pub struct ReactionCtx<'a, 'x> { /* private fields */ }
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.
-Returns the start time of the execution of this program.
+Returns the start time of the execution of this program.
This is a logical instant with microstep zero.
-Returns the current physical time.
+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.
-Returns the current logical time.
+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.
-Returns the tag at which the reaction executes.
Repeated invocation of this method will always produce the same value.
-Returns whether this tag is the shutdown tag of the +
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.
-Returns the amount of logical time elapsed since the +
Returns the amount of logical time elapsed since the start of the program. This does not take microsteps into account.
-Returns the amount of physical time elapsed since the +
Returns the amount of physical time elapsed since the start of the program.
-Since this uses Self::get_physical_time, be aware that +
Since this uses Self::get_physical_time, be aware that this function’s result may change over time.
-Returns the number of active workers in the execution of +
Returns the number of active workers in the execution of a reactor program.
Return values:
Returns the current value of a port or action at this -logical time. If the value is absent, Option::None is +
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 +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.
if let Some(value) = ctx.get(port) {
// branch is taken if the port is set
}
Returns a reference to the current value of a port or action at this -logical time. If the value is absent, Option::None is +) -> 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).
+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.
if let Some(value) = ctx.get_ref(port) {
// value is a ref to the internal value
}
Executes the provided closure on the value of the port or action. The value is fetched by reference and not copied.
@@ -80,23 +81,23 @@See also the similar Self::use_ref_opt.
-See also the similar Self::use_ref_opt.
+Executes the provided closure on the value of the port, + 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.
-Sets the value of the given port.
+See also the similar Self::use_ref.
+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.
-Sets the value of the given port, if the given value is Some
.
+
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 @@ -109,10 +110,10 @@
Returns true if the given action was triggered at the +
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).
-This is like Self::schedule_with_v, where the value is None.
+This is like Self::schedule_with_v, where the value is None.
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 previous
Schedule an action to trigger at some point in the future,
The action will carry the given value at the time it @@ -138,21 +139,21 @@
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).
+(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.
// will be executed 2 milliseconds (+ own delay) from now with that value.
-ctx.schedule_with_v(action, Some("value"), after!(2 msec));
+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
+// that's equivalent to
ctx.schedule(action, Asap);
Spawn a new thread that can use a AsyncCtx +
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 @@ -161,7 +162,7 @@
fn some_reaction(ctx: &mut ReactionCtx, phys_action: &PhysicalActionRef<u32>) {
let phys_action = phys_action.clone(); // clone to move it into other thread
@@ -173,7 +174,7 @@ Example
link.schedule_physical_with_v(&phys_action, Some(123), Asap).unwrap();
});
}
Request that the application shutdown, possibly with +
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.
From<T> for U
chooses to do.
+#[repr(transparent)]pub struct ReactorId(_);
The unique identifier of a reactor instance during +
pub struct ReactorId(/* private fields */);
The unique identifier of a reactor instance during execution.
-self
and other
) and is used by the <=
-operator. Read morekey
and return true
if they are equal.self
and other
) and is used by the <=
+operator. Read morekey
and return true
if they are equal.From<T> for U
chooses to do.
+pub struct SchedulerOptions {
- pub keep_alive: bool,
- pub timeout: Option<Duration>,
- pub threads: usize,
- pub dump_graph: bool,
+SchedulerOptions in reactor_rt - Rust
+ Struct reactor_rt::SchedulerOptions
source · pub struct SchedulerOptions {
+ pub keep_alive: bool,
+ pub timeout: Option<Duration>,
+ pub threads: usize,
+ pub dump_graph: bool,
}
Expand description
Construction parameters for the scheduler.
LFC uses target properties to set them. With the “cli”
feature, generated programs also feature CLI options to
override the defaults at runtime.
-Fields§
§keep_alive: bool
If true, we won’t shut down the scheduler as soon as
+
Fields§
§keep_alive: bool
If true, we won’t shut down the scheduler as soon as
the event queue is empty, provided there are still
live threads that can send messages to the scheduler
asynchronously.
-§timeout: Option<Duration>
Timeout of reactor execution. If provided, the reactor
+
§timeout: Option<Duration>
Timeout of reactor execution. If provided, the reactor
program will be shut down at the latest at T0 + timeout
.
Calls to request_stop
may make the program terminate earlier.
-§threads: usize
Max number of threads to use in the thread pool.
+
§threads: usize
Max number of threads to use in the thread pool.
If zero, uses one thread per core. Ignored unless
building with feature parallel-runtime
.
-§dump_graph: bool
If true, dump the dependency graph to a file before
+
§dump_graph: bool
If true, dump the dependency graph to a file before
starting execution.
-Trait Implementations§
source§impl Default for SchedulerOptions
source§fn default() -> SchedulerOptions
Returns the “default value” for a type. Read moreAuto Trait Implementations§
§impl RefUnwindSafe for SchedulerOptions
§impl Send for SchedulerOptions
§impl Sync for SchedulerOptions
§impl Unpin for SchedulerOptions
§impl UnwindSafe for SchedulerOptions
Blanket Implementations§
source§impl<T, U> Into<U> for Twhere
- U: From<T>,
const: unstable · source§fn into(self) -> U
Calls U::from(self)
.
+Trait Implementations§
source§impl Default for SchedulerOptions
source§fn default() -> SchedulerOptions
Returns the “default value” for a type. Read moreAuto Trait Implementations§
§impl RefUnwindSafe for SchedulerOptions
§impl Send for SchedulerOptions
§impl Sync for SchedulerOptions
§impl Unpin for SchedulerOptions
§impl UnwindSafe for SchedulerOptions
Blanket Implementations§
source§impl<T> BorrowMut<T> for Twhere
+ T: ?Sized,
source§fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more
\ No newline at end of file
+From<T> for U
chooses to do.
+
pub struct SyncScheduler<'x> { /* private fields */ }
The runtime scheduler.
+pub struct SyncScheduler<'x> { /* private fields */ }
The runtime scheduler.
Lifetime parameters: ’x and ’t are carried around everywhere, ’x allows us to take references into the dataflow graph, and ’t to spawn new scoped threads for physical actions. ’a is more useless but is needed to compile.
-From<T> for U
chooses to do.
+pub struct Timer {
+Timer in reactor_rt - Rust
+ Struct reactor_rt::Timer
source · pub struct Timer {
pub offset: Duration,
pub period: Duration,
- /* private fields */
+ /* private fields */
}
Expand description
A timer is conceptually a logical action that may re-schedule
itself periodically.
For periodic timers, a reaction is synthesized which reschedules
the timer.
-Fields§
§offset: Duration
Minimal duration after the start of the program after
+
Fields§
§offset: Duration
Minimal duration after the start of the program after
which the timer starts to trigger.
-§period: Duration
Period between events emitted by this timer. A period
+
§period: Duration
Period between events emitted by this timer. A period
of zero means that the timer will trigger exactly once
after the specified offset.
-Implementations§
source§impl Timer
sourcepub fn is_periodic(&self) -> bool
Whether the timer should repeat itself. A period of zero
+
Implementations§
Trait Implementations§
source§impl ReactionTrigger<()> for Timer
Trait Implementations§
source§impl ReactionTrigger<()> for Timer
source§fn is_present(&self, now: &EventTag, _start: &Instant) -> bool
Returns whether the trigger is present, given that
+the current logical time is the parameter.source§fn get_value(&self, now: &EventTag, start: &Instant) -> Option<()>
Copies the value out, if it is present. Whether a value
is present is not in general the same thing as whether this trigger
-Self::is_present. See crate::ReactionCtx::get.source§fn use_value_ref<O>(
+Self::is_present. See crate::ReactionCtx::get.
source§fn use_value_ref<O>(
&self,
- now: &EventTag,
+ now: &EventTag,
start: &Instant,
- action: impl FnOnce(Option<&()>) -> O
+ action: impl FnOnce(Option<&()>) -> O
) -> O
Execute an action using the current value of this trigger.
-The closure is called even if the value is absent (with a None
-argument).Auto Trait Implementations§
§impl RefUnwindSafe for Timer
§impl Send for Timer
§impl Sync for Timer
§impl Unpin for Timer
§impl UnwindSafe for Timer
Blanket Implementations§
Auto Trait Implementations§
§impl RefUnwindSafe for Timer
§impl Send for Timer
§impl Sync for Timer
§impl Unpin for Timer
§impl UnwindSafe for Timer
Blanket Implementations§
source§impl<T> BorrowMut<T> for Twhere
+ T: ?Sized,
source§fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more
\ No newline at end of file
+From<T> for U
chooses to do.
+
Redirecting to ../../reactor_rt/prelude/struct.Timer.html...
- +Redirecting to ../../reactor_rt/struct.Timer.html...
+ \ No newline at end of file diff --git a/reactor_rt/trait.ReactionTrigger.html b/reactor_rt/trait.ReactionTrigger.html index 7f2eaf67..4a58d7f6 100644 --- a/reactor_rt/trait.ReactionTrigger.html +++ b/reactor_rt/trait.ReactionTrigger.html @@ -1,31 +1,32 @@ -pub trait ReactionTrigger<T> {
+ReactionTrigger in reactor_rt - Rust
+ Trait reactor_rt::ReactionTrigger
source · pub trait ReactionTrigger<T> {
// Required methods
- fn get_value(&self, now: &EventTag, start: &Instant) -> Option<T>
- where T: Copy;
+ fn get_value(&self, now: &EventTag, start: &Instant) -> Option<T>
+ where T: Copy;
fn use_value_ref<O>(
&self,
- now: &EventTag,
+ now: &EventTag,
start: &Instant,
- action: impl FnOnce(Option<&T>) -> O
+ action: impl FnOnce(Option<&T>) -> O
) -> O;
// Provided method
- fn is_present(&self, now: &EventTag, start: &Instant) -> bool { ... }
+ fn is_present(&self, now: &EventTag, start: &Instant) -> bool { ... }
}
Expand description
Common trait for actions, ports, and timer objects handed
to reaction functions. This is meant to be used through the
-API of ReactionCtx instead of directly.
-Required Methods§
sourcefn get_value(&self, now: &EventTag, start: &Instant) -> Option<T>where
- T: Copy,
Copies the value out, if it is present. Whether a value
+API of ReactionCtx instead of directly.
+Required Methods§
sourcefn get_value(&self, now: &EventTag, start: &Instant) -> Option<T>where
+ T: Copy,
Copies the value out, if it is present. Whether a value
is present is not in general the same thing as whether this trigger
-Self::is_present. See crate::ReactionCtx::get.
-sourcefn use_value_ref<O>(
+Self::is_present. See crate::ReactionCtx::get.
+
Provided Methods§
sourcefn is_present(&self, now: &EventTag, start: &Instant) -> bool
Returns whether the trigger is present, given that
+
Provided Methods§
sourcefn is_present(&self, now: &EventTag, start: &Instant) -> bool
Returns whether the trigger is present, given that
the current logical time is the parameter.
-Implementors§
source§impl ReactionTrigger<()> for Timer
source§impl<T: Sync> ReactionTrigger<T> for LogicalAction<T>
source§impl<T: Sync> ReactionTrigger<T> for PhysicalActionRef<T>
source§impl<T: Sync> ReactionTrigger<T> for Port<T>
\ No newline at end of file
+
pub trait ReactorBehavior {
+ReactorBehavior in reactor_rt - Rust
+ Trait reactor_rt::ReactorBehavior
source · pub trait ReactorBehavior {
// Required methods
fn id(&self) -> ReactorId;
- fn react(&mut self, ctx: &mut ReactionCtx<'_, '_>, local_rid: LocalReactionId);
+ fn react(
+ &mut self,
+ ctx: &mut ReactionCtx<'_, '_>,
+ local_rid: LocalReactionId
+ );
fn cleanup_tag(&mut self, ctx: &CleanupCtx);
}
Expand description
The trait used by the framework to interact with the reactor
during runtime.
Importantly, it’s object-safe and has no type parameters
or associated types. This allows us to wrap it into a
Box<dyn ReactorBehavior>
.
-Required Methods§
Required Methods§
sourcefn id(&self) -> ReactorId
The unique ID of this reactor. This is given by the
framework upon construction.
-sourcefn react(&mut self, ctx: &mut ReactionCtx<'_, '_>, local_rid: LocalReactionId)
Execute a single user-written reaction.
+
sourcefn react(&mut self, ctx: &mut ReactionCtx<'_, '_>, local_rid: LocalReactionId)
Execute a single user-written reaction.
Dispatches on the reaction id, and unpacks parameters,
which are the reactor components declared as fields of
this struct.
It must always be the case that local_rid < Self::MAX_REACTION_ID
,
where Self::MAX_REACTION_ID
is defined by the assembly::ReactorInitializer,
because of object safety.
-sourcefn cleanup_tag(&mut self, ctx: &CleanupCtx)
Acknowledge that the given tag is done executing and
+
sourcefn cleanup_tag(&mut self, ctx: &CleanupCtx)
Acknowledge that the given tag is done executing and
free resources if need be.
-Implementors§
\ No newline at end of file
+
pub trait SchedulableAsAction<T: Sync> { }
Implemented by LogicalAction and PhysicalAction references -to give access to ReactionCtx::schedule and variants.
-pub trait SchedulableAsAction<T: Sync> { }
Implemented by LogicalAction and PhysicalAction references +to give access to ReactionCtx::schedule and variants.
+Duration
type to represent a span of time, typically …","The tag of an event.","Global identifier for a reaction.","","A measurement of a monotonically nondecreasing clock. …","ID of a reaction local to its containing reactor.","A logical action.","The maximum duration.","","The duration of one microsecond.","","The duration of one millisecond.","","Type of the microsteps of an EventTag.","A multiport is a vector of independent ports (its channels)","","The duration of one nanosecond.","An offset from the current event.","A physical action. Physical actions may only be used with …","A reference to a physical action. This thing is cloneable …","Represents a port, which carries values of type T
. Ports …","The context in which a reaction executes. Its API allows …","Common trait for actions, ports, and timer objects handed …","The trait used by the framework to interact with the …","The unique identifier of a reactor instance during …","","The duration of one second.","Implemented by LogicalAction and PhysicalAction references …","Construction parameters for the scheduler.","The runtime scheduler.","A unit of time, used in LF.","A timer is conceptually a logical action that may …","","A duration of zero time.","","Panics","","","","Shorthand for using After together with delay.","Shorthand for using After together with delay.","Returns the total number of whole microseconds contained …","Returns the total number of whole milliseconds contained …","Returns the total number of nanoseconds contained by this …","Returns the number of whole seconds contained by this …","Returns the number of seconds contained by this Duration
…","Returns the number of seconds contained by this Duration
…","Module containing the API to initialize a reactor program.","Convenient macro to assert equality of the current tag. …","Convenient macro to assert equality of the current tag. …","","","","","","","","","","","","","","","","","","","","","Returns Some(t)
where t
is the time self + duration
if t
…","Checked Duration
addition. Computes self + other
, …","Checked Duration
division. Computes self / other
, …","Returns the amount of time elapsed from another instant to …","Checked Duration
multiplication. Computes self * other
, …","Returns Some(t)
where t
is the time self - duration
if t
…","Checked Duration
subtraction. Computes self - other
, …","Acknowledge that the given tag is done executing and free …","","","","","","","","","","","","","","","","","","","","Creates a Duration value using the same syntax as in LF.","Creates a Duration value using the same syntax as in LF.","","","Divide Duration
by Duration
and return f32
.","Divide Duration
by Duration
and return f64
.","Divide Duration
by f32
.","Divide Duration
by f64
.","If true, dump the dependency graph to a file before …","Returns the amount of time elapsed from another instant to …","Returns the amount of time elapsed since this instant.","","","","","","","","","","","","","","","","","","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Creates a new Duration
from the specified number of …","Creates a new Duration
from the specified number of …","Creates a new Duration
from the specified number of …","Creates a new Duration
from the specified number of whole …","Creates a new Duration
from the specified number of …","Creates a new Duration
from the specified number of …","","","","","","","Copies the value out, if it is present. Whether a value is …","","","","","","","The unique ID of this reactor. This is given by the …","","","","","","","Calls U::from(self)
.","Calls U::from(self)
.","Calls U::from(self)
.","Calls U::from(self)
.","Calls U::from(self)
.","Calls U::from(self)
.","Calls U::from(self)
.","Calls U::from(self)
.","Calls U::from(self)
.","Calls U::from(self)
.","Returns whether the trigger is present, given that the …","Returns whether the trigger is present, given that the …","Returns true if this Duration
spans no time.","If true, we won’t shut down the scheduler as soon as the …","The microstep of this tag.","","","Multiplies Duration
by f32
.","Multiplies Duration
by f64
.","","","","Creates a new Duration
from the specified number of whole …","Returns an instant corresponding to “now”.","Minimal duration after the start of the program after …","The time offset from the origin of the logical timeline. …","","","","","","Period between events emitted by this timer. A period of …","The prelude that is imported at the top of reactor files …","","","Execute a single user-written reaction. Dispatches on the …","","Saturating Duration
addition. Computes self + other
, …","Returns the amount of time elapsed from another instant to …","Saturating Duration
multiplication. Computes self * other
, …","Saturating Duration
subtraction. Computes self - other
, …","","Returns the amount of time elapsed from another instant to …","","","","Returns the fractional part of this Duration
, in whole …","Returns the fractional part of this Duration
, in whole …","Returns the fractional part of this Duration
, in …","","","Convenient macro to create a tag. This is just a shorthand …","Convenient macro to create a tag. This is just a shorthand …","Max number of threads to use in the thread pool. If zero, …","Timeout of reactor execution. If provided, the reactor …","","","","","","","","","","","","","","","","","","","This recognizes the same strings as LF","","","The checked version of from_secs_f32
.","The checked version of from_secs_f64
.","","","","","","","","","","","Parse a duration from a string. This is used for CLI …","","","","","","","","","","","Execute an action using the current value of this trigger. …","Helper struct to assemble reactors during initialization. …","An error occurring during initialization of the reactor …","Intermediate result of assembly.","","","","Creates the components of a reactor.","Declares dependencies between components and reactions.","Final result of the assembly of a reactor.","Global identifier for a reaction.","","Exclusive maximum value of the local_rid
parameter of […","","Type of the construction parameters.","Kind of a port.","Wrapper around the user struct for safe dispatch.","","","The ID of a trigger component.","Type of the user struct, which contains state variables of …","Assemble this reactor. This initializes state variables, …","top level function","Innermost function.","Bind two ports together.","","Bind the ports of the upstream to those of the downstream, …","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","","","","","","","","","","Calls U::from(self)
.","Calls U::from(self)
.","Calls U::from(self)
.","Calls U::from(self)
.","Calls U::from(self)
.","Calls U::from(self)
.","Calls U::from(self)
.","Calls U::from(self)
.","Calls U::from(self)
.","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Assembles a child reactor and makes it available in the …","Assembles a bank of children reactor and makes it …","A type that can affect the logical event queue to implement","A Duration
type to represent a span of time, typically …","The tag of an event.","A measurement of a monotonically nondecreasing clock. …","A logical action.","A multiport is a vector of independent ports (its channels)","The tag of the startup event.","A reference to a physical action. This thing is cloneable …","Represents a port, which carries values of type T
. Ports …","The context in which a reaction executes. Its API allows …","A timer is conceptually a logical action that may …","Shorthand for using After together with delay.","Convenient macro to assert equality of the current tag. …","","","","","","","","","","","","","","","","","","","","","","","","Creates a Duration value using the same syntax as in LF.","Returns the amount of time elapsed since the start of the …","Iterate over only those channels that are set (have a …","Iterate over only those channels that are set (have a …","Iterate over only those channels that are set (have a …","","","","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the current value of a port or action at this …","Returns the amount of logical time elapsed since the start …","Returns the amount of physical time elapsed since the …","Returns the current logical time.","Returns the current physical time.","Returns a reference to the current value of a port or …","Returns the start time of the execution of this program.","Returns the tag at which the reaction executes.","","","","","","","","Calls U::from(self)
.","Calls U::from(self)
.","Calls U::from(self)
.","Calls U::from(self)
.","Calls U::from(self)
.","Calls U::from(self)
.","Calls U::from(self)
.","Calls U::from(self)
.","","","Returns true if this multiport is empty.","Whether the timer should repeat itself. A period of zero …","","","Returns true if the given action was triggered at the …","","","Returns whether this tag is the shutdown tag of the …","Iterate over the channels of this multiport. Returns …","Iterate over the multiport and return mutable references …","Iterate over only those channels that are set (have a …","Iterate over only those channels that are set (have a …","Iterate over only those ports that are set (have a value), …","Returns the number of channels.","Returns the microstep of this tag.","The microstep of this tag.","Returns the number of active workers in the execution of a …","Create a new tag from its offset from t0 and a microstep. …","Minimal duration after the start of the program after …","The time offset from the origin of the logical timeline. …","","Period between events emitted by this timer. A period of …","Request that the application shutdown, possibly with a …","Request that the application shutdown, possibly with a …","Schedule an action to trigger at some point in the future. …","Schedule an action to run after its own implicit time delay","Schedule an action to run after its own implicit time delay","Schedule an action to trigger at some point in the future,","Sets the value of the given port.","Sets the value of the given port, if the given value is …","Spawn a new thread that can use a AsyncCtx to push …","Convenient macro to create a tag. This is just a shorthand …","Returns the logical instant for this tag, using the …","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Alias for the unit type, so that it can be written without …","Executes the provided closure on the value of the port or …","Executes the provided closure on the value of the port, …","","","","","Returns true if the scheduler has been shutdown. When that…"],"i":[12,12,0,18,0,0,0,18,0,0,0,4,18,4,18,4,18,0,0,18,4,0,0,0,0,0,0,0,0,18,4,0,0,0,0,0,1,4,1,3,4,3,4,0,0,4,4,4,4,4,4,0,0,0,54,55,10,11,12,14,1,18,3,4,54,55,10,11,12,14,1,18,3,4,3,4,4,3,4,3,4,56,10,11,12,1,3,4,10,11,12,1,3,4,10,11,1,3,4,14,4,0,0,4,4,4,4,4,4,14,3,3,10,11,12,1,3,4,10,11,12,1,3,4,10,10,11,11,12,1,1,18,3,4,54,55,10,11,12,14,1,18,3,4,4,4,4,4,4,4,10,11,10,11,10,11,57,10,11,12,1,3,4,56,10,10,11,11,10,11,54,55,10,11,12,14,1,18,3,4,57,57,4,14,23,4,4,4,4,10,11,1,4,3,48,23,10,11,1,3,4,48,0,10,11,56,55,4,3,4,4,3,3,4,3,4,4,4,4,4,4,0,0,14,14,18,10,11,12,1,3,4,10,11,1,54,55,10,11,12,14,1,18,18,3,4,4,4,54,55,10,11,12,14,1,18,3,4,0,54,55,10,11,12,14,1,18,3,4,57,0,0,0,0,41,41,0,0,0,0,41,35,41,35,0,0,40,40,0,35,35,31,31,36,36,36,31,32,34,36,43,46,39,40,41,31,32,34,36,43,46,39,40,41,39,40,41,39,40,41,39,40,36,36,36,36,39,40,41,39,40,41,39,39,40,41,31,32,34,36,43,46,39,40,41,40,40,40,39,40,41,40,40,40,31,32,34,36,43,46,39,40,41,39,43,43,43,43,43,39,40,39,40,41,39,31,32,34,36,43,46,39,40,41,31,32,34,36,43,46,39,40,41,31,32,34,36,43,46,39,40,41,31,31,0,0,0,0,0,0,23,0,0,0,0,0,0,45,37,42,25,48,47,50,23,45,37,42,25,48,47,50,23,47,50,23,47,50,23,23,0,23,42,42,42,23,23,23,23,45,37,42,25,48,47,50,23,25,25,25,25,25,25,25,25,45,37,48,47,23,42,42,45,37,42,25,48,47,50,23,42,42,42,48,45,37,25,48,47,25,42,42,42,42,42,42,23,23,25,23,48,23,23,48,25,50,25,50,50,25,25,25,25,0,23,47,50,23,23,45,37,42,25,48,47,50,23,45,37,42,25,48,47,50,23,45,37,42,25,48,47,50,23,0,25,25,45,37,48,47,50],"f":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[[1,2]],[[3,4],3],[[4,4],4],[[3,4]],[[4,4]],0,0,[4,5],[4,5],[4,5],[4,6],[4,7],[4,8],0,0,0,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[3,4],[[9,[3]]]],[[4,4],[[9,[4]]]],[[4,2],[[9,[4]]]],[[3,3],[[9,[4]]]],[[4,2],[[9,[4]]]],[[3,4],[[9,[3]]]],[[4,4],[[9,[4]]]],0,[10,10],[11,11],[12,12],[1,1],[3,3],[4,4],[[]],[[]],[[]],[[]],[[]],[[]],[[10,10],13],[[11,11],13],[[1,1],13],[[3,3],13],[[4,4],13],[[],14],[[],4],0,0,[[4,2],4],[[4,2]],[[4,4],7],[[4,4],8],[[4,7],4],[[4,8],4],0,[[3,3],4],[3,4],[[10,10],15],[[11,11],15],[[12,12],15],[[1,1],15],[[3,3],15],[[4,4],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[10,16],17],[[10,16],17],[[11,16],17],[[11,16],17],[[12,16],17],[[1,16],17],[[1,16],17],[[18,16],17],[[3,16],[[20,[19]]]],[[4,16],[[20,[19]]]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[6,4],[6,4],[6,4],[6,4],[7,4],[8,4],[21,10],[21,11],[22,9],[22,9],[22,9],[22,9],[[23,3],9],[10],[11],[12],[1],[3],[4],[[],11],[22],[10,21],[22],[11,21],[22],[22],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[23,3],15],[[23,3],15],[4,15],0,0,[[4,2],4],[[4,2]],[[4,7],4],[[4,8],4],[24,10],[24,11],[2,1],[[6,2],4],[[],3],0,0,[[10,10],[[9,[13]]]],[[11,11],[[9,[13]]]],[[1,1],[[9,[13]]]],[[3,3],[[9,[13]]]],[[4,4],[[9,[13]]]],0,0,[10,24],[11,24],[[25,10]],[14],[[4,4],4],[[3,3],4],[[4,2],4],[[4,4],4],[[3,4],3],[[3,3],4],[[4,4],4],[[3,4]],[[4,4]],[4,2],[4,2],[4,2],[[],4],[[],4],0,0,0,0,[[18,6],4],[[]],[[]],[[]],[[]],[[]],[[]],[[],26],[[],26],[[],26],[[],20],[[],20],[[],20],[[],20],[[],20],[[],20],[[],20],[[],20],[27,[[20,[18]]]],[[],20],[[],20],[7,[[20,[4,28]]]],[8,[[20,[4,28]]]],[[],20],[[],20],[[],20],[[],20],[[],20],[[],20],[[],20],[[],20],[[],20],[[],20],[27,[[20,[4,26]]]],[[],29],[[],29],[[],29],[[],29],[[],29],[[],29],[[],29],[[],29],[[],29],[[],29],[[23,3,30]],0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[31,[[33,[32]]]],[[31,30],[[33,[32]]]],[[31,30,21,30],[[33,[34]]]],[[[36,[35]],37,37],33],[[[36,[35]],38,38],33],[[[36,[35]],38,38],33],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[39,39],[40,40],[41,41],[[]],[[]],[[]],[[39,39],13],[[40,40],13],[[[36,[35]],40,39],33],[[[36,[35]],39,40],33],[[[36,[35]],39,42],33],[[[36,[35]],39,37],33],[[39,39],15],[[40,40],15],[[41,41],15],[[],15],[[],15],[[],15],[[39,16],17],[[39,16],17],[[40,16],17],[[41,16],17],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[21,40],[22,9],[22,9],[39],[40],[41],[40,21],[22],[22],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[11,10],39],[[[43,[35]],27,[9,[4]]],[[45,[44]]]],[[[43,[35]],27,41,21],[[20,[[42,[44]],46]]]],[[[43,[35]],27,[9,[4]]],[[47,[44]]]],[[[43,[35]],27,41],[[37,[44]]]],[[[43,[35]],27,4,4],48],[[39,39],[[9,[13]]]],[[40,40],[[9,[13]]]],[[]],[[]],[[]],[[],26],[[],20],[[],20],[[],20],[[],20],[[],20],[[],20],[[],20],[[],20],[[],20],[[],20],[[],20],[[],20],[[],20],[[],20],[[],20],[[],20],[[],20],[[],20],[[],29],[[],29],[[],29],[[],29],[[],29],[[],29],[[],29],[[],29],[[],29],[[31,27],[[33,[34]]]],[[31,27,21],[[33,[34]]]],0,0,0,0,0,0,0,0,0,0,0,0,0,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[[47,[[0,[49,44]]]]],[[47,[[0,[49,44]]]]]],[50,50],[23,23],[[]],[[]],[[]],[[23,23],13],0,[23,4],[[[42,[44]]],38],[[[42,[44]]],38],[[[42,[44]]],38],[[23,23],15],[[],15],[[23,16],17],[[23,16],17],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[25,[[9,[51]]]],[25,4],[25,4],[25,3],[25,3],[25,9],[25,3],[25,23],[[[45,[44]],23,3],[[9,[44]]]],[[[37,[44]],23,3],[[9,[44]]]],[[48,23,3],9],[[[47,[44]],23,3],[[9,[44]]]],[23],[[[42,[44]],21]],[[[42,[44]],21]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[42],[42],[[[42,[44]]],15],[48,15],[[[45,[44]],23,3],15],[[[37,[44]],23,3],15],[25,15],[[48,23,3],15],[[[47,[44]],23,3],15],[25,15],[[[42,[44]]],38],[[[42,[44]]],38],[[[42,[44]]],38],[[[42,[44]]],38],[[[42,[44]]],38],[[[42,[44]]],21],[23,1],0,[25,21],[[4,2],23],0,0,[[23,23],[[9,[13]]]],0,[[25,12]],[[50,12],[[20,[52]]]],[[25,12]],[[50,47,12],[[20,[[52,[[9,[44]]]]]]]],[[50,47,[9,[44]],12],[[20,[[52,[[9,[44]]]]]]]],[[25,[9,[44]],12]],[[25,37]],[[25,37,9]],[25,53],0,[[23,3],3],[[]],[[]],[[]],[[],26],[[],20],[[],20],[[],20],[[],20],[[],20],[[],20],[[],20],[[],20],[[],20],[[],20],[[],20],[[],20],[[],20],[[],20],[[],20],[[],20],[[],29],[[],29],[[],29],[[],29],[[],29],[[],29],[[],29],[[],29],0,[[25,30]],[[25,30],9],[[[45,[44]],23,3,30]],[[[37,[44]],23,3,30]],[[48,23,3,30]],[[[47,[44]],23,3,30]],[50,15]],"p":[[3,"MicroStep"],[15,"u32"],[3,"Instant"],[3,"Duration"],[15,"u128"],[15,"u64"],[15,"f32"],[15,"f64"],[4,"Option"],[3,"LocalReactionId"],[3,"ReactorId"],[4,"Offset"],[4,"Ordering"],[3,"SchedulerOptions"],[15,"bool"],[3,"Formatter"],[6,"Result"],[4,"TimeUnit"],[3,"Error"],[4,"Result"],[15,"usize"],[3,"IndexSlice"],[3,"EventTag"],[15,"u16"],[3,"ReactionCtx"],[3,"String"],[15,"str"],[3,"TryFromFloatSecsError"],[3,"TypeId"],[8,"FnOnce"],[3,"AssemblyCtx"],[3,"FinishedReactor"],[6,"AssemblyResult"],[3,"AssemblyIntermediate"],[8,"ReactorInitializer"],[3,"DependencyDeclarator"],[3,"Port"],[8,"Iterator"],[3,"GlobalReactionId"],[3,"TriggerId"],[4,"PortKind"],[3,"Multiport"],[3,"ComponentCreator"],[8,"Sync"],[3,"LogicalAction"],[3,"AssemblyError"],[3,"PhysicalActionRef"],[3,"Timer"],[8,"Clone"],[3,"AsyncCtx"],[8,"Copy"],[3,"SendError"],[3,"JoinHandle"],[3,"PhysicalAction"],[3,"SyncScheduler"],[8,"ReactorBehavior"],[8,"ReactionTrigger"]]},\
-"vecmap":{"doc":"This is a formally verified implementation of a sparse map …","t":"EDNDNDDLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLMLLLLLLLLLLLLLLLLLLLLLLLLL","n":["Entry","KeyRef","Occupied","OccupiedEntry","Vacant","VacantEntry","VecMap","as_ref","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","clone","clone","clone_into","clone_into","cloned","contains_key","default","entry","entry_from_ref","find_random_mapping_after","fmt","fmt","from","from","from","from","from","from","from","get","get_mut","insert","insert","into","into","into","into","into","iter","key","keyref","max_key","min_entry","new","next_mapping","remove","replace","to_owned","to_owned","to_string","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","type_id","type_id","type_id","type_id","type_id"],"q":["vecmap","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","",""],"d":["A view into a single entry in a map, which may either be …","A key zipped with its internal index in this map. For some …","An occupied Entry","An occupied Entry.","A vacant Entry","A vacant Entry.","A sparse map representation over a totally ordered key …","","","","","","","","","","","","","","","","","Checks if key
is contained in the map.","","Find an entry with assumption that the key is random …","Find the entry matching key
. Use key_hint
to accelerate …","Finds entry reference, either directly associated with …","","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","","","Returns the argument unchanged.","Get the value associated with key
, if it exists.","Gets the mutable ref to the entry’s value.","Insert value
for key
in the map. If key
is already …","Sets the value of the entry with the VacantEntry’s key.","Calls U::from(self)
.","Calls U::from(self)
.","Calls U::from(self)
.","Calls U::from(self)
.","Calls U::from(self)
.","Iterate over all key-value paris in the map.","","","Obtain the key of the item with the greatest key, unless …","Obtain keyref-value pair of the item with the smallest …","","Produces the first mapping that follows the given key in …","Removes the item with key
and returns its value. If no …","Replaces the entry’s value with value
.","","","","","","","","","","","","","","","","","",""],"i":[0,0,7,0,7,0,0,1,5,7,15,14,1,5,7,15,14,1,5,1,5,1,1,5,5,5,5,5,5,1,5,7,15,14,1,1,1,5,14,5,15,5,7,15,14,1,5,1,7,5,5,5,5,5,14,5,1,1,5,7,15,14,1,5,7,15,14,1,5,7,15,14,1],"f":[0,0,0,0,0,0,0,[1,1],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[[5,[[0,[2,3,4]],2]]],[[5,[[0,[2,3,4]],2]]]],[[[1,[2]]],[[1,[2]]]],[[]],[[]],[1,[[1,[2]]]],[5,6],[[],[[5,[[0,[4,3]]]]]],[5,7],[[5,1],7],[5,8],[[[5,[[0,[4,3,9]],9]],10],11],[[[1,[12]],10],11],[[]],[[]],[[]],[[]],[[],1],[13],[[]],[5,8],[14],[5,8],[15],[[]],[[]],[[]],[[]],[[]],[5,16],0,[7,1],[5,8],[5,8],[[],5],[[5,1],8],[5,8],[14],[[]],[[]],[[],17],[[],18],[[],18],[[],18],[[],18],[[],18],[[],18],[[],18],[[],18],[[],18],[[],18],[[],19],[[],19],[[],19],[[],19],[[],19]],"p":[[3,"KeyRef"],[8,"Clone"],[8,"Eq"],[8,"Ord"],[3,"VecMap"],[15,"bool"],[4,"Entry"],[4,"Option"],[8,"Debug"],[3,"Formatter"],[6,"Result"],[8,"Display"],[15,"never"],[3,"OccupiedEntry"],[3,"VacantEntry"],[8,"Iterator"],[3,"String"],[4,"Result"],[3,"TypeId"]]}\
-}');
-if (typeof window !== 'undefined' && window.initSearch) {window.initSearch(searchIndex)};
-if (typeof exports !== 'undefined') {exports.searchIndex = searchIndex};
+var searchIndex = new Map(JSON.parse('[\
+["reactor_rt",{"doc":"The runtime library for reactor programs generated by LFC, …","t":"PPFPFFFPFFFTPTPTPFFPTTGFFFFKKFPTKFFGFTTNNNNNNQQNNNNNNCQQNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNMNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNQQNNNNNNONNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNMNNNNNNNNNNNMNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNONNONNNNNNNNNNNOONNNNNNOCNNMNNNNNNNNNNNNNNNNNNNNNNNNQQOONNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNHNNNNNNNNNNNNNNNNNNNNMNNNNNFFFIPPFFPFFPTPPRGKTTFERMNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNEFEFEEEEEEQQQQI","n":["After","Asap","AsyncCtx","DAY","Duration","EventTag","GlobalReactionId","HOUR","Instant","LocalReactionId","LogicalAction","MAX","MICRO","MICROSECOND","MILLI","MILLISECOND","MIN","MicroStep","Multiport","NANO","NANOSECOND","ORIGIN","Offset","PhysicalAction","PhysicalActionRef","Port","ReactionCtx","ReactionTrigger","ReactorBehavior","ReactorId","SEC","SECOND","SchedulableAsAction","SchedulerOptions","SyncScheduler","TimeUnit","Timer","ZERO","ZERO","abs_diff","add","add","add","add_assign","add_assign","after","after","as_micros","as_millis","as_nanos","as_secs","as_secs_f32","as_secs_f64","assembly","assert_tag_is","assert_tag_is","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","checked_add","checked_add","checked_div","checked_duration_since","checked_mul","checked_sub","checked_sub","cleanup_tag","clone","clone","clone","clone","clone","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","cmp","cmp","cmp","cmp","cmp","cmp","compare","compare","compare","compare","compare","compare","default","default","delay","delay","div","div_assign","div_duration_f32","div_duration_f64","div_f32","div_f64","dump_graph","duration_since","duration_since_start","elapsed","enumerate_set","enumerate_values","enumerate_values_ref","eq","eq","eq","eq","eq","eq","eq","equivalent","equivalent","equivalent","equivalent","equivalent","equivalent","equivalent","equivalent","equivalent","equivalent","equivalent","equivalent","equivalent","equivalent","equivalent","equivalent","equivalent","equivalent","equivalent","equivalent","equivalent","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from_micros","from_millis","from_nanos","from_secs","from_secs_f32","from_secs_f64","from_usize","from_usize","get","get","get","get_elapsed_logical_time","get_elapsed_physical_time","get_logical_time","get_mut","get_mut","get_physical_time","get_ref","get_start_time","get_tag","get_value","get_value","get_value","get_value","get_value","hash","hash","hash","hash","hash","hash","hash","id","index","index","index","index","index","index_mut","index_mut","index_mut","into","into","into","into","into","into","into","into","into","into","into","into","into","into","into","into","into","into","into_iter","into_iter","is_empty","is_periodic","is_present","is_present","is_present","is_present","is_present","is_present","is_present","is_shutdown","is_zero","iter","iter_mut","iterate_set","iterate_values","iterate_values_ref","keep_alive","len","microstep","microstep","mul","mul_assign","mul_f32","mul_f64","new","new","new","new","now","num_workers","offset","offset","offset_from_t0","partial_cmp","partial_cmp","partial_cmp","partial_cmp","partial_cmp","partial_cmp","period","prelude","raw","raw","react","request_stop","request_stop","run_main","saturating_add","saturating_duration_since","saturating_mul","saturating_sub","schedule","schedule_physical","schedule_physical_with_v","schedule_with_v","set","set_opt","spawn_physical_thread","sub","sub","sub","sub_assign","sub_assign","subsec_micros","subsec_millis","subsec_nanos","sum","sum","tag","tag","threads","timeout","to_duration","to_logical_time","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_string","to_string","to_string","to_string","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from_secs_f32","try_from_secs_f64","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_parse_duration","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","use_ref","use_ref_opt","use_value_ref","use_value_ref","use_value_ref","use_value_ref","use_value_ref","was_terminated","AssemblyCtx","AssemblyError","AssemblyIntermediate","AssemblyResult","ChildInputReference","ChildOutputReference","ComponentCreator","DependencyDeclarator","Err","FinishedReactor","GlobalReactionId","Input","MAX_REACTION_ID","Ok","Output","Params","PortKind","ReactorInitializer","SHUTDOWN","STARTUP","TriggerId","TriggerLike","Wrapped","assemble","assemble","assemble_self","bind_ports","bind_ports_iterated","bind_ports_zip","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","clone","clone","clone","clone_into","clone_into","clone_into","cmp","cmp","compare","compare","declare_triggers","declare_uses","effects_multiport","effects_port","eq","eq","eq","equivalent","equivalent","equivalent","equivalent","equivalent","equivalent","equivalent","equivalent","equivalent","fmt","fmt","fmt","fmt","from","from","from","from","from","from","from","from","from","from_usize","get","get_mut","hash","hash","hash","index","index","index_mut","into","into","into","into","into","into","into","into","into","new","new_logical_action","new_multiport","new_physical_action","new_port","new_timer","partial_cmp","partial_cmp","to_owned","to_owned","to_owned","to_string","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","with_child","with_child_bank","AsyncCtx","Duration","EventTag","Instant","LogicalAction","Multiport","PhysicalActionRef","Port","ReactionCtx","Timer","after","assert_tag_is","delay","tag","unit"],"q":[[0,"reactor_rt"],[419,"reactor_rt::assembly"],[564,"reactor_rt::prelude"],[579,"core::option"],[580,"core::clone"],[581,"core::marker"],[582,"core::cmp"],[583,"core::iter::traits::iterator"],[584,"core::marker"],[585,"core::fmt"],[586,"index_vec::idxslice"],[587,"core::hash"],[588,"crossbeam_channel::err"],[589,"std::thread"],[590,"core::marker"],[591,"alloc::string"],[592,"core::time"],[593,"core::any"],[594,"core::ops::function"]],"d":["Specify that the trigger will fire at least after the …","Specify that the trigger will fire as soon as possible. …","A type that can affect the logical event queue to implement","","A Duration
type to represent a span of time, typically …","The tag of an event.","Global identifier for a reaction.","","A measurement of a monotonically nondecreasing clock. …","ID of a reaction local to its containing reactor.","A logical action.","The maximum duration.","","The duration of one microsecond.","","The duration of one millisecond.","","Type of the microsteps of an EventTag.","A multiport is a vector of independent ports (its channels)","","The duration of one nanosecond.","The tag of the startup event.","An offset from the current event.","A physical action. Physical actions may only be used with …","A reference to a physical action. This thing is cloneable …","Represents a port, which carries values of type T
. Ports …","The context in which a reaction executes. Its API allows …","Common trait for actions, ports, and timer objects handed …","The trait used by the framework to interact with the …","The unique identifier of a reactor instance during …","","The duration of one second.","Implemented by LogicalAction and PhysicalAction references …","Construction parameters for the scheduler.","The runtime scheduler.","A unit of time, used in LF.","A timer is conceptually a logical action that may …","","A duration of zero time.","Computes the absolute difference between self
and other
.","","Panics","","","","Shorthand for using After together with [delay].","Shorthand for using After together with [delay].","Returns the total number of whole microseconds contained …","Returns the total number of whole milliseconds contained …","Returns the total number of nanoseconds contained by this …","Returns the number of whole seconds contained by this …","Returns the number of seconds contained by this Duration
…","Returns the number of seconds contained by this Duration
…","Module containing the API to initialize a reactor program.","Convenient macro to assert equality of the current tag. …","Convenient macro to assert equality of the current tag. …","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Returns Some(t)
where t
is the time self + duration
if t
…","Checked Duration
addition. Computes self + other
, …","Checked Duration
division. Computes self / other
, …","Returns the amount of time elapsed from another instant to …","Checked Duration
multiplication. Computes self * other
, …","Returns Some(t)
where t
is the time self - duration
if t
…","Checked Duration
subtraction. Computes self - other
, …","Acknowledge that the given tag is done executing and free …","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Creates a Duration value using the same syntax as in LF.","Creates a Duration value using the same syntax as in LF.","","","Divide Duration
by Duration
and return f32
.","Divide Duration
by Duration
and return f64
.","Divide Duration
by f32
.","Divide Duration
by f64
.","If true, dump the dependency graph to a file before …","Returns the amount of time elapsed from another instant to …","Returns the amount of time elapsed since the start of the …","Returns the amount of time elapsed since this instant.","Iterate over only those channels that are set (have a …","Iterate over only those channels that are set (have a …","Iterate over only those channels that are set (have a …","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Creates a new Duration
from the specified number of …","Creates a new Duration
from the specified number of …","Creates a new Duration
from the specified number of …","Creates a new Duration
from the specified number of whole …","Creates a new Duration
from the specified number of …","Creates a new Duration
from the specified number of …","","","Returns the current value of a port or action at this …","","","Returns the amount of logical time elapsed since the start …","Returns the amount of physical time elapsed since the …","Returns the current logical time.","","","Returns the current physical time.","Returns a reference to the current value of a port or …","Returns the start time of the execution of this program.","Returns the tag at which the reaction executes.","Copies the value out, if it is present. Whether a value is …","","","","","","","","","","","","The unique ID of this reactor. This is given by the …","","","","","","","","","Calls U::from(self)
.","Calls U::from(self)
.","Calls U::from(self)
.","Calls U::from(self)
.","Calls U::from(self)
.","Calls U::from(self)
.","Calls U::from(self)
.","Calls U::from(self)
.","Calls U::from(self)
.","Calls U::from(self)
.","Calls U::from(self)
.","Calls U::from(self)
.","Calls U::from(self)
.","Calls U::from(self)
.","Calls U::from(self)
.","Calls U::from(self)
.","Calls U::from(self)
.","Calls U::from(self)
.","","","Returns true if this multiport is empty.","Whether the timer should repeat itself. A period of zero …","","","Returns true if the given action was triggered at the …","","Returns whether the trigger is present, given that the …","Returns whether the trigger is present, given that the …","","Returns whether this tag is the shutdown tag of the …","Returns true if this Duration
spans no time.","Iterate over the channels of this multiport. Returns …","Iterate over the multiport and return mutable references …","Iterate over only those channels that are set (have a …","Iterate over only those channels that are set (have a …","Iterate over only those ports that are set (have a value), …","If true, we won’t shut down the scheduler as soon as the …","Returns the number of channels.","Returns the microstep of this tag.","The microstep of this tag.","","","Multiplies Duration
by f32
.","Multiplies Duration
by f64
.","","","","Creates a new Duration
from the specified number of whole …","Returns an instant corresponding to “now”.","Returns the number of active workers in the execution of a …","Create a new tag from its offset from t0 and a microstep. …","Minimal duration after the start of the program after …","The time offset from the origin of the logical timeline. …","","","","","","","Period between events emitted by this timer. A period of …","The prelude that is imported at the top of reactor files …","","","Execute a single user-written reaction. Dispatches on the …","Request that the application shutdown, possibly with a …","Request that the application shutdown, possibly with a …","","Saturating Duration
addition. Computes self + other
, …","Returns the amount of time elapsed from another instant to …","Saturating Duration
multiplication. Computes self * other
, …","Saturating Duration
subtraction. Computes self - other
, …","Schedule an action to trigger at some point in the future. …","Schedule an action to run after its own implicit time delay","Schedule an action to run after its own implicit time delay","Schedule an action to trigger at some point in the future,","Sets the value of the given port.","Sets the value of the given port, if the given value is …","Spawn a new thread that can use a AsyncCtx to push …","","Returns the amount of time elapsed from another instant to …","","","","Returns the fractional part of this Duration
, in whole …","Returns the fractional part of this Duration
, in whole …","Returns the fractional part of this Duration
, in …","","","Convenient macro to create a tag. This is just a shorthand …","Convenient macro to create a tag. This is just a shorthand …","Max number of threads to use in the thread pool. If zero, …","Timeout of reactor execution. If provided, the reactor …","","Returns the logical instant for this tag, using the …","","","","","","","","","","","","","","","","","","","","","","","","","","","","","This recognizes the same strings as LF","","","","The checked version of from_secs_f32
.","The checked version of from_secs_f64
.","","","","","","","","","","","","","","","","","","","Parse a duration from a string. This is used for CLI …","","","","","","","","","","","","","","","","","","","Executes the provided closure on the value of the port or …","Executes the provided closure on the value of the port, …","Execute an action using the current value of this trigger. …","","","","","Returns true if the scheduler has been shutdown. When that…","Helper struct to assemble reactors during initialization. …","An error occurring during initialization of the reactor …","Intermediate result of assembly.","","","","Creates the components of a reactor.","Declares dependencies between components and reactions.","Contains the error value","Final result of the assembly of a reactor.","Global identifier for a reaction.","","Exclusive maximum value of the local_rid
parameter of […","Contains the success value","","Type of the construction parameters.","Kind of a port.","Wrapper around the user struct for safe dispatch.","","","The ID of a trigger component.","","Type of the user struct, which contains state variables of …","Assemble this reactor. This initializes state variables, …","top level function","Innermost function.","Bind two ports together.","","Bind the ports of the upstream to those of the downstream, …","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","","","","","","","","","","Calls U::from(self)
.","Calls U::from(self)
.","Calls U::from(self)
.","Calls U::from(self)
.","Calls U::from(self)
.","Calls U::from(self)
.","Calls U::from(self)
.","Calls U::from(self)
.","Calls U::from(self)
.","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Assembles a child reactor and makes it available in the …","Assembles a bank of children reactor and makes it …","","A Duration
type to represent a span of time, typically …","","A measurement of a monotonically nondecreasing clock. …","","","","","","","Shorthand for using After together with [delay].","Convenient macro to assert equality of the current tag. …","Creates a Duration value using the same syntax as in LF.","Convenient macro to create a tag. This is just a shorthand …","Alias for the unit type, so that it can be written without …"],"i":[18,18,0,31,0,0,0,31,0,0,0,1,31,1,31,1,31,0,0,31,1,19,0,0,0,0,0,0,0,0,31,1,0,0,0,0,0,2,1,1,2,4,1,4,1,0,0,1,1,1,1,1,1,0,0,0,38,68,25,22,34,69,39,12,15,16,17,18,19,21,2,31,4,1,38,68,25,22,34,69,39,12,15,16,17,18,19,21,2,31,4,1,4,1,1,4,1,4,1,11,12,15,16,17,18,19,2,4,1,12,15,16,17,18,19,2,4,1,15,16,19,2,4,1,15,16,19,2,4,1,21,1,0,0,1,1,1,1,1,1,21,4,19,4,22,22,22,15,16,18,19,2,4,1,15,15,15,16,16,16,18,18,18,19,19,19,2,2,2,4,4,4,1,1,1,15,15,16,16,18,19,19,2,2,31,4,1,38,68,25,22,34,69,39,12,15,16,17,18,19,21,2,31,4,1,1,1,1,1,1,1,15,16,34,15,16,34,34,34,15,16,34,34,34,34,35,38,25,39,12,15,16,18,19,2,4,1,11,22,15,15,16,16,22,15,16,38,68,25,22,34,69,39,12,15,16,17,18,19,21,2,31,4,1,22,22,22,39,38,25,34,39,35,35,12,34,1,22,22,22,22,22,21,22,19,19,1,1,1,1,15,16,2,1,4,34,19,39,19,15,16,19,2,4,1,39,0,15,16,11,34,17,69,1,4,1,1,34,17,17,34,34,34,34,4,4,1,4,1,1,1,1,1,1,0,0,21,21,31,19,12,15,16,17,18,19,2,4,1,15,16,19,2,38,68,25,22,34,69,39,12,15,16,17,18,19,21,2,31,31,4,1,1,1,38,68,25,22,34,69,39,12,15,16,17,18,19,21,2,31,4,1,0,38,68,25,22,34,69,39,12,15,16,17,18,19,21,2,31,4,1,34,34,35,38,25,39,12,17,0,0,0,0,65,65,0,0,57,0,0,65,54,57,65,54,0,0,64,64,0,0,54,54,55,55,62,62,62,55,56,58,62,60,61,63,64,65,55,56,58,62,60,61,63,64,65,63,64,65,63,64,65,63,64,63,64,62,62,62,62,63,64,65,63,63,63,64,64,64,65,65,65,63,63,64,65,55,56,58,62,60,61,63,64,65,64,64,64,63,64,65,64,64,64,55,56,58,62,60,61,63,64,65,63,60,60,60,60,60,63,64,63,64,65,63,55,56,58,62,60,61,63,64,65,55,56,58,62,60,61,63,64,65,55,56,58,62,60,61,63,64,65,55,55,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"f":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[[1,1],1],[[2,3],-1,[]],[[4,1],4],[[1,1],1],[[4,1],5],[[1,1],5],0,0,[1,6],[1,6],[1,6],[1,7],[1,8],[1,9],0,0,0,[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[[4,1],[[10,[4]]]],[[1,1],[[10,[1]]]],[[1,3],[[10,[1]]]],[[4,4],[[10,[1]]]],[[1,3],[[10,[1]]]],[[4,1],[[10,[4]]]],[[1,1],[[10,[1]]]],0,[[[12,[-1]]],[[12,[-1]]],[13,14]],[15,15],[16,16],[17,17],[18,18],[19,19],[2,2],[4,4],[1,1],[[-1,-2],5,[],[]],[[-1,-2],5,[],[]],[[-1,-2],5,[],[]],[[-1,-2],5,[],[]],[[-1,-2],5,[],[]],[[-1,-2],5,[],[]],[[-1,-2],5,[],[]],[[-1,-2],5,[],[]],[[-1,-2],5,[],[]],[[15,15],20],[[16,16],20],[[19,19],20],[[2,2],20],[[4,4],20],[[1,1],20],[[-1,-2],20,[],[]],[[-1,-2],20,[],[]],[[-1,-2],20,[],[]],[[-1,-2],20,[],[]],[[-1,-2],20,[],[]],[[-1,-2],20,[],[]],[[],21],[[],1],0,0,[[1,3],1],[[1,3],5],[[1,1],8],[[1,1],9],[[1,8],1],[[1,9],1],0,[[4,4],1],[19,1],[4,1],[[[22,[-1]]],[[0,[[26,[],[[23,[[5,[24,[25,[-1]]]]]]]]]]],14],[[[22,[-1]]],[[0,[[26,[],[[23,[[5,[24,-1]]]]]]]]],[27,14]],[[[22,[-1]]],[[0,[[26,[],[[23,[[5,[24,-1]]]]]]]]],14],[[15,15],28],[[16,16],28],[[18,18],28],[[19,19],28],[[2,2],28],[[4,4],28],[[1,1],28],[[-1,-2],28,[],[]],[[-1,-2],28,[],[]],[[-1,-2],28,[],[]],[[-1,-2],28,[],[]],[[-1,-2],28,[],[]],[[-1,-2],28,[],[]],[[-1,-2],28,[],[]],[[-1,-2],28,[],[]],[[-1,-2],28,[],[]],[[-1,-2],28,[],[]],[[-1,-2],28,[],[]],[[-1,-2],28,[],[]],[[-1,-2],28,[],[]],[[-1,-2],28,[],[]],[[-1,-2],28,[],[]],[[-1,-2],28,[],[]],[[-1,-2],28,[],[]],[[-1,-2],28,[],[]],[[-1,-2],28,[],[]],[[-1,-2],28,[],[]],[[-1,-2],28,[],[]],[[15,29],30],[[15,29],30],[[16,29],30],[[16,29],30],[[18,29],30],[[19,29],30],[[19,29],30],[[2,29],30],[[2,29],30],[[31,29],30],[[4,29],[[33,[5,32]]]],[[1,29],[[33,[5,32]]]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[7,1],[7,1],[7,1],[7,1],[8,1],[9,1],[24,15],[24,16],[[34,-2],[[10,[-1]]],27,[[35,[-1]]]],[[-1,[37,[-2,[36,[-3]]]]],10,[],[],[]],[[-1,[37,[-2,[36,[-3]]]]],10,[],[],[]],[34,1],[34,1],[34,4],[[-1,[37,[-2,[36,[-3]]]]],10,[],[],[]],[[-1,[37,[-2,[36,[-3]]]]],10,[],[],[]],[34,4],[[34,-2],[[10,[-1]]],[],[[0,[-1]]]],[34,4],[34,19],[[35,19,4],[[10,[-1]]],27],[[[38,[-1]],19,4],[[10,[-1]]],[27,14]],[[[25,[-1]],19,4],[[10,[-1]]],[27,14]],[[39,19,4],[[10,[5]]]],[[[12,[-1]],19,4],[[10,[-1]]],[27,14]],[[15,-1],5,40],[[16,-1],5,40],[[18,-1],5,40],[[19,-1],5,40],[[2,-1],5,40],[[4,-1],5,40],[[1,-1],5,40],[11,16],[[[22,[-1]],24],-2,14,[]],[[-1,[37,[-2,[36,[-3]]]]],[],[],[],[]],[15,24],[16,24],[[-1,[37,[-2,[36,[-3]]]]],[],[],[],[]],[[[22,[-1]],24],-2,14,[]],[[-1,[37,[-2,[36,[-3]]]]],[],[],[],[]],[[-1,[37,[-2,[36,[-3]]]]],[],[],[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[[[22,[-1]]],-2,14,[]],[[[22,[-1]]],-2,14,[]],[[[22,[-1]]],28,14],[39,28],[[[38,[-1]],19,4],28,14],[[[25,[-1]],19,4],28,14],[[34,-2],28,[],[[35,[-1]]]],[[39,19,4],28],[[35,19,4],28],[[35,19,4],28],[[[12,[-1]],19,4],28,14],[34,28],[1,28],[[[22,[-1]]],[[0,[[26,[],[[23,[[25,[-1]]]]]]]]],14],[[[22,[-1]]],[[0,[[26,[],[[23,[[25,[-1]]]]]]]]],14],[[[22,[-1]]],[[0,[[26,[],[[23,[[25,[-1]]]]]]]]],14],[[[22,[-1]]],[[0,[[26,[],[[23,[-1]]]]]]],[27,14]],[[[22,[-1]]],[[0,[[26,[],[[23,[-1]]]]]]],14],0,[[[22,[-1]]],24,14],[19,2],0,[[1,3],1],[[1,3],5],[[1,8],1],[[1,9],1],[41,15],[41,16],[3,2],[[7,3],1],[[],4],[34,24],[[1,3],19],0,0,[[15,15],[[10,[20]]]],[[16,16],[[10,[20]]]],[[19,19],[[10,[20]]]],[[2,2],[[10,[20]]]],[[4,4],[[10,[20]]]],[[1,1],[[10,[20]]]],0,0,[15,41],[16,41],[[11,34,15],5],[[34,18],5],[[17,18],[[33,[5,[42,[5]]]]]],[21,5],[[1,1],1],[[4,4],1],[[1,3],1],[[1,1],1],[[34,-2,18],5,14,[[43,[-1]]]],[[17,[12,[-1]],18],[[33,[5,[42,[[10,[-1]]]]]]],14],[[17,[12,[-1]],[10,[-1]],18],[[33,[5,[42,[[10,[-1]]]]]]],14],[[34,-2,[10,[-1]],18],5,14,[[43,[-1]]]],[[34,[25,[-1]],-1],5,14],[[34,[25,[-1]],[10,[-1]]],5,14],[[34,-2],[[44,[-1]]],45,[[47,[17],[[46,[-1]]]],45]],[[4,1],4],[[4,4],1],[[1,1],1],[[4,1],5],[[1,1],5],[1,3],[1,3],[1,3],[-1,1,[[26,[],[[23,[1]]]]]],[-1,1,[[26,[],[[23,[1]]]]]],0,0,0,0,[[31,7],1],[[19,4],4],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,48,[]],[-1,48,[]],[-1,48,[]],[-1,48,[]],[-1,[[33,[-2]]],[],[]],[-1,[[33,[-2]]],[],[]],[-1,[[33,[-2]]],[],[]],[-1,[[33,[-2]]],[],[]],[-1,[[33,[-2]]],[],[]],[-1,[[33,[-2]]],[],[]],[-1,[[33,[-2]]],[],[]],[-1,[[33,[-2]]],[],[]],[-1,[[33,[-2]]],[],[]],[-1,[[33,[-2]]],[],[]],[-1,[[33,[-2]]],[],[]],[-1,[[33,[-2]]],[],[]],[-1,[[33,[-2]]],[],[]],[-1,[[33,[-2]]],[],[]],[-1,[[33,[-2]]],[],[]],[49,[[33,[31,-1]]],[]],[-1,[[33,[-2]]],[],[]],[-1,[[33,[-2]]],[],[]],[-1,[[33,[-2]]],[],[]],[8,[[33,[1,50]]]],[9,[[33,[1,50]]]],[-1,[[33,[-2]]],[],[]],[-1,[[33,[-2]]],[],[]],[-1,[[33,[-2]]],[],[]],[-1,[[33,[-2]]],[],[]],[-1,[[33,[-2]]],[],[]],[-1,[[33,[-2]]],[],[]],[-1,[[33,[-2]]],[],[]],[-1,[[33,[-2]]],[],[]],[-1,[[33,[-2]]],[],[]],[-1,[[33,[-2]]],[],[]],[-1,[[33,[-2]]],[],[]],[-1,[[33,[-2]]],[],[]],[-1,[[33,[-2]]],[],[]],[-1,[[33,[-2]]],[],[]],[-1,[[33,[-2]]],[],[]],[-1,[[33,[-2]]],[],[]],[-1,[[33,[-2]]],[],[]],[-1,[[33,[-2]]],[],[]],[49,[[33,[1,48]]]],[-1,51,[]],[-1,51,[]],[-1,51,[]],[-1,51,[]],[-1,51,[]],[-1,51,[]],[-1,51,[]],[-1,51,[]],[-1,51,[]],[-1,51,[]],[-1,51,[]],[-1,51,[]],[-1,51,[]],[-1,51,[]],[-1,51,[]],[-1,51,[]],[-1,51,[]],[-1,51,[]],[[34,-2,-4],-3,[],[[35,[-1]]],[],[[47,[[10,[-1]]],[[46,[-3]]]]]],[[34,-2,-4],[[10,[-3]]],[],[[35,[-1]]],[],[[47,[-1],[[46,[-3]]]]]],[[35,19,4,-3],-2,[],[],[[47,[[10,[-1]]],[[46,[-2]]]]]],[[[38,[-1]],19,4,-3],-2,14,[],[[47,[[10,[-1]]],[[46,[-2]]]]]],[[[25,[-1]],19,4,-3],-2,14,[],[[47,[[10,[-1]]],[[46,[-2]]]]]],[[39,19,4,-2],-1,[],[[47,[[10,[5]]],[[46,[-1]]]]]],[[[12,[-1]],19,4,-3],-2,14,[],[[47,[[10,[-1]]],[[46,[-2]]]]]],[17,28],0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[[-1,[55,[[54,[],[[52,[-2]],[53,[-1]]]]]]],[[57,[[56,[[54,[],[[52,[-2]],[53,[-1]]]]]]]]],[],[]],[[[55,[-1]],-2],[[57,[[56,[-1]]]]],54,[[47,[[55,[-1]]],[[46,[[57,[[58,[-1]]]]]]]]]],[[[55,[-1]],-2,24,[59,[[10,[49]]]],-3],[[57,[[58,[-1]]]]],54,[[47,[[60,[-1]],16],[[46,[[33,[-1,61]]]]]]],[[47,[[62,[-1]],-1,[59,[63]]],[[46,[[57,[5]]]]]]]],[[[62,[-1]],[25,[-2]],[25,[-2]]],[[57,[5]]],54,14],[[[62,[-1]],-3,-4],[[57,[5]]],54,14,[[26,[],[[23,[[25,[-2]]]]]]],[[26,[],[[23,[[25,[-2]]]]]]]],[[[62,[-1]],-3,-4],[[57,[5]]],54,14,[[26,[],[[23,[[25,[-2]]]]]]],[[26,[],[[23,[[25,[-2]]]]]]]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[63,63],[64,64],[65,65],[[-1,-2],5,[],[]],[[-1,-2],5,[],[]],[[-1,-2],5,[],[]],[[63,63],20],[[64,64],20],[[-1,-2],20,[],[]],[[-1,-2],20,[],[]],[[[62,[-1]],64,63],[[57,[5]]],54],[[[62,[-1]],63,64],[[57,[5]]],54],[[[62,[-1]],63,[22,[-2]]],[[57,[5]]],54,14],[[[62,[-1]],63,[25,[-2]]],[[57,[5]]],54,14],[[63,63],28],[[64,64],28],[[65,65],28],[[-1,-2],28,[],[]],[[-1,-2],28,[],[]],[[-1,-2],28,[],[]],[[-1,-2],28,[],[]],[[-1,-2],28,[],[]],[[-1,-2],28,[],[]],[[-1,-2],28,[],[]],[[-1,-2],28,[],[]],[[-1,-2],28,[],[]],[[63,29],30],[[63,29],30],[[64,29],30],[[65,29],30],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[24,64],[[-1,[37,[-2,[36,[-3]]]]],10,[],[],[]],[[-1,[37,[-2,[36,[-3]]]]],10,[],[],[]],[[63,-1],5,40],[[64,-1],5,40],[[65,-1],5,40],[[-1,[37,[-2,[36,[-3]]]]],[],[],[],[]],[64,24],[[-1,[37,[-2,[36,[-3]]]]],[],[],[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[[16,15],63],[[[60,[-1]],49,[10,[1]]],[[38,[-2]]],54,14],[[[60,[-1]],49,65,24],[[33,[[22,[-2]],61]]],54,14],[[[60,[-1]],49,[10,[1]]],[[12,[-2]]],54,14],[[[60,[-1]],49,65],[[25,[-2]]],54,14],[[[60,[-1]],49,1,1],39,54],[[63,63],[[10,[20]]]],[[64,64],[[10,[20]]]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,48,[]],[-1,[[33,[-2]]],[],[]],[-1,[[33,[-2]]],[],[]],[-1,[[33,[-2]]],[],[]],[-1,[[33,[-2]]],[],[]],[-1,[[33,[-2]]],[],[]],[-1,[[33,[-2]]],[],[]],[-1,[[33,[-2]]],[],[]],[-1,[[33,[-2]]],[],[]],[-1,[[33,[-2]]],[],[]],[-1,[[33,[-2]]],[],[]],[-1,[[33,[-2]]],[],[]],[-1,[[33,[-2]]],[],[]],[-1,[[33,[-2]]],[],[]],[-1,[[33,[-2]]],[],[]],[-1,[[33,[-2]]],[],[]],[-1,[[33,[-2]]],[],[]],[-1,[[33,[-2]]],[],[]],[-1,[[33,[-2]]],[],[]],[-1,51,[]],[-1,51,[]],[-1,51,[]],[-1,51,[]],[-1,51,[]],[-1,51,[]],[-1,51,[]],[-1,51,[]],[-1,51,[]],[[[55,[-1]],49,-3],[[57,[[58,[-1]]]]],54,54,[[47,[[55,[-1]],-2],[[46,[[57,[[58,[-1]]]]]]]]]],[[[55,[-1]],49,24,-2,-4],[[57,[[58,[-1]]]]],54,[[66,[24],[[46,[]]]]],54,[[47,[[55,[-1]],[67,[-3]]],[[46,[[57,[[58,[-1]]]]]]]]]],0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"c":[],"p":[[5,"Duration",0],[5,"MicroStep",0],[1,"u32"],[5,"Instant",0],[1,"tuple"],[1,"u128"],[1,"u64"],[1,"f32"],[1,"f64"],[6,"Option",579],[10,"ReactorBehavior",0],[5,"PhysicalActionRef",0],[10,"Clone",580],[10,"Sync",581],[5,"LocalReactionId",0],[5,"ReactorId",0],[5,"AsyncCtx",0],[6,"Offset",0],[5,"EventTag",0],[6,"Ordering",582],[5,"SchedulerOptions",0],[5,"Multiport",0],[17,"Item"],[1,"usize"],[5,"Port",0],[10,"Iterator",583],[10,"Copy",581],[1,"bool"],[5,"Formatter",584],[8,"Result",584],[6,"TimeUnit",0],[5,"Error",584],[6,"Result",585],[5,"ReactionCtx",0],[10,"ReactionTrigger",0],[1,"slice"],[5,"IndexSlice",586],[5,"LogicalAction",0],[5,"Timer",0],[10,"Hasher",587],[1,"u16"],[5,"SendError",588],[10,"SchedulableAsAction",0],[5,"JoinHandle",589],[10,"Send",581],[17,"Output"],[10,"FnOnce",590],[5,"String",591],[1,"str"],[5,"TryFromFloatSecsError",592],[5,"TypeId",593],[17,"Wrapped"],[17,"Params"],[10,"ReactorInitializer",419],[5,"AssemblyCtx",419],[5,"FinishedReactor",419],[8,"AssemblyResult",419],[5,"AssemblyIntermediate",419],[1,"array"],[5,"ComponentCreator",419],[5,"AssemblyError",419],[5,"DependencyDeclarator",419],[5,"GlobalReactionId",419],[5,"TriggerId",419],[6,"PortKind",419],[10,"Fn",590],[5,"Vec",594],[5,"PhysicalAction",0],[5,"SyncScheduler",0]],"b":[[175,"impl-Display-for-LocalReactionId"],[176,"impl-Debug-for-LocalReactionId"],[177,"impl-Debug-for-ReactorId"],[178,"impl-Display-for-ReactorId"],[180,"impl-Debug-for-EventTag"],[181,"impl-Display-for-EventTag"],[182,"impl-Debug-for-MicroStep"],[183,"impl-Display-for-MicroStep"],[264,"impl-IntoIterator-for-%26mut+Multiport%3CT%3E"],[265,"impl-IntoIterator-for-%26Multiport%3CT%3E"],[324,"impl-Sub%3CDuration%3E-for-Instant"],[325,"impl-Sub-for-Instant"],[332,"impl-Sum%3C%26Duration%3E-for-Duration"],[333,"impl-Sum-for-Duration"],[492,"impl-Debug-for-GlobalReactionId"],[493,"impl-Display-for-GlobalReactionId"]]}]\
+]'));
+if (typeof exports !== 'undefined') exports.searchIndex = searchIndex;
+else if (window.initSearch) window.initSearch(searchIndex);
diff --git a/settings.html b/settings.html
index a6fef80a..b6911d1d 100644
--- a/settings.html
+++ b/settings.html
@@ -1 +1,2 @@
-1 +actions.rs - source +\ No newline at end of file + -/* * Copyright (c) 2021, TU Dresden. * * Redistribution and use in source and binary forms, with or without modification, @@ -290,7 +291,7 @@ * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, @@ -338,7 +339,7 @@ impl<K, T: Sync> Action<K, T> { /// Record a future value that can be queried at a future logical time. - /// Note that we don't check that the given time is in the future. If it's + /// Note that we don't check that the given time is in the future. If it's /// in the past, the value will never be reclaimed. /// /// @@ -347,8 +348,8 @@ match self.map.entry(Reverse(time)) { Entry::Vacant(e) => e.insert(value), Entry::Occupied(ref mut e) => { - trace!("Value overwritten in an action for tag {}", time); - trace!("This means an action was scheduled several times for the same tag."); + trace!("Value overwritten in an action for tag {}", time); + trace!("This means an action was scheduled several times for the same tag."); e.replace(value) } } @@ -392,7 +393,7 @@ } } -#[cfg(not(feature = "no-unsafe"))] +#[cfg(not(feature = "no-unsafe"))] impl<T: Sync, K> triggers::ReactionTriggerWithRefAccess<T> for Action<K, T> { fn get_value_ref(&self, now: &EventTag, _start: &Instant) -> Option<&T> { self.map.get(&Reverse(*now)).map(|a| a.as_ref()).flatten() @@ -419,7 +420,7 @@ } } -#[cfg(not(feature = "no-unsafe"))] +#[cfg(not(feature = "no-unsafe"))] impl<T: Sync> triggers::ReactionTriggerWithRefAccess<T> for LogicalAction<T> { fn get_value_ref(&self, now: &EventTag, start: &Instant) -> Option<&T> { self.0.get_value_ref(now, start) @@ -556,5 +557,4 @@ self.use_value(|a| a.0.use_value_ref(now, start, action)).unwrap() } } -
1 +assembly.rs - source +\ No newline at end of file + -1 2 3 4 @@ -80,7 +81,7 @@ 80 81 82 -//! Module containing the API to initialize a reactor program. +
//! Module containing the API to initialize a reactor program. use AssemblyErrorImpl::*; @@ -139,17 +140,17 @@ fn display(&self, debug: &DebugInfoRegistry) -> String { match self.0 { CyclicDependency(upstream, downstream) => format!( - "Port {} is already in the downstream of port {}", + "Port {} is already in the downstream of port {}", debug.fmt_component(upstream), debug.fmt_component(downstream) ), - CyclicDependencyGraph => "Cyclic dependency graph".to_string(), + CyclicDependencyGraph => "Cyclic dependency graph".to_string(), CannotBind(upstream, downstream) => format!( - "Cannot bind {} to {}, downstream is already bound", + "Cannot bind {} to {}, downstream is already bound", debug.fmt_component(upstream), debug.fmt_component(downstream) ), - IdOverflow => "Overflow when allocating component ID".to_string(), + IdOverflow => "Overflow when allocating component ID".to_string(), } } } @@ -162,5 +163,4 @@ ChildInputReference, ChildOutputReference, } -
1 +ids.rs - source +\ No newline at end of file + -/* * Copyright (c) 2021, TU Dresden. * * Redistribution and use in source and binary forms, with or without modification, @@ -251,7 +252,7 @@ * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, @@ -316,8 +317,8 @@ } impl Display for $id { - fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { - write!(f, "{}", self.0) + fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { + write!(f, "{}", self.0) } } }; @@ -347,14 +348,14 @@ } impl Debug for $id { - fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - write!(f, "{:?}", self.0) + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + write!(f, "{:?}", self.0) } } impl Display for $id { - fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - write!(f, "{}", self.0) + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + write!(f, "{}", self.0) } } }; @@ -393,15 +394,15 @@ } impl FromStr for GlobalId { - type Err = &'static str; + type Err = &'static str; fn from_str(s: &str) -> Result<Self, Self::Err> { - if let Some((container, local)) = s.split_once('/') { - let container = container.parse::<ReactorIdImpl>().map_err(|_| "invalid reactor id")?; - let local = local.parse::<ReactionIdImpl>().map_err(|_| "invalid local id")?; + if let Some((container, local)) = s.split_once('/') { + let container = container.parse::<ReactorIdImpl>().map_err(|_| "invalid reactor id")?; + let local = local.parse::<ReactionIdImpl>().map_err(|_| "invalid local id")?; Ok(GlobalId::new(ReactorId::new(container), LocalReactionId::new(local))) } else { - Err("Expected format {int}/{int}") + Err("Expected format {int}/{int}") } } } @@ -446,22 +447,22 @@ impl Debug for GlobalId { #[inline] - fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { + fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { <Self as Display>::fmt(self, f) } } impl Display for GlobalId { #[inline] - fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { - write!(f, "{}/{}", self.container(), self.local()) + fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { + write!(f, "{}/{}", self.container(), self.local()) } } /// private implementation types pub(crate) mod impl_types { cfg_if! { - if #[cfg(all(target_pointer_width = "64", feature = "wide-ids"))] { + if #[cfg(all(target_pointer_width = "64", feature = "wide-ids"))] { type MyUsize = usize; type HalfUsize = u32; } else { @@ -478,5 +479,4 @@ assert_impl_all!(GlobalIdImpl: petgraph::graph::IndexType); assert_impl_all!(ReactorIdImpl: petgraph::graph::IndexType); } -
1 +lib.rs - source +\ No newline at end of file + -/* * Copyright (c) 2021, TU Dresden. * * Redistribution and use in source and binary forms, with or without modification, @@ -172,7 +173,7 @@ * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, @@ -229,7 +230,7 @@ extern crate index_vec; #[macro_use] extern crate log; -#[cfg(feature = "parallel-runtime")] +#[cfg(feature = "parallel-runtime")] extern crate rayon; #[macro_use] extern crate smallvec; @@ -284,7 +285,7 @@ /// The trait used by the framework to interact with the reactor /// during runtime. /// -/// Importantly, it's object-safe and has no type parameters +/// Importantly, it's object-safe and has no type parameters /// or associated types. This allows us to wrap it into a /// `Box<dyn ReactorBehavior>`. pub trait ReactorBehavior { @@ -309,7 +310,7 @@ assert_obj_safe!(ReactorBehavior); /// Used for benchmarking to access private API of the crate. -#[cfg(feature = "public-internals")] +#[cfg(feature = "public-internals")] #[doc(hidden)] pub mod internals { pub use crate::ids::impl_types::*; @@ -320,5 +321,4 @@ GlobalReactionId(GlobalId::from_raw(u)) } } -
1 +ports.rs - source +\ No newline at end of file + -/* * Copyright (c) 2021, TU Dresden. * * Redistribution and use in source and binary forms, with or without modification, @@ -482,7 +483,7 @@ * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, @@ -494,11 +495,11 @@ */ use std::borrow::Borrow; -#[cfg(not(feature = "no-unsafe"))] +#[cfg(not(feature = "no-unsafe"))] use std::cell::UnsafeCell; use std::collections::HashMap; use std::fmt::Debug; -#[cfg(feature = "no-unsafe")] +#[cfg(feature = "no-unsafe")] use std::ops::Deref; use std::ops::{DerefMut, Index, IndexMut}; use std::rc::Rc; @@ -558,9 +559,9 @@ id, kind, bind_status: BindStatus::Free, - #[cfg(feature = "no-unsafe")] + #[cfg(feature = "no-unsafe")] upstream_binding: Rc::new(AtomicRefCell::new(Default::default())), - #[cfg(not(feature = "no-unsafe"))] + #[cfg(not(feature = "no-unsafe"))] upstream_binding: Rc::new(UnsafeCell::new(Default::default())), } } @@ -581,7 +582,7 @@ } cfg_if! { - if #[cfg(feature = "no-unsafe")] { + if #[cfg(feature = "no-unsafe")] { pub(crate) fn use_ref<R>(&self, f: impl FnOnce(&Option<T>) -> R) -> R { use atomic_refcell::AtomicRef; let cell_ref: AtomicRef<Rc<PortCell<T>>> = AtomicRefCell::borrow(&self.upstream_binding); @@ -598,7 +599,7 @@ pub(crate) fn set_impl(&mut self, new_value: Option<T>) { use atomic_refcell::AtomicRef; - debug_assert_ne!(self.bind_status, BindStatus::Bound, "Cannot set a bound port ({:?})", self.id); + debug_assert_ne!(self.bind_status, BindStatus::Bound, "Cannot set a bound port ({:?})", self.id); let cell_ref: AtomicRef<Rc<PortCell<T>>> = AtomicRefCell::borrow(&self.upstream_binding); let class_cell: &PortCell<T> = Rc::borrow(cell_ref.deref()); @@ -633,7 +634,7 @@ #[inline] pub(crate) fn set_impl(&mut self, new_value: Option<T>) { - debug_assert_ne!(self.bind_status, BindStatus::Bound, "Cannot set a bound port"); + debug_assert_ne!(self.bind_status, BindStatus::Bound, "Cannot set a bound port"); let binding: &UnsafeCell<Rc<PortCell<T>>> = Rc::borrow(&self.upstream_binding); @@ -659,7 +660,7 @@ pub(crate) fn forward_to(&mut self, downstream: &mut Port<T>) -> Result<(), AssemblyError> { let mut mut_downstream_cell = { cfg_if! { - if #[cfg(feature = "no-unsafe")] { + if #[cfg(feature = "no-unsafe")] { (downstream.upstream_binding).borrow_mut() } else { unsafe { downstream.upstream_binding.get().as_mut().unwrap() } @@ -675,7 +676,7 @@ let my_class = { cfg_if! { - if #[cfg(feature = "no-unsafe")] { + if #[cfg(feature = "no-unsafe")] { self.upstream_binding.borrow_mut() } else { unsafe { self.upstream_binding.get().as_mut().unwrap() } @@ -718,7 +719,7 @@ } } -#[cfg(not(feature = "no-unsafe"))] +#[cfg(not(feature = "no-unsafe"))] impl<T: Sync> crate::triggers::ReactionTriggerWithRefAccess<T> for Port<T> { fn get_value_ref(&self, _now: &EventTag, _start: &Instant) -> Option<&T> { self.get_ref() @@ -746,7 +747,7 @@ } cfg_if! { - if #[cfg(feature = "no-unsafe")] { + if #[cfg(feature = "no-unsafe")] { type Downstreams<T> = AtomicRefCell<HashMap<PortId, Rc<AtomicRefCell<Rc<PortCell<T>>>>>>; type UncheckedCell<T> = AtomicRefCell<T>; } else { @@ -760,7 +761,7 @@ /// Cell for the value. value: UncheckedCell<Option<T>>, - /// This is the set of ports that are "forwarded to". + /// This is the set of ports that are "forwarded to". /// When you bind 2 ports A -> B, then the binding of B /// is updated to point to the equiv class of A. The downstream /// field of that equiv class is updated to contain B. @@ -792,7 +793,7 @@ fn set_upstream(&self, new_binding: &Rc<PortCell<T>>) { for cell_rc in (*self.downstreams.borrow()).values() { cfg_if! { - if #[cfg(feature = "no-unsafe")] { + if #[cfg(feature = "no-unsafe")] { let mut ref_mut = cell_rc.borrow_mut(); *ref_mut.deref_mut() = Rc::clone(new_binding); } else { @@ -870,7 +871,7 @@ /// and return a copy of the value. /// The returned ports are not necessarily contiguous. See /// [Self::enumerate_values] to get access to their index. - pub fn iterate_values(&self) -> impl Iterator<Item = T> + '_ + pub fn iterate_values(&self) -> impl Iterator<Item = T> + '_ where T: Copy, { @@ -881,14 +882,14 @@ /// and return a reference to the value. /// The returned ports are not necessarily contiguous. See /// [Self::enumerate_values] to get access to their index. - #[cfg(not(feature = "no-unsafe"))] - pub fn iterate_values_ref(&self) -> impl Iterator<Item = &T> + '_ { + #[cfg(not(feature = "no-unsafe"))] + pub fn iterate_values_ref(&self) -> impl Iterator<Item = &T> + '_ { self.iter().filter_map(|p| p.get_ref()) } /// Iterate over only those channels that are set (have a value), /// yielding a tuple with their index in the bank and a copy of the value. - pub fn enumerate_values(&self) -> impl Iterator<Item = (usize, T)> + '_ + pub fn enumerate_values(&self) -> impl Iterator<Item = (usize, T)> + '_ where T: Copy, { @@ -897,8 +898,8 @@ /// Iterate over only those channels that are set (have a value), /// yielding a tuple with their index in the bank and a reference to the value. - #[cfg(not(feature = "no-unsafe"))] - pub fn enumerate_values_ref(&self) -> impl Iterator<Item = (usize, &T)> + '_ { + #[cfg(not(feature = "no-unsafe"))] + pub fn enumerate_values_ref(&self) -> impl Iterator<Item = (usize, &T)> + '_ { self.iter().enumerate().filter_map(|(i, p)| p.get_ref().map(|v| (i, v))) } } @@ -909,18 +910,18 @@ } } -impl<'a, T: Sync> IntoIterator for &'a mut Multiport<T> { - type Item = &'a mut Port<T>; - type IntoIter = std::slice::IterMut<'a, Port<T>>; +impl<'a, T: Sync> IntoIterator for &'a mut Multiport<T> { + type Item = &'a mut Port<T>; + type IntoIter = std::slice::IterMut<'a, Port<T>>; fn into_iter(self) -> Self::IntoIter { self.ports.iter_mut() } } -impl<'a, T: Sync> IntoIterator for &'a Multiport<T> { - type Item = &'a Port<T>; - type IntoIter = std::slice::Iter<'a, Port<T>>; +impl<'a, T: Sync> IntoIterator for &'a Multiport<T> { + type Item = &'a Port<T>; + type IntoIter = std::slice::Iter<'a, Port<T>>; fn into_iter(self) -> Self::IntoIter { self.ports.iter() @@ -940,5 +941,4 @@ &mut self.ports[index] } } -
1 +assembly_impl.rs - source +\ No newline at end of file + -/* * Copyright (c) 2021, TU Dresden. * * Redistribution and use in source and binary forms, with or without modification, @@ -561,7 +562,7 @@ * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, @@ -585,7 +586,7 @@ /// Globals shared by all assemblers. pub(super) struct RootAssembler { /// All registered reactors - pub(super) reactors: IndexVec<ReactorId, Option<ReactorBox<'static>>>, + pub(super) reactors: IndexVec<ReactorId, Option<ReactorBox<'static>>>, /// Dependency graph pub(super) graph: DepGraph, /// Debug infos @@ -599,26 +600,26 @@ impl RootAssembler { /// Register a reactor into the global data structure that owns them during execution. - fn register_reactor<R: ReactorInitializer + 'static>(&mut self, child: R) { + fn register_reactor<R: ReactorInitializer + 'static>(&mut self, child: R) { if child.id().index() >= self.reactors.len() { self.reactors.resize_with(child.id().index() + 1, || None) } let prev = self.reactors[child.id()].replace(Box::new(child)); // this is impossible because we control how we allocate IDs entirely - debug_assert!(prev.is_none(), "Overwrote a reactor during initialization") + debug_assert!(prev.is_none(), "Overwrote a reactor during initialization") } /// Register reactors into the global data structure that owns them during execution. - fn register_bank<R: ReactorInitializer + 'static>(&mut self, bank: Vec<R>) { + fn register_bank<R: ReactorInitializer + 'static>(&mut self, bank: Vec<R>) { for child in bank { self.register_reactor(child) } } /// Top level fun that assembles the main reactor - pub fn assemble_tree<R: ReactorInitializer + 'static>( + pub fn assemble_tree<R: ReactorInitializer + 'static>( main_args: R::Params, - ) -> (ReactorVec<'static>, DepGraph, DebugInfoRegistry) { + ) -> (ReactorVec<'static>, DepGraph, DebugInfoRegistry) { let mut root = RootAssembler::default(); let assembler = AssemblyCtx::new(&mut root, ReactorDebugInfo::root::<R::Wrapped>()); @@ -631,7 +632,7 @@ let RootAssembler { graph, reactors, debug_info: id_registry, .. } = root; - let reactors = reactors.into_iter().map(|r| r.expect("Uninitialized reactor!")).collect(); + let reactors = reactors.into_iter().map(|r| r.expect("Uninitialized reactor!")).collect(); (reactors, graph, id_registry) } } @@ -649,12 +650,12 @@ } /// Helper struct to assemble reactors during initialization. -/// One assembly context is used per reactor, they can't be shared. -pub struct AssemblyCtx<'x, S> +/// One assembly context is used per reactor, they can't be shared. +pub struct AssemblyCtx<'x, S> where S: ReactorInitializer, { - globals: &'x mut RootAssembler, + globals: &'x mut RootAssembler, /// Next local ID for components != reactions cur_local: LocalReactionId, @@ -669,20 +670,20 @@ } /// Final result of the assembly of a reactor. -pub struct FinishedReactor<'x, S>(AssemblyCtx<'x, S>, S) +pub struct FinishedReactor<'x, S>(AssemblyCtx<'x, S>, S) where S: ReactorInitializer; /// Intermediate result of assembly. -pub struct AssemblyIntermediate<'x, S>(AssemblyCtx<'x, S>, S) +pub struct AssemblyIntermediate<'x, S>(AssemblyCtx<'x, S>, S) where S: ReactorInitializer; -impl<'x, S> AssemblyCtx<'x, S> +impl<'x, S> AssemblyCtx<'x, S> where S: ReactorInitializer, { - fn new(globals: &'x mut RootAssembler, debug: ReactorDebugInfo) -> Self { + fn new(globals: &'x mut RootAssembler, debug: ReactorDebugInfo) -> Self { Self { globals, // this is not zero, so that reaction ids and component ids are disjoint @@ -696,8 +697,8 @@ /// top level function pub fn assemble( self, - build_reactor_tree: impl FnOnce(Self) -> AssemblyResult<AssemblyIntermediate<'x, S>>, - ) -> AssemblyResult<FinishedReactor<'x, S>> { + build_reactor_tree: impl FnOnce(Self) -> AssemblyResult<AssemblyIntermediate<'x, S>>, + ) -> AssemblyResult<FinishedReactor<'x, S>> { let AssemblyIntermediate(ich, reactor) = build_reactor_tree(self)?; Ok(FinishedReactor(ich, reactor)) } @@ -707,12 +708,12 @@ mut self, create_self: impl FnOnce(&mut ComponentCreator<S>, ReactorId) -> Result<S, AssemblyError>, num_non_synthetic_reactions: usize, - reaction_names: [Option<&'static str>; N], + reaction_names: [Option<&'static str>; N], declare_dependencies: impl FnOnce(&mut DependencyDeclarator<S>, &mut S, [GlobalReactionId; N]) -> AssemblyResult<()>, - ) -> AssemblyResult<AssemblyIntermediate<'x, S>> { + ) -> AssemblyResult<AssemblyIntermediate<'x, S>> { // todo when feature(generic_const_exprs) is stabilized, // replace const parameter N with S::MAX_REACTION_ID.index(). - debug_assert_eq!(N, S::MAX_REACTION_ID.index(), "Should initialize all reactions"); + debug_assert_eq!(N, S::MAX_REACTION_ID.index(), "Should initialize all reactions"); // note: the ID is not known until all descendants // have been built. @@ -723,8 +724,8 @@ // Effectively, IDs are assigned depth first. This // makes this whole debug info recording very complicated. let id = self.globals.reactor_id.get_and_incr(); - let debug = self.debug.take().expect("unreachable - can only call assemble_self once"); - trace!("Children of {}: {:?}", debug.to_string(), self.children_ids); + let debug = self.debug.take().expect("unreachable - can only call assemble_self once"); + trace!("Children of {}: {:?}", debug.to_string(), self.children_ids); self.globals.debug_info.record_reactor(id, debug); for child in self.children_ids.drain(..) { self.globals.debug_info.record_reactor_container(id, child); @@ -754,7 +755,7 @@ &mut self, my_id: ReactorId, num_non_synthetic: usize, - names: [Option<&'static str>; N], + names: [Option<&'static str>; N], ) -> [GlobalReactionId; N] { assert!(num_non_synthetic <= N); @@ -783,20 +784,20 @@ /// Assembles a child reactor and makes it available in /// the scope of a function. #[inline] - pub fn with_child<Sub: ReactorInitializer + 'static, F>( + pub fn with_child<Sub: ReactorInitializer + 'static, F>( mut self, - inst_name: &'static str, + inst_name: &'static str, args: Sub::Params, action: F, - ) -> AssemblyResult<AssemblyIntermediate<'x, S>> - // we can't use impl FnOnce(...) because we want to specify explicit type parameters in the caller + ) -> AssemblyResult<AssemblyIntermediate<'x, S>> + // we can't use impl FnOnce(...) because we want to specify explicit type parameters in the caller where - F: FnOnce(Self, &mut Sub) -> AssemblyResult<AssemblyIntermediate<'x, S>>, + F: FnOnce(Self, &mut Sub) -> AssemblyResult<AssemblyIntermediate<'x, S>>, { - trace!("Assembling {}", inst_name); + trace!("Assembling {}", inst_name); let mut sub = self.assemble_sub(inst_name, None, args)?; let AssemblyIntermediate(ich, s) = action(self, &mut sub)?; - trace!("Registering {}", inst_name); + trace!("Registering {}", inst_name); ich.globals.register_reactor(sub); Ok(AssemblyIntermediate(ich, s)) } @@ -806,18 +807,18 @@ #[inline] pub fn with_child_bank<Sub, A, F>( mut self, - inst_name: &'static str, + inst_name: &'static str, bank_width: usize, arg_maker: A, action: F, - ) -> AssemblyResult<AssemblyIntermediate<'x, S>> + ) -> AssemblyResult<AssemblyIntermediate<'x, S>> where - Sub: ReactorInitializer + 'static, - // we can't use impl Fn(...) because we want to specify explicit type parameters in the calle - F: FnOnce(Self, &mut Vec<Sub>) -> AssemblyResult<AssemblyIntermediate<'x, S>>, + Sub: ReactorInitializer + 'static, + // we can't use impl Fn(...) because we want to specify explicit type parameters in the calle + F: FnOnce(Self, &mut Vec<Sub>) -> AssemblyResult<AssemblyIntermediate<'x, S>>, A: Fn(/*bank_index:*/ usize) -> Sub::Params, { - trace!("Assembling bank {}", inst_name); + trace!("Assembling bank {}", inst_name); let mut sub = (0..bank_width) .map(|i| self.assemble_sub(inst_name, Some(i), arg_maker(i))) @@ -825,7 +826,7 @@ let AssemblyIntermediate(ich, r) = action(self, &mut sub)?; - trace!("Registering bank {}", inst_name); + trace!("Registering bank {}", inst_name); ich.globals.register_bank(sub); Ok(AssemblyIntermediate(ich, r)) } @@ -835,11 +836,11 @@ #[inline(always)] fn assemble_sub<Sub: ReactorInitializer>( &mut self, - inst_name: &'static str, + inst_name: &'static str, bank_idx: Option<usize>, args: Sub::Params, ) -> AssemblyResult<Sub> { - let my_debug = self.debug.as_ref().expect("should assemble sub-reactors before self"); + let my_debug = self.debug.as_ref().expect("should assemble sub-reactors before self"); let debug_info = match bank_idx { None => my_debug.derive::<Sub>(inst_name), @@ -853,7 +854,7 @@ } } -impl<S> FinishedReactor<'_, S> +impl<S> FinishedReactor<'_, S> where S: ReactorInitializer, { @@ -864,11 +865,11 @@ } /// Declares dependencies between components and reactions. -pub struct DependencyDeclarator<'a, 'x, S: ReactorInitializer> { - assembler: &'a mut AssemblyCtx<'x, S>, +pub struct DependencyDeclarator<'a, 'x, S: ReactorInitializer> { + assembler: &'a mut AssemblyCtx<'x, S>, } -impl<S: ReactorInitializer> DependencyDeclarator<'_, '_, S> { +impl<S: ReactorInitializer> DependencyDeclarator<'_, '_, S> { #[inline] pub fn declare_triggers(&mut self, trigger: TriggerId, reaction: GlobalReactionId) -> AssemblyResult<()> { self.graph().triggers_reaction(trigger, reaction); @@ -915,10 +916,10 @@ /// todo this will just throw away bindings if both iterators are not of the same size /// normally this should be reported by LFC as a warning, maybe we should implement the same thing here #[inline] - pub fn bind_ports_zip<'a, T: Sync + 'a>( + pub fn bind_ports_zip<'a, T: Sync + 'a>( &mut self, - upstream: impl Iterator<Item = &'a mut Port<T>>, - downstream: impl Iterator<Item = &'a mut Port<T>>, + upstream: impl Iterator<Item = &'a mut Port<T>>, + downstream: impl Iterator<Item = &'a mut Port<T>>, ) -> AssemblyResult<()> { for (upstream, downstream) in upstream.zip(downstream) { self.bind_ports(upstream, downstream)?; @@ -927,16 +928,16 @@ } #[inline] - pub fn bind_ports_iterated<'a, T: Sync + 'a>( + pub fn bind_ports_iterated<'a, T: Sync + 'a>( &mut self, - upstream: impl Iterator<Item = &'a mut Port<T>>, - mut downstream: impl Iterator<Item = &'a mut Port<T>>, + upstream: impl Iterator<Item = &'a mut Port<T>>, + mut downstream: impl Iterator<Item = &'a mut Port<T>>, ) -> AssemblyResult<()> { let mut upstream = upstream.collect::<Vec<_>>(); - assert!(!upstream.is_empty(), "Empty upstream!"); + assert!(!upstream.is_empty(), "Empty upstream!"); let up_len = upstream.len(); // we have to implement this loop manually instead of with an iterator - // because we can't clone mutable references in the upstream iterator + // because we can't clone mutable references in the upstream iterator for i in 0.. { let up = &mut upstream[i % up_len]; if let Some(down) = downstream.next() { @@ -955,16 +956,16 @@ } /// Creates the components of a reactor. -pub struct ComponentCreator<'a, 'x, S: ReactorInitializer> { - assembler: &'a mut AssemblyCtx<'x, S>, +pub struct ComponentCreator<'a, 'x, S: ReactorInitializer> { + assembler: &'a mut AssemblyCtx<'x, S>, } -impl<S: ReactorInitializer> ComponentCreator<'_, '_, S> { - pub fn new_port<T: Sync>(&mut self, lf_name: &'static str, kind: PortKind) -> Port<T> { +impl<S: ReactorInitializer> ComponentCreator<'_, '_, S> { + pub fn new_port<T: Sync>(&mut self, lf_name: &'static str, kind: PortKind) -> Port<T> { self.new_port_impl(Cow::Borrowed(lf_name), kind) } - fn new_port_impl<T: Sync>(&mut self, lf_name: Cow<'static, str>, kind: PortKind) -> Port<T> { + fn new_port_impl<T: Sync>(&mut self, lf_name: Cow<'static, str>, kind: PortKind) -> Port<T> { let id = self.next_comp_id(lf_name); self.graph().record_port(id); Port::new(id, kind) @@ -972,7 +973,7 @@ pub fn new_multiport<T: Sync>( &mut self, - lf_name: &'static str, + lf_name: &'static str, kind: PortKind, len: usize, ) -> Result<Multiport<T>, AssemblyError> { @@ -988,42 +989,42 @@ fn new_port_bank_component<T: Sync>( &mut self, - lf_name: &'static str, + lf_name: &'static str, kind: PortKind, bank_id: TriggerId, index: usize, ) -> Port<T> { - let channel_id = self.next_comp_id(Cow::Owned(format!("{}[{}]", lf_name, index))); + let channel_id = self.next_comp_id(Cow::Owned(format!("{}[{}]", lf_name, index))); self.graph().record_port_bank_component(bank_id, channel_id); Port::new(channel_id, kind) } - pub fn new_logical_action<T: Sync>(&mut self, lf_name: &'static str, min_delay: Option<Duration>) -> LogicalAction<T> { + pub fn new_logical_action<T: Sync>(&mut self, lf_name: &'static str, min_delay: Option<Duration>) -> LogicalAction<T> { let id = self.next_comp_id(Cow::Borrowed(lf_name)); self.graph().record_laction(id); LogicalAction::new(id, min_delay) } - pub fn new_physical_action<T: Sync>(&mut self, lf_name: &'static str, min_delay: Option<Duration>) -> PhysicalActionRef<T> { + pub fn new_physical_action<T: Sync>(&mut self, lf_name: &'static str, min_delay: Option<Duration>) -> PhysicalActionRef<T> { let id = self.next_comp_id(Cow::Borrowed(lf_name)); self.graph().record_paction(id); PhysicalActionRef::new(id, min_delay) } - pub fn new_timer(&mut self, lf_name: &'static str, offset: Duration, period: Duration) -> Timer { + pub fn new_timer(&mut self, lf_name: &'static str, offset: Duration, period: Duration) -> Timer { let id = self.next_comp_id(Cow::Borrowed(lf_name)); self.graph().record_timer(id); Timer::new(id, offset, period) } /// Create and return a new id for a trigger component. - fn next_comp_id(&mut self, debug_name: Cow<'static, str>) -> TriggerId { + fn next_comp_id(&mut self, debug_name: Cow<'static, str>) -> TriggerId { let id = self .assembler .globals .cur_trigger .get_and_incr() - .expect("Overflow while allocating ID"); + .expect("Overflow while allocating ID"); self.assembler.globals.debug_info.record_trigger(id, debug_name); id } @@ -1098,5 +1099,4 @@ iter.map(move |(i, j)| unsafe { &mut (*__ptr.add(i)).$field_name[j] }) }}; } -
1 +context.rs - source +\ No newline at end of file + -use std::borrow::Borrow; use std::hash::{Hash, Hasher}; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; @@ -827,8 +828,8 @@ // ReactionCtx is an API built around a ReactionWave. A single // ReactionCtx may be used for multiple ReactionWaves, but // obviously at disjoint times (&mut). -pub struct ReactionCtx<'a, 'x> { - pub(super) insides: RContextForwardableStuff<'x>, +pub struct ReactionCtx<'a, 'x> { + pub(super) insides: RContextForwardableStuff<'x>, /// Logical time of the execution of this wave, constant /// during the existence of the object @@ -841,23 +842,23 @@ current_reaction: Option<GlobalReactionId>, /// Sender to schedule events that should be executed later than this wave. - rx: &'a Receiver<PhysicalEvent>, + rx: &'a Receiver<PhysicalEvent>, /// Start time of the program. initial_time: Instant, // globals, also they might be copied and passed to AsyncCtx - dataflow: &'x DataflowInfo, - debug_info: DebugInfoProvider<'a>, + dataflow: &'x DataflowInfo, + debug_info: DebugInfoProvider<'a>, /// Whether the scheduler has been shut down. - was_terminated_atomic: &'a Arc<AtomicBool>, + was_terminated_atomic: &'a Arc<AtomicBool>, /// In ReactionCtx, this will only be true if this is the shutdown tag. /// It duplicates [Self::was_terminated_atomic], to avoid an atomic /// operation within [Self::is_shutdown]. was_terminated: bool, } -impl<'a, 'x> ReactionCtx<'a, 'x> { +impl<'a, 'x> ReactionCtx<'a, 'x> { /// Returns the start time of the execution of this program. /// /// This is a logical instant with microstep zero. @@ -896,7 +897,7 @@ } /// Returns whether this tag is the shutdown tag of the - /// application. If so, it's necessarily the very last + /// application. If so, it's necessarily the very last /// invocation of the current reaction (on a given reactor /// instance). /// @@ -919,7 +920,7 @@ /// start of the program. /// /// Since this uses [Self::get_physical_time], be aware that - /// this function's result may change over time. + /// this function's result may change over time. #[inline] pub fn get_elapsed_physical_time(&self) -> Duration { self.get_physical_time() - self.get_start_time() @@ -936,7 +937,7 @@ /// the return value might vary. pub fn num_workers(&self) -> usize { cfg_if::cfg_if! { - if #[cfg(feature = "parallel-runtime")] { + if #[cfg(feature = "parallel-runtime")] { rayon::current_num_threads() } else { 1 @@ -989,8 +990,8 @@ /// } /// ``` #[inline] - #[cfg(not(feature = "no-unsafe"))] - pub fn get_ref<'q, T>(&self, container: &'q impl crate::triggers::ReactionTriggerWithRefAccess<T>) -> Option<&'q T> { + #[cfg(not(feature = "no-unsafe"))] + pub fn get_ref<'q, T>(&self, container: &'q impl crate::triggers::ReactionTriggerWithRefAccess<T>) -> Option<&'q T> { container.get_value_ref(&self.get_tag(), &self.get_start_time()) } @@ -1063,7 +1064,7 @@ assert_eq!( Some(reaction_container), port_grandpa, - "Input port {} can only be set by reactions of its grandparent, got reaction {}", + "Input port {} can only be set by reactions of its grandparent, got reaction {}", self.debug_info.id_registry.fmt_component(port_id), self.debug_info.display_reaction(self.current_reaction.unwrap()), ); @@ -1072,7 +1073,7 @@ assert_eq!( reaction_container, port_container, - "Input port {} can only be set by reactions of its parent, got reaction {}", + "Input port {} can only be set by reactions of its parent, got reaction {}", self.debug_info.id_registry.fmt_component(port_id), self.debug_info.display_reaction(self.current_reaction.unwrap()), ); @@ -1166,12 +1167,12 @@ /// ```no_run /// # use reactor_rt::prelude::*; /// # let ctx: &mut ReactionCtx = panic!(); - /// # let action: &mut LogicalAction<&'static str> = panic!(); + /// # let action: &mut LogicalAction<&'static str> = panic!(); /// // will be executed 2 milliseconds (+ own delay) from now with that value. - /// ctx.schedule_with_v(action, Some("value"), after!(2 msec)); + /// 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 + /// // that's equivalent to /// ctx.schedule(action, Asap); /// ``` #[inline] @@ -1183,7 +1184,7 @@ /// /// This is used for actions. #[inline] - pub(crate) fn enqueue_later(&mut self, downstream: &'x ExecutableReactions, tag: EventTag) { + pub(crate) fn enqueue_later(&mut self, downstream: &'x ExecutableReactions, tag: EventTag) { debug_assert!(tag > self.get_tag()); let evt = Event::execute(tag, Cow::Borrowed(downstream)); @@ -1191,14 +1192,14 @@ } #[inline] - pub(crate) fn enqueue_now(&mut self, downstream: Cow<'x, ExecutableReactions<'x>>) { + pub(crate) fn enqueue_now(&mut self, downstream: Cow<'x, ExecutableReactions<'x>>) { match &mut self.insides.todo_now { Some(ref mut do_next) => do_next.to_mut().absorb_after(downstream.as_ref(), self.cur_level.next()), None => self.insides.todo_now = Some(downstream), } } - fn reactions_triggered_by(&self, trigger: TriggerId) -> &'x ExecutableReactions<'x> { + fn reactions_triggered_by(&self, trigger: TriggerId) -> &'x ExecutableReactions<'x> { self.dataflow.reactions_triggered_by(&trigger) } @@ -1213,7 +1214,7 @@ /// 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 + /// 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]. @@ -1238,8 +1239,8 @@ where // is there a practical reason to encapsulate this? F: FnOnce(&mut AsyncCtx) -> R, - F: Send + 'static, - R: Send + 'static, + F: Send + 'static, + R: Send + 'static, { let tx = self.rx.new_sender(); let initial_time = self.initial_time; @@ -1259,7 +1260,7 @@ /// ```no_run /// # use reactor_rt::prelude::*; /// # let ctx: &mut ReactionCtx = panic!(); - /// # let action: &mut LogicalAction<&'static str> = panic!(); + /// # let action: &mut LogicalAction<&'static str> = panic!(); /// // trigger shutdown on the next microstep /// ctx.request_stop(Asap); /// @@ -1278,7 +1279,7 @@ /// Reschedule a periodic timer if need be. /// This is called by a reaction synthesized for each timer. - // note: reactions can't call this as they're only passed a shared reference to a timer. + // note: reactions can't call this as they're only passed a shared reference to a timer. #[doc(hidden)] #[inline] pub fn reschedule_timer(&mut self, timer: &mut Timer) { @@ -1290,11 +1291,11 @@ /// Schedule the first triggering of the given timer. /// This is called by a reaction synthesized for each timer. - // note: reactions can't call this as they're only passed a shared references to timers. + // note: reactions can't call this as they're only passed a shared references to timers. #[doc(hidden)] #[inline] pub fn bootstrap_timer(&mut self, timer: &mut Timer) { - // we're in startup + // we're in startup let downstream = self.reactions_triggered_by(timer.get_id()); if timer.offset.is_zero() { // no offset @@ -1308,24 +1309,24 @@ #[inline] pub(super) fn execute(&mut self, reactor: &mut ReactorBox, reaction_id: GlobalReactionId) { trace!( - " - Executing {} (level {})", + " - Executing {} (level {})", self.debug_info.display_reaction(reaction_id), self.cur_level ); - debug_assert_eq!(reactor.id(), reaction_id.0.container(), "Wrong reactor"); + debug_assert_eq!(reactor.id(), reaction_id.0.container(), "Wrong reactor"); self.current_reaction.replace(reaction_id); reactor.react(self, reaction_id.0.local()); self.current_reaction.take(); } pub(super) fn new( - rx: &'a Receiver<PhysicalEvent>, + rx: &'a Receiver<PhysicalEvent>, tag: EventTag, initial_time: Instant, - todo: ReactionPlan<'x>, - dataflow: &'x DataflowInfo, - debug_info: DebugInfoProvider<'a>, - was_terminated_atomic: &'a Arc<AtomicBool>, + todo: ReactionPlan<'x>, + dataflow: &'x DataflowInfo, + debug_info: DebugInfoProvider<'a>, + was_terminated_atomic: &'a Arc<AtomicBool>, was_terminated: bool, ) -> Self { Self { @@ -1344,7 +1345,7 @@ /// Fork a context. Some things are shared, but not the /// mutable stuff. - #[cfg(feature = "parallel-runtime")] + #[cfg(feature = "parallel-runtime")] pub(super) fn fork(&self) -> Self { Self { insides: Default::default(), @@ -1365,7 +1366,7 @@ /// Info that executing reactions need to make known to the scheduler. #[derive(Default)] -pub(super) struct RContextForwardableStuff<'x> { +pub(super) struct RContextForwardableStuff<'x> { /// Remaining reactions to execute before the wave dies. /// Using [Option] and [Cow] optimises for the case where /// zero or exactly one port/action is set, and minimises @@ -1374,15 +1375,15 @@ /// This is mutable: if a reaction sets a port, then the /// downstream of that port is inserted in into this /// data structure. - pub(super) todo_now: ReactionPlan<'x>, + pub(super) todo_now: ReactionPlan<'x>, /// Events that were produced for a strictly greater /// logical time than a current one. - pub(super) future_events: SmallVec<[Event<'x>; 4]>, + pub(super) future_events: SmallVec<[Event<'x>; 4]>, } -#[cfg(feature = "parallel-runtime")] -impl RContextForwardableStuff<'_> { +#[cfg(feature = "parallel-runtime")] +impl RContextForwardableStuff<'_> { pub(super) fn merge(mut self, other: Self) -> Self { self.absorb(other); self @@ -1395,7 +1396,7 @@ } /// A type that can affect the logical event queue to implement -/// asynchronous physical actions. This is a "link" to the event +/// asynchronous physical actions. This is a "link" to the event /// system, from the outside world. /// /// See [ReactionCtx::spawn_physical_thread]. @@ -1410,7 +1411,7 @@ impl AsyncCtx { /// Returns true if the scheduler has been shutdown. When - /// that's true, calls to other methods of this type will + /// that's true, calls to other methods of this type will /// fail with [SendError]. pub fn was_terminated(&self) -> bool { self.was_terminated.load(Ordering::SeqCst) @@ -1432,7 +1433,7 @@ let evt = PhysicalEvent::terminate_at(tag); self.tx.send(evt).map_err(|e| { - warn!("Event could not be sent! {:?}", e); + warn!("Event could not be sent! {:?}", e); SendError(()) }) } @@ -1486,7 +1487,7 @@ let evt = PhysicalEvent::trigger(tag, action.get_id()); self.tx.send(evt).map_err(|e| { - warn!("Event could not be sent! {:?}", e); + warn!("Event could not be sent! {:?}", e); SendError(action.0.forget_value(&tag)) }) }) @@ -1532,7 +1533,7 @@ /// /// If the duration is zero (eg [Asap](Self::Asap)), it does not /// mean that the trigger will fire right away. For actions, the - /// action's inherent minimum delay must be taken into account, + /// action's inherent minimum delay must be taken into account, /// and even with a zero minimal delay, a delay of one microstep /// is applied. /// @@ -1546,7 +1547,7 @@ /// Specify that the trigger will fire as soon as possible. /// This does not mean that the action will trigger right away. The - /// action's inherent minimum delay must be taken into account, + /// action's inherent minimum delay must be taken into account, /// and even with a zero minimal delay, a delay of one microstep /// is applied. This is equivalent to /// ``` @@ -1582,17 +1583,17 @@ /// Cleans up a tag /// TODO get rid of this! -/// At least for multiports it's really bad +/// At least for multiports it's really bad /// Maybe we can keep a set of the ports that are present in ReactionCtx #[doc(hidden)] pub struct CleanupCtx { - /// Tag we're cleaning up + /// Tag we're cleaning up pub tag: EventTag, } impl CleanupCtx { pub fn cleanup_multiport<T: Sync>(&self, port: &mut Multiport<T>) { - // todo bound ports don't need to be cleared + // todo bound ports don't need to be cleared for channel in port { channel.clear_value() } @@ -1610,5 +1611,4 @@ action.use_mut(|a| a.0.forget_value(&self.tag)).ok(); } } -
1 +debug.rs - source +\ No newline at end of file + -/* * Copyright (c) 2021, TU Dresden. * * Redistribution and use in source and binary forms, with or without modification, @@ -333,7 +334,7 @@ * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, @@ -351,7 +352,7 @@ use std::ops::Range; use index_vec::{Idx, IndexVec}; -use vecmap::VecMap; +use crate::vecmap::VecMap; use crate::assembly::{ReactorInitializer, TriggerId}; use crate::{GlobalReactionId, ReactorId}; @@ -371,7 +372,7 @@ /// Labels of each trigger, every trigger id in the program /// is registered here. - trigger_infos: IndexVec<TriggerId, Cow<'static, str>>, + trigger_infos: IndexVec<TriggerId, Cow<'static, str>>, /// Maps each reactor id to the id of its container. /// The main reactor is not registered. @@ -381,11 +382,11 @@ // todo better data structure, eg IndexVec<ReactorId, IndexVec<LocalReactionId, _>> /// Labels of each reaction, only reactions that have one are in here. - reaction_labels: HashMap<GlobalReactionId, Cow<'static, str>>, + reaction_labels: HashMap<GlobalReactionId, Cow<'static, str>>, } /// The reactor ID, and the local index within the reactor. -/// We don't use GlobalId because the second component is not +/// We don't use GlobalId because the second component is not /// a LocalReactionId, for trigger ids it may be as big as /// usize, so we inflate LocalReactionId to usize. type RawId = (ReactorId, usize); @@ -401,8 +402,8 @@ main_reactor: None, }; - assert_eq!(ich.trigger_infos.push(Cow::Borrowed("startup")), TriggerId::STARTUP); - assert_eq!(ich.trigger_infos.push(Cow::Borrowed("shutdown")), TriggerId::SHUTDOWN); + assert_eq!(ich.trigger_infos.push(Cow::Borrowed("startup")), TriggerId::STARTUP); + assert_eq!(ich.trigger_infos.push(Cow::Borrowed("shutdown")), TriggerId::SHUTDOWN); ich } @@ -414,33 +415,33 @@ } /// Format the id of a component. - fn fmt_component_path<'a>( - &'a self, + fn fmt_component_path<'a>( + &'a self, id: RawId, - label: Option<&'a Cow<'static, str>>, + label: Option<&'a Cow<'static, str>>, always_display_idx: bool, - ) -> impl Display + 'a { - struct PathFmt<'a> { - debug: &'a DebugInfoRegistry, + ) -> impl Display + 'a { + struct PathFmt<'a> { + debug: &'a DebugInfoRegistry, id: RawId, - label: Option<&'a Cow<'static, str>>, + label: Option<&'a Cow<'static, str>>, /// If true, the index is part of the output, /// even if the label is present. always_display_idx: bool, } use std::fmt::*; - impl Display for PathFmt<'_> { + impl Display for PathFmt<'_> { #[inline] - fn fmt(&self, f: &mut Formatter<'_>) -> Result { - write!(f, "{}", self.debug.get_debug_info(self.id.0))?; + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + write!(f, "{}", self.debug.get_debug_info(self.id.0))?; if let Some(label) = &self.label { if self.always_display_idx { - write!(f, "{}@{}", self.id.1, label) + write!(f, "{}@{}", self.id.1, label) } else { - write!(f, "{}", label) + write!(f, "{}", label) } } else { - write!(f, "{}", self.id.1) + write!(f, "{}", self.id.1) } } } @@ -449,13 +450,13 @@ } #[inline] - pub fn fmt_reaction(&self, id: GlobalReactionId) -> impl Display + '_ { + pub fn fmt_reaction(&self, id: GlobalReactionId) -> impl Display + '_ { let raw = (id.0.container(), id.0.local().index()); self.fmt_component_path(raw, self.reaction_labels.get(&id), true) } #[inline] - pub fn fmt_component(&self, id: TriggerId) -> impl Display + '_ { + pub fn fmt_component(&self, id: TriggerId) -> impl Display + '_ { self.fmt_component_path(self.raw_id_of_trigger(id), Some(&self.trigger_infos[id]), false) } @@ -481,7 +482,7 @@ fn raw_id_of_trigger(&self, id: TriggerId) -> RawId { match id { // Pretend startup and shutdown are in the last reactor. - // For programs built with LFC, it's the main reactor. + // For programs built with LFC, it's the main reactor. TriggerId::STARTUP | TriggerId::SHUTDOWN => { let last_reactor = self.reactor_infos.last_idx(); let max_idx = *self.reactor_bound.last().unwrap(); @@ -491,8 +492,8 @@ id => { match self.reactor_bound.binary_search(&id) { - // we're the upper bound of some reactor `rid`, - // ie, we're the first component of the next reactor. + // we're the upper bound of some reactor `rid`, + // ie, we're the first component of the next reactor. Ok(rid) => (rid.plus(1), 0usize), // Here, rid is the reactor which contains the trigger. // Eg if you have reactor_bound=[2, 4], @@ -513,12 +514,12 @@ .unwrap_or(TriggerId::FIRST_REGULAR) } - pub(crate) fn record_trigger(&mut self, id: TriggerId, name: Cow<'static, str>) { + pub(crate) fn record_trigger(&mut self, id: TriggerId, name: Cow<'static, str>) { let ix = self.trigger_infos.push(name); debug_assert_eq!(ix, id); } - pub(crate) fn record_reaction(&mut self, id: GlobalReactionId, name: Cow<'static, str>) { + pub(crate) fn record_reaction(&mut self, id: GlobalReactionId, name: Cow<'static, str>) { let existing = self.reaction_labels.insert(id, name); debug_assert!(existing.is_none()) } @@ -530,17 +531,17 @@ pub(crate) fn record_main_reactor(&mut self, id: ReactorId) { let prev = self.main_reactor.replace(id); - assert!(prev.is_none(), "cannot call record_main twice"); + assert!(prev.is_none(), "cannot call record_main twice"); } pub(crate) fn record_reactor_container(&mut self, parent: ReactorId, child: ReactorId) { let ix = self.reactor_container.insert(child, parent); - debug_assert!(ix.is_none(), "overwrote reactor"); + debug_assert!(ix.is_none(), "overwrote reactor"); } pub(crate) fn set_id_range(&mut self, id: ReactorId, range: Range<TriggerId>) { - assert!(range.start <= range.end, "Malformed range {:?}", range); - assert!(range.start >= TriggerId::FIRST_REGULAR, "Trigger IDs 0-1 are reserved"); + assert!(range.start <= range.end, "Malformed range {:?}", range); + assert!(range.start >= TriggerId::FIRST_REGULAR, "Trigger IDs 0-1 are reserved"); let ix = self.reactor_bound.push(range.end); assert_eq!(ix, id); @@ -551,11 +552,11 @@ pub(crate) struct ReactorDebugInfo { /// Type name #[allow(unused)] - pub type_name: &'static str, + pub type_name: &'static str, /// Simple name of the instantiation (last segment of the path) #[allow(unused)] - pub inst_name: &'static str, - /// Path to this instantiation, with trailing slash (eg `"/parent/child/"`) + pub inst_name: &'static str, + /// Path to this instantiation, with trailing slash (eg `"/parent/child/"`) inst_path: String, } @@ -568,10 +569,10 @@ #[cfg(test)] pub(crate) fn test_named(inst_path: impl Into<String>) -> Self { let mut inst_path = inst_path.into(); - inst_path.push('/'); + inst_path.push('/'); Self { - type_name: "unknown", - inst_name: "unknown", + type_name: "unknown", + inst_name: "unknown", inst_path, } } @@ -579,31 +580,31 @@ pub(crate) fn root<R>() -> Self { Self { type_name: type_name::<R>(), - inst_name: "/", - inst_path: "/".into(), + inst_name: "/", + inst_path: "/".into(), } } - pub(crate) fn derive<R: ReactorInitializer>(&self, inst_name: &'static str) -> Self { + pub(crate) fn derive<R: ReactorInitializer>(&self, inst_name: &'static str) -> Self { Self { type_name: type_name::<R::Wrapped>(), inst_name, - inst_path: format!("{}{}/", self.inst_path, inst_name), + inst_path: format!("{}{}/", self.inst_path, inst_name), } } - pub(crate) fn derive_bank_item<R: ReactorInitializer>(&self, inst_name: &'static str, bank_idx: usize) -> Self { + pub(crate) fn derive_bank_item<R: ReactorInitializer>(&self, inst_name: &'static str, bank_idx: usize) -> Self { Self { type_name: type_name::<R::Wrapped>(), inst_name, - inst_path: format!("{}{}[{}]/", self.inst_path, inst_name, bank_idx), + inst_path: format!("{}{}[{}]/", self.inst_path, inst_name, bank_idx), } } } impl Display for ReactorDebugInfo { - fn fmt(&self, f: &mut Formatter<'_>) -> Result { - write!(f, "{}", self.inst_path) + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + write!(f, "{}", self.inst_path) } } @@ -618,16 +619,16 @@ let mut trigger_id = TriggerId::FIRST_REGULAR; let reactor_0 = ReactorId::new(0); let first_trigger = trigger_id; - debug.record_reactor(reactor_0, ReactorDebugInfo::test_named("foo")); - debug.record_trigger(trigger_id.get_and_incr()?, "t0".into()); - debug.record_trigger(trigger_id.get_and_incr()?, "t1".into()); + debug.record_reactor(reactor_0, ReactorDebugInfo::test_named("foo")); + debug.record_trigger(trigger_id.get_and_incr()?, "t0".into()); + debug.record_trigger(trigger_id.get_and_incr()?, "t1".into()); debug.set_id_range(reactor_0, first_trigger..trigger_id); let reactor_1 = ReactorId::new(1); let first_trigger = trigger_id; - debug.record_reactor(reactor_1, ReactorDebugInfo::test_named("foo1")); - debug.record_trigger(trigger_id.get_and_incr()?, "t0".into()); - debug.record_trigger(trigger_id.get_and_incr()?, "t1".into()); + debug.record_reactor(reactor_1, ReactorDebugInfo::test_named("foo1")); + debug.record_trigger(trigger_id.get_and_incr()?, "t0".into()); + debug.record_trigger(trigger_id.get_and_incr()?, "t1".into()); debug.set_id_range(reactor_1, first_trigger..trigger_id); let mut trigger_id = TriggerId::FIRST_REGULAR; @@ -642,5 +643,4 @@ Ok(()) } } -
1 +dependencies.rs - source +\ No newline at end of file + -/* * Copyright (c) 2021, TU Dresden. * * Redistribution and use in source and binary forms, with or without modification, @@ -990,7 +991,7 @@ * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, @@ -1067,7 +1068,7 @@ type DepGraphImpl = DiGraph<GraphNode, EdgeWeight, GlobalIdImpl>; -/// Dependency graph representing "instantaneous" dependencies, +/// Dependency graph representing "instantaneous" dependencies, /// ie read- and write-dependencies of reactions to ports, and /// their trigger dependencies. This must be a DAG. /// @@ -1102,12 +1103,12 @@ } impl Debug for GraphNode { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match self { - GraphNode { id: GraphId::Reaction(id), .. } => write!(f, "Reaction({:?})", id), - GraphNode { id: GraphId::Trigger(TriggerId::STARTUP), .. } => write!(f, "startup"), - GraphNode { id: GraphId::Trigger(TriggerId::SHUTDOWN), .. } => write!(f, "shutdown"), - GraphNode { id: GraphId::Trigger(id), kind } => write!(f, "{:?}({:?})", kind, id.index()), + GraphNode { id: GraphId::Reaction(id), .. } => write!(f, "Reaction({:?})", id), + GraphNode { id: GraphId::Trigger(TriggerId::STARTUP), .. } => write!(f, "startup"), + GraphNode { id: GraphId::Trigger(TriggerId::SHUTDOWN), .. } => write!(f, "shutdown"), + GraphNode { id: GraphId::Trigger(id), kind } => write!(f, "{:?}({:?})", kind, id.index()), } } } @@ -1132,19 +1133,19 @@ use petgraph::dot::{Config, Dot}; // Map the node weights to nice strings. - // petgraph doesn't support custom node formatters + // petgraph doesn't support custom node formatters // https://github.com/petgraph/petgraph/issues/194 let labeled = self.dataflow.map( |_, n| match n.id { - GraphId::Reaction(id) => format!("Reaction({})", id_registry.fmt_reaction(id)), - GraphId::Trigger(TriggerId::STARTUP) => "startup".to_string(), - GraphId::Trigger(TriggerId::SHUTDOWN) => "shutdown".to_string(), - GraphId::Trigger(id) => format!("{:?}({})", n.kind, id_registry.fmt_component(id)), + GraphId::Reaction(id) => format!("Reaction({})", id_registry.fmt_reaction(id)), + GraphId::Trigger(TriggerId::STARTUP) => "startup".to_string(), + GraphId::Trigger(TriggerId::SHUTDOWN) => "shutdown".to_string(), + GraphId::Trigger(id) => format!("{:?}({})", n.kind, id_registry.fmt_component(id)), }, - |_, _| "", + |_, _| "", ); - format!("{}", Dot::with_config(&labeled, &[Config::EdgeNoLabel])) + format!("{}", Dot::with_config(&labeled, &[Config::EdgeNoLabel])) } pub(super) fn record_port(&mut self, id: TriggerId) { @@ -1164,13 +1165,13 @@ /// ``` /// /// That way when someone declares a trigger on the bank, - /// it's forwarded to individual channels in the graph. + /// it's forwarded to individual channels in the graph. /// /// When X declares a trigger/uses on the entire /// bank, an edge is added from every channel to X. /// pub(super) fn record_port_bank(&mut self, id: TriggerId, len: usize) -> Result<(), AssemblyError> { - assert!(len > 0, "empty port bank"); + assert!(len > 0, "empty port bank"); self.record(GraphId::Trigger(id), NodeKind::MultiportUpstream); for channel_id in id @@ -1265,7 +1266,7 @@ fn record(&mut self, id: GraphId, kind: NodeKind) -> GraphIx { match self.ix_by_id.entry(id) { - HEntry::Occupied(_) => panic!("Duplicate id {:?}", id), + HEntry::Occupied(_) => panic!("Duplicate id {:?}", id), HEntry::Vacant(v) => { let ix = self.dataflow.add_node(GraphNode { kind, id }); v.insert(ix); @@ -1318,7 +1319,7 @@ /// Default semantics for this edge (determined by the /// kind of source and target vertex). This only makes a /// difference for edges from a port/action to a reaction: - /// if they're labeled `Default`, they're trigger dependencies, + /// if they're labeled `Default`, they're trigger dependencies, /// otherwise use dependencies. Default, /// @@ -1344,7 +1345,7 @@ .level_numbers .get(&reaction) .copied() - .expect("reaction was not recorded in the graph"); + .expect("reaction was not recorded in the graph"); collection.insert(reaction, ix); } } @@ -1355,7 +1356,7 @@ /// Maps each trigger to the set of reactions that need /// to be scheduled when it is triggered. /// Todo: many of those are never asked for, eg those of bound ports - trigger_to_plan: IndexVec<TriggerId, Arc<ExecutableReactions<'static>>>, + trigger_to_plan: IndexVec<TriggerId, Arc<ExecutableReactions<'static>>>, } impl DataflowInfo { @@ -1369,14 +1370,14 @@ fn collect_trigger_to_plan( DepGraph { dataflow, .. }: &mut DepGraph, level_info: &ReactionLevelInfo, - ) -> IndexVec<TriggerId, Arc<ExecutableReactions<'static>>> { + ) -> IndexVec<TriggerId, Arc<ExecutableReactions<'static>>> { let mut result = IndexVec::with_capacity(dataflow.node_count() / 2); for trigger in dataflow.node_indices() { if let GraphId::Trigger(trigger_id) = dataflow[trigger].id { // if let Some(_multiport_id) = multiport_containment.get(&dataflow[trigger].id) { // assert_eq!(dataflow[trigger].kind, NodeKind::Port); - // todo!("multiports") + // todo!("multiports") // todo this is a multiport channel: // 1. if someone has declared a dependency on this individual channel, collect dependencies into DEPS // 2. else add trigger to DELAY goto 4 @@ -1400,7 +1401,7 @@ dataflow: &DepGraphImpl, trigger: GraphIx, level_info: &ReactionLevelInfo, - reactions: &mut ExecutableReactions<'static>, + reactions: &mut ExecutableReactions<'static>, ) { for downstream in dataflow.edges_directed(trigger, Outgoing) { let node = &dataflow[downstream.target()]; @@ -1412,17 +1413,17 @@ NodeKind::Reaction => { let rid = match node.id { GraphId::Reaction(rid) => rid, - _ => unreachable!("this is a reaction"), + _ => unreachable!("this is a reaction"), }; // trigger->reaction if downstream.weight() != &EdgeWeight::Use { - // so it's a trigger dependency + // so it's a trigger dependency level_info.augment(reactions, rid) } } _ => { // trigger->action? this is malformed - panic!("malformed dependency graph") + panic!("malformed dependency graph") } } } @@ -1434,13 +1435,13 @@ /// # Panics /// /// If the trigger id is not registered - pub fn reactions_triggered_by(&self, trigger: &TriggerId) -> &ExecutableReactions<'static> { + pub fn reactions_triggered_by(&self, trigger: &TriggerId) -> &ExecutableReactions<'static> { &self.trigger_to_plan[*trigger] } } cfg_if! { - if #[cfg(feature = "vec-id-sets")] { + if #[cfg(feature = "vec-id-sets")] { type LevelImpl = Vec<GlobalReactionId>; } else { type LevelImpl = std::collections::HashSet<GlobalReactionId>; @@ -1465,7 +1466,7 @@ fn insert(&mut self, id: GlobalReactionId) { cfg_if! { - if #[cfg(feature = "vec-id-sets")] { + if #[cfg(feature = "vec-id-sets")] { match self.0.binary_search(&id) { Ok(_) => {} Err(ix) => { @@ -1485,21 +1486,21 @@ fn extend(&mut self, iter: impl Iterator<Item = GlobalReactionId>) { self.0.extend(iter); cfg_if! { - if #[cfg(feature = "vec-id-sets")] { + if #[cfg(feature = "vec-id-sets")] { self.0.sort(); self.0.dedup(); } } } - pub fn iter(&self) -> impl Iterator<Item = GlobalReactionId> + '_ { + pub fn iter(&self) -> impl Iterator<Item = GlobalReactionId> + '_ { self.0.iter().cloned() } } -impl<'a> IntoIterator for &'a Level { - type Item = &'a GlobalReactionId; - type IntoIter = <&'a LevelImpl as IntoIterator>::IntoIter; +impl<'a> IntoIterator for &'a Level { + type Item = &'a GlobalReactionId; + type IntoIter = <&'a LevelImpl as IntoIterator>::IntoIter; fn into_iter(self) -> Self::IntoIter { (self.0).iter() @@ -1529,8 +1530,8 @@ } impl Display for LevelIx { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.0) + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.0) } } @@ -1545,7 +1546,7 @@ /// 1. they may be merged together (by a [DataflowInfo]). /// 2. merging two plans eliminates duplicates #[derive(Clone, Debug, Default)] -pub struct ExecutableReactions<'x> { +pub struct ExecutableReactions<'x> { /// An ordered list of levels to execute. /// /// It must by construction be the case that a reaction @@ -1562,10 +1563,10 @@ /// /// Note also that the last level in the list must be /// non-empty by construction. - levels: VecMap<LevelIx, Cow<'x, Level>>, + levels: VecMap<LevelIx, Cow<'x, Level>>, } -impl<'x> ExecutableReactions<'x> { +impl<'x> ExecutableReactions<'x> { pub fn new() -> Self { Self { levels: VecMap::new() } } @@ -1574,7 +1575,7 @@ /// with their level. Note that this does not mutate this collection /// (eg drain it), because that way we can use borrowed Cows /// and avoid more allocation. - pub fn batches(&self) -> impl Iterator<Item = &(LevelIx, Cow<'x, Level>)> + '_ { + pub fn batches(&self) -> impl Iterator<Item = &(LevelIx, Cow<'x, Level>)> + '_ { self.levels.iter() } @@ -1583,7 +1584,7 @@ } #[inline] - pub fn next_batch<'a>(&'a self, min_level_exclusive: KeyRef<&LevelIx>) -> Option<(KeyRef<&'a LevelIx>, &Level)> { + pub fn next_batch<'a>(&'a self, min_level_exclusive: KeyRef<&LevelIx>) -> Option<(KeyRef<&'a LevelIx>, &Level)> { self.levels .next_mapping(min_level_exclusive) .map(|(ix, cow)| (ix, cow.as_ref())) @@ -1596,13 +1597,13 @@ /// Merge the given set of reactions into this one. /// Ignore levels that come strictly before `min_level_inclusive`, may even clear them. - pub fn absorb_after(&mut self, src: &ExecutableReactions<'x>, min_level_inclusive: LevelIx) { + pub fn absorb_after(&mut self, src: &ExecutableReactions<'x>, min_level_inclusive: LevelIx) { let src = &src.levels; let dst = &mut self.levels; // Find the next mapping >= to the min level. - // We don't care about the mappings that come before. - // If there is none we won't loop at all. + // We don't care about the mappings that come before. + // If there is none we won't loop at all. let mut next_src = src.find_random_mapping_after(min_level_inclusive); let mut dst_position_hint: Option<KeyRef<LevelIx>> = None; @@ -1648,17 +1649,17 @@ } /// Fully merge plans of `x` and `y`. - pub(super) fn merge_cows(x: ReactionPlan<'x>, y: ReactionPlan<'x>) -> ReactionPlan<'x> { + pub(super) fn merge_cows(x: ReactionPlan<'x>, y: ReactionPlan<'x>) -> ReactionPlan<'x> { Self::merge_plans_after(x, y, LevelIx::ZERO) } - // todo would be nice to simplify this, it's hot + // todo would be nice to simplify this, it's hot /// Produce the set union of two reaction plans. /// Levels below the `min_level` are not merged, and the caller - /// shouldn't query them. For all levels >= `min_level`, + /// shouldn't query them. For all levels >= `min_level`, /// the produced reaction plan has all the reactions of /// `x` and `y` for that level. - pub(super) fn merge_plans_after(x: ReactionPlan<'x>, y: ReactionPlan<'x>, min_level: LevelIx) -> ReactionPlan<'x> { + pub(super) fn merge_plans_after(x: ReactionPlan<'x>, y: ReactionPlan<'x>, min_level: LevelIx) -> ReactionPlan<'x> { match (x, y) { (x, None) | (None, x) => x, (Some(x), y) | (y, Some(x)) if x.max_level() < min_level => y, @@ -1678,13 +1679,13 @@ } } -impl Display for ExecutableReactions<'_> { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - write!(f, "[")?; +impl Display for ExecutableReactions<'_> { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "[")?; for (_, level) in self.levels.iter() { - join_to!(f, level.iter(), ", ", "{", "} ; ")?; + join_to!(f, level.iter(), ", ", "{", "} ; ")?; } - write!(f, "]") + write!(f, "]") } } @@ -1729,17 +1730,17 @@ #[allow(unused)] fn eprintln_graph(&self) { - eprintln!("{}", self.graph.format_dot(&self.debug_info)); + eprintln!("{}", self.graph.format_dot(&self.debug_info)); } } - struct TestAssembler<'a> { - fixture: &'a mut TestGraphFixture, + struct TestAssembler<'a> { + fixture: &'a mut TestGraphFixture, reactor_id: ReactorId, first_trigger_id: TriggerId, } - impl TestAssembler<'_> { + impl TestAssembler<'_> { fn new_reactions<const N: usize>(&mut self) -> [GlobalReactionId; N] { let result = array![i => GlobalReactionId::new(self.reactor_id, LocalReactionId::from_usize(i)); N]; let mut last = None; @@ -1753,7 +1754,7 @@ result } - fn new_ports<const N: usize>(&mut self, names: [&'static str; N]) -> [TriggerId; N] { + fn new_ports<const N: usize>(&mut self, names: [&'static str; N]) -> [TriggerId; N] { let result = array![_ => self.fixture.next_trigger_id.get_and_incr().unwrap(); N]; for (i, p) in (&result).iter().enumerate() { self.fixture.graph.record_port(*p); @@ -1763,7 +1764,7 @@ } } - impl Drop for TestAssembler<'_> { + impl Drop for TestAssembler<'_> { fn drop(&mut self) { let range = self.first_trigger_id..self.fixture.next_trigger_id; self.fixture.debug_info.set_id_range(self.reactor_id, range) @@ -1816,9 +1817,9 @@ fn test_level_assignment_simple() { let mut test = TestGraphFixture::new(); - let mut builder = test.new_reactor("main"); + let mut builder = test.new_reactor("main"); let [n1, n2] = builder.new_reactions(); - let [p0] = builder.new_ports(["p0"]); + let [p0] = builder.new_ports(["p0"]); drop(builder); test.graph.reaction_effects(n1, p0); @@ -1832,9 +1833,9 @@ fn test_level_assignment_diamond_1() { let mut test = TestGraphFixture::new(); - let mut builder = test.new_reactor("main"); + let mut builder = test.new_reactor("main"); let [n1, n2] = builder.new_reactions(); - let [p0, p1] = builder.new_ports(["p0", "p1"]); + let [p0, p1] = builder.new_ports(["p0", "p1"]); drop(builder); test.graph.reaction_effects(n1, p0); @@ -1851,16 +1852,16 @@ fn test_level_assignment_diamond_1_exponential() { let mut test = TestGraphFixture::new(); - let mut builder = test.new_reactor("top"); - let [mut prev_in] = builder.new_ports(["in"]); + let mut builder = test.new_reactor("top"); + let [mut prev_in] = builder.new_ports(["in"]); drop(builder); // the number of paths in the graph is exponential // in this upper bound, here 3^60. for reactor_id in 0..60 { - let mut builder = test.new_reactor(format!("r[{}]", reactor_id)); + let mut builder = test.new_reactor(format!("r[{}]", reactor_id)); let [n1, n2] = builder.new_reactions(); - let [p0, p1, out] = builder.new_ports(["p0", "p1", "out"]); + let [p0, p1, out] = builder.new_ports(["p0", "p1", "out"]); drop(builder); // make a diamond @@ -1887,16 +1888,16 @@ fn test_level_assignment_diamond_depth2_exponential() { let mut test = TestGraphFixture::new(); - let mut builder = test.new_reactor("top"); - let [mut prev_in] = builder.new_ports(["in"]); + let mut builder = test.new_reactor("top"); + let [mut prev_in] = builder.new_ports(["in"]); drop(builder); // the number of paths in the graph is exponential // in this upper bound, here 3^60. for reactor_id in 0..60 { - let mut builder = test.new_reactor(format!("r[{}]", reactor_id)); + let mut builder = test.new_reactor(format!("r[{}]", reactor_id)); let [n1, n2] = builder.new_reactions(); - let [p0, p01, p1, p11, out] = builder.new_ports(["p0", "p01", "p1", "p11", "out"]); + let [p0, p01, p1, p11, out] = builder.new_ports(["p0", "p01", "p1", "p11", "out"]); drop(builder); // make a diamond OF DEPTH > 1 @@ -1927,9 +1928,9 @@ fn test_graph_dump() { let mut test = TestGraphFixture::new(); - let mut builder = test.new_reactor("main"); + let mut builder = test.new_reactor("main"); let [n1, n2] = builder.new_reactions(); - let [p0, p1] = builder.new_ports(["p0", "p1"]); + let [p0, p1] = builder.new_ports(["p0", "p1"]); drop(builder); test.graph.reaction_effects(n1, p0); @@ -1939,22 +1940,21 @@ assert_eq!( test.graph.format_dot(&test.debug_info), - r#"digraph { - 0 [ label = "startup" ] - 1 [ label = "shutdown" ] - 2 [ label = "Reaction(main/0)" ] - 3 [ label = "Reaction(main/1)" ] - 4 [ label = "Port(main/p0)" ] - 5 [ label = "Port(main/p1)" ] + r#"digraph { + 0 [ label = "startup" ] + 1 [ label = "shutdown" ] + 2 [ label = "Reaction(main/0)" ] + 3 [ label = "Reaction(main/1)" ] + 4 [ label = "Port(main/p0)" ] + 5 [ label = "Port(main/p1)" ] 2 -> 3 [ ] 2 -> 4 [ ] 2 -> 5 [ ] 4 -> 3 [ ] 5 -> 3 [ ] } -"# +"# ); } } -
1 +events.rs - source +\ No newline at end of file + -use std::borrow::Cow; use std::collections::VecDeque; use std::fmt::{Display, Formatter}; use std::time::Instant; @@ -346,11 +347,11 @@ } impl Display for EventTag { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { let elapsed = self.offset_from_t0; write!( f, - "(T0 + {} ns = {} ms, {})", + "(T0 + {} ns = {} ms, {})", elapsed.as_nanos(), elapsed.as_millis(), self.microstep @@ -365,26 +366,26 @@ /// [self::AsyncCtx] may only communicate with /// the scheduler by sending events. #[derive(Debug)] -pub(super) struct Event<'x> { +pub(super) struct Event<'x> { /// The tag at which the reactions to this event must be executed. /// This is always > to the latest *processed* tag, by construction /// of the reactor application. pub(super) tag: EventTag, /// A set of reactions to execute. - pub reactions: ReactionPlan<'x>, + pub reactions: ReactionPlan<'x>, /// Whether we should terminate the application at /// the tag of this event (after processing the tag). pub terminate: bool, } -impl<'x> Event<'x> { - pub fn absorb(&mut self, other: Event<'x>) { +impl<'x> Event<'x> { + pub fn absorb(&mut self, other: Event<'x>) { debug_assert_eq!(self.tag, other.tag); self.reactions = ExecutableReactions::merge_cows(self.reactions.take(), other.reactions); self.terminate |= other.terminate; } - pub fn execute(tag: EventTag, reactions: Cow<'x, ExecutableReactions<'x>>) -> Self { + pub fn execute(tag: EventTag, reactions: Cow<'x, ExecutableReactions<'x>>) -> Self { Self { tag, reactions: Some(reactions), terminate: false } } pub fn terminate_at(tag: EventTag) -> Self { @@ -426,30 +427,30 @@ /// A queue of pending [Event]s. Events are ordered by tag, /// so this is not a FIFO queue. #[derive(Default)] -pub(super) struct EventQueue<'x> { +pub(super) struct EventQueue<'x> { /// This list is sorted by the tag of each event (in ascending order). /// - /// But insertion is at worse O(n)... And it's easy to build + /// But insertion is at worse O(n)... And it's easy to build /// a pathological program where this worse case is always hit. /// Theoretically using a tree/ heap would be useful here. /// . /// .. /// ... /// .... - value_list: VecDeque<Event<'x>>, + value_list: VecDeque<Event<'x>>, } -impl<'x> EventQueue<'x> { +impl<'x> EventQueue<'x> { /// Removes and returns the earliest tag - pub fn take_earliest(&mut self) -> Option<Event<'x>> { + pub fn take_earliest(&mut self) -> Option<Event<'x>> { self.value_list.pop_front() } // todo perf: we could make a more optimal function to push a // lot of events at once. Consider the following algorithm: // - start with a sorted `self.value_list` and a (non-sorted) `new_evts: Vec<Event>` - // - sort the new events in place (in a Cow maybe). They'll - // probably come in already sorted but we can't assume this. + // - sort the new events in place (in a Cow maybe). They'll + // probably come in already sorted but we can't assume this. // Use an algorithm that best-cases for sorted data. (eg https://crates.io/crates/dmsort) // - take the earliest new event and binary search to insert it. // - then do the same thing but only on the remaining (to the right) @@ -457,12 +458,11 @@ // sort. /// Push an event into the heap. - pub(super) fn push(&mut self, evt: Event<'x>) { + pub(super) fn push(&mut self, evt: Event<'x>) { match self.value_list.binary_search_by_key(&evt.tag, |e| e.tag) { Ok(idx) => self.value_list[idx].absorb(evt), Err(idx) => self.value_list.insert(idx, evt), } } } -
1 +mod.rs - source +\ No newline at end of file + -/* * Copyright (c) 2021, TU Dresden. * * Redistribution and use in source and binary forms, with or without modification, @@ -104,7 +105,7 @@ * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, @@ -133,28 +134,28 @@ mod events; mod scheduler_impl; -#[cfg(feature = "public-internals")] +#[cfg(feature = "public-internals")] pub mod internals { pub use super::dependencies::{ExecutableReactions, Level, LevelIx, ReactionLevelInfo}; } -pub(self) type ReactionPlan<'x> = Option<Cow<'x, ExecutableReactions<'x>>>; -pub(self) type ReactorBox<'a> = Box<dyn ReactorBehavior + 'a>; -pub(self) type ReactorVec<'a> = IndexVec<ReactorId, ReactorBox<'a>>; +pub(self) type ReactionPlan<'x> = Option<Cow<'x, ExecutableReactions<'x>>>; +pub(self) type ReactorBox<'a> = Box<dyn ReactorBehavior + 'a>; +pub(self) type ReactorVec<'a> = IndexVec<ReactorId, ReactorBox<'a>>; /// Can format stuff for trace messages. #[derive(Clone)] -pub(self) struct DebugInfoProvider<'a> { - id_registry: &'a DebugInfoRegistry, +pub(self) struct DebugInfoProvider<'a> { + id_registry: &'a DebugInfoRegistry, } -impl DebugInfoProvider<'_> { +impl DebugInfoProvider<'_> { pub(self) fn display_event(&self, evt: &Event) -> String { let Event { tag, reactions, terminate } = evt; - let mut str = format!("at {}: run {}", tag, self.display_reactions(reactions)); + let mut str = format!("at {}: run {}", tag, self.display_reactions(reactions)); if *terminate { - str += ", then terminate" + str += ", then terminate" } str } @@ -162,27 +163,26 @@ pub(self) fn display_reactions(&self, reactions: &ReactionPlan) -> String { use std::fmt::*; - let mut str = "[".to_string(); + let mut str = "[".to_string(); if let Some(reactions) = reactions { for (level_no, batch) in reactions.batches() { - write!(str, "{}: ", level_no).unwrap(); - join_to!(&mut str, batch.iter(), ", ", "{", "}", |x| format!( - "{}", + write!(str, "{}: ", level_no).unwrap(); + join_to!(&mut str, batch.iter(), ", ", "{", "}", |x| format!( + "{}", self.display_reaction(x) )) .unwrap(); } } - str += "]"; + str += "]"; str } #[inline] - pub(self) fn display_reaction(&self, id: GlobalReactionId) -> impl Display + '_ { + pub(self) fn display_reaction(&self, id: GlobalReactionId) -> impl Display + '_ { self.id_registry.fmt_reaction(id) } } -
1 +scheduler_impl.rs - source +\ No newline at end of file + -/* * Copyright (c) 2021, TU Dresden. * * Redistribution and use in source and binary forms, with or without modification, @@ -519,7 +520,7 @@ * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, @@ -545,12 +546,12 @@ /// Construction parameters for the scheduler. /// -/// LFC uses target properties to set them. With the "cli" +/// LFC uses target properties to set them. With the "cli" /// feature, generated programs also feature CLI options to /// override the defaults at runtime. #[derive(Default)] pub struct SchedulerOptions { - /// If true, we won't shut down the scheduler as soon as + /// If true, we won't shut down the scheduler as soon as /// the event queue is empty, provided there are still /// live threads that can send messages to the scheduler /// asynchronously. @@ -572,9 +573,9 @@ } // Macros are placed a bit out of order to avoid exporting them -// (they're only visible in code placed AFTER them). +// (they're only visible in code placed AFTER them). // We use macros instead of private methods as the borrow checker -// needs to know we're borrowing disjoint parts of self at any time. +// needs to know we're borrowing disjoint parts of self at any time. macro_rules! debug_info { ($e:expr) => { @@ -584,30 +585,30 @@ macro_rules! push_event { ($scheduler:expr, $evt:expr) => {{ - trace!("Pushing {}", debug_info!($scheduler).display_event(&$evt)); + trace!("Pushing {}", debug_info!($scheduler).display_event(&$evt)); $scheduler.event_queue.push($evt); }}; } /// The runtime scheduler. /// -/// Lifetime parameters: 'x and 't are carried around everywhere, -/// 'x allows us to take references into the dataflow graph, and -/// 't to spawn new scoped threads for physical actions. 'a is more +/// Lifetime parameters: 'x and 't are carried around everywhere, +/// 'x allows us to take references into the dataflow graph, and +/// 't to spawn new scoped threads for physical actions. 'a is more /// useless but is needed to compile. -pub struct SyncScheduler<'x> { +pub struct SyncScheduler<'x> { /// The latest processed logical time (necessarily behind physical time). latest_processed_tag: Option<EventTag>, /// Reference to the data flow graph, which allows us to /// order reactions properly for each tag. - dataflow: &'x DataflowInfo, + dataflow: &'x DataflowInfo, /// All reactors. - reactors: ReactorVec<'x>, + reactors: ReactorVec<'x>, /// Pending events/ tags to process. - event_queue: EventQueue<'x>, + event_queue: EventQueue<'x>, /// Receiver through which asynchronous events are /// communicated to the scheduler. We only block when @@ -635,49 +636,49 @@ id_registry: DebugInfoRegistry, } -impl<'x> SyncScheduler<'x> { - pub fn run_main<R: ReactorInitializer + 'static>(options: SchedulerOptions, args: R::Params) { +impl<'x> SyncScheduler<'x> { + pub fn run_main<R: ReactorInitializer + 'static>(options: SchedulerOptions, args: R::Params) { let start = Instant::now(); - info!("Starting assembly..."); + info!("Starting assembly..."); let (reactors, graph, id_registry) = RootAssembler::assemble_tree::<R>(args); let time = Instant::now() - start; - info!("Assembly done in {} µs...", time.as_micros()); + info!("Assembly done in {} µs...", time.as_micros()); if options.dump_graph { use std::fs::File; use std::io::Write; - let path = std::env::temp_dir().join("reactors.dot"); + let path = std::env::temp_dir().join("reactors.dot"); File::create(path.clone()) - .and_then(|mut dot_file| writeln!(dot_file, "{}", graph.format_dot(&id_registry))) - .expect("Error while writing DOT file"); - eprintln!("Wrote dot file to {}", path.to_string_lossy()); + .and_then(|mut dot_file| writeln!(dot_file, "{}", graph.format_dot(&id_registry))) + .expect("Error while writing DOT file"); + eprintln!("Wrote dot file to {}", path.to_string_lossy()); } // collect dependency information let dataflow_info = DataflowInfo::new(graph).map_err(|e| e.lift(&id_registry)).unwrap(); // Using thread::scope here introduces an unnamed lifetime for - // the scope, which is captured as 't by the SyncScheduler. + // the scope, which is captured as 't by the SyncScheduler. // This is useful because it captures the constraint that the - // dataflow_info outlives 't, so that physical contexts + // dataflow_info outlives 't, so that physical contexts // can be spawned in threads that capture references - // to 'x. + // to 'x. let initial_time = Instant::now(); - #[cfg(feature = "parallel-runtime")] + #[cfg(feature = "parallel-runtime")] let rayon_thread_pool = rayon::ThreadPoolBuilder::new().num_threads(options.threads).build().unwrap(); let scheduler = SyncScheduler::new(options, id_registry, &dataflow_info, reactors, initial_time); cfg_if::cfg_if! { - if #[cfg(feature = "parallel-runtime")] { + if #[cfg(feature = "parallel-runtime")] { /// The unsafe impl is safe if scheduler instances /// are only sent between threads like this (their Rc /// internals are not copied). /// So long as the framework entirely controls the lifetime /// of SyncScheduler instances, this is enforceable. - unsafe impl Send for SyncScheduler<'_> {} + unsafe impl Send for SyncScheduler<'_> {} // install makes calls to parallel iterators use that thread pool rayon_thread_pool.install(|| scheduler.launch_event_loop()); @@ -696,7 +697,7 @@ self.startup(); loop { - // flush pending events, this doesn't block + // flush pending events, this doesn't block for evt in self.rx.try_iter() { let evt = evt.make_executable(self.dataflow); push_event!(self, evt); @@ -704,10 +705,10 @@ if let Some(evt) = self.event_queue.take_earliest() { if self.is_after_shutdown(evt.tag) { - trace!("Event is late, shutting down - event tag: {}", evt.tag); + trace!("Event is late, shutting down - event tag: {}", evt.tag); break; } - trace!("Processing event {}", self.debug().display_event(&evt)); + trace!("Processing event {}", self.debug().display_event(&evt)); match self.catch_up_physical_time(evt.tag.to_logical_time(self.initial_time)) { Ok(_) => {} Err(async_event) => { @@ -724,7 +725,7 @@ } } }; - // at this point we're at the correct time + // at this point we're at the correct time if evt.terminate || self.shutdown_time == Some(evt.tag) { return self.shutdown(evt.tag, evt.reactions); @@ -738,7 +739,7 @@ continue; } else { // all senders have hung up, or timeout - info!("Event queue is empty forever, shutting down."); + info!("Event queue is empty forever, shutting down."); break; } } // end loop @@ -749,22 +750,22 @@ // self destructor is called here } - /// Creates a new scheduler. An empty scheduler doesn't + /// Creates a new scheduler. An empty scheduler doesn't /// do anything unless some events are pushed to the queue. /// See [Self::launch_event_loop]. fn new( options: SchedulerOptions, id_registry: DebugInfoRegistry, - dependency_info: &'x DataflowInfo, - reactors: ReactorVec<'x>, + dependency_info: &'x DataflowInfo, + reactors: ReactorVec<'x>, initial_time: Instant, ) -> Self { - if !cfg!(feature = "parallel-runtime") && options.threads != 0 { - warn!("'workers' runtime parameter has no effect unless feature 'parallel-runtime' is enabled") + if !cfg!(feature = "parallel-runtime") && options.threads != 0 { + warn!("'workers' runtime parameter has no effect unless feature 'parallel-runtime' is enabled") } if options.keep_alive { - warn!("'keepalive' runtime parameter has no effect in the Rust target") + warn!("'keepalive' runtime parameter has no effect in the Rust target") } let (_, rx) = unbounded::<PhysicalEvent>(); @@ -778,7 +779,7 @@ latest_processed_tag: None, shutdown_time: options.timeout.map(|timeout| { let shutdown_tag = EventTag::ORIGIN.successor(timeout); - trace!("Timeout specified, will shut down at most at tag {}", shutdown_tag); + trace!("Timeout specified, will shut down at most at tag {}", shutdown_tag); shutdown_tag }), dataflow: dependency_info, @@ -791,30 +792,30 @@ /// physical time, and runs the startup reactions /// of all reactors. fn startup(&mut self) { - info!("Triggering startup..."); - debug_assert!(!self.reactors.is_empty(), "No registered reactors"); + info!("Triggering startup..."); + debug_assert!(!self.reactors.is_empty(), "No registered reactors"); let startup_reactions = self.dataflow.reactions_triggered_by(&TriggerId::STARTUP); self.process_tag(false, EventTag::ORIGIN, Some(Cow::Borrowed(startup_reactions))) } - fn shutdown(&mut self, shutdown_tag: EventTag, reactions: ReactionPlan<'x>) { - info!("Scheduler is shutting down, at {}", shutdown_tag); + fn shutdown(&mut self, shutdown_tag: EventTag, reactions: ReactionPlan<'x>) { + info!("Scheduler is shutting down, at {}", shutdown_tag); self.shutdown_time = Some(shutdown_tag); - let default_plan: ReactionPlan<'x> = Some(Cow::Borrowed(self.dataflow.reactions_triggered_by(&TriggerId::SHUTDOWN))); + let default_plan: ReactionPlan<'x> = Some(Cow::Borrowed(self.dataflow.reactions_triggered_by(&TriggerId::SHUTDOWN))); let reactions = ExecutableReactions::merge_cows(reactions, default_plan); self.process_tag(true, shutdown_tag, reactions); // notify concurrent threads. self.was_terminated.store(true, Ordering::SeqCst); - info!("Scheduler has been shut down") + info!("Scheduler has been shut down") } /// Returns whether the given event should be ignored and /// the event loop be terminated. This would be the case /// if the tag of the event is later than the projected - /// shutdown time. Such 'late' events may be emitted by + /// shutdown time. Such 'late' events may be emitted by /// the shutdown wave. fn is_after_shutdown(&self, t: EventTag) -> bool { self.shutdown_time.map(|shutdown_t| shutdown_t < t).unwrap_or(false) @@ -826,14 +827,14 @@ if let Some(shutdown_t) = self.shutdown_time { let absolute = shutdown_t.to_logical_time(self.initial_time); if let Some(timeout) = absolute.checked_duration_since(Instant::now()) { - trace!("Will wait for asynchronous event {} ns", timeout.as_nanos()); + trace!("Will wait for asynchronous event {} ns", timeout.as_nanos()); self.rx.recv_timeout(timeout).ok() } else { - trace!("Cannot wait, already past programmed shutdown time..."); + trace!("Cannot wait, already past programmed shutdown time..."); None } } else { - trace!("Will wait for asynchronous event without timeout"); + trace!("Will wait for asynchronous event without timeout"); self.rx.recv().ok() } } @@ -845,21 +846,21 @@ if now < target { let t = target - now; - trace!(" - Need to sleep {} ns", t.as_nanos()); + trace!(" - Need to sleep {} ns", t.as_nanos()); // we use recv_timeout as a thread::sleep so that // our sleep is interrupted properly when an async // event arrives match self.rx.recv_timeout(t) { Ok(async_evt) => { trace!( - " - Sleep interrupted by async event for tag {}, going back to queue", + " - Sleep interrupted by async event for tag {}, going back to queue", async_evt.tag ); return Err(async_evt); } Err(RecvTimeoutError::Timeout) => { /*great*/ } Err(RecvTimeoutError::Disconnected) => { - // ok, there are no physical actions in the program so it's useless to block on self.rx + // ok, there are no physical actions in the program so it's useless to block on self.rx // we still need to wait though.. if let Some(remaining) = target.checked_duration_since(Instant::now()) { std::thread::sleep(remaining); @@ -871,7 +872,7 @@ if now > target { let delay = now - target; trace!( - " - Running late by {} ns = {} µs = {} ms", + " - Running late by {} ns = {} µs = {} ms", delay.as_nanos(), delay.as_micros(), delay.as_millis() @@ -882,15 +883,15 @@ /// Create a new reaction wave to process the given /// reactions at some point in time. - fn new_reaction_ctx<'a>( + fn new_reaction_ctx<'a>( &self, tag: EventTag, - todo: ReactionPlan<'x>, - rx: &'a Receiver<PhysicalEvent>, - debug_info: DebugInfoProvider<'a>, - was_terminated_atomic: &'a Arc<AtomicBool>, + todo: ReactionPlan<'x>, + rx: &'a Receiver<PhysicalEvent>, + debug_info: DebugInfoProvider<'a>, + was_terminated_atomic: &'a Arc<AtomicBool>, was_terminated: bool, - ) -> ReactionCtx<'a, 'x> { + ) -> ReactionCtx<'a, 'x> { ReactionCtx::new( rx, tag, @@ -909,11 +910,11 @@ } /// Actually process a tag. The provided reactions are the - /// root reactions that startup the "wave". - fn process_tag(&mut self, is_shutdown: bool, tag: EventTag, mut reactions: ReactionPlan<'x>) { + /// root reactions that startup the "wave". + fn process_tag(&mut self, is_shutdown: bool, tag: EventTag, mut reactions: ReactionPlan<'x>) { if cfg!(debug_assertions) { if let Some(latest) = self.latest_processed_tag { - debug_assert!(tag > latest, "Tag ordering mismatch") + debug_assert!(tag > latest, "Tag ordering mismatch") } } self.latest_processed_tag = Some(tag); @@ -927,7 +928,7 @@ while let Some((level_no, batch)) = next_level { let level_no = level_no.cloned(); - trace!(" - Level {}", level_no); + trace!(" - Level {}", level_no); ctx.cur_level = level_no.key; /// Minimum number of reactions (inclusive) required @@ -935,8 +936,8 @@ /// TODO experiment with tweaking this const PARALLEL_THRESHOLD: usize = 3; - if cfg!(feature = "parallel-runtime") && batch.len() >= PARALLEL_THRESHOLD { - #[cfg(feature = "parallel-runtime")] + if cfg!(feature = "parallel-runtime") && batch.len() >= PARALLEL_THRESHOLD { + #[cfg(feature = "parallel-runtime")] parallel_rt_impl::process_batch(&mut ctx, &mut self.reactors, batch); } else { // the impl for non-parallel runtime @@ -964,14 +965,14 @@ } } -#[cfg(feature = "parallel-runtime")] +#[cfg(feature = "parallel-runtime")] mod parallel_rt_impl { use rayon::prelude::*; use super::*; use crate::scheduler::dependencies::Level; - pub(super) fn process_batch(ctx: &mut ReactionCtx<'_, '_>, reactors: &mut ReactorVec<'_>, batch: &Level) { + pub(super) fn process_batch(ctx: &mut ReactionCtx<'_, '_>, reactors: &mut ReactorVec<'_>, batch: &Level) { let reactors_mut = UnsafeSharedPointer(reactors.raw.as_mut_ptr()); ctx.insides.absorb( @@ -1006,13 +1007,12 @@ /// We need a Clone bound to use fold_with, but this clone /// implementation is not general purpose so I hide it. - struct CloneableCtx<'a, 'x>(ReactionCtx<'a, 'x>); + struct CloneableCtx<'a, 'x>(ReactionCtx<'a, 'x>); - impl Clone for CloneableCtx<'_, '_> { + impl Clone for CloneableCtx<'_, '_> { fn clone(&self) -> Self { Self(self.0.fork()) } } } -
1 +time.rs - source +\ No newline at end of file + -/* * Copyright (c) 2021, TU Dresden. * * Redistribution and use in source and binary forms, with or without modification, @@ -65,7 +66,7 @@ * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, @@ -94,7 +95,7 @@ } impl Display for MicroStep { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { Display::fmt(&self.0, f) } } @@ -106,5 +107,4 @@ Self(self.0 + rhs) } } -
1 +timers.rs - source +\ No newline at end of file + -/* * Copyright (c) 2021, TU Dresden. * * Redistribution and use in source and binary forms, with or without modification, @@ -107,7 +108,7 @@ * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, @@ -190,5 +191,4 @@ } } } -
1 +triggers.rs - source +\ No newline at end of file + -/* * Copyright (c) 2021, TU Dresden. * * Redistribution and use in source and binary forms, with or without modification, @@ -173,7 +174,7 @@ * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, @@ -218,7 +219,7 @@ fn use_value_ref<O>(&self, now: &EventTag, start: &Instant, action: impl FnOnce(Option<&T>) -> O) -> O; } -#[cfg(not(feature = "no-unsafe"))] +#[cfg(not(feature = "no-unsafe"))] pub trait ReactionTriggerWithRefAccess<T> { /// Returns a reference to the value, if it is present. Whether a *value* /// is present is not in general the same thing as whether *this trigger* @@ -260,7 +261,7 @@ #[allow(unused)] pub(crate) fn new(id: TriggerIdImpl) -> Self { - assert!(id > 1, "0-1 are reserved for startup & shutdown!"); + assert!(id > 1, "0-1 are reserved for startup & shutdown!"); TriggerId(id) } @@ -314,13 +315,12 @@ } impl Debug for TriggerId { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match *self { - TriggerId::STARTUP => write!(f, "startup"), - TriggerId::SHUTDOWN => write!(f, "shutdown"), - TriggerId(id) => write!(f, "{}", id), + TriggerId::STARTUP => write!(f, "startup"), + TriggerId::SHUTDOWN => write!(f, "shutdown"), + TriggerId(id) => write!(f, "{}", id), } } } -
1 +mod.rs - source +\ No newline at end of file + -/* * Copyright (c) 2021, TU Dresden. * * Redistribution and use in source and binary forms, with or without modification, @@ -295,7 +298,7 @@ * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, @@ -309,17 +312,19 @@ use std::convert::TryFrom; use std::time::Duration; +pub(crate) mod vecmap; + #[macro_export] #[doc(hidden)] macro_rules! join_to { ($f:expr, $iter:expr) => { - join_to!($f, $iter, ", ") + join_to!($f, $iter, ", ") }; ($f:expr, $iter:expr, $sep:literal) => { - join_to!($f, $iter, $sep, "", "") + join_to!($f, $iter, $sep, "", "") }; ($f:expr, $iter:expr, $sep:literal, $prefix:literal, $suffix:literal) => { - join_to!($f, $iter, $sep, $prefix, $suffix, |x| format!("{}", x)) + join_to!($f, $iter, $sep, $prefix, $suffix, |x| format!("{}", x)) }; ($f:expr, $iter:expr, $sep:literal, $prefix:literal, $suffix:literal, $display:expr) => {{ $crate::util::do_write($f, $iter, $sep, $prefix, $suffix, $display) @@ -329,21 +334,21 @@ pub(crate) fn do_write<X>( f: &mut impl std::fmt::Write, iter: impl Iterator<Item = X>, - sep: &'static str, - prefix: &'static str, - suffix: &'static str, + sep: &'static str, + prefix: &'static str, + suffix: &'static str, formatter: impl Fn(X) -> String, ) -> std::fmt::Result { let mut iter = iter; - write!(f, "{}", prefix)?; + write!(f, "{}", prefix)?; if let Some(first) = iter.next() { - write!(f, "{}", formatter(first))?; + write!(f, "{}", formatter(first))?; } for item in iter { - write!(f, "{}", sep)?; - write!(f, "{}", formatter(item))?; + write!(f, "{}", sep)?; + write!(f, "{}", formatter(item))?; } - write!(f, "{}", suffix) + write!(f, "{}", suffix) } /// Shorthand for using [After](crate::Offset::After) together with [delay]. @@ -412,7 +417,7 @@ ($amount:tt days) => { delay!($amount d) }; ($amount:tt week) => { delay!((7*$amount) d) }; ($amount:tt weeks) => { delay!($amount week) }; - ($amount:tt $i:ident) => { compile_error!(concat!("Unknown time unit `", stringify!($i), "`")) }; + ($amount:tt $i:ident) => { compile_error!(concat!("Unknown time unit `", stringify!($i), "`")) }; } /// Convenient macro to assert equality of the current tag. @@ -488,13 +493,13 @@ /// This recognizes the same strings as LF fn try_from(value: &str) -> Result<Self, Self::Error> { let u = match value { - "day" | "days" => Self::DAY, - "h" | "hour" | "hours" => Self::HOUR, - "min" | "minute" | "minutes" => Self::MIN, - "s" | "sec" | "secs" => Self::SEC, - "ms" | "msec" | "msecs" => Self::MILLI, - "us" | "usec" | "usecs" => Self::MICRO, - "ns" | "nsec" | "nsecs" => Self::NANO, + "day" | "days" => Self::DAY, + "h" | "hour" | "hours" => Self::HOUR, + "min" | "minute" | "minutes" => Self::MIN, + "s" | "sec" | "secs" => Self::SEC, + "ms" | "msec" | "msecs" => Self::MILLI, + "us" | "usec" | "usecs" => Self::MICRO, + "ns" | "nsec" | "nsecs" => Self::NANO, _ => return Err(()), }; Ok(u) @@ -526,18 +531,18 @@ /// use reactor_rt::try_parse_duration; /// use std::time::Duration; /// -/// assert_eq!(try_parse_duration("3 ms"), Ok(Duration::from_millis(3))); -/// assert_eq!(try_parse_duration("3ms"), Ok(Duration::from_millis(3))); -/// assert_eq!(try_parse_duration("5us"), Ok(Duration::from_micros(5))); -/// assert_eq!(try_parse_duration("30ns"), Ok(Duration::from_nanos(30))); -/// assert_eq!(try_parse_duration("30nsec"), Ok(Duration::from_nanos(30))); -/// assert_eq!(try_parse_duration("30secs"), Ok(Duration::from_secs(30))); +/// assert_eq!(try_parse_duration("3 ms"), Ok(Duration::from_millis(3))); +/// assert_eq!(try_parse_duration("3ms"), Ok(Duration::from_millis(3))); +/// assert_eq!(try_parse_duration("5us"), Ok(Duration::from_micros(5))); +/// assert_eq!(try_parse_duration("30ns"), Ok(Duration::from_nanos(30))); +/// assert_eq!(try_parse_duration("30nsec"), Ok(Duration::from_nanos(30))); +/// assert_eq!(try_parse_duration("30secs"), Ok(Duration::from_secs(30))); /// // unit is not required for zero -/// assert_eq!(try_parse_duration("0"), Ok(Duration::from_secs(0))); +/// assert_eq!(try_parse_duration("0"), Ok(Duration::from_secs(0))); /// -/// assert_eq!(try_parse_duration(""), Err("cannot parse empty string".into())); -/// assert_eq!(try_parse_duration("30"), Err("time unit required".into())); -/// assert_eq!(try_parse_duration("30000000000000000000000ns"), Err("number too large to fit in target type".into())); +/// assert_eq!(try_parse_duration(""), Err("cannot parse empty string".into())); +/// assert_eq!(try_parse_duration("30"), Err("time unit required".into())); +/// assert_eq!(try_parse_duration("30000000000000000000000ns"), Err("number too large to fit in target type".into())); /// /// ``` /// @@ -546,25 +551,24 @@ let mut chars = t.char_indices().skip_while(|(_, c)| c.is_numeric()); if let Some((num_end, _)) = &chars.next() { - let magnitude: u64 = t[0..*num_end].parse::<u64>().map_err(|e| format!("{}", e))?; + let magnitude: u64 = t[0..*num_end].parse::<u64>().map_err(|e| format!("{}", e))?; let unit = t[*num_end..].trim(); let duration = match TimeUnit::try_from(unit) { Ok(unit) => unit.to_duration(magnitude), - Err(_) => return Err(format!("unknown time unit '{}'", unit)), + Err(_) => return Err(format!("unknown time unit '{}'", unit)), }; Ok(duration) - } else if t != "0" { + } else if t != "0" { // no unit if !t.is_empty() { - Err("time unit required".into()) + Err("time unit required".into()) } else { - Err("cannot parse empty string".into()) + Err("cannot parse empty string".into()) } } else { Ok(Duration::from_secs(0)) } } -
1 +vecmap.rs - source +\ No newline at end of file + -/* * Copyright (c) 2021, TU Dresden. * * Redistribution and use in source and binary forms, with or without modification, @@ -348,7 +349,7 @@ * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, @@ -476,7 +477,7 @@ let from = if self.is_valid_keyref(&key) { key.min_idx } else { - 0 // it's not, maybe it was produced by another vecmap + 0 // it's not, maybe it was produced by another vecmap }; for idx in from..self.v.len() { @@ -496,7 +497,7 @@ } /// Iterate over all key-value paris in the map. - pub fn iter(&self) -> impl Iterator<Item = &(K, V)> + '_ { + pub fn iter(&self) -> impl Iterator<Item = &(K, V)> + '_ { self.v.iter() } @@ -556,7 +557,7 @@ } impl<K: Ord + Eq + Debug, V: Debug> Debug for VecMap<K, V> { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { self.v.iter().collect::<Vec<&(K, V)>>().fmt(f) } } @@ -568,38 +569,38 @@ } /// A view into a single entry in a map, which may either be vacant or occupied. -pub enum Entry<'a, K, V> +pub enum Entry<'a, K, V> where K: Ord + Eq, { /// A vacant Entry - Vacant(VacantEntry<'a, K, V>), + Vacant(VacantEntry<'a, K, V>), /// An occupied Entry - Occupied(OccupiedEntry<'a, K, V>), + Occupied(OccupiedEntry<'a, K, V>), } /// A vacant Entry. -pub struct VacantEntry<'a, K, V> +pub struct VacantEntry<'a, K, V> where K: Ord + Eq, { - map: &'a mut VecMap<K, V>, + map: &'a mut VecMap<K, V>, key: K, index: usize, } /// An occupied Entry. -pub struct OccupiedEntry<'a, K, V> +pub struct OccupiedEntry<'a, K, V> where K: Ord + Eq, { - map: &'a mut VecMap<K, V>, + map: &'a mut VecMap<K, V>, key: K, index: usize, } -impl<K, V> Entry<'_, K, V> +impl<K, V> Entry<'_, K, V> where K: Ord + Eq, { @@ -611,26 +612,26 @@ } } -impl<K, V> VacantEntry<'_, K, V> +impl<K, V> VacantEntry<'_, K, V> where K: Ord + Eq, { - /// Sets the value of the entry with the VacantEntry's key. + /// Sets the value of the entry with the VacantEntry's key. pub fn insert(self, value: V) { self.map.insert_internal(self.index, self.key, value) } } -impl<K, V> OccupiedEntry<'_, K, V> +impl<K, V> OccupiedEntry<'_, K, V> where K: Ord + Eq, { - /// Replaces the entry's value with `value`. + /// Replaces the entry's value with `value`. pub fn replace(&mut self, value: V) { self.map.v[self.index].1 = value; } - /// Gets the mutable ref to the entry's value. + /// Gets the mutable ref to the entry's value. pub fn get_mut(&mut self) -> &mut V { &mut self.map.v[self.index].1 } @@ -643,7 +644,7 @@ pub struct KeyRef<K> { pub key: K, /// This is a lower bound on the actual index of key K, - /// it doesn't need to be the index (though it usually will be). + /// it doesn't need to be the index (though it usually will be). min_idx: usize, } @@ -662,8 +663,8 @@ } impl<K: Display> Display for KeyRef<K> { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.key) + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.key) } } @@ -672,5 +673,4 @@ Self { key, min_idx: 0 } } } -
fn:
) to \
+ restrict the search to a given item kind.","Accepted kinds are: fn
, mod
, struct
, \
+ enum
, trait
, type
, macro
, \
+ and const
.","Search functions by type signature (e.g., vec -> usize
or \
+ -> vec
or String, enum:Cow -> bool
)","You can look for items with an exact name by putting double quotes around \
+ your request: \"string\"
","Look for functions that accept or return \
+ slices and \
+ arrays by writing \
+ square brackets (e.g., -> [u8]
or [] -> Option
)","Look for items inside another one by searching for a path: vec::Vec
",].map(x=>""+x+"
").join("");const div_infos=document.createElement("div");addClass(div_infos,"infos");div_infos.innerHTML="fn:
) to \
- restrict the search to a given item kind.","Accepted kinds are: fn
, mod
, struct
, \
- enum
, trait
, type
, macro
, \
- and const
.","Search functions by type signature (e.g., vec -> usize
or \
- -> vec
)","Search multiple things at once by splitting your query with comma (e.g., \
- str,u8
or String,struct:Vec,test
)","You can look for items with an exact name by putting double quotes around \
- your request: \"string\"
","Look for items inside another one by searching for a path: vec::Vec
",].map(x=>""+x+"
").join("");const div_infos=document.createElement("div");addClass(div_infos,"infos");div_infos.innerHTML="${value.replaceAll(" ", " ")}
`}else{error[index]=value}});output+=`${value}
`}else{error[index]=value}});output+=`Returns true
if the result is Ok
and the value inside of it matches a predicate.
let x: Result<u32, &str> = Ok(2);\nassert_eq!(x.is_ok_and(|x| x > 1), true);\n\nlet x: Result<u32, &str> = Ok(0);\nassert_eq!(x.is_ok_and(|x| x > 1), false);\n\nlet x: Result<u32, &str> = Err(\"hey\");\nassert_eq!(x.is_ok_and(|x| x > 1), false);
Returns true
if the result is Err
and the value inside of it matches a predicate.
use std::io::{Error, ErrorKind};\n\nlet x: Result<u32, Error> = Err(Error::new(ErrorKind::NotFound, \"!\"));\nassert_eq!(x.is_err_and(|x| x.kind() == ErrorKind::NotFound), true);\n\nlet x: Result<u32, Error> = Err(Error::new(ErrorKind::PermissionDenied, \"!\"));\nassert_eq!(x.is_err_and(|x| x.kind() == ErrorKind::NotFound), false);\n\nlet x: Result<u32, Error> = Ok(123);\nassert_eq!(x.is_err_and(|x| x.kind() == ErrorKind::NotFound), false);
Converts from Result<T, E>
to Option<E>
.
Converts self
into an Option<E>
, consuming self
,\nand discarding the success value, if any.
let x: Result<u32, &str> = Ok(2);\nassert_eq!(x.err(), None);\n\nlet x: Result<u32, &str> = Err(\"Nothing here\");\nassert_eq!(x.err(), Some(\"Nothing here\"));
Converts from &Result<T, E>
to Result<&T, &E>
.
Produces a new Result
, containing a reference\ninto the original, leaving the original in place.
let x: Result<u32, &str> = Ok(2);\nassert_eq!(x.as_ref(), Ok(&2));\n\nlet x: Result<u32, &str> = Err(\"Error\");\nassert_eq!(x.as_ref(), Err(&\"Error\"));
Converts from &mut Result<T, E>
to Result<&mut T, &mut E>
.
fn mutate(r: &mut Result<i32, i32>) {\n match r.as_mut() {\n Ok(v) => *v = 42,\n Err(e) => *e = 0,\n }\n}\n\nlet mut x: Result<i32, i32> = Ok(2);\nmutate(&mut x);\nassert_eq!(x.unwrap(), 42);\n\nlet mut x: Result<i32, i32> = Err(13);\nmutate(&mut x);\nassert_eq!(x.unwrap_err(), 0);
Maps a Result<T, E>
to Result<U, E>
by applying a function to a\ncontained Ok
value, leaving an Err
value untouched.
This function can be used to compose the results of two functions.
\nPrint the numbers on each line of a string multiplied by two.
\n\nlet line = \"1\\n2\\n3\\n4\\n\";\n\nfor num in line.lines() {\n match num.parse::<i32>().map(|i| i * 2) {\n Ok(n) => println!(\"{n}\"),\n Err(..) => {}\n }\n}
Returns the provided default (if Err
), or\napplies a function to the contained value (if Ok
).
Arguments passed to map_or
are eagerly evaluated; if you are passing\nthe result of a function call, it is recommended to use map_or_else
,\nwhich is lazily evaluated.
let x: Result<_, &str> = Ok(\"foo\");\nassert_eq!(x.map_or(42, |v| v.len()), 3);\n\nlet x: Result<&str, _> = Err(\"bar\");\nassert_eq!(x.map_or(42, |v| v.len()), 42);
Maps a Result<T, E>
to U
by applying fallback function default
to\na contained Err
value, or function f
to a contained Ok
value.
This function can be used to unpack a successful result\nwhile handling an error.
\nlet k = 21;\n\nlet x : Result<_, &str> = Ok(\"foo\");\nassert_eq!(x.map_or_else(|e| k * 2, |v| v.len()), 3);\n\nlet x : Result<&str, _> = Err(\"bar\");\nassert_eq!(x.map_or_else(|e| k * 2, |v| v.len()), 42);
Maps a Result<T, E>
to Result<T, F>
by applying a function to a\ncontained Err
value, leaving an Ok
value untouched.
This function can be used to pass through a successful result while handling\nan error.
\nfn stringify(x: u32) -> String { format!(\"error code: {x}\") }\n\nlet x: Result<u32, u32> = Ok(2);\nassert_eq!(x.map_err(stringify), Ok(2));\n\nlet x: Result<u32, u32> = Err(13);\nassert_eq!(x.map_err(stringify), Err(\"error code: 13\".to_string()));
Converts from Result<T, E>
(or &Result<T, E>
) to Result<&<T as Deref>::Target, &E>
.
Coerces the Ok
variant of the original Result
via Deref
\nand returns the new Result
.
let x: Result<String, u32> = Ok(\"hello\".to_string());\nlet y: Result<&str, &u32> = Ok(\"hello\");\nassert_eq!(x.as_deref(), y);\n\nlet x: Result<String, u32> = Err(42);\nlet y: Result<&str, &u32> = Err(&42);\nassert_eq!(x.as_deref(), y);
Converts from Result<T, E>
(or &mut Result<T, E>
) to Result<&mut <T as DerefMut>::Target, &mut E>
.
Coerces the Ok
variant of the original Result
via DerefMut
\nand returns the new Result
.
let mut s = \"HELLO\".to_string();\nlet mut x: Result<String, u32> = Ok(\"hello\".to_string());\nlet y: Result<&mut str, &mut u32> = Ok(&mut s);\nassert_eq!(x.as_deref_mut().map(|x| { x.make_ascii_uppercase(); x }), y);\n\nlet mut i = 42;\nlet mut x: Result<String, u32> = Err(42);\nlet y: Result<&mut str, &mut u32> = Err(&mut i);\nassert_eq!(x.as_deref_mut().map(|x| { x.make_ascii_uppercase(); x }), y);
Returns an iterator over the possibly contained value.
\nThe iterator yields one value if the result is Result::Ok
, otherwise none.
let x: Result<u32, &str> = Ok(7);\nassert_eq!(x.iter().next(), Some(&7));\n\nlet x: Result<u32, &str> = Err(\"nothing!\");\nassert_eq!(x.iter().next(), None);
Returns a mutable iterator over the possibly contained value.
\nThe iterator yields one value if the result is Result::Ok
, otherwise none.
let mut x: Result<u32, &str> = Ok(7);\nmatch x.iter_mut().next() {\n Some(v) => *v = 40,\n None => {},\n}\nassert_eq!(x, Ok(40));\n\nlet mut x: Result<u32, &str> = Err(\"nothing!\");\nassert_eq!(x.iter_mut().next(), None);
Returns the contained Ok
value, consuming the self
value.
Because this function may panic, its use is generally discouraged.\nInstead, prefer to use pattern matching and handle the Err
\ncase explicitly, or call unwrap_or
, unwrap_or_else
, or\nunwrap_or_default
.
Panics if the value is an Err
, with a panic message including the\npassed message, and the content of the Err
.
let x: Result<u32, &str> = Err(\"emergency failure\");\nx.expect(\"Testing expect\"); // panics with `Testing expect: emergency failure`
We recommend that expect
messages are used to describe the reason you\nexpect the Result
should be Ok
.
let path = std::env::var(\"IMPORTANT_PATH\")\n .expect(\"env variable `IMPORTANT_PATH` should be set by `wrapper_script.sh`\");
Hint: If you’re having trouble remembering how to phrase expect\nerror messages remember to focus on the word “should” as in “env\nvariable should be set by blah” or “the given binary should be available\nand executable by the current user”.
\nFor more detail on expect message styles and the reasoning behind our recommendation please\nrefer to the section on “Common Message\nStyles” in the\nstd::error
module docs.
Returns the contained Ok
value, consuming the self
value.
Because this function may panic, its use is generally discouraged.\nInstead, prefer to use pattern matching and handle the Err
\ncase explicitly, or call unwrap_or
, unwrap_or_else
, or\nunwrap_or_default
.
Panics if the value is an Err
, with a panic message provided by the\nErr
’s value.
Basic usage:
\n\nlet x: Result<u32, &str> = Ok(2);\nassert_eq!(x.unwrap(), 2);
let x: Result<u32, &str> = Err(\"emergency failure\");\nx.unwrap(); // panics with `emergency failure`
Returns the contained Ok
value or a default
Consumes the self
argument then, if Ok
, returns the contained\nvalue, otherwise if Err
, returns the default value for that\ntype.
Converts a string to an integer, turning poorly-formed strings\ninto 0 (the default value for integers). parse
converts\na string to any other type that implements FromStr
, returning an\nErr
on error.
let good_year_from_input = \"1909\";\nlet bad_year_from_input = \"190blarg\";\nlet good_year = good_year_from_input.parse().unwrap_or_default();\nlet bad_year = bad_year_from_input.parse().unwrap_or_default();\n\nassert_eq!(1909, good_year);\nassert_eq!(0, bad_year);
Returns the contained Err
value, consuming the self
value.
Panics if the value is an Ok
, with a panic message including the\npassed message, and the content of the Ok
.
let x: Result<u32, &str> = Ok(10);\nx.expect_err(\"Testing expect_err\"); // panics with `Testing expect_err: 10`
Returns the contained Err
value, consuming the self
value.
Panics if the value is an Ok
, with a custom panic message provided\nby the Ok
’s value.
let x: Result<u32, &str> = Ok(2);\nx.unwrap_err(); // panics with `2`
let x: Result<u32, &str> = Err(\"emergency failure\");\nassert_eq!(x.unwrap_err(), \"emergency failure\");
unwrap_infallible
)Returns the contained Ok
value, but never panics.
Unlike unwrap
, this method is known to never panic on the\nresult types it is implemented for. Therefore, it can be used\ninstead of unwrap
as a maintainability safeguard that will fail\nto compile if the error type of the Result
is later changed\nto an error that can actually occur.
\nfn only_good_news() -> Result<String, !> {\n Ok(\"this is fine\".into())\n}\n\nlet s: String = only_good_news().into_ok();\nprintln!(\"{s}\");
unwrap_infallible
)Returns the contained Err
value, but never panics.
Unlike unwrap_err
, this method is known to never panic on the\nresult types it is implemented for. Therefore, it can be used\ninstead of unwrap_err
as a maintainability safeguard that will fail\nto compile if the ok type of the Result
is later changed\nto a type that can actually occur.
\nfn only_bad_news() -> Result<!, String> {\n Err(\"Oops, it failed\".into())\n}\n\nlet error: String = only_bad_news().into_err();\nprintln!(\"{error}\");
Returns res
if the result is Ok
, otherwise returns the Err
value of self
.
Arguments passed to and
are eagerly evaluated; if you are passing the\nresult of a function call, it is recommended to use and_then
, which is\nlazily evaluated.
let x: Result<u32, &str> = Ok(2);\nlet y: Result<&str, &str> = Err(\"late error\");\nassert_eq!(x.and(y), Err(\"late error\"));\n\nlet x: Result<u32, &str> = Err(\"early error\");\nlet y: Result<&str, &str> = Ok(\"foo\");\nassert_eq!(x.and(y), Err(\"early error\"));\n\nlet x: Result<u32, &str> = Err(\"not a 2\");\nlet y: Result<&str, &str> = Err(\"late error\");\nassert_eq!(x.and(y), Err(\"not a 2\"));\n\nlet x: Result<u32, &str> = Ok(2);\nlet y: Result<&str, &str> = Ok(\"different result type\");\nassert_eq!(x.and(y), Ok(\"different result type\"));
Calls op
if the result is Ok
, otherwise returns the Err
value of self
.
This function can be used for control flow based on Result
values.
fn sq_then_to_string(x: u32) -> Result<String, &'static str> {\n x.checked_mul(x).map(|sq| sq.to_string()).ok_or(\"overflowed\")\n}\n\nassert_eq!(Ok(2).and_then(sq_then_to_string), Ok(4.to_string()));\nassert_eq!(Ok(1_000_000).and_then(sq_then_to_string), Err(\"overflowed\"));\nassert_eq!(Err(\"not a number\").and_then(sq_then_to_string), Err(\"not a number\"));
Often used to chain fallible operations that may return Err
.
use std::{io::ErrorKind, path::Path};\n\n// Note: on Windows \"/\" maps to \"C:\\\"\nlet root_modified_time = Path::new(\"/\").metadata().and_then(|md| md.modified());\nassert!(root_modified_time.is_ok());\n\nlet should_fail = Path::new(\"/bad/path\").metadata().and_then(|md| md.modified());\nassert!(should_fail.is_err());\nassert_eq!(should_fail.unwrap_err().kind(), ErrorKind::NotFound);
Returns res
if the result is Err
, otherwise returns the Ok
value of self
.
Arguments passed to or
are eagerly evaluated; if you are passing the\nresult of a function call, it is recommended to use or_else
, which is\nlazily evaluated.
let x: Result<u32, &str> = Ok(2);\nlet y: Result<u32, &str> = Err(\"late error\");\nassert_eq!(x.or(y), Ok(2));\n\nlet x: Result<u32, &str> = Err(\"early error\");\nlet y: Result<u32, &str> = Ok(2);\nassert_eq!(x.or(y), Ok(2));\n\nlet x: Result<u32, &str> = Err(\"not a 2\");\nlet y: Result<u32, &str> = Err(\"late error\");\nassert_eq!(x.or(y), Err(\"late error\"));\n\nlet x: Result<u32, &str> = Ok(2);\nlet y: Result<u32, &str> = Ok(100);\nassert_eq!(x.or(y), Ok(2));
Calls op
if the result is Err
, otherwise returns the Ok
value of self
.
This function can be used for control flow based on result values.
\nfn sq(x: u32) -> Result<u32, u32> { Ok(x * x) }\nfn err(x: u32) -> Result<u32, u32> { Err(x) }\n\nassert_eq!(Ok(2).or_else(sq).or_else(sq), Ok(2));\nassert_eq!(Ok(2).or_else(err).or_else(sq), Ok(2));\nassert_eq!(Err(3).or_else(sq).or_else(err), Ok(9));\nassert_eq!(Err(3).or_else(err).or_else(err), Err(3));
Returns the contained Ok
value or a provided default.
Arguments passed to unwrap_or
are eagerly evaluated; if you are passing\nthe result of a function call, it is recommended to use unwrap_or_else
,\nwhich is lazily evaluated.
let default = 2;\nlet x: Result<u32, &str> = Ok(9);\nassert_eq!(x.unwrap_or(default), 9);\n\nlet x: Result<u32, &str> = Err(\"error\");\nassert_eq!(x.unwrap_or(default), default);
Returns the contained Ok
value, consuming the self
value,\nwithout checking that the value is not an Err
.
Calling this method on an Err
is undefined behavior.
let x: Result<u32, &str> = Ok(2);\nassert_eq!(unsafe { x.unwrap_unchecked() }, 2);
let x: Result<u32, &str> = Err(\"emergency failure\");\nunsafe { x.unwrap_unchecked(); } // Undefined behavior!
Returns the contained Err
value, consuming the self
value,\nwithout checking that the value is not an Ok
.
Calling this method on an Ok
is undefined behavior.
let x: Result<u32, &str> = Ok(2);\nunsafe { x.unwrap_err_unchecked() }; // Undefined behavior!
let x: Result<u32, &str> = Err(\"emergency failure\");\nassert_eq!(unsafe { x.unwrap_err_unchecked() }, \"emergency failure\");
Maps a Result<&mut T, E>
to a Result<T, E>
by copying the contents of the\nOk
part.
let mut val = 12;\nlet x: Result<&mut i32, i32> = Ok(&mut val);\nassert_eq!(x, Ok(&mut 12));\nlet copied = x.copied();\nassert_eq!(copied, Ok(12));
Maps a Result<&mut T, E>
to a Result<T, E>
by cloning the contents of the\nOk
part.
let mut val = 12;\nlet x: Result<&mut i32, i32> = Ok(&mut val);\nassert_eq!(x, Ok(&mut 12));\nlet cloned = x.cloned();\nassert_eq!(cloned, Ok(12));
Transposes a Result
of an Option
into an Option
of a Result
.
Ok(None)
will be mapped to None
.\nOk(Some(_))
and Err(_)
will be mapped to Some(Ok(_))
and Some(Err(_))
.
#[derive(Debug, Eq, PartialEq)]\nstruct SomeErr;\n\nlet x: Result<Option<i32>, SomeErr> = Ok(Some(5));\nlet y: Option<Result<i32, SomeErr>> = Some(Ok(5));\nassert_eq!(x.transpose(), y);
result_flattening
)Converts from Result<Result<T, E>, E>
to Result<T, E>
#![feature(result_flattening)]\nlet x: Result<Result<&'static str, u32>, u32> = Ok(Ok(\"hello\"));\nassert_eq!(Ok(\"hello\"), x.flatten());\n\nlet x: Result<Result<&'static str, u32>, u32> = Ok(Err(6));\nassert_eq!(Err(6), x.flatten());\n\nlet x: Result<Result<&'static str, u32>, u32> = Err(6);\nassert_eq!(Err(6), x.flatten());
Flattening only removes one level of nesting at a time:
\n\n#![feature(result_flattening)]\nlet x: Result<Result<Result<&'static str, u32>, u32>, u32> = Ok(Ok(Ok(\"hello\")));\nassert_eq!(Ok(Ok(\"hello\")), x.flatten());\nassert_eq!(Ok(\"hello\"), x.flatten().flatten());
self
and other
) and is used by the <=
\noperator. Read moreTakes each element in the Iterator
: if it is an Err
, no further\nelements are taken, and the Err
is returned. Should no Err
\noccur, the product of all elements is returned.
This multiplies each number in a vector of strings,\nif a string could not be parsed the operation returns Err
:
let nums = vec![\"5\", \"10\", \"1\", \"2\"];\nlet total: Result<usize, _> = nums.iter().map(|w| w.parse::<usize>()).product();\nassert_eq!(total, Ok(100));\nlet nums = vec![\"5\", \"10\", \"one\", \"2\"];\nlet total: Result<usize, _> = nums.iter().map(|w| w.parse::<usize>()).product();\nassert!(total.is_err());
try_trait_v2
)Residual
type. Read moretry_trait_v2
)?
when not short-circuiting.try_trait_v2
)FromResidual::from_residual
\nas part of ?
when short-circuiting. Read moretry_trait_v2
)Output
type. Read moretry_trait_v2
)?
to decide whether the operator should produce a value\n(because this returned ControlFlow::Continue
)\nor propagate a value back to the caller\n(because this returned ControlFlow::Break
). Read moreTakes each element in the Iterator
: if it is an Err
, no further\nelements are taken, and the Err
is returned. Should no Err
occur, a\ncontainer with the values of each Result
is returned.
Here is an example which increments every integer in a vector,\nchecking for overflow:
\n\nlet v = vec![1, 2];\nlet res: Result<Vec<u32>, &'static str> = v.iter().map(|x: &u32|\n x.checked_add(1).ok_or(\"Overflow!\")\n).collect();\nassert_eq!(res, Ok(vec![2, 3]));
Here is another example that tries to subtract one from another list\nof integers, this time checking for underflow:
\n\nlet v = vec![1, 2, 0];\nlet res: Result<Vec<u32>, &'static str> = v.iter().map(|x: &u32|\n x.checked_sub(1).ok_or(\"Underflow!\")\n).collect();\nassert_eq!(res, Err(\"Underflow!\"));
Here is a variation on the previous example, showing that no\nfurther elements are taken from iter
after the first Err
.
let v = vec![3, 2, 1, 10];\nlet mut shared = 0;\nlet res: Result<Vec<u32>, &'static str> = v.iter().map(|x: &u32| {\n shared += x;\n x.checked_sub(2).ok_or(\"Underflow!\")\n}).collect();\nassert_eq!(res, Err(\"Underflow!\"));\nassert_eq!(shared, 6);
Since the third element caused an underflow, no further elements were taken,\nso the final value of shared
is 6 (= 3 + 2 + 1
), not 16.
Returns a consuming iterator over the possibly contained value.
\nThe iterator yields one value if the result is Result::Ok
, otherwise none.
let x: Result<u32, &str> = Ok(5);\nlet v: Vec<u32> = x.into_iter().collect();\nassert_eq!(v, [5]);\n\nlet x: Result<u32, &str> = Err(\"nothing!\");\nlet v: Vec<u32> = x.into_iter().collect();\nassert_eq!(v, []);
Takes each element in the Iterator
: if it is an Err
, no further\nelements are taken, and the Err
is returned. Should no Err
\noccur, the sum of all elements is returned.
This sums up every integer in a vector, rejecting the sum if a negative\nelement is encountered:
\n\nlet f = |&x: &i32| if x < 0 { Err(\"Negative element found\") } else { Ok(x) };\nlet v = vec![1, 2];\nlet res: Result<i32, _> = v.iter().map(f).sum();\nassert_eq!(res, Ok(3));\nlet v = vec![1, -2];\nlet res: Result<i32, _> = v.iter().map(f).sum();\nassert_eq!(res, Err(\"Negative element found\"));
pub enum Entry<'a, K, V>where
- K: Ord + Eq,{
- Vacant(VacantEntry<'a, K, V>),
- Occupied(OccupiedEntry<'a, K, V>),
-}
A view into a single entry in a map, which may either be vacant or occupied.
-This is a formally verified implementation of a sparse map that uses Vec underneath. -Entries are retained in sorted order by key to facilitate fast search.
-pub struct KeyRef<K> {
- pub key: K,
- /* private fields */
-}
A key zipped with its internal index in this map. -For some operations, like manually implemented iteration, -the index can be used for optimisation.
-key: K
pub struct OccupiedEntry<'a, K, V>where
- K: Ord + Eq,{ /* private fields */ }
An occupied Entry.
-pub struct VacantEntry<'a, K, V>where
- K: Ord + Eq,{ /* private fields */ }
A vacant Entry.
-pub struct VecMap<K, V>where
- K: Eq + Ord,{ /* private fields */ }
A sparse map representation over a totally ordered key type.
-Find an entry with assumption that the key is random access. -Logarithmic complexity.
-Find the entry matching key
. Use key_hint
to accelerate search.
-The function will use the provided hint to skip items before it.
-Note: This function makes two assumptions about your input:
key_hint
is valid, i.e. the underlying key is in the map and since extracting
-the reference, no item has been removed from the mapkey_hint.key <= key
If either of these assumptions is violated, you might obtain an entry which allows -destroying the well-kept order of the items.
-Finds entry reference, either directly associated with min_key_inclusive
, or the entry with the
-closest key (in terms of sorting order) greater than min_key_inclusive
. Returns None
if
-map does not contain entry with key greater or equal to min_key_inclusive
.
Insert value
for key
in the map. If key
is already contained, the function
-replaces the previously held value and returns it.
Removes the item with key
and returns its value. If no such item exists,
-it does nothing.
Checks if key
is contained in the map.
Produces the first mapping that follows the given key -in the ascending order of keys.
-Iterate over all key-value paris in the map.
-