Skip to content

Commit

Permalink
Respond to review plus some other tuning
Browse files Browse the repository at this point in the history
  • Loading branch information
edwardalee committed Oct 5, 2023
1 parent bfd12f7 commit ca455e1
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 67 deletions.
42 changes: 23 additions & 19 deletions examples/C/src/distributed/CAL.lf
Original file line number Diff line number Diff line change
Expand Up @@ -6,73 +6,77 @@
* "Consistency vs. Availability in Distributed Cyber-Physical Systems". ACM Transactions on
* Embedded Computing Systems (TECS), September 2023. https://dl.acm.org/doi/10.1145/3609119
*
* This program has two `Sense` sources of events, `s1` and `s2`, with periods 500ms and 1s
* respectively. The `s1` output is processed by the `Process` reactor, which takes at least 35ms to
* process the data (emulated by sleeping). As a consequence of this processing latency, were it not
* for the 200ms `after` delay, the 30ms deadline of the `Actuate` reactor would be violated every
* time. The deadline is on the second reaction, which cannot be invoked before the first reaction
* when both reactions are enabled.
* This program has two `Sense` sources of events, `s1` and `s2` with identical periods of 1s. The
* `s1` output is processed by the `Process` reactor, which takes at least 35ms to process the data
* (emulated by sleeping). As a consequence of this processing latency, were it not for the 200ms
* `after` delay, the 30ms deadline of the `Actuate` reactor would be violated every time. The
* deadline is on the second reaction, which cannot be invoked before the first reaction when both
* reactions are enabled.
*
* The deadline is an availability requirement, the `after` delay is a tolerance for inconsistency,
* and the 35ms processing time is a latency. As long as the actual latency is not greater than the
* 200ms tolerance for inconsistency plus the 30ms tolerance for unavailability, then availability
* requirement will be met.
* and the 35ms processing time is a latency (The C A L in CAL). As long as the actual latency is
* not greater than the 200ms tolerance for inconsistency plus the 30ms tolerance for
* unavailability, then availability requirement will be met.
*
* Removing or reducing the after delay strengthens consistency but causes deadline violations.
*
* This program uses centralized coordination, so if the processing latency plus communication
* latency exceeds the 200ms tolerance for inconsistency and the 30ms tolerance for unavailability
* (the deadline), then the coordinator will preserve consistency at the expense of availability.
* I.e., the deadline will be violated.
*
* @author Edward A. Lee
*/
target C {
coordination: centralized
timeout: 5 s
}

preamble {=
#include "platform.h"
=}

