Skip to content

Commit

Permalink
Merge pull request #2012 from lf-lang/cpp-shutdown
Browse files Browse the repository at this point in the history
Fixed timeout and shutdown in C++
  • Loading branch information
cmnrd authored Sep 20, 2023
2 parents 7284ddd + f7386ed commit 4aa386d
Show file tree
Hide file tree
Showing 9 changed files with 181 additions and 84 deletions.
28 changes: 28 additions & 0 deletions test/Cpp/src/ShutdownAsync.lf
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
target Cpp

main reactor {
logical action check_shutdown
timer request_shutdown(1 ms)
timer after_shutdown(2 ms)

reaction(request_shutdown) -> check_shutdown {=
// async_shutdown can be called from external threads to shutdown
// at the next possible tag. If it is called from a reaction, the
// next possible tag should always be the next microstep.
environment()->async_shutdown();
check_shutdown.schedule();
=}

reaction(shutdown, check_shutdown) {=
if (!(shutdown.is_present() && check_shutdown.is_present())) {
reactor::log::Error() << "shutdown was not triggered at the expcetd tag";
exit(1);
}
reactor::log::Info() << "Success!";
=}

reaction(after_shutdown) {=
reactor::log::Error() << "triggered a reaction after shutdown";
exit(2);
=}
}
25 changes: 25 additions & 0 deletions test/Cpp/src/ShutdownSync.lf
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
target Cpp

main reactor {
logical action check_shutdown
timer request_shutdown(1 ms)
timer after_shutdown(2 ms)

reaction(request_shutdown) -> check_shutdown {=
environment()->sync_shutdown();
check_shutdown.schedule();
=}

reaction(shutdown, check_shutdown) {=
if (!(shutdown.is_present() && check_shutdown.is_present())) {
reactor::log::Error() << "shutdown was not triggered at the expcetd tag";
exit(1);
}
reactor::log::Info() << "Success!";
=}

reaction(after_shutdown) {=
reactor::log::Error() << "triggered a reaction after shutdown";
exit(2);
=}
}
24 changes: 24 additions & 0 deletions test/Cpp/src/Starve.lf
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
target Cpp

main reactor {
timer t(1 s)
logical action after_shutdown: void

reaction(t) -> after_shutdown {=
reactor::log::Info() << "Timer triggered at " << get_tag();
=}

reaction(shutdown) -> after_shutdown {=
reactor::log::Info() << "Shutdown triggered at " << get_tag();
if(get_elapsed_logical_time() != 1s || get_microstep() != 1) {
reactor::log::Error() << "Shutdown invoked at wrong tag";
exit(2);
}
after_shutdown.schedule();
=}

reaction(after_shutdown) {=
reactor::log::Error() << "Executed a reaction after shutdown";
exit(1);
=}
}
19 changes: 19 additions & 0 deletions test/Cpp/src/StarveZero.lf
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
target Cpp

