reactor_rt/
lib.rs

1/*
2 * Copyright (c) 2021, TU Dresden.
3 *
4 * Redistribution and use in source and binary forms, with or without modification,
5 * are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright notice,
8 *    this list of conditions and the following disclaimer.
9 *
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 *    this list of conditions and the following disclaimer in the documentation
12 *    and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
16 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
18 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
21 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
22 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 */
24
25//! The runtime library for reactor programs generated by LFC,
26//! the [Lingua Franca](https://github.com/lf-lang/lingua-franca) compiler.
27//!
28//! Most of this crate consists of types that are manipulated
29//! only by the generated code. User-written Rust code mostly
30//! interacts with the type [ReactionCtx], which is the entry
31//! point for user documentation.
32//!
33//! Crate-level features include:
34//! - `parallel-runtime`: use Rayon to execute reactions in parallel
35//!   when possible. This is not yet the default. For some applications,
36//!   where there is no data parallelism, this may harm performance
37//!   (as well as pull in unneeded dependencies) and should be off.
38//! - `wide-ids`: Enables 64-bit wide reaction ids on 64-bit
39//!   architectures. This may reduce performance, but allows for
40//!   2^32 reactor instances compared to the default of 2^16,
41//!   which may feel a bit tight for some applications. On machines
42//!   with a pointer-width of less than 64 bits, ID types are
43//!   always 32 bits. The feature also widens trigger ids to 64 bits
44//!   if possible, which enables 2^64 individual trigger components
45//!   (ports, actions, etc.) instead of 2^32.
46//! - `vec-id-sets`: Change the implementation of reaction sets
47//!   to be a sorted vector instead of a hash set. This has a positive
48//!   performance impact, as reaction sets are typically very small.
49//!   More testing is required to determine pathological cases.
50//!   This is a default feature.
51//! - `no-unsafe`: disable optimisations that use unsafe code in this runtime.
52//!   Just provided for comparison, should probably be removed (unsafe code is fine).
53
54// #![deny(unused_crate_dependencies)]
55#![deny(unused_extern_crates)]
56// #![warn(unreachable_pub)]
57#![warn(unused_lifetimes)]
58#![warn(single_use_lifetimes)]
59#![warn(explicit_outlives_requirements)]
60
61#[macro_use]
62extern crate array_macro;
63#[cfg(test)]
64#[allow(unused, unused_imports)]
65#[macro_use]
66extern crate assert_matches;
67// #[macro_use]
68// extern crate index_vec;
69#[macro_use]
70extern crate log;
71#[cfg(feature = "parallel-runtime")]
72extern crate rayon;
73#[macro_use]
74extern crate static_assertions;
75#[macro_use]
76extern crate cfg_if;
77
78pub use std::time::{Duration, Instant};
79
80pub(crate) use scheduler::debug::*;
81
82pub use self::actions::*;
83pub use self::ids::*;
84pub use self::ports::*;
85pub use self::scheduler::*;
86pub use self::time::*;
87pub use self::timers::*;
88pub use self::triggers::ReactionTrigger;
89pub use self::util::*;
90
91#[cfg(test)]
92pub mod test;
93
94mod actions;
95mod ids;
96mod ports;
97mod scheduler;
98mod time;
99mod timers;
100mod triggers;
101mod util;
102
103pub mod assembly;
104
105/// The prelude that is imported at the top of reactor files
106/// generated by LFC.
107pub mod prelude {
108    pub use crate::Offset::*;
109    pub use crate::{
110        after, assert_tag_is, delay, tag, AsyncCtx, Duration, EventTag, Instant, LogicalAction, Multiport, PhysicalActionRef,
111        Port, ReactionCtx, Timer,
112    };
113
114    /// Alias for the unit type, so that it can be written without quotes in LF.
115    /// Otherwise it needs to be written `{= () =}`.
116    /// It is not camel-case as it is actually a primitive type.
117    #[allow(non_camel_case_types)]
118    pub type unit = ();
119}
120
121/// The trait used by the framework to interact with the reactor
122/// during runtime.
123///
124/// Importantly, it's object-safe and has no type parameters
125/// or associated types. This allows us to wrap it into a
126/// `Box<dyn ReactorBehavior>`.
127pub trait ReactorBehavior {
128    /// The unique ID of this reactor. This is given by the
129    /// framework upon construction.
130    fn id(&self) -> ReactorId;
131
132    /// Execute a single user-written reaction.
133    /// Dispatches on the reaction id, and unpacks parameters,
134    /// which are the reactor components declared as fields of
135    /// this struct.
136    ///
137    /// It must always be the case that `local_rid < Self::MAX_REACTION_ID`,
138    /// where `Self::MAX_REACTION_ID` is defined by the [assembly::ReactorInitializer],
139    /// because of object safety.
140    fn react(&mut self, ctx: &mut ReactionCtx, local_rid: LocalReactionId);
141
142    /// Acknowledge that the given tag is done executing and
143    /// free resources if need be.
144    fn cleanup_tag(&mut self, ctx: &CleanupCtx);
145}
146assert_obj_safe!(ReactorBehavior);
147
148/// Used for benchmarking to access private API of the crate.
149#[cfg(feature = "public-internals")]
150#[doc(hidden)]
151pub mod internals {
152    pub use crate::ids::impl_types::*;
153    pub use crate::scheduler::internals::*;
154    use crate::{GlobalId, GlobalReactionId};
155
156    pub fn new_global_rid(u: GlobalIdImpl) -> GlobalReactionId {
157        GlobalReactionId(GlobalId::from_raw(u))
158    }
159}