From 9fad72e3ba1a2fa10adb271ad90a698945aeaf3d Mon Sep 17 00:00:00 2001 From: Philip Top Date: Sun, 22 Apr 2018 21:07:02 -0700 Subject: [PATCH 01/10] add definitions to not use experimental/any on mac platform --- src/helics/common/CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/helics/common/CMakeLists.txt b/src/helics/common/CMakeLists.txt index 460bb86699..1e4f16254f 100644 --- a/src/helics/common/CMakeLists.txt +++ b/src/helics/common/CMakeLists.txt @@ -89,5 +89,9 @@ if (HELICS_HAVE_ZEROMQ) target_include_directories (helics_common PRIVATE "${ZeroMQ_INCLUDE_DIR}") endif(HELICS_HAVE_ZEROMQ) +if (APPLE) + target_compile_definitions(helics_common PUBLIC "-DSTX_NO_STD_ANY=1") +endif(APPLE) + install(FILES ${helics_public_common} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/helics/common COMPONENT headers) From 69e9027a9cab4738bce06bbd17e3eae0df83be74 Mon Sep 17 00:00:00 2001 From: Philip Top Date: Sun, 22 Apr 2018 21:09:12 -0700 Subject: [PATCH 02/10] add compile def to core to not use experimental/any on mac builds --- src/helics/core/CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/helics/core/CMakeLists.txt b/src/helics/core/CMakeLists.txt index b851b9b80b..d73eedd397 100644 --- a/src/helics/core/CMakeLists.txt +++ b/src/helics/core/CMakeLists.txt @@ -174,6 +174,10 @@ IF (VERSION_OPTION) ENDIF (MSVC) ENDIF(VERSION_OPTION) +if (APPLE) + target_compile_definitions(helics_core PUBLIC "-DSTX_NO_STD_ANY=1") +endif(APPLE) + if (${MPI_C_FOUND}) source_group("mpi" FILES ${MPI_SOURCE_FILES} ${MPI_HEADER_FILES}) endif (${MPI_C_FOUND}) From 58346eef0a2d5821655a04dfc1a8d9bd2ad25f91 Mon Sep 17 00:00:00 2001 From: Dheepak Krishnamurthy Date: Tue, 24 Apr 2018 15:15:51 -0600 Subject: [PATCH 03/10] Update windows.md installation --- docs/installation/windows.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/docs/installation/windows.md b/docs/installation/windows.md index a19a447cbe..8e333f3169 100644 --- a/docs/installation/windows.md +++ b/docs/installation/windows.md @@ -23,11 +23,11 @@ To set up your environment: 1.61 or later recommended (core library should build with 1.58, but tests will not). For CMake to detect it automatically either extract Boost to the root of your drive, or set the BOOST\_INSTALL\_PATH - environment variable to the install location. The cmake will only automatically find - boost 1.61 or newer. + environment variable to the install location. The cmake will only automatically find + boost 1.61 or newer. Building with Visual Studio 2017 will require boost 1.65.1 or newer and cmake 3.9 or newer. Use 14.0 versions for Visual Studio 2015, 14.1 files for Visual studio 2017. - Boost 1.66 with cmake 3.11 is the current recommended configuration. + Boost 1.66 with cmake 3.11 is the current recommended configuration. 3. *Optional* Install [ZeroMQ](http://zeromq.org/build:_start) if you need ZeroMQ support and need a copy in a global system location. We recommend skipping this step and running cmake with the @@ -39,7 +39,7 @@ To set up your environment: if you need MPI support. 5. *Optional* Install [SWIG](http://www.swig.org/download.html) - if you wish to generate the interface libraries, appropriate build files are + if you wish to generate the interface libraries, appropriate build files are included in the repository so it shouldn't be necessary to regenerate unless the libraries are modified 6. Open a Visual Studio Command Prompt, and go to your working directory. @@ -115,9 +115,12 @@ recorder (located in the 'build\src\helics\apps\player\Debug' folder): Building HELICS with python support ----------------------------------- -setting `-DBUILD_PYTHON_INTERFACE=ON` will generate a project to build the python interface, if python is installed to a system +Setting `-DBUILD_PYTHON_INTERFACE=ON` will generate a project to build the python interface, if python is installed to a system path then the appropriate libraries and flags will be automatically found. If SWIG is available and you wish to regenerate the interface set SWIG\_EXECUTABLE to the location of swig.exe. Otherwise DISABLE\_SWIG can be set to ON to build using repo sources for the interface. +We highly recommend using Anaconda3/Miniconda3 for the Python distribution. +Additionally, you will need to ensure that the Python distribution used is built using the same compiler architecture (x86/x64) as the one you are using to build HELICS, as well as the one that was used to build Boost (as mentioned above). +ZeroMQ will be built using the CMake build process. ![](../img/windows-command-line-install.png) From fa04e2399c468afaa7f03a064cb0669a60c78d8c Mon Sep 17 00:00:00 2001 From: Philip Top Date: Wed, 25 Apr 2018 13:30:20 -0700 Subject: [PATCH 04/10] Fix the fault on using the version return from apps issue #280 --- src/helics/apps/Echo.cpp | 13 ++++++----- src/helics/apps/Player.cpp | 16 +++++++++----- src/helics/apps/Recorder.cpp | 16 +++++++++----- src/helics/apps/Source.cpp | 15 ++++++++----- src/helics/apps/Tracer.cpp | 15 ++++++++----- src/helics/apps/appMain.cpp | 21 ++++++++++++------ src/helics/apps/helicsApp.cpp | 34 ++++++++++++++++++++++++----- src/helics/apps/helicsApp.hpp | 1 + tests/helics/apps/PlayerTests.cpp | 12 ++++++++++ tests/helics/apps/RecorderTests.cpp | 14 ++++++++++++ 10 files changed, 115 insertions(+), 42 deletions(-) diff --git a/src/helics/apps/Echo.cpp b/src/helics/apps/Echo.cpp index c7b0425da8..7f260faf8b 100644 --- a/src/helics/apps/Echo.cpp +++ b/src/helics/apps/Echo.cpp @@ -23,12 +23,15 @@ static const ArgDescriptors InfoArgs{{"delay", "the delay with which the echo ap Echo::Echo (int argc, char *argv[]) : App ("echo", argc, argv) { - variable_map vm_map; - argumentParser (argc, argv, vm_map, InfoArgs); - loadArguments (vm_map); - if (!masterFileName.empty ()) + if (!deactivated) { - loadFile (masterFileName); + variable_map vm_map; + argumentParser(argc, argv, vm_map, InfoArgs); + loadArguments(vm_map); + if (!masterFileName.empty()) + { + loadFile(masterFileName); + } } } diff --git a/src/helics/apps/Player.cpp b/src/helics/apps/Player.cpp index d822faf120..cc84ee5ead 100644 --- a/src/helics/apps/Player.cpp +++ b/src/helics/apps/Player.cpp @@ -50,14 +50,18 @@ static const ArgDescriptors InfoArgs{ Player::Player (int argc, char *argv[]):App("player",argc,argv) { - fed->setFlag (SOURCE_ONLY_FLAG); - variable_map vm_map; - argumentParser(argc, argv, vm_map, InfoArgs); - loadArguments(vm_map); - if (!masterFileName.empty()) + if (!deactivated) { - loadFile(masterFileName); + fed->setFlag(SOURCE_ONLY_FLAG); + variable_map vm_map; + argumentParser(argc, argv, vm_map, InfoArgs); + loadArguments(vm_map); + if (!masterFileName.empty()) + { + loadFile(masterFileName); + } } + } Player::Player (const FederateInfo &fi) : App(fi) diff --git a/src/helics/apps/Recorder.cpp b/src/helics/apps/Recorder.cpp index ea18dd299e..b3796f23b1 100644 --- a/src/helics/apps/Recorder.cpp +++ b/src/helics/apps/Recorder.cpp @@ -49,14 +49,18 @@ static const ArgDescriptors InfoArgs{ Recorder::Recorder (int argc, char *argv[]):App("recorder",argc,argv) { - fed->setFlag (OBSERVER_FLAG); - variable_map vm_map; - argumentParser(argc, argv, vm_map, InfoArgs); - loadArguments(vm_map); - if (!masterFileName.empty()) + if (!deactivated) { - loadFile(masterFileName); + fed->setFlag(OBSERVER_FLAG); + variable_map vm_map; + argumentParser(argc, argv, vm_map, InfoArgs); + loadArguments(vm_map); + if (!masterFileName.empty()) + { + loadFile(masterFileName); + } } + } Recorder::Recorder (const std::shared_ptr &core, const FederateInfo &fi):App(core,fi) diff --git a/src/helics/apps/Source.cpp b/src/helics/apps/Source.cpp index a763c35791..f97c908cee 100644 --- a/src/helics/apps/Source.cpp +++ b/src/helics/apps/Source.cpp @@ -45,13 +45,16 @@ static const ArgDescriptors InfoArgs{ Source::Source (int argc, char *argv[]):App("source",argc,argv) { - fed->setFlag(SOURCE_ONLY_FLAG); - variable_map vm_map; - argumentParser(argc, argv, vm_map, InfoArgs, "input"s); - loadArguments(vm_map); - if (!masterFileName.empty()) + if (!deactivated) { - loadFile(masterFileName); + fed->setFlag(SOURCE_ONLY_FLAG); + variable_map vm_map; + argumentParser(argc, argv, vm_map, InfoArgs, "input"s); + loadArguments(vm_map); + if (!masterFileName.empty()) + { + loadFile(masterFileName); + } } } diff --git a/src/helics/apps/Tracer.cpp b/src/helics/apps/Tracer.cpp index 7c5d894981..3debf9d164 100644 --- a/src/helics/apps/Tracer.cpp +++ b/src/helics/apps/Tracer.cpp @@ -50,13 +50,16 @@ static const ArgDescriptors InfoArgs{ Tracer::Tracer(int argc, char *argv[]):App("tracer",argc,argv) { - fed->setFlag(OBSERVER_FLAG); - variable_map vm_map; - argumentParser(argc, argv, vm_map, InfoArgs); - loadArguments(vm_map); - if (!masterFileName.empty()) + if (!deactivated) { - loadFile(masterFileName); + fed->setFlag(OBSERVER_FLAG); + variable_map vm_map; + argumentParser(argc, argv, vm_map, InfoArgs); + loadArguments(vm_map); + if (!masterFileName.empty()) + { + loadFile(masterFileName); + } } } diff --git a/src/helics/apps/appMain.cpp b/src/helics/apps/appMain.cpp index 1ee92d9f8c..8dab18515f 100644 --- a/src/helics/apps/appMain.cpp +++ b/src/helics/apps/appMain.cpp @@ -8,10 +8,12 @@ All rights reserved. See LICENSE file and DISCLAIMER for more details. #include "Recorder.hpp" #include "Echo.hpp" #include "Tracer.hpp" +#include "Source.hpp" #include "../core/BrokerFactory.hpp" #include "../core/core-exceptions.hpp" #include "../core/helicsVersion.hpp" #include +#include void showHelp() { @@ -26,6 +28,7 @@ int main (int argc, char *argv[]) if (argc == 1) { showHelp(); + return 0; } std::string arg1(argv[1]); //now redo the arguments remove the second argument which is the app name @@ -36,7 +39,7 @@ int main (int argc, char *argv[]) } try { - if (arg1 == "player") + if (boost::iequals(arg1,"player")) { helics::apps::Player Player(argc, argv); if (Player.isActive()) @@ -45,7 +48,7 @@ int main (int argc, char *argv[]) } } - else if (arg1 == "recorder") + else if (boost::iequals(arg1, "recorder")) { helics::apps::Recorder Recorder(argc, argv); if (Recorder.isActive()) @@ -62,7 +65,7 @@ int main (int argc, char *argv[]) { showHelp(); } - else if (arg1 == "echo") + else if (boost::iequals(arg1, "echo")) { helics::apps::Echo Echo(argc, argv); if (Echo.isActive()) @@ -70,15 +73,19 @@ int main (int argc, char *argv[]) Echo.run(); } } - else if (arg1 == "source") + else if (boost::iequals(arg1, "source")) { - + helics::apps::Source Source(argc, argv); + if (Source.isActive()) + { + Source.run(); + } } - else if (arg1 == "broker") + else if (boost::iequals(arg1, "broker")) { } - else if (arg1 == "tracer") + else if (boost::iequals(arg1, "tracer")) { helics::apps::Tracer Tracer(argc, argv); if (Tracer.isActive()) diff --git a/src/helics/apps/helicsApp.cpp b/src/helics/apps/helicsApp.cpp index a61ea30289..7704e216db 100644 --- a/src/helics/apps/helicsApp.cpp +++ b/src/helics/apps/helicsApp.cpp @@ -37,24 +37,46 @@ namespace helics namespace apps { -static const ArgDescriptors InfoArgs{ +static const ArgDescriptors basicAppArgs{ {"local", ArgDescriptor::arg_type_t::flag_type, "specify otherwise unspecified endpoints and publications as local( i.e.the keys will be prepended with the player name"}, - {"stop", "the time to stop the player"} + {"stop", "the time to stop the player"}, + {"quiet", ArgDescriptor::arg_type_t::flag_type, "turn off most display output"} }; App::App (const std::string &appName,int argc, char *argv[]) { variable_map vm_map; - auto res = argumentParser(argc, argv, vm_map, InfoArgs,"input"); + //check for quiet mode + for (int ii = 0; ii < argc; ++ii) + { + if (argv[ii] != nullptr) + { + if (strcmp(argv[ii], "--quiet") == 0) + { + quietMode = true; + } + } + } + auto res = argumentParser(argc, argv, vm_map, basicAppArgs,"input"); + if (vm_map.count("quiet") > 0) + { + quietMode = true; + } if (res == versionReturn) { - std::cout << helics::versionString<< '\n'; + if (!quietMode) + { + std::cout << helics::versionString << '\n'; + } } if (res == helpReturn) { - FederateInfo helpTemp(argc, argv); + if (!quietMode) + { + FederateInfo helpTemp(argc, argv); + } } - if (res < 0) + if (res != 0) { deactivated = true; return; diff --git a/src/helics/apps/helicsApp.hpp b/src/helics/apps/helicsApp.hpp index 6761492a49..f0e8fccc0a 100644 --- a/src/helics/apps/helicsApp.hpp +++ b/src/helics/apps/helicsApp.hpp @@ -108,6 +108,7 @@ class App bool useLocal = false; bool fileLoaded = false; bool deactivated = false; + bool quietMode = false; }; } // namespace apps } // namespace helics diff --git a/tests/helics/apps/PlayerTests.cpp b/tests/helics/apps/PlayerTests.cpp index 35ac0e7487..e581b4e614 100644 --- a/tests/helics/apps/PlayerTests.cpp +++ b/tests/helics/apps/PlayerTests.cpp @@ -541,6 +541,18 @@ BOOST_DATA_TEST_CASE (simple_message_player_test_files, boost::unit_test::data:: fut.get (); } +BOOST_AUTO_TEST_CASE(player_test_help) +{ + StringToCmdLine cmdArg("--version --quiet"); + helics::apps::Player play1(cmdArg.getArgCount(),cmdArg.getArgV()); + + BOOST_CHECK(!play1.isActive()); + + StringToCmdLine cmdArg2("-? --quiet"); + helics::apps::Player play2(cmdArg2.getArgCount(), cmdArg2.getArgV()); + + BOOST_CHECK(!play2.isActive()); +} /* BOOST_AUTO_TEST_CASE (simple_player_test) { diff --git a/tests/helics/apps/RecorderTests.cpp b/tests/helics/apps/RecorderTests.cpp index 1a465ebfd8..f91f072e05 100644 --- a/tests/helics/apps/RecorderTests.cpp +++ b/tests/helics/apps/RecorderTests.cpp @@ -694,4 +694,18 @@ BOOST_AUTO_TEST_CASE (recorder_test_saveFile3) boost::filesystem::remove (filename); boost::filesystem::remove (filename2); } + +BOOST_AUTO_TEST_CASE(recorder_test_help) +{ + StringToCmdLine cmdArg("--version --quiet"); + helics::apps::Recorder rec1(cmdArg.getArgCount(), cmdArg.getArgV()); + + BOOST_CHECK(!rec1.isActive()); + + StringToCmdLine cmdArg2("-? --quiet"); + helics::apps::Recorder rec2(cmdArg2.getArgCount(), cmdArg2.getArgV()); + + BOOST_CHECK(!rec2.isActive()); +} + BOOST_AUTO_TEST_SUITE_END () From a7938a66170b07dbe8bdd9202fe206c1677a9da5 Mon Sep 17 00:00:00 2001 From: Dheepak Krishnamurthy Date: Thu, 26 Apr 2018 09:22:43 -0600 Subject: [PATCH 05/10] Update docs/installation/index.md --- docs/installation/index.md | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/docs/installation/index.md b/docs/installation/index.md index abe48ddab8..2869286460 100644 --- a/docs/installation/index.md +++ b/docs/installation/index.md @@ -18,3 +18,39 @@ Lines that don’t start with `$` are typically showing the output of the previo linux ``` +The following are a few things that could be useful to know before starting out. + +Firstly, you can follow HELICS development on our [GitHub](https://github.com/GMLC-TDC/HELICS-src) page. +HELICS is open-source. The development team uses `git` for version control, and GitHub to host the code publically. +The latest HELICS will be on the `develop` branch. +Tagged releases occur on the `master` branch. +If you clone the HELICS-src repository, you will be placed in the `master` branch by default. +To switch to the `develop` branch, you can type the following: + +```bash +git checkout develop +``` + +To switch to a tagged release, you can type the following: + +```bash +git checkout v1.0.1 +``` + +You will not need a full understanding of how `git` works for installing HELICS, but if you are interested you can find a good `git` resource in [this page](https://git-scm.com/book/en/v2). + +Secondly, HELICS-src is a modern CPP cross-platform software application. +One challenge while maintaining the same codebase across multiple operating systems is that we have to ensure that everything installs correctly everywhere. +The development team uses `CMake` to build HELICS. +`CMake` is a cross-platform tool designed to build, test and package software. +Having the latest version of `CMake` can make the build process much smoother. +`CMake` reads certain files (CMakeLists.txt) from the HELICS-src repository, and creates a bunch of build files. +These build files specify how different files depend on each other and when these build files are run, HELICS is built. +The exact instructions to run on each operating system are given in the individual installation instructions, but one important thing to remember is that these build files are essentially temporary files. +If you have an issue building HELICS, once you make a change (installing/removing/adding anything), you probably need to delete these temporary files and re-generate them. +We've found in practice that you don't have to do this too often, but it can save hours of frustration if you are already aware that this needs to be done. + +Another valuable piece of information about `CMake` is that almost every "OPTION" is configurable while you generate the build files. +This means you can pass it configurations settings as a key value pair by adding `-D{NAME_OF_OPTION}={VALUE_OF_OPTION}` to the `cmake` command line interface. +For example, to build the Python extension all you need to do is pass in `-DBUILD_PYTHON_INTERFACE=ON`. +Again, there are more instructions in the individual installation pages but a useful trick to know if something isn't documented or a slightly more advanced feature is required. From 534499027c178d7acd6c56c50d7a00b3a48c42ae Mon Sep 17 00:00:00 2001 From: Philip Top Date: Thu, 26 Apr 2018 14:29:44 -0400 Subject: [PATCH 06/10] Thread safety improvements2 (#282) * change to ensure timer is canceled before exiting in brokerBase * fix data race in filters * change override specification in commsBroker * change the way the destructors work a little for the various cores to no use a virtual call * minor tweaks to test case and disconnect process * tweak some locking times --- CMakeLists.txt | 7 ++- appveyor.yml | 2 +- src/helics/application_api/Endpoints.cpp | 1 - src/helics/application_api/Federate.cpp | 11 +++-- src/helics/common/AsioServiceManager.h | 4 +- src/helics/core/BrokerBase.cpp | 55 ++++++++++++++++------- src/helics/core/CommonCore.cpp | 15 ++++--- src/helics/core/CommsBroker.hpp | 3 +- src/helics/core/CommsBroker_impl.hpp | 18 +++++--- src/helics/core/CoreBroker.cpp | 2 +- src/helics/core/ipc/IpcBroker.cpp | 2 - src/helics/core/ipc/IpcBroker.h | 3 -- src/helics/core/ipc/IpcCore.cpp | 2 - src/helics/core/ipc/IpcCore.h | 3 +- src/helics/core/tcp/TcpBroker.cpp | 2 - src/helics/core/tcp/TcpBroker.h | 3 -- src/helics/core/tcp/TcpCore.cpp | 2 - src/helics/core/tcp/TcpCore.h | 2 +- src/helics/core/tcp/TcpHelperClasses.cpp | 56 +++++++++++++++++++----- src/helics/core/tcp/TcpHelperClasses.h | 16 ++++--- src/helics/core/udp/UdpBroker.cpp | 2 - src/helics/core/udp/UdpBroker.h | 3 -- src/helics/core/udp/UdpCore.cpp | 4 +- src/helics/core/udp/UdpCore.h | 1 - src/helics/core/zmq/ZmqBroker.cpp | 2 - src/helics/core/zmq/ZmqBroker.h | 3 -- src/helics/core/zmq/ZmqCore.cpp | 2 - src/helics/core/zmq/ZmqCore.h | 3 +- tests/helics/core/ZeromqCore-tests.cpp | 11 +++-- 29 files changed, 148 insertions(+), 92 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 45d490355d..8f789a9252 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -397,11 +397,11 @@ INSTALL(FILES ${KEY_LIBRARY_FILES} OPTION(ENABLE_CLANG_TOOLS "if clang is found enable some custom targets for clang formatting and tidy" OFF) if (ENABLE_CLANG_TOOLS) -include(clang-cxx-dev-tools) + include(clang-cxx-dev-tools) endif(ENABLE_CLANG_TOOLS) if (BUILD_PYTHON_INTERFACE OR BUILD_MATLAB_INTERFACE OR BUILD_JAVA_INTERFACE OR BUILD_OCTAVE_INTERFACE) -add_subdirectory(swig) + add_subdirectory(swig) endif() @@ -507,7 +507,9 @@ endif() # ------------------------------------------------------------- # CPack # ------------------------------------------------------------- +OPTION(ENABLE_PACKAGE_BUILD "Add projects for making packages and installers for HELICS" OFF) +IF(ENABLE_PACKAGE_BUILD) set(CPACK_PACKAGE_NAME "Helics") set(CPACK_PACKAGE_VENDOR "GMLC") set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "HELICS") @@ -563,3 +565,4 @@ endif(WIN32) set(CPACK_SOURCE_IGNORE_FILES "/Build*/;/build*/;/.git/") #THIS LINE MUST BE LAST include(CPack) +ENDIF(ENABLE_PACKAGE_BUILD) \ No newline at end of file diff --git a/appveyor.yml b/appveyor.yml index 2ba3c4dfe5..df12ee13b2 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -20,7 +20,7 @@ before_build: - IF NOT EXIST C:\ProgramData\chocolatey\bin\swig.exe choco install swig --yes --limit-output #> $null - mkdir build - cd build - - cmake .. -G "Visual Studio 14 2015 Win64" -DAUTOBUILD_ZMQ=ON -DBOOST_INSTALL_PATH=C:/libraries/boost_1_63_0 -DBUILD_RELEASE_ONLY=ON -DBUILD_C_SHARED_LIB=ON -DBUILD_JAVA_INTERFACE=ON -DBUILD_HELICS_EXAMPLES=ON + - cmake .. -G "Visual Studio 14 2015 Win64" -DAUTOBUILD_ZMQ=ON -DBOOST_INSTALL_PATH=C:/libraries/boost_1_63_0 -DENABLE_PACKAGE_BUILD=ON -DBUILD_RELEASE_ONLY=ON -DBUILD_C_SHARED_LIB=ON -DBUILD_JAVA_INTERFACE=ON -DBUILD_HELICS_EXAMPLES=ON - cd .. build: diff --git a/src/helics/application_api/Endpoints.cpp b/src/helics/application_api/Endpoints.cpp index c869881f73..dc041797a8 100644 --- a/src/helics/application_api/Endpoints.cpp +++ b/src/helics/application_api/Endpoints.cpp @@ -1,5 +1,4 @@ /* - Copyright © 2017-2018, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC All rights reserved. See LICENSE file and DISCLAIMER for more details. diff --git a/src/helics/application_api/Federate.cpp b/src/helics/application_api/Federate.cpp index 9159990972..451bf47d95 100644 --- a/src/helics/application_api/Federate.cpp +++ b/src/helics/application_api/Federate.cpp @@ -543,10 +543,11 @@ iteration_time Federate::requestTimeIterative (Time nextInternalTimeStep, iterat void Federate::requestTimeAsync (Time nextInternalTimeStep) { - auto asyncInfo = asyncCallInfo->lock(); + auto exp = op_states::execution; if (state.compare_exchange_strong(exp,op_states::pending_time)) { + auto asyncInfo = asyncCallInfo->lock(); asyncInfo->timeRequestFuture = std::async (std::launch::async, [this, nextInternalTimeStep]() { return coreObject->timeRequest (fedID, nextInternalTimeStep); }); @@ -562,10 +563,11 @@ void Federate::requestTimeAsync (Time nextInternalTimeStep) @return the granted time step*/ void Federate::requestTimeIterativeAsync (Time nextInternalTimeStep, iteration_request iterate) { - auto asyncInfo = asyncCallInfo->lock(); + auto exp = op_states::execution; if (state.compare_exchange_strong(exp, op_states::pending_iterative_time)) { + auto asyncInfo = asyncCallInfo->lock(); asyncInfo->timeRequestIterativeFuture = std::async (std::launch::async, [this, nextInternalTimeStep, iterate]() { return coreObject->requestTimeIterative (fedID, nextInternalTimeStep, iterate); @@ -582,11 +584,14 @@ void Federate::requestTimeIterativeAsync (Time nextInternalTimeStep, iteration_r @return the granted time step*/ Time Federate::requestTimeComplete () { - auto asyncInfo = asyncCallInfo->lock(); + auto exp = op_states::pending_time; if (state.compare_exchange_strong(exp, op_states::execution)) { + + auto asyncInfo = asyncCallInfo->lock(); auto newTime = asyncInfo->timeRequestFuture.get (); + asyncInfo = nullptr; //remove the lock; Time oldTime = currentTime; currentTime = newTime; updateTime (newTime, oldTime); diff --git a/src/helics/common/AsioServiceManager.h b/src/helics/common/AsioServiceManager.h index d109b597df..10ff5a98b7 100644 --- a/src/helics/common/AsioServiceManager.h +++ b/src/helics/common/AsioServiceManager.h @@ -16,8 +16,7 @@ All rights reserved. See LICENSE file and DISCLAIMER for more details. * LLNS Copyright End */ -#ifndef ASIO_SERVICE_MANAGER_HEADER_ -#define ASIO_SERVICE_MANAGER_HEADER_ +#pragma once #include #include @@ -123,5 +122,4 @@ class AsioServiceManager void serviceProcessingLoop(std::shared_ptr ptr); -#endif diff --git a/src/helics/core/BrokerBase.cpp b/src/helics/core/BrokerBase.cpp index a2ea21013a..bba63e7bbf 100644 --- a/src/helics/core/BrokerBase.cpp +++ b/src/helics/core/BrokerBase.cpp @@ -9,6 +9,7 @@ All rights reserved. See LICENSE file and DISCLAIMER for more details. #include "../common/AsioServiceManager.h" #include "../common/argParser.h" #include "../common/logger.h" + #include "ForwardingTimeCoordinator.hpp" #include "helics/helics-config.h" #include "helicsVersion.hpp" @@ -252,12 +253,36 @@ void BrokerBase::addActionMessage (ActionMessage &&m) } } -using activeProtector = std::shared_ptr>; -void timerTickHandler (BrokerBase *bbase, activeProtector active, const boost::system::error_code &error) +using activeProtector = libguarded::guarded>; + +static void haltTimer(activeProtector &active, boost::asio::steady_timer &tickTimer) +{ + bool TimerRunning = true; + { + auto p = active.lock(); + if (p->second) + { + p->first = false; + tickTimer.cancel(); + } + else + { + TimerRunning = false; + } + } + while (TimerRunning) + { + std::this_thread::yield(); + auto res = active.load(); + TimerRunning = res.second; + } +} + +static void timerTickHandler (BrokerBase *bbase, activeProtector &active, const boost::system::error_code &error) { - auto p = active->lock (); - if (*p) + auto p = active.lock (); + if (p->first) { if (error != boost::asio::error::operation_aborted) { @@ -268,7 +293,7 @@ void timerTickHandler (BrokerBase *bbase, activeProtector active, const boost::s catch (std::exception &e) { std::cout << "exception caught from addActionMessage" << std::endl; - } + } } else { @@ -277,6 +302,7 @@ void timerTickHandler (BrokerBase *bbase, activeProtector active, const boost::s bbase->addActionMessage (M); } } + p->second = false; } bool BrokerBase::tryReconnect () { return false; } @@ -288,12 +314,13 @@ void BrokerBase::queueProcessingLoop () auto serv = AsioServiceManager::getServicePointer (); auto serviceLoop = AsioServiceManager::runServiceLoop (); boost::asio::steady_timer ticktimer (serv->getBaseService ()); - auto active = std::make_shared> (true); + activeProtector active(true,false); - auto timerCallback = [this, active](const boost::system::error_code &ec) { + auto timerCallback = [this, &active](const boost::system::error_code &ec) { timerTickHandler (this, active, ec); }; ticktimer.expires_at (std::chrono::steady_clock::now () + std::chrono::milliseconds (tickTimer)); + active = std::make_pair(true, true); ticktimer.async_wait (timerCallback); int messagesSinceLastTick = 0; auto logDump = [&, this]() { @@ -331,29 +358,27 @@ void BrokerBase::queueProcessingLoop () messagesSinceLastTick = 0; // reschedule the timer ticktimer.expires_at (std::chrono::steady_clock::now () + std::chrono::milliseconds (tickTimer)); + active = std::make_pair(true, true); ticktimer.async_wait (timerCallback); break; case CMD_IGNORE: break; case CMD_TERMINATE_IMMEDIATELY: - active->store(false); - ticktimer.cancel (); + haltTimer(active, ticktimer); serviceLoop = nullptr; - mainLoopIsRunning.store (false); - logDump (); + mainLoopIsRunning.store(false); + logDump(); return; // immediate return case CMD_STOP: - active->store(false); - ticktimer.cancel (); + haltTimer(active, ticktimer); serviceLoop = nullptr; if (!haltOperations) { processCommand (std::move (command)); mainLoopIsRunning.store (false); logDump (); - return processDisconnect (); + processDisconnect (); } - return; default: if (!haltOperations) diff --git a/src/helics/core/CommonCore.cpp b/src/helics/core/CommonCore.cpp index 7baf84aec1..565e5ed178 100644 --- a/src/helics/core/CommonCore.cpp +++ b/src/helics/core/CommonCore.cpp @@ -2400,12 +2400,17 @@ void CommonCore::processCommand (ActionMessage &&command) { if (command.dest_id == global_broker_id) { - auto filtI = filters.find (fed_handle_pair (global_broker_id, command.dest_handle)); - if (filtI != nullptr) - { - filtI->target = {command.source_id, command.source_handle}; - timeCoord->addDependency (command.source_id); + helics::FilterInfo *filtI = nullptr; + { //scope for the lock_guard + std::lock_guard lock(_handlemutex); + filtI = filters.find(fed_handle_pair(global_broker_id, command.dest_handle)); + if (filtI != nullptr) + { + filtI->target = { command.source_id, command.source_handle }; + timeCoord->addDependency(command.source_id); + } } + auto filthandle = getHandleInfo (command.dest_handle); if (filthandle != nullptr) { diff --git a/src/helics/core/CommsBroker.hpp b/src/helics/core/CommsBroker.hpp index 3a9b4f4886..c65055a208 100644 --- a/src/helics/core/CommsBroker.hpp +++ b/src/helics/core/CommsBroker.hpp @@ -38,7 +38,8 @@ class CommsBroker : public BrokerT private: virtual void brokerDisconnect () override; virtual bool tryReconnect () override; - + /** disconnect the comm object*/ + void commDisconnect(); public: virtual void transmit (int route_id, const ActionMessage &cmd) override; diff --git a/src/helics/core/CommsBroker_impl.hpp b/src/helics/core/CommsBroker_impl.hpp index 104253d36e..0fadd00f5e 100644 --- a/src/helics/core/CommsBroker_impl.hpp +++ b/src/helics/core/CommsBroker_impl.hpp @@ -43,7 +43,7 @@ CommsBroker::~CommsBroker () if (exp == 0) { lock.unlock (); - brokerDisconnect (); + commDisconnect (); lock.lock (); exp = 1; } @@ -61,15 +61,21 @@ CommsBroker::~CommsBroker () template void CommsBroker::brokerDisconnect () { - std::unique_lock lock (dataMutex); + commDisconnect(); +} + +template +void CommsBroker::commDisconnect() +{ + std::unique_lock lock(dataMutex); if (comms) { int exp = 0; - if (disconnectionStage.compare_exchange_strong (exp, 1)) + if (disconnectionStage.compare_exchange_strong(exp, 1)) { - auto comm_ptr = comms.get (); - lock.unlock (); // we don't want to hold the lock while calling disconnect that could cause deadlock - comm_ptr->disconnect (); + auto comm_ptr = comms.get(); + lock.unlock(); // we don't want to hold the lock while calling disconnect that could cause deadlock + comm_ptr->disconnect(); disconnectionStage = 2; } } diff --git a/src/helics/core/CoreBroker.cpp b/src/helics/core/CoreBroker.cpp index 23307423c2..9886ba15b9 100644 --- a/src/helics/core/CoreBroker.cpp +++ b/src/helics/core/CoreBroker.cpp @@ -994,7 +994,7 @@ bool CoreBroker::connect () bool CoreBroker::isConnected () const { return ((brokerState == operating) || (brokerState == connected)); } void CoreBroker::processDisconnect (bool skipUnregister) -{ +{ LOG_NORMAL (0, getIdentifier (), "||disconnecting"); if (brokerState > broker_state_t::initialized) { diff --git a/src/helics/core/ipc/IpcBroker.cpp b/src/helics/core/ipc/IpcBroker.cpp index f943ef3740..bb34b69a61 100644 --- a/src/helics/core/ipc/IpcBroker.cpp +++ b/src/helics/core/ipc/IpcBroker.cpp @@ -44,8 +44,6 @@ IpcBroker::IpcBroker (bool rootBroker) noexcept : CommsBroker (rootBroker) {} IpcBroker::IpcBroker (const std::string &broker_name) : CommsBroker (broker_name) {} -IpcBroker::~IpcBroker () = default; - void IpcBroker::displayHelp (bool local_only) { std::cout << " Help for Interprocess Broker: \n"; diff --git a/src/helics/core/ipc/IpcBroker.h b/src/helics/core/ipc/IpcBroker.h index 07dabf733b..0e773482f1 100644 --- a/src/helics/core/ipc/IpcBroker.h +++ b/src/helics/core/ipc/IpcBroker.h @@ -24,9 +24,6 @@ class IpcBroker final : public CommsBroker static void displayHelp(bool local_only = false); void initializeFromArgs(int argc, const char *const *argv) override; - /**destructor*/ - virtual ~IpcBroker(); - virtual std::string getAddress() const override; private: diff --git a/src/helics/core/ipc/IpcCore.cpp b/src/helics/core/ipc/IpcCore.cpp index de77f68a7e..e007300676 100644 --- a/src/helics/core/ipc/IpcCore.cpp +++ b/src/helics/core/ipc/IpcCore.cpp @@ -42,8 +42,6 @@ IpcCore::IpcCore () noexcept {} IpcCore::IpcCore (const std::string &core_name) : CommsBroker (core_name) {} -IpcCore::~IpcCore () = default; - void IpcCore::initializeFromArgs (int argc, const char *const *argv) { if (brokerState == created) diff --git a/src/helics/core/ipc/IpcCore.h b/src/helics/core/ipc/IpcCore.h index d34f804b9e..9d211d7c8f 100644 --- a/src/helics/core/ipc/IpcCore.h +++ b/src/helics/core/ipc/IpcCore.h @@ -21,8 +21,7 @@ class IpcCore final : public CommsBroker /** default constructor*/ IpcCore () noexcept; IpcCore (const std::string &core_name); - /** destructor*/ - ~IpcCore (); + virtual void initializeFromArgs (int argc, const char *const *argv) override; public: diff --git a/src/helics/core/tcp/TcpBroker.cpp b/src/helics/core/tcp/TcpBroker.cpp index e2bdd192a3..3c072051db 100644 --- a/src/helics/core/tcp/TcpBroker.cpp +++ b/src/helics/core/tcp/TcpBroker.cpp @@ -14,8 +14,6 @@ TcpBroker::TcpBroker (bool rootBroker) noexcept : CommsBroker (rootBroker) {} TcpBroker::TcpBroker (const std::string &broker_name) : CommsBroker (broker_name) {} -TcpBroker::~TcpBroker () = default; - void TcpBroker::displayHelp (bool local_only) { std::cout << " Help for TCP Broker: \n"; diff --git a/src/helics/core/tcp/TcpBroker.h b/src/helics/core/tcp/TcpBroker.h index 4b6f3a69a6..55479c3796 100644 --- a/src/helics/core/tcp/TcpBroker.h +++ b/src/helics/core/tcp/TcpBroker.h @@ -25,9 +25,6 @@ class TcpBroker final : public CommsBroker void initializeFromArgs (int argc, const char *const *argv) override; - /**destructor*/ - virtual ~TcpBroker (); - virtual std::string getAddress () const override; static void displayHelp (bool local_only = false); diff --git a/src/helics/core/tcp/TcpCore.cpp b/src/helics/core/tcp/TcpCore.cpp index 711686925c..5c5bb5444c 100644 --- a/src/helics/core/tcp/TcpCore.cpp +++ b/src/helics/core/tcp/TcpCore.cpp @@ -13,8 +13,6 @@ namespace tcp { TcpCore::TcpCore () noexcept {} -TcpCore::~TcpCore () = default; - TcpCore::TcpCore (const std::string &core_name) : CommsBroker (core_name) {} void TcpCore::initializeFromArgs (int argc, const char *const *argv) diff --git a/src/helics/core/tcp/TcpCore.h b/src/helics/core/tcp/TcpCore.h index 58db4cc347..1c67d6b6bd 100644 --- a/src/helics/core/tcp/TcpCore.h +++ b/src/helics/core/tcp/TcpCore.h @@ -20,7 +20,7 @@ class TcpCore final : public CommsBroker /** default constructor*/ TcpCore () noexcept; TcpCore (const std::string &core_name); - ~TcpCore (); + virtual void initializeFromArgs (int argc, const char *const *argv) override; public: diff --git a/src/helics/core/tcp/TcpHelperClasses.cpp b/src/helics/core/tcp/TcpHelperClasses.cpp index 8e976e5270..5d1dd10d29 100644 --- a/src/helics/core/tcp/TcpHelperClasses.cpp +++ b/src/helics/core/tcp/TcpHelperClasses.cpp @@ -18,22 +18,32 @@ void TcpRxConnection::start () { if (triggerhalt) { + receiving = false; return; } if (state == connection_state_t::prestart) { + receiving = true; state=connection_state_t::halted; } connection_state_t exp = connection_state_t::halted; if (state.compare_exchange_strong (exp, connection_state_t::receiving)) { + if (receiving == false) + { + receiving = true; + } socket_.async_receive (boost::asio::buffer (data.data () + residBufferSize, data.size () - residBufferSize), - [connection = shared_from_this ()](const boost::system::error_code &error, + [this](const boost::system::error_code &error, size_t bytes_transferred) { - connection->handle_read (error, bytes_transferred); + handle_read (error, bytes_transferred); }); } + else if (exp!=connection_state_t::receiving) + { + receiving = false; + } } void TcpRxConnection::setDataCall(std::function dataFunc) @@ -64,6 +74,7 @@ void TcpRxConnection::handle_read (const boost::system::error_code &error, size_ if (triggerhalt) { state = connection_state_t::halted; + receiving = false; return; } if (!error) @@ -88,6 +99,7 @@ void TcpRxConnection::handle_read (const boost::system::error_code &error, size_ else if (error == boost::asio::error::operation_aborted) { state = connection_state_t::halted; + receiving = false; return; } else @@ -116,14 +128,23 @@ void TcpRxConnection::handle_read (const boost::system::error_code &error, size_ state = connection_state_t::halted; start (); } + else + { + receiving = false; + } } else if ((error != boost::asio::error::eof) && (error != boost::asio::error::operation_aborted)) { if (error != boost::asio::error::connection_reset) { std::cerr << "receive error " << error.message () << std::endl; - state = connection_state_t::halted; } + state = connection_state_t::halted; + receiving = false; + } + else + { + receiving = false; } } } @@ -153,6 +174,10 @@ void TcpRxConnection::close () std::cerr << "error occurred sending shutdown::" << ec << std::endl; } socket_.close (); + while (receiving) + { + std::this_thread::yield(); + } } @@ -250,8 +275,13 @@ TcpServer::pointer TcpServer::create (boost::asio::io_service &io_service, int P return pointer (new TcpServer (io_service, PortNum, nominalBufferSize)); } + void TcpServer::start () { + if (halted) + { + return; + } bool exp = false; if (accepting.compare_exchange_strong (exp, true)) { @@ -260,15 +290,18 @@ void TcpServer::start () { for (auto &conn :*connects) { - conn->start (); + if (!conn->isReceiving()) + { + conn->start(); + } } } TcpRxConnection::pointer new_connection = TcpRxConnection::create (acceptor_.get_io_service (), bufferSize); auto &socket = new_connection->socket(); - acceptor_.async_accept (socket, [server = shared_from_this (), connection=std::move(new_connection)]( + acceptor_.async_accept (socket, [this, connection=std::move(new_connection)]( const boost::system::error_code &error) { - server->handle_accept (connection, error); + handle_accept (connection, error); }); } } @@ -287,7 +320,10 @@ void TcpServer::handle_accept (TcpRxConnection::pointer new_connection, const bo connects->push_back(std::move(new_connection)); } accepting = false; - start (); + if (!halted) + { + start(); + } } else if (error != boost::asio::error::operation_aborted) { @@ -302,10 +338,8 @@ void TcpServer::handle_accept (TcpRxConnection::pointer new_connection, const bo void TcpServer::close () { - if (accepting) - { - acceptor_.close(); - } + halted = true; + acceptor_.close(); auto connects = connections.lock(); for (auto &conn : *connects) { diff --git a/src/helics/core/tcp/TcpHelperClasses.h b/src/helics/core/tcp/TcpHelperClasses.h index 31bebd8a80..ad25b5c6d5 100644 --- a/src/helics/core/tcp/TcpHelperClasses.h +++ b/src/helics/core/tcp/TcpHelperClasses.h @@ -29,20 +29,24 @@ class TcpRxConnection : public std::enable_shared_from_this }; typedef std::shared_ptr pointer; - + /** create an RxConnection object using the specified service and bufferSize*/ static pointer create (boost::asio::io_service &io_service, size_t bufferSize) { return pointer (new TcpRxConnection (io_service, bufferSize)); } - + /** get the underlying socket object*/ boost::asio::ip::tcp::socket &socket () { return socket_; } /** start the receiving loop*/ void start(); /** close the socket*/ void close (); - + bool isReceiving() const + { + return receiving.load(); + } + /** set the callback for the data object*/ void setDataCall(std::function dataFunc); - + /** set the callback for an error*/ void setErrorCall(std::function errorFunc); /** send raw data @@ -59,12 +63,13 @@ class TcpRxConnection : public std::enable_shared_from_this : socket_ (io_service), data (bufferSize) { } - + /** function for handling the asynchronous return from a read request*/ void handle_read (const boost::system::error_code &error, size_t bytes_transferred); std::atomic residBufferSize{0}; boost::asio::ip::tcp::socket socket_; std::vector data; std::atomic triggerhalt{ false }; + std::atomic receiving{ false }; std::function dataCall; std::function errorCall; std::atomic state{connection_state_t::prestart}; @@ -214,6 +219,7 @@ class TcpServer : public std::enable_shared_from_this size_t bufferSize; std::function dataCall; std::function errorCall; + std::atomic halted{ false }; guarded>> connections; }; diff --git a/src/helics/core/udp/UdpBroker.cpp b/src/helics/core/udp/UdpBroker.cpp index 2d27b377ab..fcbfc4ba59 100644 --- a/src/helics/core/udp/UdpBroker.cpp +++ b/src/helics/core/udp/UdpBroker.cpp @@ -15,8 +15,6 @@ UdpBroker::UdpBroker (bool rootBroker) noexcept : CommsBroker (rootBroker) {} UdpBroker::UdpBroker (const std::string &broker_name) : CommsBroker (broker_name) {} -UdpBroker::~UdpBroker () = default; - void UdpBroker::displayHelp (bool local_only) { std::cout << " Help for UDP Broker: \n"; diff --git a/src/helics/core/udp/UdpBroker.h b/src/helics/core/udp/UdpBroker.h index f2f2c8f1a0..54226aad03 100644 --- a/src/helics/core/udp/UdpBroker.h +++ b/src/helics/core/udp/UdpBroker.h @@ -25,9 +25,6 @@ class UdpBroker final : public CommsBroker void initializeFromArgs (int argc, const char *const *argv) override; - /**destructor*/ - virtual ~UdpBroker (); - virtual std::string getAddress () const override; static void displayHelp (bool local_only = false); diff --git a/src/helics/core/udp/UdpCore.cpp b/src/helics/core/udp/UdpCore.cpp index 3f6c1c8d7b..33889aa9de 100644 --- a/src/helics/core/udp/UdpCore.cpp +++ b/src/helics/core/udp/UdpCore.cpp @@ -1,9 +1,9 @@ /* - Copyright © 2017-2018, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC All rights reserved. See LICENSE file and DISCLAIMER for more details. */ + #include "UdpCore.h" #include "UdpComms.h" @@ -13,8 +13,6 @@ namespace udp { UdpCore::UdpCore () noexcept {} -UdpCore::~UdpCore () = default; - UdpCore::UdpCore (const std::string &core_name) : CommsBroker (core_name) {} void UdpCore::initializeFromArgs (int argc, const char *const *argv) diff --git a/src/helics/core/udp/UdpCore.h b/src/helics/core/udp/UdpCore.h index 67fef70c7f..7e56741787 100644 --- a/src/helics/core/udp/UdpCore.h +++ b/src/helics/core/udp/UdpCore.h @@ -19,7 +19,6 @@ class UdpCore final : public CommsBroker /** default constructor*/ UdpCore() noexcept; UdpCore(const std::string &core_name); - ~UdpCore(); virtual void initializeFromArgs(int argc, const char *const *argv) override; public: diff --git a/src/helics/core/zmq/ZmqBroker.cpp b/src/helics/core/zmq/ZmqBroker.cpp index 228c8f8ae0..7d5ed79eb4 100644 --- a/src/helics/core/zmq/ZmqBroker.cpp +++ b/src/helics/core/zmq/ZmqBroker.cpp @@ -15,8 +15,6 @@ ZmqBroker::ZmqBroker (bool rootBroker) noexcept : CommsBroker (rootBroker) {} ZmqBroker::ZmqBroker (const std::string &broker_name) : CommsBroker (broker_name) {} -ZmqBroker::~ZmqBroker () = default; - void ZmqBroker::displayHelp (bool local_only) { std::cout << " Help for Zero MQ Broker: \n"; diff --git a/src/helics/core/zmq/ZmqBroker.h b/src/helics/core/zmq/ZmqBroker.h index 7065dcd3a7..415c15fcf5 100644 --- a/src/helics/core/zmq/ZmqBroker.h +++ b/src/helics/core/zmq/ZmqBroker.h @@ -26,9 +26,6 @@ class ZmqBroker final:public CommsBroker void initializeFromArgs(int argc, const char * const *argv) override; - /**destructor*/ - virtual ~ZmqBroker(); - virtual std::string getAddress() const override; static void displayHelp(bool local_only = false); private: diff --git a/src/helics/core/zmq/ZmqCore.cpp b/src/helics/core/zmq/ZmqCore.cpp index be5574ba4f..dd53ab0fe7 100644 --- a/src/helics/core/zmq/ZmqCore.cpp +++ b/src/helics/core/zmq/ZmqCore.cpp @@ -13,8 +13,6 @@ namespace zeromq { ZmqCore::ZmqCore () noexcept {} -ZmqCore::~ZmqCore () = default; - ZmqCore::ZmqCore (const std::string &core_name) : CommsBroker (core_name) {} void ZmqCore::initializeFromArgs (int argc, const char *const *argv) diff --git a/src/helics/core/zmq/ZmqCore.h b/src/helics/core/zmq/ZmqCore.h index 0d47e224fb..0250a339f0 100644 --- a/src/helics/core/zmq/ZmqCore.h +++ b/src/helics/core/zmq/ZmqCore.h @@ -22,8 +22,7 @@ class ZmqCore final: public CommsBroker { ZmqCore() noexcept; /** construct from with a core name*/ ZmqCore(const std::string &core_name); - /** destructor*/ - ~ZmqCore(); + virtual void initializeFromArgs (int argc, const char * const *argv) override; public: diff --git a/tests/helics/core/ZeromqCore-tests.cpp b/tests/helics/core/ZeromqCore-tests.cpp index e217fb511d..3e055a9618 100644 --- a/tests/helics/core/ZeromqCore-tests.cpp +++ b/tests/helics/core/ZeromqCore-tests.cpp @@ -162,12 +162,17 @@ BOOST_AUTO_TEST_CASE (zmqRequestSet_test2) repSocket3.send (msg); // make sure the check receives all messages - reqset.checkForMessages (std::chrono::milliseconds (150)); + reqset.checkForMessages (std::chrono::milliseconds (50)); if (reqset.waiting ()) { - reqset.checkForMessages (std::chrono::milliseconds (150)); + reqset.checkForMessages (std::chrono::milliseconds (50)); } - BOOST_CHECK (!reqset.waiting ()); + //since we have 3 sockets we might have to do this twice since it returns immediately if it has a message + if (reqset.waiting()) + { + reqset.checkForMessages(std::chrono::milliseconds(50)); + } + BOOST_REQUIRE (!reqset.waiting ()); reqset.transmit (1, M); reqset.transmit (2, M); reqset.transmit (3, M); From 0a85955ee4005890be639e6d3631e36674cc0093 Mon Sep 17 00:00:00 2001 From: Philip Top Date: Thu, 26 Apr 2018 15:45:51 -0400 Subject: [PATCH 07/10] Additional timing tests (#285) * add a new test for period and timeDelta changes mid simulation * this adds some test cases to timing_tests and a fix for #284 --- src/helics/core/FederateState.cpp | 38 ++--------------- tests/helics/application_api/TimingTests.cpp | 44 ++++++++++++++++++++ 2 files changed, 48 insertions(+), 34 deletions(-) diff --git a/src/helics/core/FederateState.cpp b/src/helics/core/FederateState.cpp index a4b43bcec1..994236ac1a 100644 --- a/src/helics/core/FederateState.cpp +++ b/src/helics/core/FederateState.cpp @@ -1036,40 +1036,7 @@ iteration_state FederateState::processActionMessage (ActionMessage &cmd) } break; - /* - case CMD_REG_DST_FILTER: - case CMD_NOTIFY_DST_FILTER: - { - if (!checkActionFlag (cmd, clone_flag)) - { - auto endI = getEndpoint (cmd.dest_handle); - if (endI != nullptr) - { - addDependency (cmd.source_id); - } - } - else - { - auto endI = getEndpoint(cmd.dest_handle); - if (endI != nullptr) - { - addDependency(cmd.source_id); - } - } - break; - } - case CMD_REG_SRC_FILTER: - case CMD_NOTIFY_SRC_FILTER: - { - auto endI = getEndpoint (cmd.dest_handle); - if (endI != nullptr) - { - endI->hasFilter = true; - addDependent (cmd.source_id); - } - } - break; - */ + case CMD_FED_ACK: if (state != HELICS_CREATED) { @@ -1087,6 +1054,9 @@ iteration_state FederateState::processActionMessage (ActionMessage &cmd) return iteration_state::next_step; } break; + case CMD_FED_CONFIGURE: + processConfigUpdate(cmd); + break; } return iteration_state::continue_processing; } diff --git a/tests/helics/application_api/TimingTests.cpp b/tests/helics/application_api/TimingTests.cpp index 1860f5f0ba..1ad73c0a6d 100644 --- a/tests/helics/application_api/TimingTests.cpp +++ b/tests/helics/application_api/TimingTests.cpp @@ -147,4 +147,48 @@ BOOST_AUTO_TEST_CASE (timing_with_impact_window) vFed2 ->finalize (); // this will also test finalizing while a time request is ongoing otherwise it will time out. } + +BOOST_AUTO_TEST_CASE(timing_with_minDelta_change) +{ + SetupTest("test", 1,1.0); + auto vFed1 = GetFederateAs(0); + + vFed1->enterExecutionState(); + + auto res = vFed1->requestTime(1.0); + // check that the request is only granted at the appropriate period + + BOOST_CHECK_EQUAL(res, 1.0); + + //purposely requesting 1.0 to test min delta + res = vFed1->requestTime(1.0); + BOOST_CHECK_EQUAL(res, 2.0); + + vFed1->setTimeDelta(0.1); + res = vFed1->requestTime(res); + BOOST_CHECK_EQUAL(res, 2.1); + vFed1->finalize(); +} + +BOOST_AUTO_TEST_CASE(timing_with_period_change) +{ + SetupTest("test", 1); + auto vFed1 = GetFederateAs(0); + vFed1->setPeriod(1.0); + vFed1->enterExecutionState(); + + auto res = vFed1->requestTime(1.0); + // check that the request is only granted at the appropriate period + + BOOST_CHECK_EQUAL(res, 1.0); + + //purposely requesting 1.0 to test min delta + res = vFed1->requestTime(1.0); + BOOST_CHECK_EQUAL(res, 2.0); + + vFed1->setPeriod(0.1); + res = vFed1->requestTime(res); + BOOST_CHECK_EQUAL(res, 2.1); + vFed1->finalize(); +} BOOST_AUTO_TEST_SUITE_END () From 8514ebb74a7fcb882c4b22158e7c93b559b7375f Mon Sep 17 00:00:00 2001 From: Philip Top Date: Fri, 27 Apr 2018 11:26:52 -0400 Subject: [PATCH 08/10] Version update args (#286) * update version and fix argument processing for apps * update documentation, and fix issue that could potentially cause a deadlock between federates, particularly in recorders * send output to screen for python tests --- .travis.yml | 2 +- CHANGELOG.md | 7 ++- CMakeLists.txt | 4 +- appveyor.yml | 2 +- docs/apps/App.md | 10 ++--- docs/apps/Broker.md | 8 ++-- docs/apps/Player.md | 4 +- docs/apps/Source.md | 6 +-- docs/apps/Tracer.md | 2 +- docs/installation/linux.md | 2 +- docs/installation/mac.md | 6 +-- docs/installation/windows.md | 9 ++-- docs/introduction/java.md | 2 +- docs/mainpage.dox | 4 +- src/helics/common/argParser.cpp | 12 +++-- src/helics/core/FederateState.cpp | 50 ++++++++------------- tests/helics/application_api/CMakeLists.txt | 4 +- tests/helics/apps/SourceTests.cpp | 8 ++-- tests/helics/core/ZeromqCore-tests.cpp | 36 ++++++++++++--- tests/python_helics/test_message_filter.py | 19 ++++---- 20 files changed, 110 insertions(+), 87 deletions(-) diff --git a/.travis.yml b/.travis.yml index 641fa73d5e..481198eaa3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -191,7 +191,7 @@ script: # - echo "$LD_LIBRARY_PATH" # - echo "$DYLD_FALLBACK_LIBRARY_PATH" - python3 -m helics - - python3 -m pytest -v ../tests/python_helics + - python3 -m pytest -sv ../tests/python_helics notifications: email: false diff --git a/CHANGELOG.md b/CHANGELOG.md index 4a23f7664c..5742f2735e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,12 @@ All notable changes to this project after the 1.0.0 release will be documented i The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/). This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [unreleased] +## [1.0.2] -2018-04-28 +### Fixed + - Bug not allowing command line parameters separate from the command if a positional argument was in usage + - Fixed Bug for federate not allowing changes in period or minTimeDelay after entry to execution mode + - added python2 interface option (this will be available but not fully capable going forward) + - A few more race conditions fixed from clang thread-sanitizer ## [1.0.1] - 2018-04-22 ### Fixed diff --git a/CMakeLists.txt b/CMakeLists.txt index 8f789a9252..58efc89b9a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,9 +12,9 @@ project (HELICS) #----------------------------------------------------------------------------- set (HELICS_VERSION_MAJOR 1) set (HELICS_VERSION_MINOR 0) -set (HELICS_VERSION_PATCH 1) +set (HELICS_VERSION_PATCH 2) set (HELICS_VERSION_BUILD 0) -set (HELICS_DATE "04-22-18") +set (HELICS_DATE "04-28-18") set (HELICS_VERSION "${HELICS_VERSION_MAJOR}.${HELICS_VERSION_MINOR}.${HELICS_VERSION_PATCH}") set (HELICS_VERSION_STRING "${HELICS_VERSION} ${HELICS_DATE}") diff --git a/appveyor.yml b/appveyor.yml index df12ee13b2..646b06a4a1 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,6 +1,6 @@ shallow_clone: true -version: 1.0.1.{build} +version: 1.0.2.{build} image: Visual Studio 2015 diff --git a/docs/apps/App.md b/docs/apps/App.md index 0412ad0741..328d0077c4 100644 --- a/docs/apps/App.md +++ b/docs/apps/App.md @@ -1,7 +1,7 @@ helics_app ======= -The helics apps executable is one of the HELICS apps available with the library +The HELICS apps executable is one of the HELICS apps available with the library Its purpose is to provide a common executable for running any of the other as typical syntax is as follows @@ -11,9 +11,9 @@ helics-app.exe possible apps are #### Echo -The [Echo](echo.md) app is a responsive app that will echo any message sent to its endpoints back to the orginal source with a specified delay +The [Echo](echo.md) app is a responsive app that will echo any message sent to its endpoints back to the original source with a specified delay -THis is useful for testing communication pathways and in combination with filters can be used to create some interesting situations +This is useful for testing communication pathways and in combination with filters can be used to create some interesting situations #### Player The [player](Player.md) app will generate signals through specified interfaces from prescribed data @@ -29,9 +29,9 @@ The additional purpose is used as a library object as the basis for additional d #### Source -The [Source](Source.md) app is a signal generator like the player execpt that is can generate signals from defined patterns including some random signals in value and timing, and other patterns like sine, square wave, ramps +The [Source](Source.md) app is a signal generator like the player except that is can generate signals from defined patterns including some random signals in value and timing, and other patterns like sine, square wave, ramps and others. Used much like the player in situations some test signals are needed. #### Broker -The [Broker](Broker.md) executes a broker like the stand alone Broker app. \ No newline at end of file +The [Broker](Broker.md) executes a broker like the stand alone Broker app. diff --git a/docs/apps/Broker.md b/docs/apps/Broker.md index ae543286ca..5066c37758 100644 --- a/docs/apps/Broker.md +++ b/docs/apps/Broker.md @@ -1,7 +1,7 @@ Broker ======= -Brokers function as intermediaries or roots in the HELICS hiearchy +Brokers function as intermediaries or roots in the HELICS hierarchy The Broker can be run through the helics_broker or via helics-app @@ -51,7 +51,7 @@ the player executable also takes an untagged argument of a file name for example helics_player player_file.txt --stop 5 ``` -Players support both delimited text files and json files some examples can be found in +Players support both delimited text files and JSON files some examples can be found in [Player configuation Examples](https://github.com/GMLC-TDC/HELICS-src/tree/master/tests/helics/apps/test_files) @@ -79,7 +79,7 @@ the optional third column specifies a type valid types are time specifications are typically numerical with optional units `5` or `"500 ms"` or `23.7us` if there is a space between the number and units it must be enclosed in quotes if no units are specified the time defaults to units specified via `--timeunits` or seconds if none were specified -valid units are "s", "ms","us","min", "day", "hr", "ns", "ps" the default precision in HELICS is ns so time specified in ps is not guaranteed to be precise +valid units are "s", "ms", "us", "min", "day", "hr", "ns", "ps" the default precision in HELICS is ns so time specified in ps is not guaranteed to be precise | identifier | type | Example | @@ -194,5 +194,5 @@ Example JSON } ``` -some configuration can also be done through JSON through elements of "stop","local","separator","timeunits" +some configuration can also be done through JSON through elements of "stop", "local", "separator", "timeunits" and file elements can be used to load up additional files diff --git a/docs/apps/Player.md b/docs/apps/Player.md index ebaa5fb47d..bf7f602219 100644 --- a/docs/apps/Player.md +++ b/docs/apps/Player.md @@ -53,7 +53,7 @@ the player executable also takes an untagged argument of a file name for example helics_player player_file.txt --stop 5 ``` -Players support both delimited text files and json files some examples can be found in +Players support both delimited text files and JSON files some examples can be found in [Player configuation Examples](https://github.com/GMLC-TDC/HELICS-src/tree/master/tests/helics/apps/test_files) @@ -81,7 +81,7 @@ the optional third column specifies a type valid types are time specifications are typically numerical with optional units `5` or `"500 ms"` or `23.7us` if there is a space between the number and units it must be enclosed in quotes if no units are specified the time defaults to units specified via `--timeunits` or seconds if none were specified -valid units are "s", "ms","us","min", "day", "hr", "ns", "ps" the default precision in HELICS is ns so time specified in ps is not guaranteed to be precise +valid units are "s", "ms", "us", "min", "day", "hr", "ns", "ps" the default precision in HELICS is ns so time specified in ps is not guaranteed to be precise | identifier | type | Example | diff --git a/docs/apps/Source.md b/docs/apps/Source.md index 5200504828..9bb4bd1a5f 100644 --- a/docs/apps/Source.md +++ b/docs/apps/Source.md @@ -1,10 +1,10 @@ Source ======= -The Source app generates signals for other federates, it functions similarly to the +The Source app generates signals for other federates, it functions similarly to the player but doesn't take a prescribed file instead it generates signals according to some -mathematical function, like sine, ramp, pulse, or random walk. -THis can be useful for sending probing signals or just testing responses of the federate to various stimuli. +mathematical function, like sine, ramp, pulse, or random walk. +This can be useful for sending probing signals or just testing responses of the federate to various stimuli. Command line arguments diff --git a/docs/apps/Tracer.md b/docs/apps/Tracer.md index 89354e861d..656385909e 100644 --- a/docs/apps/Tracer.md +++ b/docs/apps/Tracer.md @@ -61,7 +61,7 @@ the tracer executable also takes an untagged argument of a file name for example helics_app tracer tracer_file.txt --stop 5 ``` -Tracers support both delimited text files and json files some examples can be found in +Tracers support both delimited text files and JSON files some examples can be found in [Player configuation Examples](https://github.com/GMLC-TDC/HELICS-src/tree/master/tests/helics/apps/test_files) diff --git a/docs/installation/linux.md b/docs/installation/linux.md index 78c646c340..46eae59ce2 100644 --- a/docs/installation/linux.md +++ b/docs/installation/linux.md @@ -82,7 +82,7 @@ IPython 6.2.1 -- An enhanced Interactive Python. Type '?' for help. In [1]: import helics In [2]: helics.helicsGetVersion() -Out[2]: '1.0.0-alpha.3 (02-12-18)' +Out[2]: '1.0.2 (04-28-18)' ``` diff --git a/docs/installation/mac.md b/docs/installation/mac.md index 4b7e4d15bc..217741afd2 100644 --- a/docs/installation/mac.md +++ b/docs/installation/mac.md @@ -124,10 +124,10 @@ recorder: cd /path/to/helics_install/bin $ helics_player --version -0.1 +1.0.2 (04-28-18) $ helics_recorder --version -0.1 +1.0.2 (04-28-18) ``` Building HELICS with python support @@ -159,7 +159,7 @@ IPython 6.2.1 -- An enhanced Interactive Python. Type '?' for help. In [1]: import helics In [2]: helics.helicsGetVersion() -Out[2]: '1.0.0-alpha.3 (02-12-18)' +Out[2]: '1.0.2 (04-28-18)' ``` diff --git a/docs/installation/windows.md b/docs/installation/windows.md index 8e333f3169..abc9a7cee8 100644 --- a/docs/installation/windows.md +++ b/docs/installation/windows.md @@ -106,10 +106,10 @@ recorder (located in the 'build\src\helics\apps\player\Debug' folder): > cd C:\Path\To\build\src\helics\apps\Debug > helics_player.exe --version -0.1 +1.0.2 04-28-2018 > helics_recorder.exe --version -0.1 +1.0.2 04-28-2018 ``` Building HELICS with python support @@ -140,7 +140,7 @@ cmake --build . --config Release --target install Add the following to the Windows PYTHONPATH environment variable or run the following in the command line. ```bash -set PYTHONPATH=C:\local\helics-v1.0.0\python;%PYTHONPATH% +set PYTHONPATH=C:\local\helics-v1.0.2\python;%PYTHONPATH% ``` If you open a interactive Python session and import helics, you should be able to get the version of `helics` and an output that is similar to the following. @@ -154,9 +154,8 @@ IPython 6.2.1 -- An enhanced Interactive Python. Type '?' for help. In [1]: import helics In [2]: helics.helicsGetVersion() -Out[2]: '1.0.0 (04-15-18)' +Out[2]: '1.0.2 (04-28-18)' ``` ![](../img/windows-python-success.png) - diff --git a/docs/introduction/java.md b/docs/introduction/java.md index 457dbee0e0..ed64f0cd5b 100644 --- a/docs/introduction/java.md +++ b/docs/introduction/java.md @@ -28,7 +28,7 @@ java -Djava.library.path="/Library/Java/Extensions:/Network/Library/Java/Extensi You should see the output that is similar to the following. ``` -HELICS Version: 1.0.0-beta.1 02-26-18 +HELICS Version: 1.0.2 (04-28-18) ``` creating a jar file. diff --git a/docs/mainpage.dox b/docs/mainpage.dox index 0bab1437c3..8497399884 100644 --- a/docs/mainpage.dox +++ b/docs/mainpage.dox @@ -2,7 +2,7 @@ @mainpage HELICS @image html HELICS_Logo.png width=5cm -

HELICS (Hiearchical Engine for Large-scale infrastructre Co-Simulation) is a co-simulation plaform +

HELICS (Hierarchical Engine for Large-Scale infrastructure Co-Simulation) is a co-simulation platform


@@ -11,4 +11,4 @@ [Disclaimer](../../DISCLAIMER)
[license](../../LICENSE) - */ \ No newline at end of file + */ diff --git a/src/helics/common/argParser.cpp b/src/helics/common/argParser.cpp index 26bbca08ec..6e46f58452 100644 --- a/src/helics/common/argParser.cpp +++ b/src/helics/common/argParser.cpp @@ -74,6 +74,7 @@ int argumentParser (int argc, if (!posName.empty ()) { hidden.add_options () (posName.c_str (), po::value (), "positional argument"); + hidden.add_options() ("extra_positional_arguments", po::value>(), "unknown positional argument"); cmd_line.add (hidden); config_file.add (hidden); } @@ -98,7 +99,8 @@ int argumentParser (int argc, else { po::positional_options_description p; - p.add (posName.c_str (), -1); + p.add (posName.c_str (), 1); + p.add("extra_positional_arguments", 20); po::command_line_parser parser{argc, argv}; parser.options (cmd_line).allow_unregistered ().positional (p); parser.style (xstyle); @@ -118,7 +120,10 @@ int argumentParser (int argc, // program options control if (cmd_vm.count ("help") > 0) { - std::cout << visible << '\n'; + if (cmd_vm.count("quiet") == 0) + { + std::cout << visible << '\n'; + } return helpReturn; } if (cmd_vm.count ("version") > 0) @@ -134,7 +139,8 @@ int argumentParser (int argc, else { po::positional_options_description p; - p.add (posName.c_str (), -1); + p.add (posName.c_str (), 1); + p.add("extra_positional_arguments", 20); po::store (po::command_line_parser (argc, argv) .options (cmd_line) .allow_unregistered () diff --git a/src/helics/core/FederateState.cpp b/src/helics/core/FederateState.cpp index 994236ac1a..4a0317f878 100644 --- a/src/helics/core/FederateState.cpp +++ b/src/helics/core/FederateState.cpp @@ -437,8 +437,7 @@ iteration_result FederateState::enterExecutingState (iteration_request iterate) } addAction (exec); - ActionMessage execReq (CMD_EXEC_CHECK); - queue.emplace (execReq); + auto ret = processQueue (); if (ret == iteration_state::next_step) { @@ -523,7 +522,6 @@ iteration_time FederateState::requestTime (Time nextTime, iteration_request iter addAction (treq); LOG_TRACE (timeCoord->printTimeStatus ()); // timeCoord->timeRequest (nextTime, iterate, nextValueTime (), nextMessageTime ()); - queue.push (CMD_TIME_CHECK); auto ret = processQueue (); time_granted = timeCoord->getGrantedTime (); @@ -765,35 +763,13 @@ iteration_state FederateState::processActionMessage (ActionMessage &cmd) { if (state == HELICS_INITIALIZING) { - auto grant = timeCoord->checkExecEntry (); - switch (grant) - { - case iteration_state::iterating: - timeGranted_mode = true; - return grant; - case iteration_state::next_step: - setState (HELICS_EXECUTING); - LOG_DEBUG ("Granting Execution"); - timeGranted_mode = true; - return grant; - case iteration_state::continue_processing: - break; - default: - timeGranted_mode = true; - return grant; - } + cmd.setAction(CMD_EXEC_CHECK); + return processActionMessage(cmd); } else if (state == HELICS_EXECUTING) { - auto ret = timeCoord->checkTimeGrant (); - if (ret != iteration_state::continue_processing) - { - time_granted = timeCoord->getGrantedTime (); - allowed_send_time = timeCoord->allowedSendTime (); - LOG_DEBUG (std::string ("Granted Time=") + std::to_string (time_granted)); - timeGranted_mode = true; - return ret; - } + cmd.setAction(CMD_TIME_CHECK); + return processActionMessage(cmd); } } } @@ -819,7 +795,13 @@ iteration_state FederateState::processActionMessage (ActionMessage &cmd) } timeCoord->enteringExecMode (iterate); timeGranted_mode = false; - return processDelayQueue (); + auto ret = processDelayQueue(); + if (ret != iteration_state::continue_processing) + { + return ret; + } + cmd.setAction(CMD_EXEC_CHECK); + return processActionMessage(cmd); } FALLTHROUGH case CMD_EXEC_GRANT: @@ -924,7 +906,13 @@ iteration_state FederateState::processActionMessage (ActionMessage &cmd) } timeCoord->timeRequest (cmd.actionTime, iterate, nextValueTime (), nextMessageTime ()); timeGranted_mode = false; - return processDelayQueue (); + auto ret=processDelayQueue (); + if (ret != iteration_state::continue_processing) + { + return ret; + } + cmd.setAction(CMD_TIME_CHECK); + return processActionMessage(cmd); } FALLTHROUGH case CMD_TIME_GRANT: diff --git a/tests/helics/application_api/CMakeLists.txt b/tests/helics/application_api/CMakeLists.txt index 680e5825fa..81e6f2073f 100644 --- a/tests/helics/application_api/CMakeLists.txt +++ b/tests/helics/application_api/CMakeLists.txt @@ -91,9 +91,9 @@ target_compile_definitions(application-api-tests PRIVATE "-DQUICK_TESTS_ONLY") target_compile_definitions(key-tests PRIVATE "-DKEY_TESTS") add_test(NAME key-tests COMMAND key-tests --log_level=message --report_level=short) -add_test(NAME application-api-tests COMMAND application-api-tests --log_level=test_suite --report_level=short) +add_test(NAME application-api-tests COMMAND application-api-tests --log_level=message --report_level=short) -add_test(NAME extended-api-tests COMMAND extended-api-tests --log_level=test_suite --report_level=short) +add_test(NAME extended-api-tests COMMAND extended-api-tests --log_level=message --report_level=short) foreach(keyfile IN LISTS KEY_LIBRARY_FILES) diff --git a/tests/helics/apps/SourceTests.cpp b/tests/helics/apps/SourceTests.cpp index 8538431f34..f2ae30dbb5 100644 --- a/tests/helics/apps/SourceTests.cpp +++ b/tests/helics/apps/SourceTests.cpp @@ -97,7 +97,7 @@ BOOST_AUTO_TEST_CASE (simple_source_test2) src1.finalize (); }); vfed.enterExecutionState (); - auto retTime = vfed.requestTime (5); + auto retTime = vfed.requestTime (1.1); BOOST_CHECK_EQUAL (retTime, 1.0); auto val = sub1.getValue (); BOOST_CHECK_EQUAL (val, 1.3); @@ -189,9 +189,9 @@ BOOST_AUTO_TEST_CASE (sine_source_test) BOOST_AUTO_TEST_CASE (simple_source_test_file) { - helics::FederateInfo fi ("player1"); + helics::FederateInfo fi ("source1"); fi.coreType = helics::core_type::TEST; - fi.coreName = "core1"; + fi.coreName = "corep"; fi.coreInitString = "2"; helics::apps::Source src1 (fi); src1.loadFile (std::string (TEST_DIR) + "/test_files/simple_source_test.json"); @@ -204,7 +204,7 @@ BOOST_AUTO_TEST_CASE (simple_source_test_file) src1.finalize (); }); vfed.enterExecutionState (); - auto retTime = vfed.requestTime (5); + auto retTime = vfed.requestTime (1.1); BOOST_CHECK_EQUAL (retTime, 1.0); auto val = sub1.getValue (); BOOST_CHECK_EQUAL (val, 1.3); diff --git a/tests/helics/core/ZeromqCore-tests.cpp b/tests/helics/core/ZeromqCore-tests.cpp index 3e055a9618..df17de5c0e 100644 --- a/tests/helics/core/ZeromqCore-tests.cpp +++ b/tests/helics/core/ZeromqCore-tests.cpp @@ -383,7 +383,7 @@ BOOST_AUTO_TEST_CASE (zmqComm_transmit_add_route) std::atomic counter2{0}; std::atomic counter3{0}; helics::zeromq::ZmqComms comm (host, host); - helics::zeromq::ZmqComms comm2 (host, ""); + helics::zeromq::ZmqComms comm2 (host, std::string()); helics::zeromq::ZmqComms comm3 (host, host); comm.setBrokerPort (23405); @@ -425,13 +425,25 @@ BOOST_AUTO_TEST_CASE (zmqComm_transmit_add_route) comm.transmit (0, helics::CMD_ACK); - std::this_thread::sleep_for (std::chrono::milliseconds (250)); + std::this_thread::yield(); + if (counter2 != 1) + { + std::this_thread::sleep_for(std::chrono::milliseconds(200)); + } BOOST_REQUIRE_EQUAL (counter2, 1); BOOST_CHECK (act2.lock()->action () == helics::action_message_def::action_t::cmd_ack); comm3.transmit (0, helics::CMD_ACK); - std::this_thread::sleep_for (std::chrono::milliseconds (250)); + std::this_thread::yield(); + if (counter2 != 2) + { + std::this_thread::sleep_for(std::chrono::milliseconds(200)); + } + if (counter2 != 2) + { + std::this_thread::sleep_for(std::chrono::milliseconds(200)); + } BOOST_REQUIRE_EQUAL (counter2, 2); BOOST_CHECK (act2.lock()->action () == helics::action_message_def::action_t::cmd_ack); @@ -439,10 +451,14 @@ BOOST_AUTO_TEST_CASE (zmqComm_transmit_add_route) comm2.transmit (3, helics::CMD_ACK); - std::this_thread::sleep_for (std::chrono::milliseconds (250)); + std::this_thread::yield(); + if (counter3 != 1) + { + std::this_thread::sleep_for (std::chrono::milliseconds (200)); + } if (counter3 != 1) { - std::this_thread::sleep_for (std::chrono::milliseconds (250)); + std::this_thread::sleep_for(std::chrono::milliseconds(200)); } BOOST_REQUIRE_EQUAL (counter3, 1); BOOST_CHECK (act3.lock()->action () == helics::action_message_def::action_t::cmd_ack); @@ -451,7 +467,15 @@ BOOST_AUTO_TEST_CASE (zmqComm_transmit_add_route) comm2.transmit (4, helics::CMD_ACK); - std::this_thread::sleep_for (std::chrono::milliseconds (250)); + std::this_thread::yield(); + if (counter != 1) + { + std::this_thread::sleep_for(std::chrono::milliseconds(200)); + } + if (counter != 1) + { + std::this_thread::sleep_for(std::chrono::milliseconds(200)); + } BOOST_REQUIRE_EQUAL (counter, 1); BOOST_CHECK (act.lock()->action () == helics::action_message_def::action_t::cmd_ack); diff --git a/tests/python_helics/test_message_filter.py b/tests/python_helics/test_message_filter.py index 235b29f616..6a6b5fe50d 100644 --- a/tests/python_helics/test_message_filter.py +++ b/tests/python_helics/test_message_filter.py @@ -116,25 +116,26 @@ def test_message_filter_function(broker): assert status == 0 assert state == 2 data = "hello world" - # TODO: Fix segfaults on the next line + print("step 1") h.helicsEndpointSendMessageRaw(p1, "port2", data) - - # TODO: Also segfaults + print("step 2") grantedtime = h.helicsFederateRequestTimeAsync (mFed, 1.0) assert grantedtime == 0 status, grantedtime = h.helicsFederateRequestTime(fFed, 1.0) + print("step 3") assert status == 0 assert grantedtime == 1.0 status, grantedtime = h.helicsFederateRequestTimeComplete (mFed) + print("step 4") assert status == 0 assert grantedtime == 1.0 - f2 = h.helicsFederateRegisterDestinationFilter (fFed, h.helics_custom_filter, "filter2", "port2") - ep1 = h.helicsFederateRegisterEndpoint (fFed, "fout", "") - f3 = h.helicsFederateRegisterSourceFilter (fFed, h.helics_custom_filter, "", "filter0/fout") + h.helicsFederateFinalize(mFed) + h.helicsFederateFinalize(fFed) + print("step 5") + #f2 = h.helicsFederateRegisterDestinationFilter (fFed, h.helics_custom_filter, "filter2", "port2") + #ep1 = h.helicsFederateRegisterEndpoint (fFed, "fout", "") + #f3 = h.helicsFederateRegisterSourceFilter (fFed, h.helics_custom_filter, "", "filter0/fout") FreeFederate(fFed) FreeFederate(mFed) - - - From 556e11807bdbc5c978901f5b5d03092be13fc8bf Mon Sep 17 00:00:00 2001 From: Philip Top Date: Fri, 27 Apr 2018 09:12:58 -0700 Subject: [PATCH 09/10] add try catch loops to c shared_library and add delay to filter registration python tests --- .../shared_api_library/FederateExport.cpp | 93 ++++++++++++++----- tests/python_helics/test_message_filter.py | 1 + 2 files changed, 73 insertions(+), 21 deletions(-) diff --git a/src/helics/shared_api_library/FederateExport.cpp b/src/helics/shared_api_library/FederateExport.cpp index f173fd9448..1082a2ad71 100644 --- a/src/helics/shared_api_library/FederateExport.cpp +++ b/src/helics/shared_api_library/FederateExport.cpp @@ -93,15 +93,23 @@ std::shared_ptr getMessageFedSharedPtr (helics_federate helics_federate helicsCreateValueFederate (const helics_federate_info_t fi) { auto *fed = new helics::FedObject; - fed->index = getMasterHolder ()->addFed (fed); - if (fi == nullptr) + try { - fed->fedptr = std::make_shared (helics::FederateInfo ()); + if (fi == nullptr) + { + fed->fedptr = std::make_shared(helics::FederateInfo()); + } + else + { + fed->fedptr = std::make_shared(*reinterpret_cast (fi)); + } } - else + catch (const helics::RegistrationFailure &) { - fed->fedptr = std::make_shared (*reinterpret_cast (fi)); + delete fed; + return nullptr; } + fed->index = getMasterHolder()->addFed(fed); fed->type = helics::vtype::valueFed; fed->valid = fedValidationIdentifier; return reinterpret_cast (fed); @@ -110,8 +118,16 @@ helics_federate helicsCreateValueFederate (const helics_federate_info_t fi) helics_federate helicsCreateValueFederateFromJson (const char *json) { auto *fed = new helics::FedObject; - fed->index = getMasterHolder ()->addFed (fed); - fed->fedptr = std::make_shared ((json != nullptr) ? std::string (json) : std::string ()); + try + { + fed->fedptr = std::make_shared((json != nullptr) ? std::string(json) : std::string()); + } + catch (const helics::RegistrationFailure &) + { + delete fed; + return nullptr; + } + fed->index = getMasterHolder()->addFed(fed); fed->type = helics::vtype::valueFed; fed->valid = fedValidationIdentifier; return reinterpret_cast (fed); @@ -121,15 +137,24 @@ helics_federate helicsCreateValueFederateFromJson (const char *json) helics_federate helicsCreateMessageFederate (const helics_federate_info_t fi) { auto *fed = new helics::FedObject; - fed->index = getMasterHolder ()->addFed (fed); - if (fi == nullptr) + try { - fed->fedptr = std::make_shared (helics::FederateInfo ()); + if (fi == nullptr) + { + fed->fedptr = std::make_shared(helics::FederateInfo()); + } + else + { + fed->fedptr = std::make_shared(*reinterpret_cast (fi)); + } } - else + catch (const helics::RegistrationFailure &) { - fed->fedptr = std::make_shared (*reinterpret_cast (fi)); + delete fed; + return nullptr; } + + fed->index = getMasterHolder()->addFed(fed); fed->type = helics::vtype::messageFed; fed->valid = fedValidationIdentifier; return reinterpret_cast (fed); @@ -138,8 +163,17 @@ helics_federate helicsCreateMessageFederate (const helics_federate_info_t fi) helics_federate helicsCreateMessageFederateFromJson (const char *json) { auto *fed = new helics::FedObject; - fed->index = getMasterHolder ()->addFed (fed); - fed->fedptr = std::make_shared ((json != nullptr) ? std::string (json) : std::string ()); + + try + { + fed->fedptr = std::make_shared((json != nullptr) ? std::string(json) : std::string()); + } + catch (const helics::RegistrationFailure &) + { + delete fed; + return nullptr; + } + fed->index = getMasterHolder()->addFed(fed); fed->type = helics::vtype::messageFed; fed->valid = fedValidationIdentifier; return reinterpret_cast (fed); @@ -149,15 +183,23 @@ helics_federate helicsCreateMessageFederateFromJson (const char *json) helics_federate helicsCreateCombinationFederate (const helics_federate_info_t fi) { auto *fed = new helics::FedObject; - fed->index = getMasterHolder ()->addFed (fed); - if (fi == nullptr) + try { - fed->fedptr = std::make_shared (helics::FederateInfo ()); + if (fi == nullptr) + { + fed->fedptr = std::make_shared(helics::FederateInfo()); + } + else + { + fed->fedptr = std::make_shared(*reinterpret_cast (fi)); + } } - else + catch (const helics::RegistrationFailure &) { - fed->fedptr = std::make_shared (*reinterpret_cast (fi)); + delete fed; + return nullptr; } + fed->index = getMasterHolder()->addFed(fed); fed->type = helics::vtype::combinationFed; fed->valid = fedValidationIdentifier; return reinterpret_cast (fed); @@ -166,8 +208,17 @@ helics_federate helicsCreateCombinationFederate (const helics_federate_info_t fi helics_federate helicsCreateCombinationFederateFromJson (const char *json) { auto *fed = new helics::FedObject; - fed->index = getMasterHolder ()->addFed (fed); - fed->fedptr = std::make_shared ((json != nullptr) ? std::string (json) : std::string ()); + try + { + fed->fedptr = std::make_shared((json != nullptr) ? std::string(json) : std::string()); + } + catch (const helics::RegistrationFailure &) + { + delete fed; + return nullptr; + } + + fed->index = getMasterHolder()->addFed(fed); fed->type = helics::vtype::combinationFed; fed->valid = fedValidationIdentifier; return reinterpret_cast (fed); diff --git a/tests/python_helics/test_message_filter.py b/tests/python_helics/test_message_filter.py index 6a6b5fe50d..826b00d05d 100644 --- a/tests/python_helics/test_message_filter.py +++ b/tests/python_helics/test_message_filter.py @@ -94,6 +94,7 @@ def test_message_filter_registration(broker): FreeFederate(fFed) FreeFederate(mFed) + time.sleep(1.0) def test_message_filter_function(broker): From 241e42ebe06e0aa6f4e8b455c101b7197515f2a9 Mon Sep 17 00:00:00 2001 From: Philip Top Date: Fri, 27 Apr 2018 09:19:26 -0700 Subject: [PATCH 10/10] remove extra print statements --- tests/python_helics/test_message_filter.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/tests/python_helics/test_message_filter.py b/tests/python_helics/test_message_filter.py index 826b00d05d..10b01adaf3 100644 --- a/tests/python_helics/test_message_filter.py +++ b/tests/python_helics/test_message_filter.py @@ -117,23 +117,18 @@ def test_message_filter_function(broker): assert status == 0 assert state == 2 data = "hello world" - print("step 1") h.helicsEndpointSendMessageRaw(p1, "port2", data) - print("step 2") grantedtime = h.helicsFederateRequestTimeAsync (mFed, 1.0) assert grantedtime == 0 status, grantedtime = h.helicsFederateRequestTime(fFed, 1.0) - print("step 3") assert status == 0 assert grantedtime == 1.0 status, grantedtime = h.helicsFederateRequestTimeComplete (mFed) - print("step 4") assert status == 0 assert grantedtime == 1.0 h.helicsFederateFinalize(mFed) h.helicsFederateFinalize(fFed) - print("step 5") #f2 = h.helicsFederateRegisterDestinationFilter (fFed, h.helics_custom_filter, "filter2", "port2") #ep1 = h.helicsFederateRegisterEndpoint (fFed, "fout", "") #f3 = h.helicsFederateRegisterSourceFilter (fFed, h.helics_custom_filter, "", "filter0/fout")