main reactor {
logical action after_shutdown: void

reaction(shutdown) -> after_shutdown {=
reactor::log::Info() << "Shutdown triggered at " << get_tag();
if(get_elapsed_logical_time() != 0s || get_microstep() != 1) {
reactor::log::Error() << "Shutdown invoked at wrong tag";
exit(2);
}
after_shutdown.schedule();
=}

reaction(after_shutdown) {=
reactor::log::Error() << "Executed a reaction after shutdown";
exit(1);
=}
}
29 changes: 26 additions & 3 deletions test/Cpp/src/TimeLimit.lf
Original file line number Diff line number Diff line change
Expand Up @@ -19,23 +19,39 @@ reactor Clock(offset: time = 0, period: time = 1 sec) {
reactor Destination {
input x: int
state s: int = 1
state shutdown_invoked: bool = false
input check_shutdown: void

reaction(x) {=
//std::cout << "Received " << *x.get() << '\n';
if (*x.get() != s) {
std::cerr << "Error: Expected " << s << " and got " << *x.get() << '\n';
reactor::log::Error() << "Expected " << s << " and got " << *x.get();
exit(1);
}
if (*x.get() == 12 && !shutdown_invoked) {
reactor::log::Error() << "Shutdown wasn't invoked!";
}
s++;
=}

reaction(shutdown) {=
std::cout << "**** shutdown reaction invoked.\n";
shutdown_invoked = true;
if(get_microstep() != 1) {
reactor::log::Error() << "Expected microstep == 1, but got " << get_microstep();
exit(2);
}
if (s != 12) {
std::cerr << "ERROR: Expected 12 but got " << s << '\n';
reactor::log::Error() << "Expected 12 but got " << s;
exit(1);
}
=}

reaction(check_shutdown) {=
if (!shutdown_invoked) {
reactor::log::Error() << "Shutdown wasn't invoked!";
}
=}
}

main reactor TimeLimit(period: time = 1 sec) {
Expand All @@ -44,7 +60,14 @@ main reactor TimeLimit(period: time = 1 sec) {
d = new Destination()
c.y -> d.x

reaction(stop) {=
logical action check: void

reaction(stop) -> check {=
environment()->sync_shutdown();
check.schedule();
=}

reaction(check) -> d.check_shutdown {=
d.check_shutdown.set();
=}
}
44 changes: 0 additions & 44 deletions test/Cpp/src/Timeout_Test.lf

This file was deleted.

66 changes: 50 additions & 16 deletions test/Cpp/src/properties/Timeout.lf
Original file line number Diff line number Diff line change
@@ -1,31 +1,65 @@
/**
* A test for the timeout functionality in Lingua Franca.
*
* @author Maiko Brants TU Dresden
*
* Modeled after the C version of this test.
*/
target Cpp {
timeout: 1 sec
timeout: 11 msec
}

main reactor {
timer t(1 sec, 1 sec)
import Sender from "../lib/LoopedActionSender.lf"

reactor Consumer {
input in: int
state success: bool = false

state triggered: bool = false
logical action after_shutdown: void

reaction(t) {=
triggered = true;
if (get_elapsed_logical_time() != 1s) {
std::cout << "ERROR: triggered reaction at an unexpected tag";
timer check_shutdown(11 ms)

reaction(in) {=
auto current{get_elapsed_logical_time()};
if(current > 11ms ){
reactor::log::Error() << "Received at: " << current.count() << ". Failed to enforce timeout.";
exit(1);
} else if(current == 11ms) {
success=true;
}
=}

reaction(shutdown) {=
if (get_elapsed_logical_time() != 1s || get_microstep() != 0) {
std::cout << "ERROR: shutdown invoked at an unexpected tag";
exit(2);
reaction(shutdown) -> after_shutdown {=
reactor::log::Info() << "Shutdown invoked at tag " << get_tag();
if((get_elapsed_logical_time() == 11ms ) && get_microstep() == 0 && (success == true)){
reactor::log::Info() << "SUCCESS: successfully enforced timeout.";
after_shutdown.schedule();
} else {
reactor::log::Error() << "Failed to enforce timeout at the correct tag.";
exit(1);
}
=}

if (triggered) {
std::cout << "SUCCESS!\n";
} else {
std::cout << "ERROR: reaction was not invoked!\n";
reaction(check_shutdown, shutdown) {=
if (check_shutdown.is_present() && !shutdown.is_present()) {
reactor::log::Error() << "Shutdown was not triggered at the expected tag";
exit(2);
}
if (!check_shutdown.is_present() && shutdown.is_present()) {
reactor::log::Error() << "Shutdown was triggered at an unxpected tag: " << get_tag();
exit(2);
}
=}

reaction(after_shutdown) {=
reactor::log::Error() << "Executed a reaction after timeout.";
exit(2);
=}
}

main reactor {
consumer = new Consumer()
producer = new Sender(take_a_break_after=10, break_interval = 1 msec)

producer.out -> consumer.in
}
28 changes: 8 additions & 20 deletions test/Cpp/src/properties/TimeoutZero.lf
Original file line number Diff line number Diff line change
@@ -1,31 +1,19 @@
target Cpp {
timeout: 0 sec
timeout: 0 s
}

main reactor {
timer t(0, 1 sec)
timer should_never_trigger(1 s)

state triggered: bool = false

reaction(t) {=
triggered = true;
if (get_elapsed_logical_time() != 0s) {
std::cout << "ERROR: triggered reaction at an unexpected tag";
reaction(startup, shutdown) {=
if (!(startup.is_present() && shutdown.is_present())) {
reactor::log::Error() << "Shutdown was not triggered at startup";
exit(1);
}
=}

reaction(shutdown) {=
if (get_elapsed_logical_time() != 0s || get_microstep() != 0) {
std::cout << "ERROR: shutdown invoked at an unexpected tag";
exit(2);
}

if (triggered) {
std::cout << "SUCCESS!\n";
} else {
std::cout << "ERROR: reaction was not invoked!\n";
exit(2);
}
reaction(should_never_trigger) {=
reactor::log::Error() << "Executed a reaction after timeout.";
exit(2);
=}
}

0 comments on commit 4aa386d

Please sign in to comment.