Skip to content

Commit

Permalink
Merge pull request #2128 from lf-lang/last-time
Browse files Browse the repository at this point in the history
Fix minimum spacing of actions and reference to freed event
  • Loading branch information
lhstrh authored Dec 14, 2023
2 parents f6ef5dc + ebc23f9 commit 04e3456
Show file tree
Hide file tree
Showing 8 changed files with 141 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,13 @@ public static String generateInitializers(ReactorInstance instance) {
? CTypes.getInstance().getTargetTimeExpr(minSpacing)
: CGenerator.UNDEFINED_MIN_SPACING)
+ ";";
var lastTimeInitializer = triggerStructName + ".last_time = NEVER;";
code.addAll(
List.of(
"// Initializing action " + action.getFullName(),
offsetInitializer,
periodInitializer));
periodInitializer,
lastTimeInitializer));

var mode = action.getMode(false);
if (mode != null) {
Expand Down
2 changes: 1 addition & 1 deletion core/src/main/java/org/lflang/generator/c/CGenerator.java
Original file line number Diff line number Diff line change
Expand Up @@ -1253,7 +1253,7 @@ private void generateInteractingContainedReactors(
constructorCode.pr(
String.join(
"\n",
portOnSelf + "_trigger.last = NULL;",
portOnSelf + "_trigger.last_time = NEVER;",
portOnSelf + "_trigger.number_of_reactions = " + triggered.size() + ";"));

// Set the physical_time_of_arrival
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1024,7 +1024,7 @@ private static void createTriggerT(
var varName = variable.getName();
// variable is a port, a timer, or an action.
body.pr("trigger_t _lf__" + varName + ";");
constructorCode.pr("self->_lf__" + varName + ".last = NULL;");
constructorCode.pr("self->_lf__" + varName + ".last_time = NEVER;");
constructorCode.pr(
CExtensionUtils.surroundWithIfFederatedDecentralized(
"self->_lf__"
Expand Down Expand Up @@ -1097,7 +1097,7 @@ public static void generateBuiltinTriggeredReactionsArray(
constructorCode.pr(
String.join(
"\n",
"self->_lf__" + name + ".last = NULL;",
"self->_lf__" + name + ".last_time = NEVER;",
"self->_lf__" + name + ".reactions = &self->_lf__" + name + "_reactions[0];",
"self->_lf__" + name + ".number_of_reactions = " + reactions.size() + ";",
"self->_lf__" + name + ".is_timer = false;"));
Expand Down
45 changes: 45 additions & 0 deletions test/C/src/LastTimeDefer.lf
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Test for https://github.com/lf-lang/reactor-c/issues/145
// This tests the defer policy, which is the default.
target C {
timeout: 1 s
}

main reactor {
timer t(0, 100 ms)
logical action a(1 ms, 300 ms): int
state c: int = 0
state c2: int = 0 // For expected values.
state last: time = 0

reaction(startup) {=
// Unfortunately, a time state variable cannot be initialized with NEVER.
// So we do that here.
self->last = NEVER;
=}

reaction(t) -> a {=
tag_t now = lf_tag();
instant_t start = lf_time_start();
lf_print("(Timer) Current: " PRINTF_TIME ", Scheduled: " PRINTF_TIME ", Count: %d",
now.time - start, now.time + MSEC(1) - start, self->c
);
lf_schedule_int(a, 0, self->c++);
=}

reaction(a) {=
tag_t now = lf_tag();
instant_t start = lf_time_start();
lf_print("(Action) Current: " PRINTF_TIME ", Microstep: %d, Count: %d",
now.time - start, now.microstep, a->value
);
// Check min_spacing.
if (now.time < self->last + MSEC(300)) {
lf_print_error_and_exit("Minimum spacing of 300ms was violated.");
}
// The value should be equal to the current state c before incrementing.
if (a->value != self->c2++) {
lf_print_error_and_exit("Expected value %d", self->c2 - 1);
}
self->last = now.time;
=}
}
44 changes: 44 additions & 0 deletions test/C/src/LastTimeDrop.lf
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Test for https://github.com/lf-lang/reactor-c/issues/145
// This tests the drop policy.
target C {
timeout: 1 s
}

main reactor {
timer t(0, 100 ms)
logical action a(1 ms, 300 ms, "drop"): int
state c: int = 0
state last: time = 0

reaction(startup) {=
// Unfortunately, a time state variable cannot be initialized with NEVER.
// So we do that here.
self->last = NEVER;
=}

reaction(t) -> a {=
tag_t now = lf_tag();
instant_t start = lf_time_start();
lf_print("(Timer) Current: " PRINTF_TIME ", Scheduled: " PRINTF_TIME ", Count: %d",
now.time - start, now.time + MSEC(1) - start, self->c
);
lf_schedule_int(a, 0, self->c++);
=}

reaction(a) {=
tag_t now = lf_tag();
instant_t start = lf_time_start();
lf_print("(Action) Current: " PRINTF_TIME ", Microstep: %d, Count: %d",
now.time - start, now.microstep, a->value
);
// Check min_spacing.
if (now.time < self->last + MSEC(300)) {
lf_print_error_and_exit("Minimum spacing of 300ms was violated.");
}
// The value should be equal to the current state c before incrementing.
if (a->value != self->c - 1) {
lf_print_error_and_exit("Expected value %d", self->c - 1);
}
self->last = now.time;
=}
}
44 changes: 44 additions & 0 deletions test/C/src/LastTimeReplace.lf
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Test for https://github.com/lf-lang/reactor-c/issues/145
// This tests the replace policy.
target C {
timeout: 1 s
}

main reactor {
timer t(0, 100 ms)
logical action a(1 ms, 300 ms, "replace"): int
state c: int = 0
state last: time = 0

reaction(startup) {=
// Unfortunately, a time state variable cannot be initialized with NEVER.
// So we do that here.
self->last = NEVER;
=}

reaction(t) -> a {=
tag_t now = lf_tag();
instant_t start = lf_time_start();
lf_print("(Timer) Current: " PRINTF_TIME ", Scheduled: " PRINTF_TIME ", Count: %d",
now.time - start, now.time + MSEC(1) - start, self->c
);
lf_schedule_int(a, 0, self->c++);
=}

reaction(a) {=
tag_t now = lf_tag();
instant_t start = lf_time_start();
lf_print("(Action) Current: " PRINTF_TIME ", Microstep: %d, Count: %d",
now.time - start, now.microstep, a->value
);
// Check min_spacing.
if (now.time < self->last + MSEC(300)) {
lf_print_error_and_exit("Minimum spacing of 300ms was violated.");
}
// The value should be equal to the current state c before incrementing.
if (a->value != self->c - 1) {
lf_print_error_and_exit("Expected value %d", self->c - 1);
}
self->last = now.time;
=}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ reactor Receiver(takeBreakAfter: number = 10, breakInterval: time = 550 msec) {
state receivedMessages: number = 0
state totalReceivedMessages: number = 0
state breaks: number = 0
timer t(0, 1 msec) // This will impact the performance
timer t(0, 10 msec) // This will impact the performance

// but forces the logical time to advance Comment this line for a more sensible log output.
reaction(inp) {=
Expand Down

0 comments on commit 04e3456

Please sign in to comment.