diff --git a/.github/scripts/test-lfc.sh b/.github/scripts/test-lfc.sh index 20c087db81..a59d4acd3b 100755 --- a/.github/scripts/test-lfc.sh +++ b/.github/scripts/test-lfc.sh @@ -50,7 +50,7 @@ bin/lfc --output-path . test/C/src/Minimal.lf # --runtime-version Specify the version of the runtime # library used for compiling LF # programs. -bin/lfc --runtime-version f157be30bbeab0e2a991f29f9c7f388ca39681a7 test/Cpp/src/Minimal.lf +bin/lfc --runtime-version e80cd36ce5bd625a7b167e7dfd65d25f78b0dd01 test/Cpp/src/Minimal.lf # -w,--workers Specify the default number of worker threads. bin/lfc -w 2 test/C/src/Minimal.lf diff --git a/org.lflang/src/lib/cpp/reactor-cpp b/org.lflang/src/lib/cpp/reactor-cpp index a37f0ade9e..e80cd36ce5 160000 --- a/org.lflang/src/lib/cpp/reactor-cpp +++ b/org.lflang/src/lib/cpp/reactor-cpp @@ -1 +1 @@ -Subproject commit a37f0ade9ee0f97606528fd7ba67712495948373 +Subproject commit e80cd36ce5bd625a7b167e7dfd65d25f78b0dd01 diff --git a/org.lflang/src/org/lflang/generator/cpp/CppRos2NodeGenerator.kt b/org.lflang/src/org/lflang/generator/cpp/CppRos2NodeGenerator.kt index 064f6758f8..22e3c3045a 100644 --- a/org.lflang/src/org/lflang/generator/cpp/CppRos2NodeGenerator.kt +++ b/org.lflang/src/org/lflang/generator/cpp/CppRos2NodeGenerator.kt @@ -59,14 +59,13 @@ class CppRos2NodeGenerator( | : Node("$nodeName", node_options) { | unsigned workers = ${if (targetConfig.workers != 0) targetConfig.workers else "std::thread::hardware_concurrency()"}; | bool fast{${targetConfig.fastMode}}; - | bool keepalive{${targetConfig.keepalive}}; | reactor::Duration lf_timeout{${targetConfig.timeout?.toCppCode() ?: "reactor::Duration::max()"}}; | | // provide a globally accessible reference to this node | // FIXME: this is pretty hacky... | lf_node = this; | - | lf_env = std::make_unique(workers, keepalive, fast, lf_timeout); + | lf_env = std::make_unique(workers, fast, lf_timeout); | | // instantiate the main reactor | lf_main_reactor = std::make_unique<${main.name}> ("${main.name}", lf_env.get(), ${main.name}::Parameters{}); diff --git a/org.lflang/src/org/lflang/generator/cpp/CppStandaloneMainGenerator.kt b/org.lflang/src/org/lflang/generator/cpp/CppStandaloneMainGenerator.kt index 171b59c485..07cd3f8ba2 100644 --- a/org.lflang/src/org/lflang/generator/cpp/CppStandaloneMainGenerator.kt +++ b/org.lflang/src/org/lflang/generator/cpp/CppStandaloneMainGenerator.kt @@ -60,7 +60,6 @@ class CppStandaloneMainGenerator( | | unsigned workers = ${if (targetConfig.workers != 0) targetConfig.workers else "std::thread::hardware_concurrency()"}; | bool fast{${targetConfig.fastMode}}; - | bool keepalive{${targetConfig.keepalive}}; | reactor::Duration timeout = ${targetConfig.timeout?.toCppCode() ?: "reactor::Duration::max()"}; | | // the timeout variable needs to be tested beyond fitting the Duration-type @@ -69,7 +68,6 @@ class CppStandaloneMainGenerator( | .add_options() | ("w,workers", "the number of worker threads used by the scheduler", cxxopts::value(workers)->default_value(std::to_string(workers)), "'unsigned'") | ("o,timeout", "Time after which the execution is aborted.", cxxopts::value(timeout)->default_value(time_to_string(timeout)), "'FLOAT UNIT'") - | ("k,keepalive", "Continue execution even when there are no events to process.", cxxopts::value(keepalive)->default_value("${targetConfig.keepalive}")) | ("f,fast", "Allow logical time to run faster than physical time.", cxxopts::value(fast)->default_value("${targetConfig.fastMode}")) | ("help", "Print help"); | @@ -91,7 +89,7 @@ class CppStandaloneMainGenerator( | return parse_error ? -1 : 0; | } | - | reactor::Environment e{workers, keepalive, fast, timeout}; + | reactor::Environment e{workers, fast, timeout}; | | // instantiate the main reactor | ${generateMainReactorInstantiation()} diff --git a/org.lflang/src/org/lflang/validation/LFValidator.java b/org.lflang/src/org/lflang/validation/LFValidator.java index f53987e2b5..c2fcb1cf34 100644 --- a/org.lflang/src/org/lflang/validation/LFValidator.java +++ b/org.lflang/src/org/lflang/validation/LFValidator.java @@ -623,7 +623,7 @@ public void checkParameter(Parameter param) { Reactor reactor = (Reactor) container; if (reactor.isMain()) { // we need to check for the cli parameters that are always taken - List cliParams = List.of("t", "threads", "o", "timeout", "k", "keepalive", "f", "fast", "help"); + List cliParams = List.of("t", "threads", "o", "timeout", "f", "fast", "help"); if (cliParams.contains(param.getName())) { error("Parameter '" + param.getName() + "' is already in use as command line argument by Lingua Franca,", @@ -1030,6 +1030,7 @@ public void checkTargetProperties(KeyValuePairs targetProperties) { validateClockSyncTargetProperties(targetProperties); validateSchedulerTargetProperties(targetProperties); validateRos2TargetProperties(targetProperties); + validateKeepalive(targetProperties); } private KeyValuePair getKeyValuePair(KeyValuePairs targetProperties, TargetProperty property) { @@ -1125,6 +1126,14 @@ private void validateSchedulerTargetProperties(KeyValuePairs targetProperties) { } } + private void validateKeepalive(KeyValuePairs targetProperties) { + KeyValuePair keepalive = getKeyValuePair(targetProperties, TargetProperty.KEEPALIVE); + if (keepalive != null && target == Target.CPP) { + warning("The keepalive property is inferred automatically by the C++ " + + "runtime and the value given here is ignored", keepalive, Literals.KEY_VALUE_PAIR__NAME); + } + } + private void validateRos2TargetProperties(KeyValuePairs targetProperties) { KeyValuePair ros2 = getKeyValuePair(targetProperties, TargetProperty.ROS2); KeyValuePair ros2Dependencies = getKeyValuePair(targetProperties, TargetProperty.ROS2_DEPENDENCIES); diff --git a/test/Cpp/src/concurrent/AsyncCallback.lf b/test/Cpp/src/concurrent/AsyncCallback.lf index 29fedc41e8..984132f133 100644 --- a/test/Cpp/src/concurrent/AsyncCallback.lf +++ b/test/Cpp/src/concurrent/AsyncCallback.lf @@ -1,7 +1,6 @@ // Test asynchronous callbacks that trigger a physical action. target Cpp { timeout: 2 sec, - keepalive: true, cmake-include: "AsyncCallback.cmake" } diff --git a/test/Cpp/src/concurrent/AsyncCallback2.lf b/test/Cpp/src/concurrent/AsyncCallback2.lf index ea493a32cd..322413617b 100644 --- a/test/Cpp/src/concurrent/AsyncCallback2.lf +++ b/test/Cpp/src/concurrent/AsyncCallback2.lf @@ -1,7 +1,6 @@ // Test asynchronous callbacks that trigger a non-physical action. target Cpp { timeout: 2 sec, - keepalive: true, cmake-include: "AsyncCallback.cmake" } diff --git a/test/Cpp/src/properties/Keepalive.lf b/test/Cpp/src/properties/Keepalive.lf deleted file mode 100644 index 1fe6c5e1bc..0000000000 --- a/test/Cpp/src/properties/Keepalive.lf +++ /dev/null @@ -1,43 +0,0 @@ -target Cpp { - keepalive: true, - cmake-include: "../concurrent/AsyncCallback.cmake" -} - -main reactor { - public preamble {= - #include - =} - - state thread: std::thread - - physical action a - state success: bool{false} - - reaction(startup) -> a {= - // start new thread - this->thread = std::thread([&] () { - // Simulate time passing before a callback occurs - std::this_thread::sleep_for(1s); - a.schedule(); - }); - =} - - reaction(a) {= - success = true; - environment()->sync_shutdown(); - =} - - reaction(shutdown) {= - if (success) { - std::cout << "SUCCESS!\n"; - } else { - std::cout << "ERROR: reaction was not invoked!\n"; - exit(1); - } - - // make sure to join the thread before shutting down - if(thread.joinable()) { - thread.join(); - } - =} -}