reactor Sense(period: time = 500 ms) {
// Produce a counting sequence starting with 1.
reactor Sense(period: time = 1 s) {
state count: int = 1
output out: int
timer t(period, period)
timer t(0, period)

reaction(t) -> out {=
lf_set(out, self->count++);
=}
}

// Pass the input unchanged to the output, but take a long time to do it.
reactor Process {
input in: int
output out: int

reaction(in) -> out {=
lf_sleep(MSEC(35));
lf_set(out, in->value * 2);
lf_set(out, in->value);
=}
}

// Report the inputs.
reactor Actuate {
input in1: int
input in2: int

reaction(in1) {=
printf(PRINTF_TIME ": Received %d\n", lf_time_logical_elapsed(), in1->value);
lf_print(PRINTF_TIME ": Received on in1: %d", lf_time_logical_elapsed(), in1->value);
=}

reaction(in2) {=
printf(PRINTF_TIME ": Second input: %d\n", lf_time_logical_elapsed(), in2->value);
lf_print(PRINTF_TIME ": Received on in2: %d", lf_time_logical_elapsed(), in2->value);
=} deadline(30 ms) {=
printf(PRINTF_TIME ": Second input: %d ", lf_time_logical_elapsed(), in2->value);
printf("PANIC! Deadline violated!\n");
lf_print(PRINTF_TIME ": Received on in2: %d", lf_time_logical_elapsed(), in2->value);
lf_print(" *** PANIC! Deadline violated!");
=}
}

federated reactor {
s1 = new Sense(period = 500 ms)
s2 = new Sense(period = 1 s)
s1 = new Sense()
s2 = new Sense()
c1 = new Process()
a = new Actuate()
s1.out -> c1.in
Expand Down
74 changes: 26 additions & 48 deletions examples/C/src/distributed/CALDecentralized.lf
Original file line number Diff line number Diff line change
Expand Up @@ -6,82 +6,60 @@
* "Consistency vs. Availability in Distributed Cyber-Physical Systems". ACM Transactions on
* Embedded Computing Systems (TECS), September 2023. https://dl.acm.org/doi/10.1145/3609119
*
* This program has two `Sense` sources of events, `s1` and `s2`, with periods 500ms and 1s
* respectively. The `s1` output is processed by the `Process` reactor, which takes at least 35ms to
* process the data (emulated by sleeping). As a consequence of this processing delay, were it not
* for the 200ms `after` delay, the 30ms deadline of the `Actuate` reactor would be violated every
* time. The deadline is on the second reaction, which cannot be invoked before the first reaction
* when both reactions are enabled.
*
* The deadline is an availability requirement, the `after` delay is a tolerance for inconsistency,
* and the 35ms processing time is a latency. As long as the actual latency is not greater than the
* 200ms tolerance for inconsistency plus the 30ms tolerance for unavailability, then availability
* requirement will be met.
* This program is just like CAL.lf except that it uses decentralized coordination.
*
* Removing or reducing the after delay strengthens consistency but causes deadline violations.
*
* This program uses decentralized coordination, so if the processing latency plus communication
* latency exceeds the 200ms tolerance for inconsistency plus the 30ms tolerance for unavailability
* (the deadline), then the coordinator can preserve availability at the expense of consistency.
* (the deadline), then the system can only preserve availability at the expense of consistency.
* However, in order to do that, you need to adjust the STP offset, which corresponds to the
* processing offset in the CAL theorem. If you remove the 200ms `after` delay, you will need to
* increase the STP offset in the `Actuate` reactor to get proper decentralized control. Any number
* significantly larger than the 35ms processing latency should be sufficient to prevent STP
* violations, but such a number will result in a deadline violation. Setting a lower number
* prevents the deadline violation, but at the cost of getting consistency violations.
* increase the STP offset in the `Actuate` reactor to ensure that it does not prematurely assume
* the inputs are absent. Any number significantly larger than the 35ms processing latency should be
* sufficient to prevent STP violations, but such a number will result in a deadline violation.
* Setting a lower number prevents the deadline violation, but at the cost of getting consistency
* violations. It is also possible to get _both_ deadline and consistency violations.
*
* @author Edward A. Lee
*/
target C {
coordination: decentralized
coordination: decentralized,
timeout: 5 s
}

preamble {=
#include "platform.h"
=}

reactor Sense(period: time = 500 ms) {
state count: int = 1
output out: int
timer t(period, period)
import Sense, Process from "CAL.lf"

reaction(t) -> out {=
lf_set(out, self->count++);
=}
}

reactor Process {
input in: int
output out: int

reaction(in) -> out {=
lf_sleep(MSEC(35));
lf_set(out, in->value * 2);
=}
// Override the base class to provide an STP offset.
reactor ProcessFed(STP_offset: time = 10 ms) extends Process {
}

reactor Actuate {
// Report inputs received.
// STP_offset parameter is needed to ensure receiving the last input at time 5s.
// This has to be less than the deadline or the deadline will always be violated.
reactor Actuate(STP_offset: time = 20 ms) {
input in1: int
input in2: int

reaction(in1) {=
printf(PRINTF_TIME ": Received %d\n", lf_time_logical_elapsed(), in1->value);
=} STP(10 ms) {=
printf(PRINTF_TIME ": Consistency violation! Received %d\n", lf_time_logical_elapsed(), in1->value);
lf_print(PRINTF_TIME ": Received on in1: %d", lf_time_logical_elapsed(), in1->value);
=} STP(0) {=
// No _additional_ STP offset is needed here.
lf_print(PRINTF_TIME ": Consistency violation! Received %d", lf_time_logical_elapsed(), in1->value);
=}

reaction(in2) {=
printf(PRINTF_TIME ": Second input: %d\n", lf_time_logical_elapsed(), in2->value);
lf_print(PRINTF_TIME ": Received on in2: %d", lf_time_logical_elapsed(), in2->value);
=} deadline(30 ms) {=
printf(PRINTF_TIME ": Second input: %d ", lf_time_logical_elapsed(), in2->value);
printf("PANIC! Deadline violated!\n");
lf_print(PRINTF_TIME ": Received on in2: %d", lf_time_logical_elapsed(), in2->value);
lf_print(" *** PANIC! Deadline violated!");
=}
}

federated reactor {
s1 = new Sense(period = 500 ms)
s2 = new Sense(period = 1 s)
c1 = new Process()
s1 = new Sense()
s2 = new Sense()
c1 = new ProcessFed()
a = new Actuate()
s1.out -> c1.in
c1.out -> a.in1 after 200 ms
Expand Down

0 comments on commit ca455e1

Please sign in to comment.