From 755240de6f97d7f1257bfb31320b3babb5b3b650 Mon Sep 17 00:00:00 2001 From: Ryan Mast Date: Thu, 10 May 2018 17:05:37 -0700 Subject: [PATCH 01/10] Add Xcode 8gm, OS X 10.11 to daily builds matrix --- .travis.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/.travis.yml b/.travis.yml index 3105bb0afc..89afd0878e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -26,6 +26,10 @@ _basic_env: packages: - g++-6 - valgrind +- &daily_osx + if: type = cron + os: osx + compiler: clang - &linux_base if: type != cron os: linux @@ -146,6 +150,13 @@ jobs: - SHARED_LIB_EXT=so - USE_SWIG=true - CXX_STANDARD=17 + # XCode 8gm, OS X 10.11 + - <<: *daily_osx + env: + - MATRIX_EVAL="COMPILER=clang && BUILD_TYPE=Release && TRAVIS_XCODE_VERSION=8gm" + - HOMEBREW_NO_AUTO_UPDATE=1 + - SHARED_LIB_EXT=dylib + osx_image: xcode8 branches: except: From ad0e9e81bad505fbd0d0bfcc966420a44db66c72 Mon Sep 17 00:00:00 2001 From: Dheepak Krishnamurthy Date: Fri, 11 May 2018 11:51:42 -0600 Subject: [PATCH 02/10] Add delay option --- .../python/timing-demo/timing-federate1.py | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/examples/python/timing-demo/timing-federate1.py b/examples/python/timing-demo/timing-federate1.py index e82ab26637..939bbea057 100644 --- a/examples/python/timing-demo/timing-federate1.py +++ b/examples/python/timing-demo/timing-federate1.py @@ -90,7 +90,7 @@ def destroy_value_federate(fed, broker): h.helicsCloseLibrary() -def main(): +def main(delay=None): broker = create_broker() fed = create_value_federate(broker) @@ -98,14 +98,17 @@ def main(): pubid = h.helicsFederateRegisterGlobalTypePublication(fed, "federate1-to-federate2", h.HELICS_DATA_TYPE_STRING, "") subid = h.helicsFederateRegisterSubscription(fed, "federate2-to-federate1", "double", "") epid = h.helicsFederateRegisterGlobalEndpoint(fed, "endpoint1", "") - # fid = h.helicsFederateRegisterSourceFilter(fed, h.helics_delay_filter, "endpoint2", "filter-name") + + if delay is not None: + fid = h.helicsFederateRegisterSourceFilter(fed, h.helics_delay_filter, "endpoint2", "filter-name") h.helicsSubscriptionSetDefaultDouble(subid, 0) print("Entering execution mode") h.helicsFederateEnterExecutionMode(fed) - # h.helicsFilterSet(fid, "delay", 2.0) + if delay is not None: + h.helicsFilterSet(fid, "delay", 2.0) grantedtime = -1 while True: @@ -137,6 +140,15 @@ def main(): if __name__ == "__main__": + import argparse + parser = argparse.ArgumentParser() + + parser.add_argument("--delay", default=False, help="Delay messages") + args = parser.parse_args() + if args.delay is not False: + delay = args.delay + else: + delay = None - main() + main(delay) From 0e4d0b0e98816684c5eafde506bd035fe96c6135 Mon Sep 17 00:00:00 2001 From: Philip Top Date: Fri, 11 May 2018 21:22:06 -0700 Subject: [PATCH 03/10] Cxx shared rework (#317) * rework the cmake files for the Cxx shared library, so it can now build simultaneously with C shared library and build on Windows. * update cmake with version info * add system interface include directories * update guardedTypes to accomodate OSX 8 * always include shared_mutex * update changelog * had to replace isnan with std::isnan in helicsTypes.cpp to get it to build in Linux --- CHANGELOG.md | 14 +- CMakeLists.txt | 151 ++++++++++--------- ThirdParty/libguarded/deferred_guarded.hpp | 6 +- ThirdParty/libguarded/ordered_guarded.hpp | 5 + ThirdParty/libguarded/shared_guarded.hpp | 7 +- src/helics/application_api/CMakeLists.txt | 17 +-- src/helics/application_api/helicsTypes.cpp | 6 +- src/helics/common/CMakeLists.txt | 12 +- src/helics/common/GuardedTypes.hpp | 8 +- src/helics/core/CMakeLists.txt | 14 +- src/helics/shared_api_library/CMakeLists.txt | 1 + tests/helics/CMakeLists.txt | 9 +- tests/helics/shared_library/CMakeLists.txt | 14 -- 13 files changed, 132 insertions(+), 132 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e15d32f301..8d08c5d023 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,17 +4,23 @@ 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). -## [1.1] +## [Unreleased] +### Changed + - the CXX shared library can now be built alongside the C shared library and can be built on Windows. +### Fixed + - compilation issue with Xcode 8.0 + +## [1.1.0] - 2018-05-09 ### Added - namedpoint functions in the C++ for publications and subscriptions, and corresponding functions in the C interface and language API's - - boolean publication and subscription for C++ interface, and corresponding functions in the C interface and language API's + - Boolean publication and subscription for C++ interface, and corresponding functions in the C interface and language API's - new options for brokers, --local, --ipv4, --ipv6, --all, are shortcuts for specifying external network interfaces - additional documentation, CONTRIBUTORS, ROADMAP, CONTRIBUTIONS, and some other other documentation improvements ### Changed - the default interface configuration for federates and brokers. The --interface option is less important as interfaces should mostly get automatically determined by the broker address - - minor configuration changes to cmake to be more conforming with modern cmake best practices + - minor configuration changes to CMAKE configuration to be more conforming with modern CMAKE best practices - cleaned up header installation for app directory - - shared libary construction now uses some headers generated by cmake + - shared library construction now uses some headers generated by CMAKE ### Fixed - better error checking in the C interface - fixes for occasionally failing tests diff --git a/CMakeLists.txt b/CMakeLists.txt index b7a6c2addd..34df4c2369 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -66,10 +66,10 @@ else() endif() -IF(NOT MSVC) - OPTION(BUILD_CXX_SHARED_LIB "Build a Shared Libraries of the CXX interface gcc/clang only" OFF) +#IF(NOT MSVC) + OPTION(BUILD_CXX_SHARED_LIB "Build a Shared Libraries of the CXX interface" OFF) mark_as_advanced(BUILD_CXX_SHARED_LIB) -ENDIF() +#ENDIF() if (INTERFACE_BUILD OR BUILD_C_SHARED_LIB OR BUILD_CXX_SHARED_LIB) set(BUILD_SHARED_LIBS ON) @@ -91,19 +91,25 @@ if (NOT CMAKE_DEBUG_POSTFIX) set(CMAKE_DEBUG_POSTFIX d) endif() +#add a baseline library for underlying dependencies and flags +add_library(helics_base INTERFACE) +add_library(helics_base_includes INTERFACE) -#these are for the common locations of build directories. they will get copied over for install if needed outside of build -include_directories ("${PROJECT_SOURCE_DIR}/ThirdParty") -include_directories ("${PROJECT_BINARY_DIR}/libs/include") - - - +target_link_libraries(helics_base INTERFACE helics_base_includes) # Prohibit in-source build IF("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}") message(FATAL_ERROR "In-source build is not supported. Please, use an empty directory for building the project.") ENDIF() include(compiler_flags) +message(STATUS "setting version build options to \"${VERSION_OPTION}\"") +IF (VERSION_OPTION) + IF (MSVC) + target_compile_options(helics_base_includes INTERFACE ${VERSION_OPTION}) + ELSE() + target_compile_options(helics_base_includes INTERFACE $<$:${VERSION_OPTION}>) + ENDIF (MSVC) +ENDIF(VERSION_OPTION) IF(UNIX) # Since default builds of boost library under Unix don't use @@ -178,26 +184,6 @@ FILE(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/logs) # ------------------------------------------------------------- include(addBoost) -# ------------------------------------------------------------- -# Add the main HELICS library -# ------------------------------------------------------------- - -add_library(helics-static STATIC - $ - $ - $ -) - -message(STATUS "setting version build options to \"${VERSION_OPTION}\"") -IF (VERSION_OPTION) - IF (MSVC) - target_compile_options(helics-static PUBLIC ${VERSION_OPTION}) - ELSE(MSVC) - target_compile_options(helics-static PUBLIC $<$:${VERSION_OPTION}>) - ENDIF (MSVC) -ENDIF(VERSION_OPTION) - - # ------------------------------------------------------------- # Enable ZeroMQ # ------------------------------------------------------------- @@ -241,10 +227,10 @@ if (NOT MSVC) endif(NOT MSVC) find_package(Threads REQUIRED) -target_link_libraries(helics-static PUBLIC Threads::Threads) +target_link_libraries(helics_base INTERFACE Threads::Threads) IF (UNIX AND NOT APPLE) - target_link_libraries(helics-static PUBLIC rt) + target_link_libraries(helics_base INTERFACE rt) ENDIF() IF(MSYS) @@ -252,15 +238,15 @@ IF(MSYS) if (BOOST_VERSION_LEVEL GREATER 1) #set(DISABLE_TCP_CORE TRUE) set(DISABLE_TCP_CORE FALSE) - target_link_libraries(helics-static PUBLIC wsock32 ws2_32) + target_link_libraries(helics_base INTERFACE wsock32 ws2_32) else() set(DISABLE_TCP_CORE TRUE) message(STATUS, "disabling TCP core |${DISABLE_TCP_CORE}|") - target_link_libraries(helics-static PUBLIC ws2_32) + target_link_libraries(helics_base INTERFACE ws2_32) endif() else() - target_link_libraries(helics-static PUBLIC wsock32 ws2_32) + target_link_libraries(helics_base INTERFACE wsock32 ws2_32) endif() ENDIF(MSYS) @@ -268,12 +254,12 @@ ENDIF(MSYS) if (HELICS_HAVE_ZEROMQ) if (ZMQ_USE_STATIC_LIBRARY) set(ZeroMQ_DEPENDENCY ${ZeroMQ_STATIC_LIBRARY}) - target_add_definitions(helics-static PUBLIC -DZMQ_STATIC) + target_add_definitions(helics_base_includes INTERFACE -DZMQ_STATIC) else() set(ZeroMQ_DEPENDENCY ${ZeroMQ_LIBRARY}) endif() message(STATUS "zmq dep ${ZeroMQ_DEPENDENCY}") - target_link_libraries(helics-static PUBLIC ${ZeroMQ_DEPENDENCY}) + target_link_libraries(helics_base INTERFACE ${ZeroMQ_DEPENDENCY}) else(HELICS_HAVE_ZEROMQ) if (ZeroMQ_ENABLE) message(WARNING "ZeroMQ not found") @@ -281,12 +267,25 @@ else(HELICS_HAVE_ZEROMQ) endif (HELICS_HAVE_ZEROMQ) if (MPI_C_FOUND) - target_link_libraries(helics-static PUBLIC ${MPI_C_LIBRARIES}) + target_link_libraries(helics_base INTERFACE ${MPI_C_LIBRARIES}) endif (MPI_C_FOUND) -target_link_libraries(helics-static PUBLIC ${Boost_LIBRARIES_core}) +target_link_libraries(helics_base INTERFACE ${Boost_LIBRARIES_core}) +# ------------------------------------------------------------- +# global include directories +# ------------------------------------------------------------- +target_include_directories(helics_base_includes INTERFACE + $ + $ + $ +) + +target_include_directories(helics_base_includes SYSTEM INTERFACE + $ + $ +) include(GNUInstallDirs) @@ -330,39 +329,52 @@ OPTION(BUILD_PLAYER "Build a helics player standalone executable" ON) OPTION(BUILD_RECORDER "Build a helics recorder standalone executable" ON) OPTION(BUILD_APPS "Build helics applications" ON) -# we aren't ready for this for the whole library yet -IF(BUILD_SHARED_LIBS AND NOT BUILD_CXX_SHARED_LIB) - IF(UNIX) - add_compile_options($<$:-fvisibility=hidden>) - add_compile_options($<$:-fvisibility=hidden>) - ELSE(UNIX) - IF(MINGW) - add_compile_options($<$:-fvisibility=hidden>) - add_compile_options($<$:-fvisibility=hidden>) - ENDIF(MINGW) - ENDIF(UNIX) -ENDIF() + + + +# ------------------------------------------------------------- +# Add the main HELICS library +# ------------------------------------------------------------- + +add_library(helics-static STATIC + $ + $ + $ +) + + +target_link_libraries(helics-static PUBLIC helics_base) IF(BUILD_CXX_SHARED_LIB) - if (BUILD_C_SHARED_LIB OR INTERFACE_BUILD) - message(WARNING "Building the CXX shared library and C shared library in the same build is not advisable due to conflicting symbol visibility guidelines and is unlikely to work very well") - endif() + #if (BUILD_C_SHARED_LIB OR INTERFACE_BUILD) + # message(WARNING "Building the CXX shared library and C shared library in the same build is not advisable due to conflicting symbol visibility guidelines and is unlikely to work very well") + #endif() - add_library(helics-shared SHARED src/empty.cpp) - target_link_libraries(helics-shared helics-static) - if (WIN32) - IF(MINGW) - set_target_properties(helics-shared PROPERTIES - LINK_FLAGS "-Wl,--whole-archive") - ELSE(MINGW) - set_target_properties(helics-shared PROPERTIES - LINK_FLAGS "/WHOLEARCHIVE") - endif() + add_library(helics-shared SHARED + src/empty.cpp + $ + $ + $ +) + + target_link_libraries(helics-shared PRIVATE helics_base) - elseif (APPLE) - set_target_properties(helics-shared PROPERTIES - LINK_FLAGS "-Wl,-all_load") - else () + if (WIN32) + set_target_properties(helics-shared PROPERTIES + WINDOWS_EXPORT_ALL_SYMBOLS TRUE) + + # IF(MINGW) + # set_target_properties(helics-shared PROPERTIES + # LINK_FLAGS "-Wl,--whole-archive") + # ELSE(MINGW) + # set_target_properties(helics-shared PROPERTIES + # LINK_FLAGS "/WHOLEARCHIVE") + # endif() + # + #elseif (APPLE) + # set_target_properties(helics-shared PROPERTIES + # LINK_FLAGS "-Wl,-all_load") + #else () # set_target_properties(helics-shared PROPERTIES # LINK_FLAGS "-Wl,--whole-archive") endif () @@ -385,8 +397,6 @@ endif() add_subdirectory (src) - - #----------------------------------------------------------------------------- # Setup CTEST environment #----------------------------------------------------------------------------- @@ -425,6 +435,9 @@ add_subdirectory(docs) set(HELICS_CMAKECONFIG_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}" CACHE STRING "install path for HELICSConfig.cmake") +install (TARGETS helics_base EXPORT helics-targets) +install (TARGETS helics_base_includes EXPORT helics-targets) + install (TARGETS helics-static EXPORT helics-targets DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libs) diff --git a/ThirdParty/libguarded/deferred_guarded.hpp b/ThirdParty/libguarded/deferred_guarded.hpp index 1f9ff7fa29..7d98bd90b0 100644 --- a/ThirdParty/libguarded/deferred_guarded.hpp +++ b/ThirdParty/libguarded/deferred_guarded.hpp @@ -19,7 +19,6 @@ #include #include #include - #include namespace libguarded @@ -41,8 +40,13 @@ typename std::add_lvalue_reference::type declref(); The shared_handle returned by the various lock methods is moveable but not copyable. */ +#ifdef LIBGUARDED_NO_DEFAULT +template +class deferred_guarded +#else template class deferred_guarded +#endif { private: class shared_deleter; diff --git a/ThirdParty/libguarded/ordered_guarded.hpp b/ThirdParty/libguarded/ordered_guarded.hpp index e02ecef2ba..c0dbb10ee2 100644 --- a/ThirdParty/libguarded/ordered_guarded.hpp +++ b/ThirdParty/libguarded/ordered_guarded.hpp @@ -48,8 +48,13 @@ namespace libguarded The handle returned by the various lock methods is moveable but not copyable. */ +#ifdef LIBGUARDED_NO_DEFAULT +template +class ordered_guarded +#else template class ordered_guarded +#endif { private: class shared_deleter; diff --git a/ThirdParty/libguarded/shared_guarded.hpp b/ThirdParty/libguarded/shared_guarded.hpp index 58f17560ee..1cd36363a1 100644 --- a/ThirdParty/libguarded/shared_guarded.hpp +++ b/ThirdParty/libguarded/shared_guarded.hpp @@ -36,7 +36,7 @@ namespace libguarded /** \headerfile shared_guarded.hpp - This templated class wraps an object and allows only one thread at + This templated class wraps an object and allows only one thread at a time to modify the protected object. This class will use std::shared_timed_mutex for the internal @@ -46,8 +46,13 @@ namespace libguarded The handle returned by the various lock methods is moveable but not copyable. */ +#ifdef LIBGUARDED_NO_DEFAULT +template +class shared_guarded +#else template class shared_guarded +#endif { private: class deleter; diff --git a/src/helics/application_api/CMakeLists.txt b/src/helics/application_api/CMakeLists.txt index 9db329c325..7a2f330b47 100644 --- a/src/helics/application_api/CMakeLists.txt +++ b/src/helics/application_api/CMakeLists.txt @@ -50,19 +50,10 @@ FederateInfo.cpp add_library(application_api OBJECT ${application_api_sources} ${public_application_api_headers} ${private_application_api_headers}) -IF (VERSION_OPTION) - IF (MSVC) - target_compile_options(application_api PUBLIC ${VERSION_OPTION}) - ELSE() - target_compile_options(application_api PUBLIC $<$:${VERSION_OPTION}>) - ENDIF (MSVC) -ENDIF(VERSION_OPTION) - -target_include_directories(application_api SYSTEM PUBLIC ${Boost_INCLUDE_DIR}) -target_include_directories(application_api SYSTEM PRIVATE ${PROJECT_SOURCE_DIR}/ThirdParty) +target_include_directories(application_api PRIVATE $) +target_include_directories(application_api SYSTEM PRIVATE $) +target_compile_definitions(application_api PRIVATE $) +target_compile_options(application_api PRIVATE $) install(FILES ${public_application_api_headers} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/helics/application_api COMPONENT headers) - -link_directories(${external_link_directories}) - diff --git a/src/helics/application_api/helicsTypes.cpp b/src/helics/application_api/helicsTypes.cpp index 1d02304b71..5590bdd0dd 100644 --- a/src/helics/application_api/helicsTypes.cpp +++ b/src/helics/application_api/helicsTypes.cpp @@ -827,7 +827,7 @@ data_block typeConvert (helics_type_t type, const named_point &val) { return ValueConverter::convert (val); } - if (isnan (val.value)) + if (std::isnan (val.value)) { // just convert the string return typeConvert (type, val.name); @@ -846,7 +846,7 @@ data_block typeConvert (helics_type_t type, const named_point &val) default: return ValueConverter::convert (val); case helics_type_t::helicsString: - return (isnan (val.value)) ? val.name : helicsNamedPointString (val); + return (std::isnan (val.value)) ? val.name : helicsNamedPointString (val); case helics_type_t::helicsComplexVector: { std::complex v2 (val.value, 0.0); @@ -863,7 +863,7 @@ data_block typeConvert (helics_type_t type, const char *str, double val) { return ValueConverter::convert (named_point (str, val)); } - if (isnan (val)) + if (std::isnan (val)) { // just convert the string return typeConvert (type, str); diff --git a/src/helics/common/CMakeLists.txt b/src/helics/common/CMakeLists.txt index c44e8f44d9..daeb66b94c 100644 --- a/src/helics/common/CMakeLists.txt +++ b/src/helics/common/CMakeLists.txt @@ -85,15 +85,11 @@ list(APPEND common_sources ${PROJECT_SOURCE_DIR}/ThirdParty/jsoncpp.cpp) add_library(helics_common OBJECT ${common_sources} ${common_headers}) set_target_properties(helics_common PROPERTIES LINKER_LANGUAGE CXX) -IF (VERSION_OPTION) - IF (MSVC) - target_compile_options(helics_common PUBLIC ${VERSION_OPTION}) - ELSE() - target_compile_options(helics_common PUBLIC $<$:${VERSION_OPTION}>) - ENDIF (MSVC) -ENDIF(VERSION_OPTION) +target_include_directories(helics_common PRIVATE $) +target_include_directories(helics_common SYSTEM PRIVATE $) +target_compile_definitions(helics_common PRIVATE $) -target_include_directories(helics_common SYSTEM PRIVATE ${Boost_INCLUDE_DIR}) +target_compile_options(helics_common PRIVATE $) if (HELICS_HAVE_ZEROMQ) target_include_directories (helics_common PRIVATE "${ZeroMQ_INCLUDE_DIR}") diff --git a/src/helics/common/GuardedTypes.hpp b/src/helics/common/GuardedTypes.hpp index 2ee4b431d5..2003758884 100644 --- a/src/helics/common/GuardedTypes.hpp +++ b/src/helics/common/GuardedTypes.hpp @@ -6,12 +6,18 @@ All rights reserved. See LICENSE file and DISCLAIMER for more details. #pragma once +#include "helics/compiler-config.h" +#ifndef HAVE_SHARED_TIMED_MUTEX +#ifndef HAVE_SHARED_MUTEX + #define LIBGUARDED_NO_DEFAULT 1 +#endif +#endif #include #include #include #include -#include "helics/compiler-config.h" + template using guarded = libguarded::guarded; diff --git a/src/helics/core/CMakeLists.txt b/src/helics/core/CMakeLists.txt index 705e86dc27..68534ae596 100644 --- a/src/helics/core/CMakeLists.txt +++ b/src/helics/core/CMakeLists.txt @@ -166,13 +166,10 @@ endif (HELICS_HAVE_MPI) add_library(helics_core OBJECT ${SRC_FILES} ${INCLUDE_FILES} ${PUBLIC_INCLUDE_FILES}) -IF (VERSION_OPTION) - IF (MSVC) - target_compile_options(helics_core PUBLIC ${VERSION_OPTION}) - ELSE() - target_compile_options(helics_core PUBLIC $<$:${VERSION_OPTION}>) - ENDIF (MSVC) -ENDIF(VERSION_OPTION) +target_include_directories(helics_core PRIVATE $) +target_include_directories(helics_core SYSTEM PRIVATE $) +target_compile_definitions(helics_core PRIVATE $) +target_compile_options(helics_core PRIVATE $) if (APPLE) target_compile_definitions(helics_core PUBLIC "-DSTX_NO_STD_ANY=1") @@ -194,9 +191,6 @@ if (NOT DISABLE_TCP_CORE) source_group("tcp" FILES ${TCP_SOURCE_FILES} ${TCP_HEADER_FILES}) endif() -target_include_directories(helics_core SYSTEM PRIVATE ${Boost_INCLUDE_DIR}) -target_include_directories(helics_core SYSTEM PRIVATE ${PROJECT_SOURCE_DIR}/ThirdParty) - if (HELICS_HAVE_ZEROMQ) target_include_directories (helics_core PRIVATE "${ZeroMQ_INCLUDE_DIR}") endif (HELICS_HAVE_ZEROMQ) diff --git a/src/helics/shared_api_library/CMakeLists.txt b/src/helics/shared_api_library/CMakeLists.txt index 0eba51bc38..17de1a7b64 100644 --- a/src/helics/shared_api_library/CMakeLists.txt +++ b/src/helics/shared_api_library/CMakeLists.txt @@ -41,6 +41,7 @@ target_include_directories(helicsSharedLib PUBLIC $ ) +set_target_properties(helicsSharedLib PROPERTIES CXX_VISIBILITY_PRESET hidden C_VISIBILITY_PRESET hidden) target_link_libraries(helicsSharedLib PRIVATE helics-static) if (UNIX OR MINGW) if (NOT APPLE) diff --git a/tests/helics/CMakeLists.txt b/tests/helics/CMakeLists.txt index 2adbb2ca5e..60d81f2b52 100644 --- a/tests/helics/CMakeLists.txt +++ b/tests/helics/CMakeLists.txt @@ -8,14 +8,7 @@ #add a baseline library for underlying dependencies and flags for test executables add_library(helics_test_base INTERFACE) target_link_libraries(helics_test_base INTERFACE ${Boost_LIBRARIES_test}) - -target_include_directories(helics_test_base SYSTEM INTERFACE - $ -) - -#set_property(TARGET helics_test_base APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES -# $ -# ) +target_link_libraries(helics_test_base INTERFACE helics_base_includes) add_subdirectory(common) diff --git a/tests/helics/shared_library/CMakeLists.txt b/tests/helics/shared_library/CMakeLists.txt index 2a24551598..6640e61a13 100644 --- a/tests/helics/shared_library/CMakeLists.txt +++ b/tests/helics/shared_library/CMakeLists.txt @@ -40,20 +40,6 @@ add_executable(shared-library-tests ${c_shared_library_test_sources} ctestFixtur add_executable(shared-library-tests-cpp ${cpp_shared_library_test_sources} cpptestFixtures.hpp) -target_include_directories(shared-library-tests PRIVATE ${PROJECT_SOURCE_DIR}/src) - -target_include_directories(shared-library-tests-cpp PRIVATE ${PROJECT_SOURCE_DIR}/src) - -IF (VERSION_OPTION) - IF (MSVC) - target_compile_options(shared-library-tests PUBLIC ${VERSION_OPTION}) - target_compile_options(shared-library-tests-cpp PUBLIC ${VERSION_OPTION}) - ELSE() - target_compile_options(shared-library-tests PUBLIC $<$:${VERSION_OPTION}>) - target_compile_options(shared-library-tests-cpp PUBLIC $<$:${VERSION_OPTION}>) - ENDIF (MSVC) -ENDIF(VERSION_OPTION) - target_link_libraries(shared-library-tests helicsSharedLib ${Boost_LIBRARIES_core} helics_test_base) target_link_libraries(shared-library-tests-cpp helicsSharedLib ${Boost_LIBRARIES_core} helics_test_base) From 8d8288b4f3655e8606b7dddf4bd3a5812680fcc9 Mon Sep 17 00:00:00 2001 From: Philip Top Date: Sun, 13 May 2018 05:52:15 -0700 Subject: [PATCH 04/10] Zmq version update (#321) * update Cereal and libzmq cmake code and version number * update json and workaround issue if json in installed on the system so it doesn't interfere with included libraries * fix zmq include --- CHANGELOG.md | 8 +- CMakeLists.txt | 12 +- ThirdParty/cereal/archives/xml.hpp | 12 +- ThirdParty/cereal/details/static_object.hpp | 5 +- ThirdParty/cereal/types/bitset.hpp | 4 +- ThirdParty/cereal/types/variant.hpp | 7 +- ThirdParty/cereal/version.hpp | 52 +++ ThirdParty/json/json-forwards.h | 26 +- ThirdParty/json/{json.h => jsoncpp.h} | 89 ++-- ThirdParty/jsoncpp.cpp | 395 +++++++++++------- config/cmake/FindZeroMQ.cmake | 7 +- config/cmake/addZeroMQ.cmake | 69 ++- config/cmake/buildlibZMQ.cmake | 4 +- src/helics/application_api/queryFunctions.cpp | 9 +- src/helics/apps/helicsApp.hpp | 7 +- src/helics/common/CMakeLists.txt | 4 +- src/helics/common/JsonProcessingFunctions.hpp | 9 +- src/helics/core/CMakeLists.txt | 9 +- src/helics/core/CoreBroker.cpp | 2 +- src/helics/shared_api_library/CMakeLists.txt | 4 - 20 files changed, 437 insertions(+), 297 deletions(-) create mode 100644 ThirdParty/cereal/version.hpp rename ThirdParty/json/{json.h => jsoncpp.h} (96%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8d08c5d023..2edc922b61 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,12 +1,16 @@ # Changelog All notable changes to this project after the 1.0.0 release will be documented in this file -The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/). +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] ### Changed + - upgrade autobuild ZMQ version to 4.2.5 and change CMake scripts to use zmq target + - update cereal library with latest bug fixes + - update jsoncpp with latest version - the CXX shared library can now be built alongside the C shared library and can be built on Windows. + ### Fixed - compilation issue with Xcode 8.0 @@ -16,11 +20,13 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - Boolean publication and subscription for C++ interface, and corresponding functions in the C interface and language API's - new options for brokers, --local, --ipv4, --ipv6, --all, are shortcuts for specifying external network interfaces - additional documentation, CONTRIBUTORS, ROADMAP, CONTRIBUTIONS, and some other other documentation improvements + ### Changed - the default interface configuration for federates and brokers. The --interface option is less important as interfaces should mostly get automatically determined by the broker address - minor configuration changes to CMAKE configuration to be more conforming with modern CMAKE best practices - cleaned up header installation for app directory - shared library construction now uses some headers generated by CMAKE + ### Fixed - better error checking in the C interface - fixes for occasionally failing tests diff --git a/CMakeLists.txt b/CMakeLists.txt index 34df4c2369..d3f962ed47 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -253,10 +253,10 @@ ENDIF(MSYS) if (HELICS_HAVE_ZEROMQ) if (ZMQ_USE_STATIC_LIBRARY) - set(ZeroMQ_DEPENDENCY ${ZeroMQ_STATIC_LIBRARY}) + set(ZeroMQ_DEPENDENCY libzmq-static) target_add_definitions(helics_base_includes INTERFACE -DZMQ_STATIC) else() - set(ZeroMQ_DEPENDENCY ${ZeroMQ_LIBRARY}) + set(ZeroMQ_DEPENDENCY libzmq) endif() message(STATUS "zmq dep ${ZeroMQ_DEPENDENCY}") target_link_libraries(helics_base INTERFACE ${ZeroMQ_DEPENDENCY}) @@ -360,12 +360,12 @@ IF(BUILD_CXX_SHARED_LIB) target_link_libraries(helics-shared PRIVATE helics_base) if (WIN32) - set_target_properties(helics-shared PROPERTIES + set_target_properties(helics-shared PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS TRUE) - + # IF(MINGW) - # set_target_properties(helics-shared PROPERTIES - # LINK_FLAGS "-Wl,--whole-archive") + # set_target_properties(helics-shared PROPERTIES + # LINK_FLAGS "-Wl,--whole-archive") # ELSE(MINGW) # set_target_properties(helics-shared PROPERTIES # LINK_FLAGS "/WHOLEARCHIVE") diff --git a/ThirdParty/cereal/archives/xml.hpp b/ThirdParty/cereal/archives/xml.hpp index 7bad8f96e5..4228565840 100644 --- a/ThirdParty/cereal/archives/xml.hpp +++ b/ThirdParty/cereal/archives/xml.hpp @@ -110,10 +110,10 @@ namespace cereal static Options Default(){ return Options(); } //! Specify specific options for the XMLOutputArchive - /*! @param precision The precision used for floating point numbers - @param indent Whether to indent each line of XML - @param outputType Whether to output the type of each serialized object as an attribute - @param sizeAttributes Whether dynamically sized containers output the size=dynamic attribute */ + /*! @param precision_ The precision used for floating point numbers + @param indent_ Whether to indent each line of XML + @param outputType_ Whether to output the type of each serialized object as an attribute + @param sizeAttributes_ Whether dynamically sized containers output the size=dynamic attribute */ explicit Options( int precision_ = std::numeric_limits::max_digits10, bool indent_ = true, bool outputType_ = false, @@ -210,7 +210,7 @@ namespace cereal itsNodes.top().node->append_attribute( itsXML.allocate_attribute( "type", "cereal binary data" ) ); finishNode(); - }; + } //! @} /*! @name Internal Functionality @@ -467,7 +467,7 @@ namespace cereal std::memcpy( data, decoded.data(), decoded.size() ); finishNode(); - }; + } //! @} /*! @name Internal Functionality diff --git a/ThirdParty/cereal/details/static_object.hpp b/ThirdParty/cereal/details/static_object.hpp index 51be358188..7152a003b2 100644 --- a/ThirdParty/cereal/details/static_object.hpp +++ b/ThirdParty/cereal/details/static_object.hpp @@ -67,13 +67,12 @@ namespace cereal class CEREAL_DLL_EXPORT StaticObject { private: - //! Forces instantiation at pre-execution time - static void instantiate( T const * ) {} static T & create() { static T t; - instantiate(&instance); + //! Forces instantiation at pre-execution time + (void)instance; return t; } diff --git a/ThirdParty/cereal/types/bitset.hpp b/ThirdParty/cereal/types/bitset.hpp index 12d3a8276f..22ff534f67 100644 --- a/ThirdParty/cereal/types/bitset.hpp +++ b/ThirdParty/cereal/types/bitset.hpp @@ -67,7 +67,7 @@ namespace cereal if( bits[i] ) chunk |= mask; - mask >>= 1; + mask = static_cast(mask >> 1); // output current chunk when mask is empty (8 bits) if( mask == 0 ) @@ -163,7 +163,7 @@ namespace cereal if( chunk & mask ) bits[i] = 1; - mask >>= 1; + mask = static_cast(mask >> 1); } break; } diff --git a/ThirdParty/cereal/types/variant.hpp b/ThirdParty/cereal/types/variant.hpp index 137cd8972a..920e9e175d 100644 --- a/ThirdParty/cereal/types/variant.hpp +++ b/ThirdParty/cereal/types/variant.hpp @@ -32,6 +32,7 @@ #include "cereal/cereal.hpp" #include +#include namespace cereal { @@ -80,7 +81,7 @@ namespace cereal template inline void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::variant const & variant ) { - auto index = variant.index(); + std::int32_t index = static_cast(variant.index()); ar( CEREAL_NVP_("index", index) ); variant_detail::variant_save_visitor visitor(ar); std::visit(visitor, variant); @@ -92,9 +93,9 @@ namespace cereal { using variant_t = typename std::variant; - decltype(variant.index()) index; + std::int32_t index; ar( CEREAL_NVP_("index", index) ); - if(index >= std::variant_size_v) + if(index >= static_cast(std::variant_size_v)) throw Exception("Invalid 'index' selector when deserializing std::variant"); variant_detail::load_variant<0, variant_t, VariantTypes...>(ar, index, variant); diff --git a/ThirdParty/cereal/version.hpp b/ThirdParty/cereal/version.hpp new file mode 100644 index 0000000000..c06f84943d --- /dev/null +++ b/ThirdParty/cereal/version.hpp @@ -0,0 +1,52 @@ +/*! \file version.hpp + \brief Macros to detect cereal version + + These macros can assist in determining the version of cereal. Be + warned that cereal is not guaranteed to be compatible across + different versions. For more information on releases of cereal, + see https://github.com/USCiLab/cereal/releases. + + \ingroup utility */ +/* + Copyright (c) 2018, Shane Grant + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of cereal nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef CEREAL_VERSION_HPP_ +#define CEREAL_VERSION_HPP_ + +//! The major version +#define CEREAL_VERSION_MAJOR 1 +//! The minor version +#define CEREAL_VERSION_MINOR 2 +//! The patch version +#define CEREAL_VERSION_PATCH 3 + +//! The full version as a single number +#define CEREAL_VERSION (CEREAL_VERSION_MAJOR * 10000 \ + + CEREAL_VERSION_MINOR * 100 \ + + CEREAL_VERSION_PATCH) + +#endif // CEREAL_VERSION_HPP_ diff --git a/ThirdParty/json/json-forwards.h b/ThirdParty/json/json-forwards.h index a650a591ce..25699a2000 100644 --- a/ThirdParty/json/json-forwards.h +++ b/ThirdParty/json/json-forwards.h @@ -1,4 +1,4 @@ -/// Json-cpp amalgated forward header (http://jsoncpp.sourceforge.net/). +/// Json-cpp amalgamated forward header (http://jsoncpp.sourceforge.net/). /// It is intended to be used with #include "json/json-forwards.h" /// This header provides forward declaration for all JsonCpp types. @@ -73,9 +73,9 @@ license you like. -#ifndef JSON_FORWARD_AMALGATED_H_INCLUDED -# define JSON_FORWARD_AMALGATED_H_INCLUDED -/// If defined, indicates that the source file is amalgated +#ifndef JSON_FORWARD_AMALGAMATED_H_INCLUDED +# define JSON_FORWARD_AMALGAMATED_H_INCLUDED +/// If defined, indicates that the source file is amalgamated /// to prevent private header inclusion. #define JSON_IS_AMALGAMATION @@ -110,9 +110,9 @@ license you like. #define JSON_USE_EXCEPTION 1 #endif -/// If defined, indicates that the source file is amalgated +/// If defined, indicates that the source file is amalgamated /// to prevent private header inclusion. -/// Remarks: it is automatically defined in the generated amalgated header. +/// Remarks: it is automatically defined in the generated amalgamated header. // #define JSON_IS_AMALGAMATION #ifdef JSON_IN_CPPTL @@ -163,21 +163,29 @@ license you like. #endif // defined(_MSC_VER) -// In c++11 the override keyword allows you to explicity define that a function +// In c++11 the override keyword allows you to explicitly define that a function // is intended to override the base-class version. This makes the code more -// managable and fixes a set of common hard-to-find bugs. +// manageable and fixes a set of common hard-to-find bugs. #if __cplusplus >= 201103L # define JSONCPP_OVERRIDE override # define JSONCPP_NOEXCEPT noexcept +# define JSONCPP_OP_EXPLICIT explicit #elif defined(_MSC_VER) && _MSC_VER > 1600 && _MSC_VER < 1900 # define JSONCPP_OVERRIDE override # define JSONCPP_NOEXCEPT throw() +# if _MSC_VER >= 1800 // MSVC 2013 +# define JSONCPP_OP_EXPLICIT explicit +# else +# define JSONCPP_OP_EXPLICIT +# endif #elif defined(_MSC_VER) && _MSC_VER >= 1900 # define JSONCPP_OVERRIDE override # define JSONCPP_NOEXCEPT noexcept +# define JSONCPP_OP_EXPLICIT explicit #else # define JSONCPP_OVERRIDE # define JSONCPP_NOEXCEPT throw() +# define JSONCPP_OP_EXPLICIT #endif #ifndef JSON_HAS_RVALUE_REFERENCES @@ -330,4 +338,4 @@ class ValueConstIterator; -#endif //ifndef JSON_FORWARD_AMALGATED_H_INCLUDED +#endif //ifndef JSON_FORWARD_AMALGAMATED_H_INCLUDED diff --git a/ThirdParty/json/json.h b/ThirdParty/json/jsoncpp.h similarity index 96% rename from ThirdParty/json/json.h rename to ThirdParty/json/jsoncpp.h index c91b3476c7..557217900f 100644 --- a/ThirdParty/json/json.h +++ b/ThirdParty/json/jsoncpp.h @@ -72,9 +72,9 @@ license you like. -#ifndef JSON_AMALGATED_H_INCLUDED -# define JSON_AMALGATED_H_INCLUDED -/// If defined, indicates that the source file is amalgated +#ifndef JSON_AMALGAMATED_H_INCLUDED +# define JSON_AMALGAMATED_H_INCLUDED +/// If defined, indicates that the source file is amalgamated /// to prevent private header inclusion. #define JSON_IS_AMALGAMATION @@ -87,10 +87,10 @@ license you like. #ifndef JSON_VERSION_H_INCLUDED # define JSON_VERSION_H_INCLUDED -# define JSONCPP_VERSION_STRING "1.8.3" +# define JSONCPP_VERSION_STRING "1.8.4" # define JSONCPP_VERSION_MAJOR 1 # define JSONCPP_VERSION_MINOR 8 -# define JSONCPP_VERSION_PATCH 3 +# define JSONCPP_VERSION_PATCH 4 # define JSONCPP_VERSION_QUALIFIER # define JSONCPP_VERSION_HEXA ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | (JSONCPP_VERSION_PATCH << 8)) @@ -143,9 +143,9 @@ license you like. #define JSON_USE_EXCEPTION 1 #endif -/// If defined, indicates that the source file is amalgated +/// If defined, indicates that the source file is amalgamated /// to prevent private header inclusion. -/// Remarks: it is automatically defined in the generated amalgated header. +/// Remarks: it is automatically defined in the generated amalgamated header. // #define JSON_IS_AMALGAMATION #ifdef JSON_IN_CPPTL @@ -196,21 +196,29 @@ license you like. #endif // defined(_MSC_VER) -// In c++11 the override keyword allows you to explicity define that a function +// In c++11 the override keyword allows you to explicitly define that a function // is intended to override the base-class version. This makes the code more -// managable and fixes a set of common hard-to-find bugs. +// manageable and fixes a set of common hard-to-find bugs. #if __cplusplus >= 201103L # define JSONCPP_OVERRIDE override # define JSONCPP_NOEXCEPT noexcept +# define JSONCPP_OP_EXPLICIT explicit #elif defined(_MSC_VER) && _MSC_VER > 1600 && _MSC_VER < 1900 # define JSONCPP_OVERRIDE override # define JSONCPP_NOEXCEPT throw() +# if _MSC_VER >= 1800 // MSVC 2013 +# define JSONCPP_OP_EXPLICIT explicit +# else +# define JSONCPP_OP_EXPLICIT +# endif #elif defined(_MSC_VER) && _MSC_VER >= 1900 # define JSONCPP_OVERRIDE override # define JSONCPP_NOEXCEPT noexcept +# define JSONCPP_OP_EXPLICIT explicit #else # define JSONCPP_OVERRIDE # define JSONCPP_NOEXCEPT throw() +# define JSONCPP_OP_EXPLICIT #endif #ifndef JSON_HAS_RVALUE_REFERENCES @@ -554,6 +562,13 @@ enum CommentPlacement { numberOfCommentPlacement }; +/** \brief Type of precision for formatting of real values. + */ +enum PrecisionType { + significantDigits = 0, ///< we set max number of significant digits in string + decimalPlaces ///< we set max number of digits after "." in string +}; + //# ifdef JSON_USE_CPPTL // typedef CppTL::AnyEnumerator EnumMemberNames; // typedef CppTL::AnyEnumerator EnumValues; @@ -561,7 +576,7 @@ enum CommentPlacement { /** \brief Lightweight wrapper to tag static string. * - * Value constructor and objectValue member assignement takes advantage of the + * Value constructor and objectValue member assignment takes advantage of the * StaticString and avoid the cost of string duplication when storing the * string or the member name. * @@ -665,7 +680,17 @@ class JSON_API Value { static const UInt64 maxUInt64; #endif // defined(JSON_HAS_INT64) + /// Default precision for real value for string representation. + static const UInt defaultRealPrecision; + +// Workaround for bug in the NVIDIAs CUDA 9.1 nvcc compiler +// when using gcc and clang backend compilers. CZString +// cannot be defined as private. See issue #486 +#ifdef __NVCC__ +public: +#else private: +#endif #ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION class CZString { public: @@ -845,8 +870,8 @@ Json_helics::Value obj_value(Json_helics::objectValue); // {} /// otherwise, false. bool empty() const; - /// Return isNull() - bool operator!() const; + /// Return !isNull() + JSONCPP_OP_EXPLICIT operator bool() const; /// Remove all object members and array elements. /// \pre type() is arrayValue, objectValue, or nullValue @@ -1044,6 +1069,9 @@ Json_helics::Value obj_value(Json_helics::objectValue); // {} private: void initBasic(ValueType type, bool allocated = false); + void dupPayload(const Value& other); + void releasePayload(); + void dupMeta(const Value& other); Value& resolveReference(const char* key); Value& resolveReference(const char* key, const char* end); @@ -1315,14 +1343,9 @@ class JSON_API ValueIterator : public ValueIteratorBase { pointer operator->() const { return &deref(); } }; -} // namespace Json_helics +inline void swap(Value& a, Value& b) { a.swap(b); } - -namespace std { -/// Specialize std::swap() for Json_helics::Value. -template<> -inline void swap(Json_helics::Value& a, Json_helics::Value& b) { a.swap(b); } -} +} // namespace Json_helics #pragma pack(pop) @@ -1379,7 +1402,7 @@ namespace Json_helics { * * \deprecated Use CharReader and CharReaderBuilder. */ -class JSONCPP_DEPRECATED("Use CharReader and CharReaderBuilder instead") JSON_API Reader { +class JSON_API Reader { public: typedef char Char; typedef const Char* Location; @@ -1399,11 +1422,13 @@ class JSONCPP_DEPRECATED("Use CharReader and CharReaderBuilder instead") JSON_AP /** \brief Constructs a Reader allowing all features * for parsing. */ + JSONCPP_DEPRECATED("Use CharReader and CharReaderBuilder instead") Reader(); /** \brief Constructs a Reader allowing the specified feature set * for parsing. */ + JSONCPP_DEPRECATED("Use CharReader and CharReaderBuilder instead") Reader(const Features& features); /** \brief Read a Value from a JSON @@ -1865,18 +1890,23 @@ class JSON_API StreamWriterBuilder : public StreamWriter::Factory { /** Configuration of this builder. Available settings (case-sensitive): - "commentStyle": "None" or "All" - - "indentation": "" + - "indentation": "". + - Setting this to an empty string also omits newline characters. - "enableYAMLCompatibility": false or true - slightly change the whitespace around colons - "dropNullPlaceholders": false or true - Drop the "null" string from the writer's output for nullValues. Strictly speaking, this is not valid JSON. But when the output is being - fed to a browser's Javascript, it makes for smaller output and the + fed to a browser's JavaScript, it makes for smaller output and the browser can handle the output just fine. - "useSpecialFloats": false or true - If true, outputs non-finite floating point values in the following way: NaN values as "NaN", positive infinity as "Infinity", and negative infinity as "-Infinity". + - "precision": int + - Number of precision digits for formatting of real values. + - "precisionType": "significant"(default) or "decimal" + - Type of precision for formatting of real values. You can examine 'settings_` yourself to see the defaults. You can also write and read them just like any @@ -1924,7 +1954,7 @@ class JSONCPP_DEPRECATED("Use StreamWriter instead") JSON_API Writer { * * The JSON document is written in a single line. It is not intended for 'human' *consumption, - * but may be usefull to support feature such as RPC where bandwith is limited. + * but may be useful to support feature such as RPC where bandwidth is limited. * \sa Reader, Value * \deprecated Use StreamWriterBuilder. */ @@ -1941,7 +1971,7 @@ class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API FastWriter /** \brief Drop the "null" string from the writer's output for nullValues. * Strictly speaking, this is not valid JSON. But when the output is being - * fed to a browser's Javascript, it makes for smaller output and the + * fed to a browser's JavaScript, it makes for smaller output and the * browser can handle the output just fine. */ void dropNullPlaceholders(); @@ -1955,7 +1985,7 @@ class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API FastWriter void writeValue(const Value& value); JSONCPP_STRING document_; - bool yamlCompatiblityEnabled_; + bool yamlCompatibilityEnabled_; bool dropNullPlaceholders_; bool omitEndingLineFeed_; }; @@ -2006,7 +2036,7 @@ class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API StyledWrite private: void writeValue(const Value& value); void writeArrayValue(const Value& value); - bool isMultineArray(const Value& value); + bool isMultilineArray(const Value& value); void pushValue(const JSONCPP_STRING& value); void writeIndent(); void writeWithIndent(const JSONCPP_STRING& value); @@ -2079,7 +2109,7 @@ class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API StyledStrea private: void writeValue(const Value& value); void writeArrayValue(const Value& value); - bool isMultineArray(const Value& value); + bool isMultilineArray(const Value& value); void pushValue(const JSONCPP_STRING& value); void writeIndent(); void writeWithIndent(const JSONCPP_STRING& value); @@ -2110,7 +2140,8 @@ JSONCPP_STRING JSON_API valueToString(UInt value); #endif // if defined(JSON_HAS_INT64) JSONCPP_STRING JSON_API valueToString(LargestInt value); JSONCPP_STRING JSON_API valueToString(LargestUInt value); -JSONCPP_STRING JSON_API valueToString(double value); +JSONCPP_STRING JSON_API valueToString(double value, unsigned int precision = Value::defaultRealPrecision, + PrecisionType precisionType = PrecisionType::significantDigits); JSONCPP_STRING JSON_API valueToString(bool value); JSONCPP_STRING JSON_API valueToQuotedString(const char* value); @@ -2204,4 +2235,4 @@ JSON_API JSONCPP_OSTREAM& operator<<(JSONCPP_OSTREAM&, const Value& root); -#endif //ifndef JSON_AMALGATED_H_INCLUDED +#endif //ifndef JSON_AMALGAMATED_H_INCLUDED diff --git a/ThirdParty/jsoncpp.cpp b/ThirdParty/jsoncpp.cpp index b5ae8d6480..e1a20b1304 100644 --- a/ThirdParty/jsoncpp.cpp +++ b/ThirdParty/jsoncpp.cpp @@ -1,4 +1,4 @@ -/// Json-cpp amalgated source (http://jsoncpp.sourceforge.net/). +/// Json-cpp amalgamated source (http://jsoncpp.sourceforge.net/). /// It is intended to be used with #include "json/json.h" // ////////////////////////////////////////////////////////////////////// @@ -73,7 +73,7 @@ license you like. -#include "json/json.h" +#include "json/jsoncpp.h" #ifndef JSON_IS_AMALGAMATION #error "Compile with -I PATH_TO_JSON_DIRECTORY" @@ -157,7 +157,7 @@ enum { typedef char UIntToStringBuffer[uintToStringBufferSize]; /** Converts an unsigned integer to string. - * @param value Unsigned interger to convert to string + * @param value Unsigned integer to convert to string * @param current Input/Output string buffer. * Must have at least uintToStringBufferSize chars free. */ @@ -195,6 +195,20 @@ static inline void fixNumericLocaleInput(char* begin, char* end) { } } +/** + * Delete zeros in the end of string, if it isn't last zero before '.' character. + */ +static inline void fixZerosInTheEnd(char* begin, char* end) { + end--; + while ((begin < end) && (*end == '0')) { + // don't delete last zero before point. + if (*(end - 1) != '.') { + *end = '\0'; + } + end--; + } +} + } // namespace Json_helics { #endif // LIB_JSONCPP_JSON_TOOL_H_INCLUDED @@ -225,7 +239,6 @@ static inline void fixNumericLocaleInput(char* begin, char* end) { #include "json_tool.h" #endif // if !defined(JSON_IS_AMALGAMATION) #include -#include #include #include #include @@ -234,24 +247,25 @@ static inline void fixNumericLocaleInput(char* begin, char* end) { #include #include -#if defined(_MSC_VER) -#if !defined(WINCE) && defined(__STDC_SECURE_LIB__) && _MSC_VER >= 1500 // VC++ 9.0 and above -#define snprintf sprintf_s -#elif _MSC_VER >= 1900 // VC++ 14.0 and above -#define snprintf std::snprintf -#else -#define snprintf _snprintf -#endif -#elif defined(__ANDROID__) || defined(__QNXNTO__) -#define snprintf snprintf -#elif __cplusplus >= 201103L -#if !defined(__MINGW32__) && !defined(__CYGWIN__) -#define snprintf std::snprintf -#endif -#endif +#if __cplusplus >= 201103L + #include -#if defined(__QNXNTO__) -#define sscanf std::sscanf + #if !defined(snprintf) + #define snprintf std::snprintf + #endif + + #if !defined(sscanf) + #define sscanf std::sscanf + #endif +#else + #include + + #if defined(_MSC_VER) + #define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1 + #if !defined(snprintf) + #define snprintf _snprintf + #endif + #endif #endif #if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0 @@ -2488,6 +2502,11 @@ ValueIterator& ValueIterator::operator=(const SelfType& other) { #include // size_t #include // min() +// Disable warning C4702 : unreachable code +#if defined(_MSC_VER) && _MSC_VER >= 1800 // VC++ 12.0 and above +#pragma warning(disable:4702) +#endif + #define JSON_ASSERT_UNREACHABLE assert(false) namespace Json_helics { @@ -2533,6 +2552,8 @@ const LargestInt Value::minLargestInt = LargestInt(~(LargestUInt(-1) / 2)); const LargestInt Value::maxLargestInt = LargestInt(LargestUInt(-1) / 2); const LargestUInt Value::maxLargestUInt = LargestUInt(-1); +const UInt Value::defaultRealPrecision = 17; + #if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) template static inline bool InRange(double d, T min, U max) { @@ -2910,48 +2931,9 @@ Value::Value(bool value) { value_.bool_ = value; } -Value::Value(Value const& other) - : type_(other.type_), allocated_(false) - , - comments_(0), start_(other.start_), limit_(other.limit_) -{ - switch (type_) { - case nullValue: - case intValue: - case uintValue: - case realValue: - case booleanValue: - value_ = other.value_; - break; - case stringValue: - if (other.value_.string_ && other.allocated_) { - unsigned len; - char const* str; - decodePrefixedString(other.allocated_, other.value_.string_, - &len, &str); - value_.string_ = duplicateAndPrefixStringValue(str, len); - allocated_ = true; - } else { - value_.string_ = other.value_.string_; - allocated_ = false; - } - break; - case arrayValue: - case objectValue: - value_.map_ = new ObjectValues(*other.value_.map_); - break; - default: - JSON_ASSERT_UNREACHABLE; - } - if (other.comments_) { - comments_ = new CommentInfo[numberOfCommentPlacement]; - for (int comment = 0; comment < numberOfCommentPlacement; ++comment) { - const CommentInfo& otherComment = other.comments_[comment]; - if (otherComment.comment_) - comments_[comment].setComment( - otherComment.comment_, strlen(otherComment.comment_)); - } - } +Value::Value(const Value& other) { + dupPayload(other); + dupMeta(other); } #if JSON_HAS_RVALUE_REFERENCES @@ -2963,24 +2945,7 @@ Value::Value(Value&& other) { #endif Value::~Value() { - switch (type_) { - case nullValue: - case intValue: - case uintValue: - case realValue: - case booleanValue: - break; - case stringValue: - if (allocated_) - releasePrefixedStringValue(value_.string_); - break; - case arrayValue: - case objectValue: - delete value_.map_; - break; - default: - JSON_ASSERT_UNREACHABLE; - } + releasePayload(); delete[] comments_; @@ -3003,9 +2968,8 @@ void Value::swapPayload(Value& other) { } void Value::copyPayload(const Value& other) { - type_ = other.type_; - value_ = other.value_; - allocated_ = other.allocated_; + releasePayload(); + dupPayload(other); } void Value::swap(Value& other) { @@ -3017,9 +2981,8 @@ void Value::swap(Value& other) { void Value::copy(const Value& other) { copyPayload(other); - comments_ = other.comments_; - start_ = other.start_; - limit_ = other.limit_; + delete[] comments_; + dupMeta(other); } ValueType Value::type() const { return type_; } @@ -3431,7 +3394,7 @@ bool Value::empty() const { return false; } -bool Value::operator!() const { return isNull(); } +Value::operator bool() const { return ! isNull(); } void Value::clear() { JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue || @@ -3458,7 +3421,7 @@ void Value::resize(ArrayIndex newSize) { if (newSize == 0) clear(); else if (newSize > oldSize) - (*this)[newSize - 1]; + this->operator[](newSize - 1); else { for (ArrayIndex index = newSize; index < oldSize; ++index) { value_.map_->erase(index); @@ -3518,6 +3481,75 @@ void Value::initBasic(ValueType vtype, bool allocated) { limit_ = 0; } +void Value::dupPayload(const Value& other) { + type_ = other.type_; + allocated_ = false; + switch (type_) { + case nullValue: + case intValue: + case uintValue: + case realValue: + case booleanValue: + value_ = other.value_; + break; + case stringValue: + if (other.value_.string_ && other.allocated_) { + unsigned len; + char const* str; + decodePrefixedString(other.allocated_, other.value_.string_, + &len, &str); + value_.string_ = duplicateAndPrefixStringValue(str, len); + allocated_ = true; + } else { + value_.string_ = other.value_.string_; + } + break; + case arrayValue: + case objectValue: + value_.map_ = new ObjectValues(*other.value_.map_); + break; + default: + JSON_ASSERT_UNREACHABLE; + } +} + +void Value::releasePayload() { + switch (type_) { + case nullValue: + case intValue: + case uintValue: + case realValue: + case booleanValue: + break; + case stringValue: + if (allocated_) + releasePrefixedStringValue(value_.string_); + break; + case arrayValue: + case objectValue: + delete value_.map_; + break; + default: + JSON_ASSERT_UNREACHABLE; + } +} + +void Value::dupMeta(const Value& other) { + if (other.comments_) { + comments_ = new CommentInfo[numberOfCommentPlacement]; + for (int comment = 0; comment < numberOfCommentPlacement; ++comment) { + const CommentInfo& otherComment = other.comments_[comment]; + if (otherComment.comment_) + comments_[comment].setComment( + otherComment.comment_, strlen(otherComment.comment_)); + } + } else { + comments_ = 0; + } + start_ = other.start_; + limit_ = other.limit_; +} + // Access an object value by name, create a null member if it does not exist. // @pre Type of '*this' is object or null. // @param key is null-terminated. @@ -3644,7 +3676,12 @@ bool Value::removeMember(const char* key, const char* cend, Value* removed) ObjectValues::iterator it = value_.map_->find(actualKey); if (it == value_.map_->end()) return false; - *removed = it->second; + if (removed) +#if JSON_HAS_RVALUE_REFERENCES + *removed = std::move(it->second); +#else + *removed = it->second; +#endif value_.map_->erase(it); return true; } @@ -4158,58 +4195,66 @@ Value& Path::make(Value& root) const { #include #include #include -#include - -#if defined(_MSC_VER) && _MSC_VER >= 1200 && _MSC_VER < 1800 // Between VC++ 6.0 and VC++ 11.0 -#include -#define isfinite _finite -#elif defined(__sun) && defined(__SVR4) //Solaris -#if !defined(isfinite) -#include -#define isfinite finite -#endif -#elif defined(_AIX) -#if !defined(isfinite) -#include -#define isfinite finite -#endif -#elif defined(__hpux) -#if !defined(isfinite) -#if defined(__ia64) && !defined(finite) -#define isfinite(x) ((sizeof(x) == sizeof(float) ? \ - _Isfinitef(x) : _IsFinite(x))) -#else -#include -#define isfinite finite -#endif -#endif -#else -#include -#if !(defined(__QNXNTO__)) // QNX already defines isfinite -#define isfinite std::isfinite -#endif -#endif -#if defined(_MSC_VER) -#if !defined(WINCE) && defined(__STDC_SECURE_LIB__) && _MSC_VER >= 1500 // VC++ 9.0 and above -#define snprintf sprintf_s -#elif _MSC_VER >= 1900 // VC++ 14.0 and above -#define snprintf std::snprintf +#if __cplusplus >= 201103L + #include + #include + + #if !defined(isnan) + #define isnan std::isnan + #endif + + #if !defined(isfinite) + #define isfinite std::isfinite + #endif + + #if !defined(snprintf) + #define snprintf std::snprintf + #endif #else -#define snprintf _snprintf -#endif -#elif defined(__ANDROID__) || defined(__QNXNTO__) -#define snprintf snprintf -#elif __cplusplus >= 201103L -#if !defined(__MINGW32__) && !defined(__CYGWIN__) -#define snprintf std::snprintf -#endif -#endif + #include + #include + + #if defined(_MSC_VER) + #if !defined(isnan) + #include + #define isnan _isnan + #endif + + #if !defined(isfinite) + #include + #define isfinite _finite + #endif + + #define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1 + #if !defined(snprintf) + #define snprintf _snprintf + #endif + #endif + + #if defined(__sun) && defined(__SVR4) //Solaris + #if !defined(isfinite) + #include + #define isfinite finite + #endif + #endif + + #if defined(__hpux) + #if !defined(isfinite) + #if defined(__ia64) && !defined(finite) + #define isfinite(x) ((sizeof(x) == sizeof(float) ? _Isfinitef(x) : _IsFinite(x))) + #endif + #endif + #endif + + #if !defined(isnan) + // IEEE standard states that NaN values will not compare to themselves + #define isnan(x) (x!=x) + #endif -#if defined(__BORLANDC__) -#include -#define isfinite _finite -#define snprintf _snprintf + #if !defined(isfinite) + #define isfinite finite + #endif #endif #if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0 @@ -4262,21 +4307,29 @@ JSONCPP_STRING valueToString(UInt value) { #endif // # if defined(JSON_HAS_INT64) namespace { -JSONCPP_STRING valueToString(double value, bool useSpecialFloats, unsigned int precision) { +JSONCPP_STRING valueToString(double value, bool useSpecialFloats, unsigned int precision, PrecisionType precisionType) { // Allocate a buffer that is more than large enough to store the 16 digits of // precision requested below. char buffer[36]; int len = -1; char formatString[15]; - snprintf(formatString, sizeof(formatString), "%%.%dg", precision); + if (precisionType == PrecisionType::significantDigits) { + snprintf(formatString, sizeof(formatString), "%%.%ug", precision); + } else { + snprintf(formatString, sizeof(formatString), "%%.%uf", precision); + } // Print into the buffer. We need not request the alternative representation - // that always has a decimal point because JSON doesn't distingish the + // that always has a decimal point because JSON doesn't distinguish the // concepts of reals and integers. if (isfinite(value)) { len = snprintf(buffer, sizeof(buffer), formatString, value); fixNumericLocale(buffer, buffer + len); + // to delete use-less too much zeros in the end of string + if (precisionType == PrecisionType::decimalPlaces) { + fixZerosInTheEnd(buffer, buffer + len); + } // try to ensure we preserve the fact that this was given to us as a double on input if (!strchr(buffer, '.') && !strchr(buffer, 'e')) { @@ -4284,8 +4337,8 @@ JSONCPP_STRING valueToString(double value, bool useSpecialFloats, unsigned int p } } else { - // IEEE standard states that NaN values will not compare to themselves - if (value != value) { + + if (isnan(value)) { len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "NaN" : "null"); } else if (value < 0) { len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "-Infinity" : "-1e+9999"); @@ -4298,7 +4351,9 @@ JSONCPP_STRING valueToString(double value, bool useSpecialFloats, unsigned int p } } -JSONCPP_STRING valueToString(double value) { return valueToString(value, false, 17); } +JSONCPP_STRING valueToString(double value, unsigned int precision, PrecisionType precisionType) { + return valueToString(value, false, precision, precisionType); +} JSONCPP_STRING valueToString(bool value) { return value ? "true" : "false"; } @@ -4343,7 +4398,7 @@ static unsigned int utf8ToCodepoint(const char*& s, const char* e) { s += 2; // surrogates aren't valid codepoints itself // shouldn't be UTF-8 encoded - if (calculated >= 0xD800 && calculated >= 0xDFFF) + if (calculated >= 0xD800 && calculated <= 0xDFFF) return REPLACEMENT_CHARACTER; // oversized encoded characters are invalid return calculated < 0x800 ? REPLACEMENT_CHARACTER : calculated; @@ -4353,7 +4408,7 @@ static unsigned int utf8ToCodepoint(const char*& s, const char* e) { if (e - s < 4) return REPLACEMENT_CHARACTER; - unsigned int calculated = ((firstByte & 0x07) << 24) + unsigned int calculated = ((firstByte & 0x07) << 18) | ((static_cast(s[1]) & 0x3F) << 12) | ((static_cast(s[2]) & 0x3F) << 6) | (static_cast(s[3]) & 0x3F); @@ -4478,10 +4533,10 @@ Writer::~Writer() {} // ////////////////////////////////////////////////////////////////// FastWriter::FastWriter() - : yamlCompatiblityEnabled_(false), dropNullPlaceholders_(false), + : yamlCompatibilityEnabled_(false), dropNullPlaceholders_(false), omitEndingLineFeed_(false) {} -void FastWriter::enableYAMLCompatibility() { yamlCompatiblityEnabled_ = true; } +void FastWriter::enableYAMLCompatibility() { yamlCompatibilityEnabled_ = true; } void FastWriter::dropNullPlaceholders() { dropNullPlaceholders_ = true; } @@ -4541,7 +4596,7 @@ void FastWriter::writeValue(const Value& value) { if (it != members.begin()) document_ += ','; document_ += valueToQuotedStringN(name.data(), static_cast(name.length())); - document_ += yamlCompatiblityEnabled_ ? ": " : ":"; + document_ += yamlCompatibilityEnabled_ ? ": " : ":"; writeValue(value[name]); } document_ += '}'; @@ -4630,7 +4685,7 @@ void StyledWriter::writeArrayValue(const Value& value) { if (size == 0) pushValue("[]"); else { - bool isArrayMultiLine = isMultineArray(value); + bool isArrayMultiLine = isMultilineArray(value); if (isArrayMultiLine) { writeWithIndent("["); indent(); @@ -4668,7 +4723,7 @@ void StyledWriter::writeArrayValue(const Value& value) { } } -bool StyledWriter::isMultineArray(const Value& value) { +bool StyledWriter::isMultilineArray(const Value& value) { ArrayIndex const size = value.size(); bool isMultiLine = size * 3 >= rightMargin_; childValues_.clear(); @@ -4767,7 +4822,8 @@ bool StyledWriter::hasCommentForValue(const Value& value) { StyledStreamWriter::StyledStreamWriter(JSONCPP_STRING indentation) : document_(NULL), rightMargin_(74), indentation_(indentation), - addChildValues_() {} + addChildValues_(), indented_(false) +{} void StyledStreamWriter::write(JSONCPP_OSTREAM& out, const Value& root) { document_ = &out; @@ -4847,7 +4903,7 @@ void StyledStreamWriter::writeArrayValue(const Value& value) { if (size == 0) pushValue("[]"); else { - bool isArrayMultiLine = isMultineArray(value); + bool isArrayMultiLine = isMultilineArray(value); if (isArrayMultiLine) { writeWithIndent("["); indent(); @@ -4887,7 +4943,7 @@ void StyledStreamWriter::writeArrayValue(const Value& value) { } } -bool StyledStreamWriter::isMultineArray(const Value& value) { +bool StyledStreamWriter::isMultilineArray(const Value& value) { ArrayIndex const size = value.size(); bool isMultiLine = size * 3 >= rightMargin_; childValues_.clear(); @@ -4999,12 +5055,13 @@ struct BuiltStyledStreamWriter : public StreamWriter JSONCPP_STRING const& nullSymbol, JSONCPP_STRING const& endingLineFeedSymbol, bool useSpecialFloats, - unsigned int precision); + unsigned int precision, + PrecisionType precisionType); int write(Value const& root, JSONCPP_OSTREAM* sout) JSONCPP_OVERRIDE; private: void writeValue(Value const& value); void writeArrayValue(Value const& value); - bool isMultineArray(Value const& value); + bool isMultilineArray(Value const& value); void pushValue(JSONCPP_STRING const& value); void writeIndent(); void writeWithIndent(JSONCPP_STRING const& value); @@ -5028,6 +5085,7 @@ struct BuiltStyledStreamWriter : public StreamWriter bool indented_ : 1; bool useSpecialFloats_ : 1; unsigned int precision_; + PrecisionType precisionType_; }; BuiltStyledStreamWriter::BuiltStyledStreamWriter( JSONCPP_STRING const& indentation, @@ -5036,7 +5094,8 @@ BuiltStyledStreamWriter::BuiltStyledStreamWriter( JSONCPP_STRING const& nullSymbol, JSONCPP_STRING const& endingLineFeedSymbol, bool useSpecialFloats, - unsigned int precision) + unsigned int precision, + PrecisionType precisionType) : rightMargin_(74) , indentation_(indentation) , cs_(cs) @@ -5047,6 +5106,7 @@ BuiltStyledStreamWriter::BuiltStyledStreamWriter( , indented_(false) , useSpecialFloats_(useSpecialFloats) , precision_(precision) + , precisionType_(precisionType) { } int BuiltStyledStreamWriter::write(Value const& root, JSONCPP_OSTREAM* sout) @@ -5076,7 +5136,7 @@ void BuiltStyledStreamWriter::writeValue(Value const& value) { pushValue(valueToString(value.asLargestUInt())); break; case realValue: - pushValue(valueToString(value.asDouble(), useSpecialFloats_, precision_)); + pushValue(valueToString(value.asDouble(), useSpecialFloats_, precision_, precisionType_)); break; case stringValue: { @@ -5128,7 +5188,7 @@ void BuiltStyledStreamWriter::writeArrayValue(Value const& value) { if (size == 0) pushValue("[]"); else { - bool isMultiLine = (cs_ == CommentStyle::All) || isMultineArray(value); + bool isMultiLine = (cs_ == CommentStyle::All) || isMultilineArray(value); if (isMultiLine) { writeWithIndent("["); indent(); @@ -5170,7 +5230,7 @@ void BuiltStyledStreamWriter::writeArrayValue(Value const& value) { } } -bool BuiltStyledStreamWriter::isMultineArray(Value const& value) { +bool BuiltStyledStreamWriter::isMultilineArray(Value const& value) { ArrayIndex const size = value.size(); bool isMultiLine = size * 3 >= rightMargin_; childValues_.clear(); @@ -5288,6 +5348,7 @@ StreamWriter* StreamWriterBuilder::newStreamWriter() const { JSONCPP_STRING indentation = settings_["indentation"].asString(); JSONCPP_STRING cs_str = settings_["commentStyle"].asString(); + JSONCPP_STRING pt_str = settings_["precisionType"].asString(); bool eyc = settings_["enableYAMLCompatibility"].asBool(); bool dnp = settings_["dropNullPlaceholders"].asBool(); bool usf = settings_["useSpecialFloats"].asBool(); @@ -5300,6 +5361,14 @@ StreamWriter* StreamWriterBuilder::newStreamWriter() const } else { throwRuntimeError("commentStyle must be 'All' or 'None'"); } + PrecisionType precisionType(significantDigits); + if (pt_str == "significant") { + precisionType = PrecisionType::significantDigits; + } else if (pt_str == "decimal") { + precisionType = PrecisionType::decimalPlaces; + } else { + throwRuntimeError("precisionType must be 'significant' or 'decimal'"); + } JSONCPP_STRING colonSymbol = " : "; if (eyc) { colonSymbol = ": "; @@ -5314,7 +5383,7 @@ StreamWriter* StreamWriterBuilder::newStreamWriter() const JSONCPP_STRING endingLineFeedSymbol; return new BuiltStyledStreamWriter( indentation, cs, - colonSymbol, nullSymbol, endingLineFeedSymbol, usf, pre); + colonSymbol, nullSymbol, endingLineFeedSymbol, usf, pre, precisionType); } static void getValidWriterKeys(std::set* valid_keys) { @@ -5325,6 +5394,7 @@ static void getValidWriterKeys(std::set* valid_keys) valid_keys->insert("dropNullPlaceholders"); valid_keys->insert("useSpecialFloats"); valid_keys->insert("precision"); + valid_keys->insert("precisionType"); } bool StreamWriterBuilder::validate(Json_helics::Value* invalid) const { @@ -5357,6 +5427,7 @@ void StreamWriterBuilder::setDefaults(Json_helics::Value* settings) (*settings)["dropNullPlaceholders"] = false; (*settings)["useSpecialFloats"] = false; (*settings)["precision"] = 17; + (*settings)["precisionType"] = "significant"; //! [StreamWriterBuilderDefaults] } diff --git a/config/cmake/FindZeroMQ.cmake b/config/cmake/FindZeroMQ.cmake index fb33d47e96..375af0a423 100644 --- a/config/cmake/FindZeroMQ.cmake +++ b/config/cmake/FindZeroMQ.cmake @@ -50,7 +50,7 @@ if (MSVC) #message(STATUS "toolset =${CMAKE_VS_PLATFORM_TOOLSET}") if (${ZeroMQ_NAME} MATCHES "registry") # if key was not found, the string "registry" is returned - set(_ZeroMQ_VERSIONS "4_2_3" "4_2_2" "4_2_1" "4_2_0" "4_1_5" "4_1_4" "4_0_4" "4_0_3" "4_0_2" "4_0_1" "4_0_0") + set(_ZeroMQ_VERSIONS "4_2_5" "4_2_4" "4_2_3" "4_2_2" "4_2_1" "4_2_0" "4_1_5" "4_1_4" "4_0_4" "4_0_3" "4_0_2" "4_0_1" "4_0_0") set(ZeroMQ_LIBRARY_NAME) foreach(ver ${_ZeroMQ_VERSIONS}) @@ -84,6 +84,10 @@ if (ZeroMQ_INCLUDE_DIR AND ZeroMQ_LIBRARY AND NOT ZeroMQ_LIBRARY-NOTFOUND) set(ZeroMQ_FOUND 1) message(STATUS "Found ZeroMQ library: ${ZeroMQ_LIBRARY}") message(STATUS "Found ZeroMQ headers: ${ZeroMQ_INCLUDE_DIR}") + #this is static because we are pointing to the library for the linker, not the shared object + add_library(libzmq STATIC IMPORTED) + set_target_properties(libzmq PROPERTIES IMPORTED_LOCATION "${ZeroMQ_LIBRARY}") + set_target_properties(libzmq PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${ZeroMQ_INCLUDE_DIR}") else() IF(NOT ZeroMQ_FIND_QUIETLY) message(SEND_ERROR "Could not find ZeroMQ libraries/headers! Please install ZeroMQ with libraries and headers") @@ -92,3 +96,4 @@ endif() # show the ZeroMQ_INCLUDE_DIR and ZeroMQ_LIBRARY variables only in the advanced view mark_as_advanced(ZeroMQ_ROOT_DIR ZeroMQ_INCLUDE_DIR ZeroMQ_LIBRARY ZeroMQ_FOUND) + diff --git a/config/cmake/addZeroMQ.cmake b/config/cmake/addZeroMQ.cmake index 12d0cf69ce..456d8c2803 100644 --- a/config/cmake/addZeroMQ.cmake +++ b/config/cmake/addZeroMQ.cmake @@ -3,57 +3,50 @@ OPTION(ZMQ_USE_STATIC_LIBRARY "use the ZMQ static library" OFF) -SHOW_VARIABLE(ZeroMQ_LIBRARY_PATH PATH +SHOW_VARIABLE(ZeroMQ_INSTALL_PATH PATH "path to the zmq libraries" "${PROJECT_BINARY_DIR}/libs") -SHOW_VARIABLE(ZeroMQ_INCLUDE_PATH PATH - "path to the zmq headers" "${PROJECT_BINARY_DIR}/libs") +set(ZMQ_CMAKE_SUFFIXES + cmake/ZeroMQ + cmake + CMake/ZeroMQ + lib/cmake) + +find_package(ZeroMQ QUIET + HINTS + ${ZeroMQ_INSTALL_PATH} + ${PROJECT_BINARY_DIR}/libs/ + PATH_SUFFIXES ${ZMQ_CMAKE_SUFFIXES} + ) -set(ZeroMQ_FIND_QUIETLY ON) -if (EXISTS ${PROJECT_BINARY_DIR}/libs/cmake/ZeroMQ/ZeroMQConfig.cmake) - include(${PROJECT_BINARY_DIR}/libs/cmake/ZeroMQ/ZeroMQConfig.cmake) - set(ZMQ_CMAKE_INCLUDE ${PROJECT_BINARY_DIR}/libs/cmake/ZeroMQ/ZeroMQConfig.cmake) - #message(STATUS "loading zmq cmake") - if (NOT ZeroMQ_LIBRARY) - set(ZeroMQ_LIBRARY libzmq) - endif() - if (NOT ZeroMQ_STATIC_LIBRARY) - set(ZeroMQ_STATIC_LIBRARY libzmq-static) - endif() - set(ZeroMQ_FOUND 1) -else() +if (NOT ZeroMQ_FOUND) + message(STATUS "initialZMQ not found") if (ZMQ_USE_STATIC_LIBRARY OR AUTOBUILD_ZMQ) include(buildlibZMQ) build_libzmq() - set(ZeroMQ_INSTALL_PATH ${PROJECT_BINARY_DIR}/libs) - include(${ZeroMQ_INSTALL_PATH}/cmake/ZeroMQ/ZeroMQConfig.cmake) - set(ZMQ_CMAKE_INCLUDE ${ZeroMQ_INSTALL_PATH}/cmake/ZeroMQ/ZeroMQConfig.cmake) - if (NOT ZeroMQ_LIBRARY) - set(ZeroMQ_LIBRARY libzmq) - endif() - if (NOT ZeroMQ_STATIC_LIBRARY) - set(ZeroMQ_STATIC_LIBRARY libzmq-static) - endif() - set(ZeroMQ_FOUND 1) + find_package(ZeroMQ + HINTS + ${ZeroMQ_INSTALL_PATH} + ${PROJECT_BINARY_DIR}/libs/ + PATH_SUFFIXES ${ZMQ_CMAKE_SUFFIXES} + ) else() + set(ZeroMQ_FIND_QUIETLY ON) find_package(ZeroMQ) - if (NOT ZeroMQ_INCLUDE_DIR) + if (NOT ZeroMQ_FOUND) OPTION(AUTOBUILD_ZMQ "enable ZMQ to automatically download and build" ON) IF (AUTOBUILD_ZMQ) include(buildlibZMQ) build_libzmq() - set(ZeroMQ_INSTALL_PATH ${PROJECT_BINARY_DIR}/libs) - include(${ZeroMQ_INSTALL_PATH}/cmake/ZeroMQ/ZeroMQConfig.cmake) - set(ZMQ_CMAKE_INCLUDE ${ZeroMQ_INSTALL_PATH}/cmake/ZeroMQ/ZeroMQConfig.cmake) - if (NOT ZeroMQ_LIBRARY) - set(ZeroMQ_LIBRARY libzmq) - endif() - if (NOT ZeroMQ_STATIC_LIBRARY) - set(ZeroMQ_STATIC_LIBRARY libzmq-static) - endif() - set(ZeroMQ_FOUND 1) + find_package(ZeroMQ + HINTS + ${ZeroMQ_INSTALL_PATH} + ${PROJECT_BINARY_DIR}/libs/ + PATH_SUFFIXES ${ZMQ_CMAKE_SUFFIXES} + ) ENDIF(AUTOBUILD_ZMQ) - endif(NOT ZeroMQ_INCLUDE_DIR) + endif() endif() endif() +message(STATUS "includes $") \ No newline at end of file diff --git a/config/cmake/buildlibZMQ.cmake b/config/cmake/buildlibZMQ.cmake index 7c959ad595..babf7040ff 100644 --- a/config/cmake/buildlibZMQ.cmake +++ b/config/cmake/buildlibZMQ.cmake @@ -30,7 +30,7 @@ set(trigger_build_dir ${CMAKE_BINARY_DIR}/autobuild/force_libzmq) if (ZMQ_USE_STATIC_LIBRARY) set(zmq_static_build ON) set(zmq_shared_build ON) - set(extra_cxx_flags "${extra_cxx_flags} -fPIC") + set(extra_cxx_flags "${extra_cxx_flags} -fPIC") else() set(zmq_static_build ON) set(zmq_shared_build ON) @@ -53,7 +53,7 @@ set(trigger_build_dir ${CMAKE_BINARY_DIR}/autobuild/force_libzmq) ExternalProject_Add(libzmq SOURCE_DIR ${PROJECT_BINARY_DIR}/Download/libzmq GIT_REPOSITORY https://github.com/zeromq/libzmq.git - GIT_TAG v4.2.3 + GIT_TAG v4.2.5 DOWNLOAD_COMMAND " " UPDATE_COMMAND " " BINARY_DIR ${PROJECT_BINARY_DIR}/ThirdParty/libzmq diff --git a/src/helics/application_api/queryFunctions.cpp b/src/helics/application_api/queryFunctions.cpp index fe308a1399..dd3d8ae4d7 100644 --- a/src/helics/application_api/queryFunctions.cpp +++ b/src/helics/application_api/queryFunctions.cpp @@ -9,14 +9,7 @@ All rights reserved. See LICENSE file and DISCLAIMER for more details. #include "Federate.hpp" #include -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable : 4702) -#include "json/json.h" -#pragma warning(pop) -#else -#include "json/json.h" -#endif +#include "json/jsoncpp.h" #include diff --git a/src/helics/apps/helicsApp.hpp b/src/helics/apps/helicsApp.hpp index f0e8fccc0a..478833d95d 100644 --- a/src/helics/apps/helicsApp.hpp +++ b/src/helics/apps/helicsApp.hpp @@ -6,7 +6,7 @@ All rights reserved. See LICENSE file and DISCLAIMER for more details. #pragma once #include "../application_api/CombinationFederate.hpp" - +#include "json/json-forwards.h" namespace boost { namespace program_options @@ -15,11 +15,6 @@ class variables_map; } } -namespace Json_helics -{ -class Value; -} - namespace helics { namespace apps diff --git a/src/helics/common/CMakeLists.txt b/src/helics/common/CMakeLists.txt index daeb66b94c..5143d72006 100644 --- a/src/helics/common/CMakeLists.txt +++ b/src/helics/common/CMakeLists.txt @@ -92,8 +92,8 @@ target_compile_definitions(helics_common PRIVATE $) if (HELICS_HAVE_ZEROMQ) - target_include_directories (helics_common PRIVATE "${ZeroMQ_INCLUDE_DIR}") -endif(HELICS_HAVE_ZEROMQ) +target_include_directories(helics_common SYSTEM PRIVATE $) +endif (HELICS_HAVE_ZEROMQ) if (APPLE) target_compile_definitions(helics_common PUBLIC "-DSTX_NO_STD_ANY=1") diff --git a/src/helics/common/JsonProcessingFunctions.hpp b/src/helics/common/JsonProcessingFunctions.hpp index eef70bf15f..f6d5005536 100644 --- a/src/helics/common/JsonProcessingFunctions.hpp +++ b/src/helics/common/JsonProcessingFunctions.hpp @@ -10,14 +10,7 @@ All rights reserved. See LICENSE file and DISCLAIMER for more details. using the jsoncpp library */ -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable : 4702) -#include "json/json.h" -#pragma warning(pop) -#else -#include "json/json.h" -#endif +#include "json/jsoncpp.h" #include "../core/helics-time.hpp" /** load a JSON string or filename that points to a JSON file and return a diff --git a/src/helics/core/CMakeLists.txt b/src/helics/core/CMakeLists.txt index 68534ae596..eb4744a25e 100644 --- a/src/helics/core/CMakeLists.txt +++ b/src/helics/core/CMakeLists.txt @@ -179,9 +179,10 @@ if (HELICS_HAVE_MPI) source_group("mpi" FILES ${MPI_SOURCE_FILES} ${MPI_HEADER_FILES}) endif (HELICS_HAVE_MPI) -if (HELICS_HAVE_ZMQ) +if (HELICS_HAVE_ZEROMQ) + target_include_directories(helics_core SYSTEM PRIVATE $) source_group("zmq" FILES ${ZMQ_SOURCE_FILES} ${ZMQ_HEADER_FILES}) -endif(HELICS_HAVE_ZMQ) +endif(HELICS_HAVE_ZEROMQ) source_group("udp" FILES ${UDP_SOURCE_FILES} ${UDP_HEADER_FILES}) source_group("ipc" FILES ${IPC_SOURCE_FILES} ${IPC_HEADER_FILES}) @@ -191,10 +192,6 @@ if (NOT DISABLE_TCP_CORE) source_group("tcp" FILES ${TCP_SOURCE_FILES} ${TCP_HEADER_FILES}) endif() -if (HELICS_HAVE_ZEROMQ) - target_include_directories (helics_core PRIVATE "${ZeroMQ_INCLUDE_DIR}") -endif (HELICS_HAVE_ZEROMQ) - if (HELICS_HAVE_MPI) target_include_directories(helics_core PRIVATE "${MPI_C_INCLUDE_DIR}" "${MPI_C_HEADER_DIR}" "${MPI_C_ADDITIONAL_INCLUDE_DIRS}") endif(HELICS_HAVE_MPI) diff --git a/src/helics/core/CoreBroker.cpp b/src/helics/core/CoreBroker.cpp index 45af791412..a250010536 100644 --- a/src/helics/core/CoreBroker.cpp +++ b/src/helics/core/CoreBroker.cpp @@ -16,7 +16,7 @@ All rights reserved. See LICENSE file and DISCLAIMER for more details. #include "ForwardingTimeCoordinator.hpp" #include "loggingHelper.hpp" #include -#include +#include namespace helics { diff --git a/src/helics/shared_api_library/CMakeLists.txt b/src/helics/shared_api_library/CMakeLists.txt index 17de1a7b64..fd2eb2a0e5 100644 --- a/src/helics/shared_api_library/CMakeLists.txt +++ b/src/helics/shared_api_library/CMakeLists.txt @@ -49,10 +49,6 @@ if (UNIX OR MINGW) endif(NOT APPLE) endif() -if (HELICS_HAVE_ZEROMQ) - target_include_directories (helicsSharedLib PRIVATE "${ZeroMQ_INCLUDE_DIR}") -endif(HELICS_HAVE_ZEROMQ) - set_target_properties (helicsSharedLib PROPERTIES FOLDER interfaces) INSTALL(TARGETS helicsSharedLib EXPORT helics-targets From 34d2770bc9e151849cb06b6c6be57e4301c72396 Mon Sep 17 00:00:00 2001 From: Philip Top Date: Fri, 18 May 2018 13:06:41 -0700 Subject: [PATCH 05/10] Broker app (#323) * move some cmake configuration around, move broker executable to apps folder * move library cmake configuration to more sensible location * added BrokerApp, Still some work on getting it to play nicely with other apps * update HELICS config Issue #322 * update examples to use BrokerApp * fix a couple more warnings --- CHANGELOG.md | 4 + CMakeLists.txt | 147 +--- ThirdParty/jsoncpp.cpp | 7 +- config/HELICSConfig.cmake.in | 5 + config/HELICSImport.cmake.in | 13 - config/cmake/addZeroMQ.cmake | 4 +- examples/FilterFederate1/CMakeLists.txt | 4 - examples/comboFederates1/CMakeLists.txt | 6 +- examples/comboFederates1/comboFed.cpp | 14 +- examples/messageFederates1/CMakeLists.txt | 14 +- examples/messageFederates1/messageFed.cpp | 16 +- examples/messageFederates1/messageFedObj.cpp | 84 +-- examples/valueFederates1/CMakeLists.txt | 6 +- examples/valueFederates1/valueFed.cpp | 14 +- src/helics/CMakeLists.txt | 70 +- src/helics/application_api/Federate.hpp | 2 +- src/helics/apps/BrokerApp.cpp | 123 ++++ src/helics/apps/BrokerApp.hpp | 71 ++ src/helics/apps/CMakeLists.txt | 68 +- src/helics/apps/Echo.cpp | 2 +- src/helics/apps/Echo.hpp | 8 +- src/helics/apps/Player.cpp | 2 +- src/helics/apps/Player.hpp | 3 +- src/helics/apps/Recorder.cpp | 2 +- src/helics/apps/Recorder.hpp | 3 +- src/helics/apps/Source.cpp | 2 +- src/helics/apps/Source.hpp | 3 +- src/helics/apps/Tracer.cpp | 2 +- src/helics/apps/Tracer.hpp | 3 +- src/helics/apps/appMain.cpp | 38 +- src/helics/apps/helics-broker.cpp | 31 + src/helics/apps/helicsApp.hpp | 2 +- src/helics/apps/playerMain.cpp | 9 +- src/helics/apps/recorderMain.cpp | 11 +- src/helics/common/MapTraits.hpp | 6 +- src/helics/common/cppzmq/zmq.hpp | 736 +++++++++++-------- src/helics/common/cppzmq/zmq_addon.hpp | 513 +++++-------- src/helics/common/timeRepresentation.hpp | 2 +- src/helics/core/CMakeLists.txt | 17 - src/helics/core/core-types.hpp | 1 + src/helics/core/helics-broker.cpp | 65 -- src/helics/cpp98/CMakeLists.txt | 1 + src/helics/shared_api_library/CMakeLists.txt | 28 +- tests/helics/CMakeLists.txt | 4 +- tests/helics/apps/PlayerTests.cpp | 4 +- 45 files changed, 1097 insertions(+), 1073 deletions(-) delete mode 100644 config/HELICSImport.cmake.in create mode 100644 src/helics/apps/BrokerApp.cpp create mode 100644 src/helics/apps/BrokerApp.hpp create mode 100644 src/helics/apps/helics-broker.cpp delete mode 100644 src/helics/core/helics-broker.cpp diff --git a/CHANGELOG.md b/CHANGELOG.md index 2edc922b61..81665a9286 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,10 +5,14 @@ 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] +### Added + - BrokerApp as a slightly more convenient runner to Brokers + ### Changed - upgrade autobuild ZMQ version to 4.2.5 and change CMake scripts to use zmq target - update cereal library with latest bug fixes - update jsoncpp with latest version + - moved helics_broker executable code to the apps repository - the CXX shared library can now be built alongside the C shared library and can be built on Windows. ### Fixed diff --git a/CMakeLists.txt b/CMakeLists.txt index d3f962ed47..1561ea5830 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -184,24 +184,6 @@ FILE(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/logs) # ------------------------------------------------------------- include(addBoost) -# ------------------------------------------------------------- -# Enable ZeroMQ -# ------------------------------------------------------------- - -OPTION(ZeroMQ_ENABLE "Enable ZeroMQ networking library" ON) -# If ZeroMQ library is enabled try to locate it and link against it - -IF (ZeroMQ_ENABLE) - include(addZeroMQ) - - if (ZeroMQ_FOUND) - set(HELICS_HAVE_ZEROMQ TRUE) - else(ZeroMQ_FOUND) - set(HELICS_HAVE_ZEROMQ FALSE) - endif(ZeroMQ_FOUND) - ELSE(ZeroMQ_ENABLE) - set(HELICS_HAVE_ZEROMQ FALSE) -ENDIF(ZeroMQ_ENABLE) # ------------------------------------------------------------- # finding MPI @@ -212,6 +194,7 @@ IF (MPI_ENABLE) include(addMPI) if (MPI_C_FOUND) set(HELICS_HAVE_MPI TRUE) + target_link_libraries(helics_base INTERFACE ${MPI_C_LIBRARIES}) else() set(HELICS_HAVE_MPI FALSE) endif (MPI_C_FOUND) @@ -222,9 +205,9 @@ ENDIF(MPI_ENABLE) # ------------------------------------------------------------- # add threading support # ------------------------------------------------------------- -if (NOT MSVC) +if (NOT WIN32) set(THREADS_PREFER_PTHREAD_FLAG ON) -endif(NOT MSVC) +endif(NOT WIN32) find_package(Threads REQUIRED) target_link_libraries(helics_base INTERFACE Threads::Threads) @@ -233,6 +216,9 @@ IF (UNIX AND NOT APPLE) target_link_libraries(helics_base INTERFACE rt) ENDIF() +# ------------------------------------------------------------- +# check for some things with TCP core +# ------------------------------------------------------------- IF(MSYS) if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") if (BOOST_VERSION_LEVEL GREATER 1) @@ -251,25 +237,35 @@ IF(MSYS) ENDIF(MSYS) -if (HELICS_HAVE_ZEROMQ) - if (ZMQ_USE_STATIC_LIBRARY) - set(ZeroMQ_DEPENDENCY libzmq-static) - target_add_definitions(helics_base_includes INTERFACE -DZMQ_STATIC) - else() - set(ZeroMQ_DEPENDENCY libzmq) - endif() - message(STATUS "zmq dep ${ZeroMQ_DEPENDENCY}") - target_link_libraries(helics_base INTERFACE ${ZeroMQ_DEPENDENCY}) -else(HELICS_HAVE_ZEROMQ) - if (ZeroMQ_ENABLE) - message(WARNING "ZeroMQ not found") - endif() -endif (HELICS_HAVE_ZEROMQ) +# ------------------------------------------------------------- +# Enable ZeroMQ +# ------------------------------------------------------------- -if (MPI_C_FOUND) - target_link_libraries(helics_base INTERFACE ${MPI_C_LIBRARIES}) -endif (MPI_C_FOUND) +OPTION(ZeroMQ_ENABLE "Enable ZeroMQ networking library" ON) +# If ZeroMQ library is enabled try to locate it and link against it +IF (ZeroMQ_ENABLE) + include(addZeroMQ) + + if (ZeroMQ_FOUND) + set(HELICS_HAVE_ZEROMQ TRUE) + if (ZMQ_USE_STATIC_LIBRARY) + set(ZeroMQ_DEPENDENCY libzmq-static) + target_add_definitions(helics_base_includes INTERFACE -DZMQ_STATIC) + else() + set(ZeroMQ_DEPENDENCY libzmq) + endif() + #message(STATUS "zmq dep ${ZeroMQ_DEPENDENCY}") + target_link_libraries(helics_base INTERFACE ${ZeroMQ_DEPENDENCY}) + else(ZeroMQ_FOUND) + set(HELICS_HAVE_ZEROMQ FALSE) + endif(ZeroMQ_FOUND) + ELSE(ZeroMQ_ENABLE) + set(HELICS_HAVE_ZEROMQ FALSE) + if (ZeroMQ_ENABLE) + message(WARNING "ZeroMQ not found") + endif() +ENDIF(ZeroMQ_ENABLE) target_link_libraries(helics_base INTERFACE ${Boost_LIBRARIES_core}) @@ -324,63 +320,12 @@ if (NOT Boost_USE_STATIC_LIBS) list(APPEND CMAKE_BUILD_RPATH ${Boost_LIBRARY_DIRS}) endif() - +OPTION(BUILD_BROKER "Build a helics Broker executable" ON) OPTION(BUILD_PLAYER "Build a helics player standalone executable" ON) OPTION(BUILD_RECORDER "Build a helics recorder standalone executable" ON) -OPTION(BUILD_APPS "Build helics applications" ON) - +OPTION(BUILD_APPS "Build helics application to run various apps" ON) - -# ------------------------------------------------------------- -# Add the main HELICS library -# ------------------------------------------------------------- - -add_library(helics-static STATIC - $ - $ - $ -) - - -target_link_libraries(helics-static PUBLIC helics_base) - -IF(BUILD_CXX_SHARED_LIB) - #if (BUILD_C_SHARED_LIB OR INTERFACE_BUILD) - # message(WARNING "Building the CXX shared library and C shared library in the same build is not advisable due to conflicting symbol visibility guidelines and is unlikely to work very well") - #endif() - - add_library(helics-shared SHARED - src/empty.cpp - $ - $ - $ -) - - target_link_libraries(helics-shared PRIVATE helics_base) - - if (WIN32) - set_target_properties(helics-shared PROPERTIES - WINDOWS_EXPORT_ALL_SYMBOLS TRUE) - - # IF(MINGW) - # set_target_properties(helics-shared PROPERTIES - # LINK_FLAGS "-Wl,--whole-archive") - # ELSE(MINGW) - # set_target_properties(helics-shared PROPERTIES - # LINK_FLAGS "/WHOLEARCHIVE") - # endif() - # - #elseif (APPLE) - # set_target_properties(helics-shared PROPERTIES - # LINK_FLAGS "-Wl,-all_load") - #else () - # set_target_properties(helics-shared PROPERTIES - # LINK_FLAGS "-Wl,--whole-archive") - endif () - -endif() - FILE(GLOB KEY_LIBRARY_FILES ${PROJECT_BINARY_DIR}/libs/bin/*) message(STATUS "key files ${KEY_LIBRARY_FILES}") @@ -433,26 +378,13 @@ endif() add_subdirectory(docs) -set(HELICS_CMAKECONFIG_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}" CACHE STRING "install path for HELICSConfig.cmake") install (TARGETS helics_base EXPORT helics-targets) install (TARGETS helics_base_includes EXPORT helics-targets) -install (TARGETS helics-static EXPORT helics-targets - DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libs) - - #install(FILES $ DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libs OPTIONAL) - set(helics_static_file "${CMAKE_STATIC_LIBRARY_PREFIX}helics-static${CMAKE_STATIC_LIBRARY_SUFFIX}") - set(helics_static_file_debug "${CMAKE_STATIC_LIBRARY_PREFIX}helics-static${CMAKE_DEBUG_POSTFIX}${CMAKE_STATIC_LIBRARY_SUFFIX}") +set(helics_static_file "${CMAKE_STATIC_LIBRARY_PREFIX}helics-static${CMAKE_STATIC_LIBRARY_SUFFIX}") +set(helics_static_file_debug "${CMAKE_STATIC_LIBRARY_PREFIX}helics-static${CMAKE_DEBUG_POSTFIX}${CMAKE_STATIC_LIBRARY_SUFFIX}") IF(BUILD_CXX_SHARED_LIB) - install (TARGETS helics-shared EXPORT helics-targets - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) - - INSTALL(FILES $ DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libs) - INSTALL(FILES $ DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT libs) - set(helics_cxx_shared_file "${CMAKE_SHARED_LIBRARY_PREFIX}helics-shared${CMAKE_SHARED_LIBRARY_SUFFIX}") set(helics_cxx_shared_file_debug "${CMAKE_SHARED_LIBRARY_PREFIX}helics-shared${CMAKE_DEBUG_POSTFIX}${CMAKE_SHARED_LIBRARY_SUFFIX}") ELSE (BUILD_CXX_SHARED_LIB) @@ -468,6 +400,7 @@ ELSE() set(helics_c_shared_file_debug ) ENDIF() +set(HELICS_CMAKECONFIG_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}" CACHE STRING "install path for HELICSConfig.cmake") install (EXPORT helics-targets NAMESPACE Helics:: @@ -522,12 +455,8 @@ write_basic_package_version_file(${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Conf VERSION ${HELICS_VERSION_MAJOR}.${HELICS_VERSION_MINOR}.${HELICS_VERSION_PATCH}-${HELICS_VERSION_BUILD} COMPATIBILITY SameMajorVersion) -configure_file(config/${PROJECT_NAME}Import.cmake.in - "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Import.cmake" @ONLY) - install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake - ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Import.cmake DESTINATION ${HELICS_CMAKECONFIG_INSTALL_DIR} COMPONENT libs) diff --git a/ThirdParty/jsoncpp.cpp b/ThirdParty/jsoncpp.cpp index e1a20b1304..06b26825bd 100644 --- a/ThirdParty/jsoncpp.cpp +++ b/ThirdParty/jsoncpp.cpp @@ -247,7 +247,7 @@ static inline void fixZerosInTheEnd(char* begin, char* end) { #include #include -#if __cplusplus >= 201103L +#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1900) #include #if !defined(snprintf) @@ -261,6 +261,9 @@ static inline void fixZerosInTheEnd(char* begin, char* end) { #include #if defined(_MSC_VER) +#ifdef _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES +#undef _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES +#endif #define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1 #if !defined(snprintf) #define snprintf _snprintf @@ -4196,7 +4199,7 @@ Value& Path::make(Value& root) const { #include #include -#if __cplusplus >= 201103L +#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1900) #include #include diff --git a/config/HELICSConfig.cmake.in b/config/HELICSConfig.cmake.in index bb88fdf781..2e9e15478e 100644 --- a/config/HELICSConfig.cmake.in +++ b/config/HELICSConfig.cmake.in @@ -49,5 +49,10 @@ find_program(HELICS_BROKER helics_broker PATH ${PACKAGE_PREFIX_DIR}/@CMAKE_INSTALL_BINDIR@ NO_DEFAULT_PATH) + +set(THREADS_PREFER_PTHREAD_FLAG ON) +find_package(Threads REQUIRED) +include(${CMAKE_CURRENT_LIST_DIR}/helics-targets.cmake) + check_required_components(${PN}) diff --git a/config/HELICSImport.cmake.in b/config/HELICSImport.cmake.in deleted file mode 100644 index 3ae533619a..0000000000 --- a/config/HELICSImport.cmake.in +++ /dev/null @@ -1,13 +0,0 @@ -#file to import the helics target and all the needed dependencies - -set(THREADS_PREFER_PTHREAD_FLAG ON) -find_package(Threads REQUIRED) -include(${CMAKE_CURRENT_LIST_DIR}/helics-targets.cmake) -set(ZMQ_CMAKE_INCLUDE @ZMQ_CMAKE_INCLUDE@) - -if (EXISTS ${ZMQ_CMAKE_INCLUDE}) - include(${ZMQ_CMAKE_INCLUDE}) -endif() - -include(${CMAKE_CURRENT_LIST_DIR}/HELICSConfig.cmake) - diff --git a/config/cmake/addZeroMQ.cmake b/config/cmake/addZeroMQ.cmake index 456d8c2803..b27db47316 100644 --- a/config/cmake/addZeroMQ.cmake +++ b/config/cmake/addZeroMQ.cmake @@ -47,6 +47,4 @@ if (NOT ZeroMQ_FOUND) ENDIF(AUTOBUILD_ZMQ) endif() endif() -endif() - -message(STATUS "includes $") \ No newline at end of file +endif() \ No newline at end of file diff --git a/examples/FilterFederate1/CMakeLists.txt b/examples/FilterFederate1/CMakeLists.txt index 864ac2e9b8..3cb7f0373f 100644 --- a/examples/FilterFederate1/CMakeLists.txt +++ b/examples/FilterFederate1/CMakeLists.txt @@ -1,9 +1,5 @@ add_executable(filterFed FilterFed.cpp) -include_directories(SYSTEM ${Boost_INCLUDE_DIR}) -include_directories(SYSTEM ${PROJECT_SOURCE_DIR}/ThirdParty) -include_directories(${PROJECT_SOURCE_DIR}/src) - target_link_libraries(filterFed helics-static) set_target_properties (filterFed PROPERTIES diff --git a/examples/comboFederates1/CMakeLists.txt b/examples/comboFederates1/CMakeLists.txt index da13d86d8c..5876d58d3e 100644 --- a/examples/comboFederates1/CMakeLists.txt +++ b/examples/comboFederates1/CMakeLists.txt @@ -1,12 +1,8 @@ -include_directories( SYSTEM ${Boost_INCLUDE_DIR}) -#include_directories(SYSTEM ${PROJECT_SOURCE_DIR}/ThirdParty) -include_directories(${PROJECT_SOURCE_DIR}/src) - add_executable(comboFed comboFed.cpp) -target_link_libraries(comboFed helics-static) +target_link_libraries(comboFed helics_apps-static) set_target_properties (comboFed PROPERTIES diff --git a/examples/comboFederates1/comboFed.cpp b/examples/comboFederates1/comboFed.cpp index 89c4d7b6de..9f9e7ad703 100644 --- a/examples/comboFederates1/comboFed.cpp +++ b/examples/comboFederates1/comboFed.cpp @@ -6,7 +6,7 @@ All rights reserved. See LICENSE file and DISCLAIMER for more details. #include "helics/application_api/CombinationFederate.hpp" #include #include -#include "helics/core/BrokerFactory.hpp" +#include "helics/apps/BrokerApp.hpp" #include "helics/common/argParser.h" static const helics::ArgDescriptors InfoArgs{ @@ -57,10 +57,10 @@ int main (int argc, char *argv[]) } fi.logLevel = 5; - std::shared_ptr brk; + helics::apps::BrokerApp brk; if (vm.count("startbroker") > 0) { - brk = helics::BrokerFactory::create(fi.coreType, vm["startbroker"].as()); + brk = helics::apps::BrokerApp(fi.coreType, vm["startbroker"].as()); } auto cFed = std::make_unique (fi); @@ -99,14 +99,6 @@ int main (int argc, char *argv[]) } cFed->finalize (); - if (brk) - { - while (brk->isConnected()) - { - std::this_thread::yield(); - } - brk = nullptr; - } return 0; } diff --git a/examples/messageFederates1/CMakeLists.txt b/examples/messageFederates1/CMakeLists.txt index 0990110530..26e8e064ab 100644 --- a/examples/messageFederates1/CMakeLists.txt +++ b/examples/messageFederates1/CMakeLists.txt @@ -1,18 +1,10 @@ add_executable(messageFed messageFed.cpp) add_executable(messageFedObj messageFedObj.cpp) -include_directories(SYSTEM ${Boost_INCLUDE_DIR}) -include_directories(SYSTEM ${PROJECT_SOURCE_DIR}/ThirdParty) -include_directories(${PROJECT_SOURCE_DIR}/src) +target_link_libraries(messageFed helics_apps-static) +target_link_libraries(messageFedObj helics_apps-static) -target_link_libraries(messageFed helics-static) -target_link_libraries(messageFedObj helics-static) - -set_target_properties (messageFed PROPERTIES - FOLDER examples -) - -set_target_properties (messageFedObj PROPERTIES +set_target_properties (messageFed messageFedObj PROPERTIES FOLDER examples ) diff --git a/examples/messageFederates1/messageFed.cpp b/examples/messageFederates1/messageFed.cpp index f208e273b6..0799c4c574 100644 --- a/examples/messageFederates1/messageFed.cpp +++ b/examples/messageFederates1/messageFed.cpp @@ -6,11 +6,11 @@ All rights reserved. See LICENSE file and DISCLAIMER for more details. #include "helics/application_api/MessageFederate.hpp" #include #include -#include "helics/core/BrokerFactory.hpp" +#include "helics/apps/BrokerApp.hpp" #include "helics/common/argParser.h" static const helics::ArgDescriptors InfoArgs{ - {"startbroker","start a broker with the specified arguments"}, + {"startbroker", "start a broker with the specified arguments"}, {"target,t", "name of the target federate"}, { "messagetarget", "name of the target federate, same as target" }, {"endpoint,e", "name of the target endpoint"}, @@ -50,10 +50,10 @@ int main (int argc, char *argv[]) } fi.logLevel = 5; - std::shared_ptr brk; + helics::apps::BrokerApp brk; if (vm.count("startbroker") > 0) { - brk = helics::BrokerFactory::create(fi.coreType, vm["startbroker"].as()); + brk = helics::apps::BrokerApp(fi.coreType, vm["startbroker"].as()); } auto mFed = std::make_unique (fi); @@ -82,14 +82,6 @@ int main (int argc, char *argv[]) } mFed->finalize (); - if (brk) - { - while (brk->isConnected()) - { - std::this_thread::yield(); - } - brk = nullptr; - } return 0; } diff --git a/examples/messageFederates1/messageFedObj.cpp b/examples/messageFederates1/messageFedObj.cpp index 6cf43eb236..51cd6222c7 100644 --- a/examples/messageFederates1/messageFedObj.cpp +++ b/examples/messageFederates1/messageFedObj.cpp @@ -4,90 +4,82 @@ Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance All rights reserved. See LICENSE file and DISCLAIMER for more details. */ #include "helics/application_api/Endpoints.hpp" +#include "helics/apps/BrokerApp.hpp" +#include "helics/common/argParser.h" #include #include -#include "helics/core/BrokerFactory.hpp" -#include "helics/common/argParser.h" static const helics::ArgDescriptors InfoArgs{ - {"startbroker","start a broker with the specified arguments"}, - {"target,t", "name of the target federate"}, - {"endpoint,e", "name of the target endpoint"}, - {"source,s", "name of the source endpoint"} - //name is captured in the argument processor for federateInfo + {"startbroker", "start a broker with the specified arguments"}, + {"target,t", "name of the target federate"}, + {"endpoint,e", "name of the target endpoint"}, + {"source,s", "name of the source endpoint"} + // name is captured in the argument processor for federateInfo }; int main (int argc, char *argv[]) { - helics::FederateInfo fi("fed"); + helics::FederateInfo fi ("fed"); helics::variable_map vm; - auto parseResult = argumentParser(argc, argv, vm, InfoArgs); - fi.loadInfoFromArgs(argc, argv); + auto parseResult = argumentParser (argc, argv, vm, InfoArgs); + fi.loadInfoFromArgs (argc, argv); if (parseResult != 0) { return 0; } - std::string targetfederate = "fed"; - if (vm.count("target") > 0) - { - targetfederate = vm["target"].as(); - } + std::string targetfederate = "fed"; + if (vm.count ("target") > 0) + { + targetfederate = vm["target"].as (); + } std::string targetEndpoint = "endpoint"; - if (vm.count("endpoint") > 0) { - targetEndpoint = vm["endpoint"].as(); + if (vm.count ("endpoint") > 0) + { + targetEndpoint = vm["endpoint"].as (); } std::string target = targetfederate + "/" + targetEndpoint; std::string myendpoint = "endpoint"; - if (vm.count("source") > 0) + if (vm.count ("source") > 0) { - myendpoint = vm["source"].as(); + myendpoint = vm["source"].as (); } fi.logLevel = 5; - std::shared_ptr brk; - if (vm.count("startbroker") > 0) + helics::apps::BrokerApp brk; + if (vm.count ("startbroker") > 0) { - brk = helics::BrokerFactory::create(fi.coreType, vm["startbroker"].as()); + brk = helics::apps::BrokerApp (fi.coreType, vm["startbroker"].as ()); } auto mFed = std::make_unique (fi); - auto name = mFed->getName(); - std::cout << " registering endpoint '" << myendpoint << "' for " << name<<'\n'; + auto name = mFed->getName (); + std::cout << " registering endpoint '" << myendpoint << "' for " << name << '\n'; // create the endpoint using the Endpoint object interface - helics::Endpoint endpoint(mFed.get(), myendpoint); - + helics::Endpoint endpoint (mFed.get (), myendpoint); std::cout << "entering init State\n"; mFed->enterInitializationState (); std::cout << "entered init State\n"; mFed->enterExecutionState (); std::cout << "entered exec State\n"; - // set a defined target for the endpoint so it doesn't have to specfied on every call - endpoint.setTargetDestination(target); - for (int i=1; i<10; ++i) { - std::string message = "message sent from "+name+" to "+target+" at time " + std::to_string(i); - endpoint.send(message.data(), message.size()); + // set a defined target for the endpoint so it doesn't have to specified on every call + endpoint.setTargetDestination (target); + for (int i = 1; i < 10; ++i) + { + std::string message = "message sent from " + name + " to " + target + " at time " + std::to_string (i); + endpoint.send (message.data (), message.size ()); std::cout << message << std::endl; auto newTime = mFed->requestTime (i); - std::cout << "processed time " << static_cast (newTime) << "\n"; - while (endpoint.hasMessage()) - { - auto nmessage = endpoint.getMessage(); - std::cout << "received message from " << nmessage->source << " at " << static_cast(nmessage->time) << " ::" << nmessage->data.to_string() << '\n'; - } - - } - mFed->finalize (); - if (brk) - { - while (brk->isConnected()) + std::cout << "processed time " << static_cast (newTime) << "\n"; + while (endpoint.hasMessage ()) { - std::this_thread::yield(); + auto nmessage = endpoint.getMessage (); + std::cout << "received message from " << nmessage->source << " at " + << static_cast (nmessage->time) << " ::" << nmessage->data.to_string () << '\n'; } - brk = nullptr; } + mFed->finalize (); return 0; } - diff --git a/examples/valueFederates1/CMakeLists.txt b/examples/valueFederates1/CMakeLists.txt index 4d480e0d69..e5b7d3218d 100644 --- a/examples/valueFederates1/CMakeLists.txt +++ b/examples/valueFederates1/CMakeLists.txt @@ -1,10 +1,6 @@ add_executable(valueFed valueFed.cpp) -include_directories(SYSTEM ${Boost_INCLUDE_DIR}) -include_directories(SYSTEM ${PROJECT_SOURCE_DIR}/ThirdParty) -include_directories(${PROJECT_SOURCE_DIR}/src) - -target_link_libraries(valueFed helics-static) +target_link_libraries(valueFed helics_apps-static) set_target_properties (valueFed PROPERTIES FOLDER examples diff --git a/examples/valueFederates1/valueFed.cpp b/examples/valueFederates1/valueFed.cpp index 3702028f77..d393b4f8ac 100644 --- a/examples/valueFederates1/valueFed.cpp +++ b/examples/valueFederates1/valueFed.cpp @@ -6,7 +6,7 @@ All rights reserved. See LICENSE file and DISCLAIMER for more details. #include "helics/application_api/ValueFederate.hpp" #include #include -#include "helics/core/BrokerFactory.hpp" +#include "helics/apps/BrokerApp.hpp" #include "helics/common/argParser.h" static const helics::ArgDescriptors InfoArgs{ @@ -27,10 +27,10 @@ int main (int argc, const char * const *argv) } fi.logLevel = 5; - std::shared_ptr brk; + helics::apps::BrokerApp brk; if (vm.count("startbroker") > 0) { - brk = helics::BrokerFactory::create(fi.coreType, vm["startbroker"].as()); + brk = helics::apps::BrokerApp(fi.coreType, vm["startbroker"].as()); } std::string target = "fed"; @@ -64,14 +64,6 @@ int main (int argc, const char * const *argv) std::cout << "processed time " << static_cast (newTime) << "\n"; } vFed->finalize (); - if (brk) - { - while (brk->isConnected()) - { - std::this_thread::yield(); - } - brk = nullptr; - } return 0; } diff --git a/src/helics/CMakeLists.txt b/src/helics/CMakeLists.txt index 2269df9c14..b39e7dbd7c 100644 --- a/src/helics/CMakeLists.txt +++ b/src/helics/CMakeLists.txt @@ -8,15 +8,75 @@ add_subdirectory(common) add_subdirectory(core) add_subdirectory(application_api) +# ------------------------------------------------------------- +# Add the main HELICS library +# ------------------------------------------------------------- + +add_library(helics-static STATIC + $ + $ + $ +) + +target_link_libraries(helics-static PUBLIC helics_base) + +IF(BUILD_CXX_SHARED_LIB) + #if (BUILD_C_SHARED_LIB OR INTERFACE_BUILD) + # message(WARNING "Building the CXX shared library and C shared library in the same build is not advisable due to conflicting symbol visibility guidelines and is unlikely to work very well") + #endif() + + add_library(helics-shared SHARED + src/empty.cpp + $ + $ + $ +) + + target_link_libraries(helics-shared PRIVATE helics_base) + + if (WIN32) + set_target_properties(helics-shared PROPERTIES + WINDOWS_EXPORT_ALL_SYMBOLS TRUE) + + # IF(MINGW) + # set_target_properties(helics-shared PROPERTIES + # LINK_FLAGS "-Wl,--whole-archive") + # ELSE(MINGW) + # set_target_properties(helics-shared PROPERTIES + # LINK_FLAGS "/WHOLEARCHIVE") + # endif() + # + #elseif (APPLE) + # set_target_properties(helics-shared PROPERTIES + # LINK_FLAGS "-Wl,-all_load") + #else () + # set_target_properties(helics-shared PROPERTIES + # LINK_FLAGS "-Wl,--whole-archive") + endif () + +endif() + install(FILES flag-definitions.h helics.hpp DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/helics COMPONENT headers) -IF(BUILD_PLAYER OR BUILD_RECORDER OR BUILD_APPS) +install (TARGETS helics-static EXPORT helics-targets + DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libs) + +IF(BUILD_CXX_SHARED_LIB) + install (TARGETS helics-shared EXPORT helics-targets + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) + + INSTALL(FILES $ DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libs) + INSTALL(FILES $ DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT libs) + +ENDIF(BUILD_CXX_SHARED_LIB) + add_subdirectory(apps) -ENDIF() if (BUILD_C_SHARED_LIB OR INTERFACE_BUILD) -add_subdirectory(shared_api_library) -add_subdirectory(cpp98) -install(FILES chelics.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/helics COMPONENT headers) + add_subdirectory(shared_api_library) + add_subdirectory(cpp98) + install(FILES chelics.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/helics COMPONENT headers) endif() diff --git a/src/helics/application_api/Federate.hpp b/src/helics/application_api/Federate.hpp index d76be7c7b1..7e1930e282 100644 --- a/src/helics/application_api/Federate.hpp +++ b/src/helics/application_api/Federate.hpp @@ -54,7 +54,7 @@ class FederateInfo : public CoreFederateInfo /** default constructor*/ FederateInfo () = default; /** construct from the federate name*/ - FederateInfo (std::string fedname) : name (fedname){}; + explicit FederateInfo (std::string fedname) : name (std::move(fedname)){}; /** construct from the name and type*/ FederateInfo (std::string fedname, core_type cType) : name (std::move (fedname)), coreType (cType){}; /** load a federateInfo object from command line arguments diff --git a/src/helics/apps/BrokerApp.cpp b/src/helics/apps/BrokerApp.cpp new file mode 100644 index 0000000000..99697e40ee --- /dev/null +++ b/src/helics/apps/BrokerApp.cpp @@ -0,0 +1,123 @@ +/* +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 "BrokerApp.hpp" +#include "../common/argParser.h" +#include "../common/stringToCmdLine.h" +#include "../core/BrokerFactory.hpp" +#include "../core/CoreBroker.hpp" +#include "../core/core-exceptions.hpp" +#include "../core/helicsVersion.hpp" +#include "helics/helics-config.h" +#include +#include + +static const helics::ArgDescriptors InfoArgs{ + {"name,n", "name of the broker"}, + {"type,t", "type of the broker (\"(zmq)\", \"ipc\", \"test\", \"mpi\", \"test\", \"tcp\", \"udp\")"}}; + +namespace helics +{ +namespace apps +{ +BrokerApp::BrokerApp (int argc, char *argv[]) { loadFromArguments (argc, argv); } + +BrokerApp::BrokerApp (core_type ctype, int argc, char *argv[]) : type (ctype) { loadFromArguments (argc, argv); } + +BrokerApp::BrokerApp (const std::string &argString) +{ + StringToCmdLine cmdargs (argString); + loadFromArguments (cmdargs.getArgCount (), cmdargs.getArgV ()); +} + +BrokerApp::BrokerApp (core_type ctype, const std::string &argString) : type (ctype) +{ + StringToCmdLine cmdargs (argString); + loadFromArguments (cmdargs.getArgCount (), cmdargs.getArgV ()); +} + +BrokerApp::~BrokerApp () +{ + if (!broker) + { + return; + } + bool sleep_toggle = false; + while (broker->isConnected ()) + { + if (!sleep_toggle) + { + std::this_thread::yield (); + } + else + { + std::this_thread::sleep_for (std::chrono::milliseconds (200)); + } + sleep_toggle = !sleep_toggle; + } + broker = nullptr; + helics::BrokerFactory::cleanUpBrokers (500); +} + +void BrokerApp::loadFromArguments (int argc, char *argv[]) +{ + helics::variable_map vm; + auto exit_early = helics::argumentParser (argc, argv, vm, InfoArgs); + + if (exit_early != 0) + { + if (exit_early == helics::helpReturn) + { + helics::BrokerFactory::displayHelp (); + } + else if (exit_early == helics::versionReturn) + { + std::cout << helics::versionString << '\n'; + } + return; + } + + std::string name = (vm.count ("name") > 0) ? vm["name"].as () : ""; + if (vm.count ("type") > 0) + { + try + { + type = coreTypeFromString (vm["type"].as ()); + } + catch (std::invalid_argument &ie) + { + std::cerr << "Unable to generate broker from specified type: " << ie.what () << '\n'; + throw; + } + } + + broker = BrokerFactory::create (type, name, argc, argv); + if (!broker->isConnected ()) + { + throw (ConnectionFailure ("Broker is unable to connect\n")); + } +} + +/** run the Echo federate until the specified time +@param stopTime_input the desired stop time +*/ +/** check if the Broker is running*/ +bool BrokerApp::isActive () const { return ((broker) && (broker->isConnected ())); } + +/** forceably disconnect the broker*/ +void BrokerApp::forceTerminate () +{ + if (!broker) + { + return; + } + if (broker->isConnected ()) + { + broker->disconnect (); + } +} + +} // namespace apps +} // namespace helics diff --git a/src/helics/apps/BrokerApp.hpp b/src/helics/apps/BrokerApp.hpp new file mode 100644 index 0000000000..fbbd258fa4 --- /dev/null +++ b/src/helics/apps/BrokerApp.hpp @@ -0,0 +1,71 @@ +/* +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. +*/ +#pragma once + +#include "../core/core-types.hpp" + +#include +#include + +namespace helics +{ +class Broker; + +namespace apps +{ +/** class implementing a Broker object. This object is meant to a be a very simple broker executor with a similar interface to the other apps +*/ +class BrokerApp +{ +public: + /** default constructor*/ + BrokerApp() = default; + /** construct from command line arguments + @param argc the number of arguments + @param argv the strings in the input + */ + BrokerApp(int argc, char *argv[]); + /** construct from command line arguments + @param argc the number of arguments + @param argv the strings in the input + */ + BrokerApp(core_type ctype, int argc, char *argv[]); + /** construct from command line arguments parsed as a single string + @param argString a merged string with all the arguments + */ + explicit BrokerApp(const std::string &argString); + /** construct from command line arguments parsed as a single string + @param ctype the type of broker to create + @param argString a merged string with all the arguments + */ + BrokerApp(core_type ctype, const std::string &argString); + /** move construction*/ + BrokerApp(BrokerApp &&other_echo) = default; + /** move assignment*/ + BrokerApp &operator= (BrokerApp &&brokerApp) = default; + /** the destructor will wait until the broker is finished before returning- unless forceTerminate() is used*/ + ~BrokerApp(); + + /** run the Echo federate until the specified time + @param stopTime_input the desired stop time + */ + /** check if the Broker is running*/ + bool isActive() const; + + /** forceably disconnect the broker*/ + void forceTerminate(); + + /** overload the -> operator so broker functions can be called if needed + */ + auto *operator->() const { return broker.operator->(); } + +private: + void loadFromArguments(int argc, char *argv[]); + core_type type = core_type::ZMQ; + std::shared_ptr broker; //!< the actual endpoint objects +}; +} +} diff --git a/src/helics/apps/CMakeLists.txt b/src/helics/apps/CMakeLists.txt index 34c7ff9b1b..8c4bb63a26 100644 --- a/src/helics/apps/CMakeLists.txt +++ b/src/helics/apps/CMakeLists.txt @@ -10,6 +10,7 @@ set(helics_apps_public_headers Source.hpp Tracer.hpp helicsApp.hpp + BrokerApp.hpp ) set(helics_apps_private_headers @@ -26,20 +27,18 @@ set(helics_apps_library_files Source.cpp Tracer.cpp helicsApp.cpp + BrokerApp.cpp ) add_library(helics_apps-static STATIC ${helics_apps_library_files} ${helics_apps_public_headers} ${helics_apps_private_headers}) target_link_libraries(helics_apps-static PUBLIC helics-static) -target_include_directories(helics_apps-static SYSTEM PRIVATE ${Boost_INCLUDE_DIR}) - -target_include_directories(helics_apps-static SYSTEM PRIVATE ${PROJECT_SOURCE_DIR}/ThirdParty) if (BUILD_PLAYER) add_executable(helics_player playerMain.cpp) target_link_libraries(helics_player helics_apps-static ) set_target_properties (helics_player PROPERTIES FOLDER apps) - target_include_directories(helics_player SYSTEM PRIVATE ${Boost_INCLUDE_DIR}) + INSTALL(TARGETS helics_player DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT applications) endif() @@ -47,58 +46,37 @@ if (BUILD_RECORDER) add_executable(helics_recorder recorderMain.cpp) target_link_libraries(helics_recorder helics_apps-static) set_target_properties (helics_recorder PROPERTIES FOLDER apps) - target_include_directories(helics_recorder SYSTEM PRIVATE ${Boost_INCLUDE_DIR}) + INSTALL(TARGETS helics_recorder DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT applications) endif() -if(BUILD_PLAYER OR BUILD_RECORDER OR BUILD_APPS) +if (BUILD_BROKER) +add_executable(helics_broker helics-broker.cpp) + target_link_libraries(helics_broker helics_apps-static) + set_target_properties (helics_broker PROPERTIES FOLDER apps) + set(HELICS_BROKER_LOC ${CMAKE_CURRENT_BINARY_DIR} CACHE INTERNAL "build folder location of the broker") + INSTALL(TARGETS helics_broker DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT applications) + +endif() + +if(BUILD_PLAYER OR BUILD_RECORDER OR BUILD_APPS OR BUILD_BROKER) add_executable(helics_app appMain.cpp) target_link_libraries(helics_app helics_apps-static) set_target_properties (helics_app PROPERTIES FOLDER apps) - target_include_directories(helics_app SYSTEM PRIVATE ${Boost_INCLUDE_DIR}) + INSTALL(TARGETS helics_app DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT applications) + if (WIN32) + foreach(keyfile IN LISTS KEY_LIBRARY_FILES) +add_custom_command(TARGET helics_app POST_BUILD # Adds a post-build event to core tests + COMMAND ${CMAKE_COMMAND} -E copy_if_different # which executes "cmake - E copy_if_different..." + "${keyfile}" # <--this is in-file + "$/") # <--this is out-file path +endforeach(keyfile) +endif() endif() INSTALL(TARGETS helics_apps-static EXPORT helics-targets DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libs) -#install(FILES $ DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL COMPONENT libs) - INSTALL(FILES ${helics_apps_public_headers} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/helics/apps COMPONENT headers) -if (BUILD_PLAYER) -INSTALL(TARGETS helics_player DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT applications) - -foreach(keyfile IN LISTS KEY_LIBRARY_FILES) -add_custom_command(TARGET helics_player POST_BUILD # Adds a post-build event to core tests - COMMAND ${CMAKE_COMMAND} -E copy_if_different # which executes "cmake - E copy_if_different..." - "${keyfile}" # <--this is in-file - "$/") # <--this is out-file path -endforeach(keyfile) - -endif() - -if (BUILD_RECORDER) -INSTALL(TARGETS helics_recorder DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT applications) -if (NOT BUILD_PLAYER) -foreach(keyfile IN LISTS KEY_LIBRARY_FILES) -add_custom_command(TARGET helics_recorder POST_BUILD # Adds a post-build event to core tests - COMMAND ${CMAKE_COMMAND} -E copy_if_different # which executes "cmake - E copy_if_different..." - "${keyfile}" # <--this is in-file - "$/") # <--this is out-file path -endforeach(keyfile) -endif() -endif() - -if(BUILD_PLAYER OR BUILD_RECORDER OR BUILD_APPS) -INSTALL(TARGETS helics_app DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT applications) -if (NOT BUILD_PLAYER AND NOT BUILD_RECORDER) -foreach(keyfile IN LISTS KEY_LIBRARY_FILES) -add_custom_command(TARGET helics_app POST_BUILD # Adds a post-build event to core tests - COMMAND ${CMAKE_COMMAND} -E copy_if_different # which executes "cmake - E copy_if_different..." - "${keyfile}" # <--this is in-file - "$/") # <--this is out-file path -endforeach(keyfile) -endif() -endif() - diff --git a/src/helics/apps/Echo.cpp b/src/helics/apps/Echo.cpp index 7f260faf8b..f8deac8c00 100644 --- a/src/helics/apps/Echo.cpp +++ b/src/helics/apps/Echo.cpp @@ -39,7 +39,7 @@ Echo::Echo (const FederateInfo &fi) : App (fi) {} Echo::Echo (const std::shared_ptr &core, const FederateInfo &fi) : App (core, fi) {} -Echo::Echo (const std::string &jsonString) : App (jsonString) { loadJsonFile (jsonString); } +Echo::Echo (const std::string &name, const std::string &jsonString) : App (name, jsonString) { loadJsonFile (jsonString); } void Echo::runTo (Time stopTime_input) { diff --git a/src/helics/apps/Echo.hpp b/src/helics/apps/Echo.hpp index dccc528a60..bacf15059b 100644 --- a/src/helics/apps/Echo.hpp +++ b/src/helics/apps/Echo.hpp @@ -14,10 +14,11 @@ namespace helics { namespace apps { -/** class implementing a Echo object, which will generate endpoint interfaces and send a data message back to the +/** class implementing an Echo object, which will generate endpoint interfaces and send a data message back to the source at the with a specified delay @details the Echo class is NOT threadsafe in general, don't try to use it from multiple threads without external protection, -that will result in undefined behavior. the exception is the setEchoDelay function is threadsafe +that will result in undefined behavior. One exception is the setEchoDelay function is threadsafe, and const methods will not cause problems but may not give consistent answers +if used from multiple threads unless protected. */ class Echo:public App { @@ -41,7 +42,7 @@ class Echo:public App /**constructor taking a file with the required information @param[in] jsonString file or json string defining the federate information and other configuration */ - explicit Echo (const std::string &jsonString); + Echo (const std::string &name, const std::string &jsonString); /** move construction*/ Echo (Echo &&other_echo) = default; @@ -62,6 +63,7 @@ class Echo:public App /** get the number of points loaded*/ auto echoCount () const { return echoCounter; } /** set the delay time + Function is threadsafe */ void setEchoDelay (Time delay); diff --git a/src/helics/apps/Player.cpp b/src/helics/apps/Player.cpp index cc84ee5ead..60040982ca 100644 --- a/src/helics/apps/Player.cpp +++ b/src/helics/apps/Player.cpp @@ -74,7 +74,7 @@ Player::Player (const std::shared_ptr &core, const FederateInfo &fi):App(c fed->setFlag (SOURCE_ONLY_FLAG); } -Player::Player (const std::string &jsonString) : App (jsonString) +Player::Player (const std::string &name, const std::string &jsonString) : App (name, jsonString) { fed->setFlag (SOURCE_ONLY_FLAG); Player::loadJsonFile(jsonString); diff --git a/src/helics/apps/Player.hpp b/src/helics/apps/Player.hpp index b6e8313e3b..a59d6eed71 100644 --- a/src/helics/apps/Player.hpp +++ b/src/helics/apps/Player.hpp @@ -62,9 +62,10 @@ class Player:public App */ Player (const std::shared_ptr &core, const FederateInfo &fi); /**constructor taking a file with the required information + @param[in] name the name of the app @param[in] jsonString file or JSON string defining the federate information and other configuration */ - explicit Player (const std::string &jsonString); + Player (const std::string &name, const std::string &jsonString); /** move construction*/ Player (Player &&other_player) = default; diff --git a/src/helics/apps/Recorder.cpp b/src/helics/apps/Recorder.cpp index b3796f23b1..de66cfca85 100644 --- a/src/helics/apps/Recorder.cpp +++ b/src/helics/apps/Recorder.cpp @@ -68,7 +68,7 @@ Recorder::Recorder (const std::shared_ptr &core, const FederateInfo &fi):A fed->setFlag (OBSERVER_FLAG); } -Recorder::Recorder (const std::string &jsonString) : App(jsonString) +Recorder::Recorder (const std::string &name, const std::string &jsonString) : App(name, jsonString) { fed->setFlag (OBSERVER_FLAG); Recorder::loadJsonFile(jsonString); diff --git a/src/helics/apps/Recorder.hpp b/src/helics/apps/Recorder.hpp index 21345c16c2..0867658001 100644 --- a/src/helics/apps/Recorder.hpp +++ b/src/helics/apps/Recorder.hpp @@ -59,9 +59,10 @@ namespace apps */ Recorder(const std::shared_ptr &core, const FederateInfo &fi); /**constructor taking a file with the required information + @param[in] name the name of the app @param[in] file a file defining the federate information */ - explicit Recorder(const std::string &jsonString); + Recorder(const std::string &name, const std::string &jsonString); /** move construction*/ Recorder(Recorder &&other_recorder) = default; /** move assignment*/ diff --git a/src/helics/apps/Source.cpp b/src/helics/apps/Source.cpp index f97c908cee..506a1eeebe 100644 --- a/src/helics/apps/Source.cpp +++ b/src/helics/apps/Source.cpp @@ -68,7 +68,7 @@ Source::Source(const std::shared_ptr &core, const FederateInfo &fi):App(co fed->setFlag(SOURCE_ONLY_FLAG); } -Source::Source(const std::string &jsonString) : App(jsonString) +Source::Source(const std::string &name, const std::string &jsonString) : App(name, jsonString) { fed->setFlag(SOURCE_ONLY_FLAG); diff --git a/src/helics/apps/Source.hpp b/src/helics/apps/Source.hpp index 6de0e582aa..8128ff22ca 100644 --- a/src/helics/apps/Source.hpp +++ b/src/helics/apps/Source.hpp @@ -74,9 +74,10 @@ class Source:public App */ Source (const std::shared_ptr &core, const FederateInfo &fi); /**constructor taking a file with the required information + @param[in] name the name of the app @param[in] jsonString file or JSON string defining the federate information and other configuration */ - explicit Source (const std::string &jsonString); + Source (const std::string &name, const std::string &jsonString); /** move construction*/ Source (Source &&other_source) = default; diff --git a/src/helics/apps/Tracer.cpp b/src/helics/apps/Tracer.cpp index 3debf9d164..72bde9f5f7 100644 --- a/src/helics/apps/Tracer.cpp +++ b/src/helics/apps/Tracer.cpp @@ -68,7 +68,7 @@ Tracer::Tracer(const std::shared_ptr &core, const FederateInfo &fi):App(co fed->setFlag(OBSERVER_FLAG); } -Tracer::Tracer(const std::string &jsonString) : App(jsonString) +Tracer::Tracer(const std::string &name, const std::string &jsonString) : App(name,jsonString) { fed->setFlag(OBSERVER_FLAG); loadJsonFile(jsonString); diff --git a/src/helics/apps/Tracer.hpp b/src/helics/apps/Tracer.hpp index 489a635ba2..ed75b6655f 100644 --- a/src/helics/apps/Tracer.hpp +++ b/src/helics/apps/Tracer.hpp @@ -41,9 +41,10 @@ class Tracer: public App */ Tracer (const std::shared_ptr &core, const FederateInfo &fi); /**constructor taking a file with the required information + @param[in] name the name of the app @param[in] file a file defining the federate information */ - explicit Tracer (const std::string &jsonString); + Tracer (const std::string &name, const std::string &jsonString); /** move construction*/ Tracer (Tracer &&other_tracer) = default; /** move assignment*/ diff --git a/src/helics/apps/appMain.cpp b/src/helics/apps/appMain.cpp index 8dab18515f..7ac5cc6be1 100644 --- a/src/helics/apps/appMain.cpp +++ b/src/helics/apps/appMain.cpp @@ -9,6 +9,7 @@ All rights reserved. See LICENSE file and DISCLAIMER for more details. #include "Echo.hpp" #include "Tracer.hpp" #include "Source.hpp" +#include "BrokerApp.hpp" #include "../core/BrokerFactory.hpp" #include "../core/core-exceptions.hpp" #include "../core/helicsVersion.hpp" @@ -31,6 +32,7 @@ int main (int argc, char *argv[]) return 0; } std::string arg1(argv[1]); + int ret = 0; //now redo the arguments remove the second argument which is the app name argc -= 1; for (int ii = 2; ii <= argc; ++ii) @@ -41,19 +43,19 @@ int main (int argc, char *argv[]) { if (boost::iequals(arg1,"player")) { - helics::apps::Player Player(argc, argv); - if (Player.isActive()) + helics::apps::Player player(argc, argv); + if (player.isActive()) { - Player.run(); + player.run(); } } else if (boost::iequals(arg1, "recorder")) { - helics::apps::Recorder Recorder(argc, argv); - if (Recorder.isActive()) + helics::apps::Recorder recorder(argc, argv); + if (recorder.isActive()) { - Recorder.run(); + recorder.run(); } } @@ -67,23 +69,24 @@ int main (int argc, char *argv[]) } else if (boost::iequals(arg1, "echo")) { - helics::apps::Echo Echo(argc, argv); - if (Echo.isActive()) + helics::apps::Echo echo(argc, argv); + if (echo.isActive()) { - Echo.run(); + echo.run(); } } else if (boost::iequals(arg1, "source")) { - helics::apps::Source Source(argc, argv); - if (Source.isActive()) + helics::apps::Source source(argc, argv); + if (source.isActive()) { - Source.run(); + source.run(); } } else if (boost::iequals(arg1, "broker")) { - + helics::apps::BrokerApp broker(argc, argv); + //broker just waits on the destructor if it was active so this is all we do } else if (boost::iequals(arg1, "tracer")) { @@ -103,19 +106,16 @@ int main (int argc, char *argv[]) catch (const std::invalid_argument &ia) { std::cerr << ia.what() << std::endl; - helics::cleanupHelicsLibrary(); - return (-2); + ret = -2; } catch (const helics::HelicsException &he) { std::cerr << he.what() << std::endl; - helics::cleanupHelicsLibrary(); - return (-4); + ret = -4; } - helics::cleanupHelicsLibrary(); - return 0; + return ret; } diff --git a/src/helics/apps/helics-broker.cpp b/src/helics/apps/helics-broker.cpp new file mode 100644 index 0000000000..f8f913f007 --- /dev/null +++ b/src/helics/apps/helics-broker.cpp @@ -0,0 +1,31 @@ +/* +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 "BrokerApp.hpp" +#include "../core/core-exceptions.hpp" +#include "../application_api/Federate.hpp" +#include + +int main (int argc, char *argv[]) +{ + int ret = 0; + try + { + helics::apps::BrokerApp broker(argc, argv); + } + catch (const std::invalid_argument &ia) + { + std::cerr << ia.what() << std::endl; + ret = -2; + } + catch (const helics::HelicsException &he) + { + std::cerr << he.what() << std::endl; + ret = -4; + } + + helics::cleanupHelicsLibrary(); + return ret; +} diff --git a/src/helics/apps/helicsApp.hpp b/src/helics/apps/helicsApp.hpp index 478833d95d..c979ac090f 100644 --- a/src/helics/apps/helicsApp.hpp +++ b/src/helics/apps/helicsApp.hpp @@ -46,7 +46,7 @@ class App /**constructor taking a file with the required information @param[in] jsonString file or JSON string defining the federate information and other configuration */ - explicit App (const std::string &appName, const std::string &jsonString); + App (const std::string &appName, const std::string &jsonString); /** move construction*/ App (App &&other_app) = default; diff --git a/src/helics/apps/playerMain.cpp b/src/helics/apps/playerMain.cpp index c092b9b972..9d047a2415 100644 --- a/src/helics/apps/playerMain.cpp +++ b/src/helics/apps/playerMain.cpp @@ -10,6 +10,7 @@ All rights reserved. See LICENSE file and DISCLAIMER for more details. int main (int argc, char *argv[]) { + int ret = 0; try { helics::apps::Player Player(argc, argv); @@ -22,18 +23,16 @@ int main (int argc, char *argv[]) catch (const std::invalid_argument &ia) { std::cerr << ia.what() << std::endl; - helics::cleanupHelicsLibrary(); - return (-2); + ret = -2; } catch (const helics::HelicsException &he) { std::cerr << he.what() << std::endl; - helics::cleanupHelicsLibrary(); - return (-4); + ret = -4; } helics::cleanupHelicsLibrary(); - return 0; + return ret; } diff --git a/src/helics/apps/recorderMain.cpp b/src/helics/apps/recorderMain.cpp index 3526db91b3..a919391311 100644 --- a/src/helics/apps/recorderMain.cpp +++ b/src/helics/apps/recorderMain.cpp @@ -11,6 +11,7 @@ All rights reserved. See LICENSE file and DISCLAIMER for more details. int main(int argc, char *argv[]) { + int ret = 0; try { helics::apps::Recorder Recorder(argc, argv); @@ -20,21 +21,19 @@ int main(int argc, char *argv[]) } } - catch (const std::invalid_argument &ia) + catch (const std::invalid_argument &ia) { std::cerr << ia.what() << std::endl; - helics::cleanupHelicsLibrary(); - return (-2); + ret = -2; } catch (const helics::HelicsException &he) { std::cerr << he.what() << std::endl; - helics::cleanupHelicsLibrary(); - return (-4); + ret = -4; } helics::cleanupHelicsLibrary(); - return 0; + return ret; } diff --git a/src/helics/common/MapTraits.hpp b/src/helics/common/MapTraits.hpp index 5344e577a6..ff86ab954a 100644 --- a/src/helics/common/MapTraits.hpp +++ b/src/helics/common/MapTraits.hpp @@ -15,19 +15,19 @@ so arithmetic types, pointers, and strings others may be added if needed template struct is_easily_hashable { - static const bool value = std::is_scalar::value; + static constexpr bool value = std::is_scalar::value; }; /** type overload for std::string*/ template <> struct is_easily_hashable { - static const bool value = true; + static constexpr bool value = true; }; /** type overload for std::wstring*/ template <> struct is_easily_hashable { - static const bool value = true; + static constexpr bool value = true; }; diff --git a/src/helics/common/cppzmq/zmq.hpp b/src/helics/common/cppzmq/zmq.hpp index 5e0e832f90..9a14e67a0a 100644 --- a/src/helics/common/cppzmq/zmq.hpp +++ b/src/helics/common/cppzmq/zmq.hpp @@ -26,6 +26,14 @@ #ifndef __ZMQ_HPP_INCLUDED__ #define __ZMQ_HPP_INCLUDED__ +#if (__cplusplus >= 201402L) +#define ZMQ_DEPRECATED(msg) [[deprecated(msg)]] +#elif defined(_MSC_VER) +#define ZMQ_DEPRECATED(msg) __declspec(deprecated(msg)) +#elif defined(__GNUC__) +#define ZMQ_DEPRECATED(msg) __attribute__((deprecated(msg))) +#endif + #if (__cplusplus >= 201103L) #define ZMQ_CPP11 #define ZMQ_NOTHROW noexcept @@ -42,24 +50,37 @@ #include -#include #include #include -#include + +#include #include -#include +#include #include +#include +#include +#include + +/* Version macros for compile-time API version detection */ +#define CPPZMQ_VERSION_MAJOR 4 +#define CPPZMQ_VERSION_MINOR 3 +#define CPPZMQ_VERSION_PATCH 0 + +#define CPPZMQ_VERSION \ + ZMQ_MAKE_VERSION(CPPZMQ_VERSION_MAJOR, CPPZMQ_VERSION_MINOR, \ + CPPZMQ_VERSION_PATCH) #ifdef ZMQ_CPP11 #include #include #include +#include +#include #endif // Detect whether the compiler supports C++11 rvalue references. -#if (defined(__GNUC__) && (__GNUC__ > 4 || \ - (__GNUC__ == 4 && __GNUC_MINOR__ > 2)) && \ - defined(__GXX_EXPERIMENTAL_CXX0X__)) +#if (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 2)) \ + && defined(__GXX_EXPERIMENTAL_CXX0X__)) #define ZMQ_HAS_RVALUE_REFS #define ZMQ_DELETED_FUNCTION = delete #elif defined(__clang__) @@ -73,8 +94,8 @@ #define ZMQ_DELETED_FUNCTION #endif #elif defined(_MSC_VER) && (_MSC_VER >= 1900) - #define ZMQ_HAS_RVALUE_REFS - #define ZMQ_DELETED_FUNCTION = delete + #define ZMQ_HAS_RVALUE_REFS + #define ZMQ_DELETED_FUNCTION = delete #elif defined(_MSC_VER) && (_MSC_VER >= 1600) #define ZMQ_HAS_RVALUE_REFS #define ZMQ_DELETED_FUNCTION @@ -89,7 +110,8 @@ #if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 1, 0) #define ZMQ_HAS_PROXY_STEERABLE /* Socket event data */ -typedef struct { +typedef struct +{ uint16_t event; // id of the event as bitfield int32_t value ; // value is either error code, fd or reconnect interval } zmq_event_t; @@ -111,59 +133,45 @@ typedef struct { namespace zmq { - typedef zmq_free_fn free_fn; typedef zmq_pollitem_t pollitem_t; class error_t : public std::exception { public: - error_t () : errnum (zmq_errno ()) {} #ifdef ZMQ_CPP11 - virtual const char *what () const noexcept override - { - return zmq_strerror (errnum); - } + virtual const char *what() const noexcept { return zmq_strerror(errnum); } #else - virtual const char *what() const throw () - { - return zmq_strerror(errnum); - } + virtual const char *what() const throw() { return zmq_strerror(errnum); } #endif - int num () const - { - return errnum; - } + int num() const { return errnum; } private: - int errnum; }; inline int poll (zmq_pollitem_t const* items_, size_t nitems_, long timeout_ = -1) { - int rc = zmq_poll (const_cast(items_), static_cast(nitems_), timeout_); + int rc = zmq_poll(const_cast(items_), + static_cast(nitems_), timeout_); if (rc < 0) throw error_t (); return rc; } - inline int poll(zmq_pollitem_t const* items, size_t nitems) - { - return poll(items, nitems, -1); - } - #ifdef ZMQ_CPP11 - inline int poll(zmq_pollitem_t const* items, size_t nitems, std::chrono::milliseconds timeout) - { - return poll(items, nitems, static_cast(timeout.count())); - } +inline int +poll(zmq_pollitem_t const *items, size_t nitems, std::chrono::milliseconds timeout) +{ + return poll(items, nitems, static_cast(timeout.count())); +} - inline int poll(std::vector const& items, std::chrono::milliseconds timeout) - { - return poll(items.data(), items.size(), static_cast(timeout.count())); - } +inline int poll(std::vector const &items, + std::chrono::milliseconds timeout) +{ + return poll(items.data(), items.size(), static_cast(timeout.count())); +} inline int poll(std::vector const& items, long timeout_ = -1) { @@ -172,23 +180,23 @@ namespace zmq #endif - inline void proxy (void *frontend, void *backend, void *capture) { int rc = zmq_proxy (frontend, backend, capture); if (rc != 0) throw error_t (); } - + #ifdef ZMQ_HAS_PROXY_STEERABLE - inline void proxy_steerable (void *frontend, void *backend, void *capture, void *control) +inline void +proxy_steerable(void *frontend, void *backend, void *capture, void *control) { int rc = zmq_proxy_steerable (frontend, backend, capture, control); if (rc != 0) throw error_t (); } #endif - + inline void version (int *major_, int *minor_, int *patch_) { zmq_version (major_, minor_, patch_); @@ -208,7 +216,6 @@ namespace zmq friend class socket_t; public: - inline message_t () { int rc = zmq_msg_init (&msg); @@ -231,19 +238,17 @@ namespace zmq auto size_ = std::distance(first, last) * sizeof(value_t); #else typedef typename std::iterator_traits::difference_type size_type; - size_type const size_ = std::distance(first, last)*sizeof(value_t); + size_type const size_ = std::distance(first, last) * sizeof(value_t); #endif - - - + int const rc = zmq_msg_init_size (&msg, size_); if (rc != 0) throw error_t (); value_t* dest = data(); - while (first != last) - { + while (first != last) { *dest = *first; - ++dest; ++first; + ++dest; + ++first; } } @@ -255,16 +260,22 @@ namespace zmq memcpy(data(), data_, size_); } - inline message_t (void *data_, size_t size_, free_fn *ffn_, - void *hint_ = NULL) + inline message_t(void *data_, size_t size_, free_fn *ffn_, void *hint_ = NULL) { int rc = zmq_msg_init_data (&msg, data_, size_, ffn_, hint_); if (rc != 0) throw error_t (); } +#if defined(ZMQ_BUILD_DRAFT_API) && defined(ZMQ_CPP11) + template + message_t(const T &msg_) : message_t(std::begin(msg_), std::end(msg_)) + { + } +#endif + #ifdef ZMQ_HAS_RVALUE_REFS - inline message_t (message_t &&rhs): msg (rhs.msg) + inline message_t(message_t &&rhs) : msg(rhs.msg) { int rc = zmq_msg_init (&rhs.msg); if (rc != 0) @@ -315,8 +326,7 @@ namespace zmq memcpy(data(), data_, size_); } - inline void rebuild (void *data_, size_t size_, free_fn *ffn_, - void *hint_ = NULL) + inline void rebuild(void *data_, size_t size_, free_fn *ffn_, void *hint_ = NULL) { int rc = zmq_msg_close (&msg); if (rc != 0) @@ -371,24 +381,70 @@ namespace zmq return static_cast( data() ); } + ZMQ_DEPRECATED("from 4.3.0, use operator== instead") inline bool equal(const message_t* other) const ZMQ_NOTHROW { - if (size() != other->size()) - return false; - std::string a(data(), size()); - std::string b(other->data(), other->size()); - return a == b; + return *this == *other; } + inline bool operator==(const message_t &other) const ZMQ_NOTHROW + { + const size_t my_size = size(); + return my_size == other.size() && 0 == memcmp(data(), other.data(), my_size); + } + + inline bool operator!=(const message_t &other) const ZMQ_NOTHROW + { + return !(*this == other); + } + #if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 1, 0) - inline const char* gets(const char *property_) - { - const char* value = zmq_msg_gets (&msg, property_); - if (value == NULL) - throw error_t (); - return value; - } + inline const char *gets(const char *property_) + { + const char *value = zmq_msg_gets(&msg, property_); + if (value == NULL) + throw error_t(); + return value; + } #endif + /** Dump content to string. Ascii chars are readable, the rest is printed as hex. + * Probably ridiculously slow. + */ + inline std::string str() const + { + // Partly mutuated from the same method in zmq::multipart_t + std::stringstream os; + + const unsigned char *msg_data = this->data(); + unsigned char byte; + size_t size = this->size(); + int is_ascii[2] = {0, 0}; + + os << "zmq::message_t [size " << std::dec << std::setw(3) + << std::setfill('0') << size << "] ("; + // Totally arbitrary + if (size >= 1000) { + os << "... too big to print)"; + } else { + while (size--) { + byte = *msg_data++; + + is_ascii[1] = (byte >= 33 && byte < 127); + if (is_ascii[1] != is_ascii[0]) + os << " "; // Separate text/non text + + if (is_ascii[1]) { + os << byte; + } else { + os << std::hex << std::uppercase << std::setw(2) + << std::setfill('0') << static_cast(byte); + } + is_ascii[0] = is_ascii[1]; + } + os << ")"; + } + return os.str(); + } private: // The underlying message @@ -413,7 +469,8 @@ namespace zmq } - inline explicit context_t (int io_threads_, int max_sockets_ = ZMQ_MAX_SOCKETS_DFLT) + inline explicit context_t(int io_threads_, + int max_sockets_ = ZMQ_MAX_SOCKETS_DFLT) { ptr = zmq_ctx_new (); if (ptr == NULL) @@ -438,10 +495,16 @@ namespace zmq } #endif - inline ~context_t () ZMQ_NOTHROW - { - close(); - } + inline int setctxopt(int option_, int optval_) + { + int rc = zmq_ctx_set(ptr, option_, optval_); + ZMQ_ASSERT(rc == 0); + return rc; + } + + inline int getctxopt(int option_) { return zmq_ctx_get(ptr, option_); } + + inline ~context_t() ZMQ_NOTHROW { close(); } inline void close() ZMQ_NOTHROW { @@ -456,17 +519,13 @@ namespace zmq // Be careful with this, it's probably only useful for // using the C api together with an existing C++ api. // Normally you should never need to use this. - inline ZMQ_EXPLICIT operator void* () ZMQ_NOTHROW - { - return ptr; - } + inline ZMQ_EXPLICIT operator void *() ZMQ_NOTHROW { return ptr; } - inline ZMQ_EXPLICIT operator void const* () const ZMQ_NOTHROW - { - return ptr; - } - private: + inline ZMQ_EXPLICIT operator void const *() const ZMQ_NOTHROW { return ptr; } + inline operator bool() const ZMQ_NOTHROW { return ptr != NULL; } + + private: void *ptr; context_t (const context_t&) ZMQ_DELETED_FUNCTION; @@ -486,22 +545,23 @@ namespace zmq xsub = ZMQ_XSUB, push = ZMQ_PUSH, pull = ZMQ_PULL, +#ifdef ZMQ_BUILD_DRAFT_API + server = ZMQ_SERVER, + client = ZMQ_CLIENT, +#endif #if ZMQ_VERSION_MAJOR >= 4 - stream = ZMQ_STREAM, + stream = ZMQ_STREAM, #endif - pair = ZMQ_PAIR + pair = ZMQ_PAIR }; #endif class socket_t { friend class monitor_t; - friend class poller_t; + public: - inline socket_t(context_t& context_, int type_) - { - init(context_, type_); - } + inline socket_t(context_t &context_, int type_) { init(context_, type_); } #ifdef ZMQ_CPP11 inline socket_t(context_t& context_, socket_type type_) @@ -511,12 +571,10 @@ namespace zmq #endif #ifdef ZMQ_HAS_RVALUE_REFS - inline socket_t(socket_t&& rhs) ZMQ_NOTHROW : - ptr(rhs.ptr), - ctxptr(rhs.ctxptr) + inline socket_t(socket_t &&rhs) ZMQ_NOTHROW : ptr(rhs.ptr), ctxptr(rhs.ctxptr) { - rhs.ptr = NULL; - rhs.ctxptr = NULL; + rhs.ptr = NULL; + rhs.ctxptr = NULL; } inline socket_t& operator=(socket_t&& rhs) ZMQ_NOTHROW { @@ -525,20 +583,11 @@ namespace zmq } #endif - inline ~socket_t () ZMQ_NOTHROW - { - close(); - } + inline ~socket_t() ZMQ_NOTHROW { close(); } - inline operator void* () ZMQ_NOTHROW - { - return ptr; - } + inline operator void *() ZMQ_NOTHROW { return ptr; } - inline operator void const* () const ZMQ_NOTHROW - { - return ptr; - } + inline operator void const *() const ZMQ_NOTHROW { return ptr; } inline void close() ZMQ_NOTHROW { @@ -550,18 +599,16 @@ namespace zmq ptr = 0 ; } - inline void setsockopt(int option_, const std::string &optval) - { - setsockopt(option_, optval.c_str(), optval.length()); - } + inline void setsockopt(int option_, const std::string &optval) + { + setsockopt(option_, optval.c_str(), optval.length()); + } - template inline void setsockopt(int option_, T const& optval) + template inline void setsockopt(int option_, T const &optval) { setsockopt(option_, &optval, sizeof(T) ); } - - inline void setsockopt (int option_, const void *optval_, size_t optvallen_) { @@ -586,7 +633,6 @@ namespace zmq return optval; } - inline void bind(std::string const& addr) { bind(addr.c_str()); @@ -639,7 +685,7 @@ namespace zmq { return(ptr != NULL); } - + inline size_t send(std::string const& msg, int flags_ = 0) { int nbytes = zmq_send(ptr, (void *)msg.c_str(), msg.size(), flags_); @@ -702,7 +748,7 @@ namespace zmq return false; throw error_t (); } - + private: inline void init(context_t& context_, int type_) { @@ -731,164 +777,157 @@ namespace zmq class monitor_t { public: - monitor_t() : socketPtr(NULL), monitor_socket(NULL) {} - - virtual ~monitor_t() - { - if (socketPtr) - zmq_socket_monitor(socketPtr, NULL, 0); + monitor_t() : socketPtr(NULL), monitor_socket(NULL) {} - if (monitor_socket) - zmq_close (monitor_socket); + virtual ~monitor_t() + { + if (socketPtr) + zmq_socket_monitor(socketPtr, NULL, 0); - } + if (monitor_socket) + zmq_close(monitor_socket); + } #ifdef ZMQ_HAS_RVALUE_REFS - monitor_t(monitor_t&& rhs) ZMQ_NOTHROW : - socketPtr(rhs.socketPtr), - monitor_socket(rhs.monitor_socket) - { - rhs.socketPtr = NULL; - rhs.monitor_socket = NULL; - } + monitor_t(monitor_t &&rhs) ZMQ_NOTHROW : socketPtr(rhs.socketPtr), + monitor_socket(rhs.monitor_socket) + { + rhs.socketPtr = NULL; + rhs.monitor_socket = NULL; + } - socket_t& operator=(socket_t&& rhs) ZMQ_DELETED_FUNCTION ; + socket_t &operator=(socket_t &&rhs) ZMQ_DELETED_FUNCTION; #endif - - void monitor(socket_t &socket, std::string const& addr, int events = ZMQ_EVENT_ALL) - { + void + monitor(socket_t &socket, std::string const &addr, int events = ZMQ_EVENT_ALL) + { monitor(socket, addr.c_str(), events); } void monitor(socket_t &socket, const char *addr_, int events = ZMQ_EVENT_ALL) { - init (socket, addr_, events) ; - while(true) - { - check_event(-1) ; - } + init(socket, addr_, events); + while (true) { + check_event(-1); } + } - void init(socket_t &socket, std::string const& addr, int events = ZMQ_EVENT_ALL) - { - init(socket, addr.c_str(), events); - } + void init(socket_t &socket, std::string const &addr, int events = ZMQ_EVENT_ALL) + { + init(socket, addr.c_str(), events); + } - void init(socket_t &socket, const char *addr_, int events = ZMQ_EVENT_ALL) - { + void init(socket_t &socket, const char *addr_, int events = ZMQ_EVENT_ALL) + { int rc = zmq_socket_monitor(socket.ptr, addr_, events); if (rc != 0) throw error_t (); socketPtr = socket.ptr; - monitor_socket = zmq_socket (socket.ctxptr, ZMQ_PAIR); - assert (monitor_socket); + monitor_socket = zmq_socket(socket.ctxptr, ZMQ_PAIR); + assert(monitor_socket); - rc = zmq_connect (monitor_socket, addr_); + rc = zmq_connect(monitor_socket, addr_); assert (rc == 0); - + on_monitor_started(); - } - - bool check_event(int timeout = 0) - { - assert (monitor_socket); + } + + bool check_event(int timeout = 0) + { + assert(monitor_socket); - zmq_msg_t eventMsg; - zmq_msg_init (&eventMsg); + zmq_msg_t eventMsg; + zmq_msg_init (&eventMsg); - zmq::pollitem_t items [] = { - { monitor_socket, 0, ZMQ_POLLIN, 0 }, - }; + zmq::pollitem_t items[] = { + {monitor_socket, 0, ZMQ_POLLIN, 0}, + }; - zmq::poll (&items [0], 1, timeout); + zmq::poll(&items[0], 1, timeout); - if (items [0].revents & ZMQ_POLLIN) - { - int rc = zmq_msg_recv (&eventMsg, monitor_socket, 0); + if (items[0].revents & ZMQ_POLLIN) { + int rc = zmq_msg_recv(&eventMsg, monitor_socket, 0); if (rc == -1 && zmq_errno() == ETERM) - return false; + return false; assert (rc != -1); - } - else - { - zmq_msg_close (&eventMsg); - return false; - } + } else { + zmq_msg_close(&eventMsg); + return false; + } #if ZMQ_VERSION_MAJOR >= 4 - const char* data = static_cast(zmq_msg_data(&eventMsg)); - zmq_event_t msgEvent; - memcpy(&msgEvent.event, data, sizeof(uint16_t)); data += sizeof(uint16_t); - memcpy(&msgEvent.value, data, sizeof(int32_t)); - zmq_event_t* event = &msgEvent; + const char* data = static_cast(zmq_msg_data(&eventMsg)); + zmq_event_t msgEvent; + memcpy(&msgEvent.event, data, sizeof(uint16_t)); + data += sizeof(uint16_t); + memcpy(&msgEvent.value, data, sizeof(int32_t)); + zmq_event_t* event = &msgEvent; #else - zmq_event_t* event = static_cast(zmq_msg_data(&eventMsg)); + zmq_event_t* event = static_cast(zmq_msg_data(&eventMsg)); #endif - + #ifdef ZMQ_NEW_MONITOR_EVENT_LAYOUT - zmq_msg_t addrMsg; - zmq_msg_init (&addrMsg); - int rc = zmq_msg_recv (&addrMsg, monitor_socket, 0); - if (rc == -1 && zmq_errno() == ETERM) - { - zmq_msg_close (&eventMsg); - return false; - } + zmq_msg_t addrMsg; + zmq_msg_init (&addrMsg); + int rc = zmq_msg_recv(&addrMsg, monitor_socket, 0); + if (rc == -1 && zmq_errno() == ETERM) { + zmq_msg_close(&eventMsg); + return false; + } - assert (rc != -1); - const char* str = static_cast(zmq_msg_data (&addrMsg)); - std::string address(str, str + zmq_msg_size(&addrMsg)); - zmq_msg_close (&addrMsg); + assert (rc != -1); + const char* str = static_cast(zmq_msg_data (&addrMsg)); + std::string address(str, str + zmq_msg_size(&addrMsg)); + zmq_msg_close (&addrMsg); #else - // Bit of a hack, but all events in the zmq_event_t union have the same layout so this will work for all event types. - std::string address = event->data.connected.addr; + // Bit of a hack, but all events in the zmq_event_t union have the same layout so this will work for all event types. + std::string address = event->data.connected.addr; #endif #ifdef ZMQ_EVENT_MONITOR_STOPPED - if (event->event == ZMQ_EVENT_MONITOR_STOPPED) - { - zmq_msg_close (&eventMsg); - return true; - } + if (event->event == ZMQ_EVENT_MONITOR_STOPPED) { + zmq_msg_close(&eventMsg); + return true; + } #endif - switch (event->event) { - case ZMQ_EVENT_CONNECTED: - on_event_connected(*event, address.c_str()); - break; - case ZMQ_EVENT_CONNECT_DELAYED: - on_event_connect_delayed(*event, address.c_str()); - break; - case ZMQ_EVENT_CONNECT_RETRIED: - on_event_connect_retried(*event, address.c_str()); - break; - case ZMQ_EVENT_LISTENING: - on_event_listening(*event, address.c_str()); - break; - case ZMQ_EVENT_BIND_FAILED: - on_event_bind_failed(*event, address.c_str()); - break; - case ZMQ_EVENT_ACCEPTED: - on_event_accepted(*event, address.c_str()); - break; - case ZMQ_EVENT_ACCEPT_FAILED: - on_event_accept_failed(*event, address.c_str()); - break; - case ZMQ_EVENT_CLOSED: - on_event_closed(*event, address.c_str()); - break; - case ZMQ_EVENT_CLOSE_FAILED: - on_event_close_failed(*event, address.c_str()); - break; - case ZMQ_EVENT_DISCONNECTED: - on_event_disconnected(*event, address.c_str()); - break; + switch (event->event) { + case ZMQ_EVENT_CONNECTED: + on_event_connected(*event, address.c_str()); + break; + case ZMQ_EVENT_CONNECT_DELAYED: + on_event_connect_delayed(*event, address.c_str()); + break; + case ZMQ_EVENT_CONNECT_RETRIED: + on_event_connect_retried(*event, address.c_str()); + break; + case ZMQ_EVENT_LISTENING: + on_event_listening(*event, address.c_str()); + break; + case ZMQ_EVENT_BIND_FAILED: + on_event_bind_failed(*event, address.c_str()); + break; + case ZMQ_EVENT_ACCEPTED: + on_event_accepted(*event, address.c_str()); + break; + case ZMQ_EVENT_ACCEPT_FAILED: + on_event_accept_failed(*event, address.c_str()); + break; + case ZMQ_EVENT_CLOSED: + on_event_closed(*event, address.c_str()); + break; + case ZMQ_EVENT_CLOSE_FAILED: + on_event_close_failed(*event, address.c_str()); + break; + case ZMQ_EVENT_DISCONNECTED: + on_event_disconnected(*event, address.c_str()); + break; #ifdef ZMQ_BUILD_DRAFT_API #if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 3) case ZMQ_EVENT_HANDSHAKE_FAILED_NO_DETAIL: @@ -912,14 +951,14 @@ namespace zmq break; #endif #endif - default: - on_event_unknown(*event, address.c_str()); - break; - } - zmq_msg_close (&eventMsg); + default: + on_event_unknown(*event, address.c_str()); + break; + } + zmq_msg_close (&eventMsg); - return true ; - } + return true; + } #ifdef ZMQ_EVENT_MONITOR_STOPPED void abort() @@ -927,104 +966,187 @@ namespace zmq if (socketPtr) zmq_socket_monitor(socketPtr, NULL, 0); - if (monitor_socket) - zmq_close (monitor_socket); + if (monitor_socket) + zmq_close(monitor_socket); - socketPtr = NULL; - monitor_socket = NULL; + socketPtr = NULL; + monitor_socket = NULL; } #endif virtual void on_monitor_started() {} - virtual void on_event_connected(const zmq_event_t &event_, const char* addr_) { (void)event_; (void)addr_; } - virtual void on_event_connect_delayed(const zmq_event_t &event_, const char* addr_) { (void)event_; (void)addr_; } - virtual void on_event_connect_retried(const zmq_event_t &event_, const char* addr_) { (void)event_; (void)addr_; } - virtual void on_event_listening(const zmq_event_t &event_, const char* addr_) { (void)event_; (void)addr_; } - virtual void on_event_bind_failed(const zmq_event_t &event_, const char* addr_) { (void)event_; (void)addr_; } - virtual void on_event_accepted(const zmq_event_t &event_, const char* addr_) { (void)event_; (void)addr_; } - virtual void on_event_accept_failed(const zmq_event_t &event_, const char* addr_) { (void)event_; (void)addr_; } - virtual void on_event_closed(const zmq_event_t &event_, const char* addr_) { (void)event_; (void)addr_; } - virtual void on_event_close_failed(const zmq_event_t &event_, const char* addr_) { (void)event_; (void)addr_; } - virtual void on_event_disconnected(const zmq_event_t &event_, const char* addr_) { (void)event_; (void)addr_; } + virtual void on_event_connected(const zmq_event_t &event_, const char *addr_) + { + (void) event_; + (void) addr_; + } + virtual void on_event_connect_delayed(const zmq_event_t &event_, + const char *addr_) + { + (void) event_; + (void) addr_; + } + virtual void on_event_connect_retried(const zmq_event_t &event_, + const char *addr_) + { + (void) event_; + (void) addr_; + } + virtual void on_event_listening(const zmq_event_t &event_, const char *addr_) + { + (void) event_; + (void) addr_; + } + virtual void on_event_bind_failed(const zmq_event_t &event_, const char *addr_) + { + (void) event_; + (void) addr_; + } + virtual void on_event_accepted(const zmq_event_t &event_, const char *addr_) + { + (void) event_; + (void) addr_; + } + virtual void on_event_accept_failed(const zmq_event_t &event_, const char *addr_) + { + (void) event_; + (void) addr_; + } + virtual void on_event_closed(const zmq_event_t &event_, const char *addr_) + { + (void) event_; + (void) addr_; + } + virtual void on_event_close_failed(const zmq_event_t &event_, const char *addr_) + { + (void) event_; + (void) addr_; + } + virtual void on_event_disconnected(const zmq_event_t &event_, const char *addr_) + { + (void) event_; + (void) addr_; + } #if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 3) - virtual void on_event_handshake_failed_no_detail(const zmq_event_t &event_, const char* addr_) { (void) event_; (void) addr_; } - virtual void on_event_handshake_failed_protocol(const zmq_event_t &event_, const char* addr_) { (void) event_; (void) addr_; } - virtual void on_event_handshake_failed_auth(const zmq_event_t &event_, const char* addr_) { (void) event_; (void) addr_; } - virtual void on_event_handshake_succeeded(const zmq_event_t &event_, const char* addr_) { (void) event_; (void) addr_; } + virtual void on_event_handshake_failed_no_detail(const zmq_event_t &event_, + const char *addr_) + { + (void) event_; + (void) addr_; + } + virtual void on_event_handshake_failed_protocol(const zmq_event_t &event_, + const char *addr_) + { + (void) event_; + (void) addr_; + } + virtual void on_event_handshake_failed_auth(const zmq_event_t &event_, + const char *addr_) + { + (void) event_; + (void) addr_; + } + virtual void on_event_handshake_succeeded(const zmq_event_t &event_, + const char *addr_) + { + (void) event_; + (void) addr_; + } #elif ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 1) - virtual void on_event_handshake_failed(const zmq_event_t &event_, const char* addr_) { (void) event_; (void) addr_; } - virtual void on_event_handshake_succeed(const zmq_event_t &event_, const char* addr_) { (void) event_; (void) addr_; } + virtual void on_event_handshake_failed(const zmq_event_t &event_, + const char *addr_) + { + (void) event_; + (void) addr_; + } + virtual void on_event_handshake_succeed(const zmq_event_t &event_, + const char *addr_) + { + (void) event_; + (void) addr_; + } #endif - virtual void on_event_unknown(const zmq_event_t &event_, const char* addr_) { (void)event_; (void)addr_; } - private: + virtual void on_event_unknown(const zmq_event_t &event_, const char *addr_) + { + (void) event_; + (void) addr_; + } - monitor_t (const monitor_t&) ZMQ_DELETED_FUNCTION; - void operator = (const monitor_t&) ZMQ_DELETED_FUNCTION; + private: + monitor_t(const monitor_t &) ZMQ_DELETED_FUNCTION; + void operator=(const monitor_t &) ZMQ_DELETED_FUNCTION; - void* socketPtr; - void *monitor_socket ; - }; + void *socketPtr; + void *monitor_socket; +}; #if defined(ZMQ_BUILD_DRAFT_API) && defined(ZMQ_CPP11) && defined(ZMQ_HAVE_POLLER) - class poller_t +template class poller_t +{ + public: + void add(zmq::socket_t &socket, short events, T *user_data) { - public: - poller_t () : poller_ptr (zmq_poller_new ()) - { - if (!poller_ptr) - throw error_t (); - } - - ~poller_t () - { - zmq_poller_destroy (&poller_ptr); + if (0 + != zmq_poller_add(poller_ptr.get(), static_cast(socket), + user_data, events)) { + throw error_t(); } + } - bool add (zmq::socket_t &socket, short events, std::function &handler) - { - if (0 == zmq_poller_add (poller_ptr, socket.ptr, handler ? &handler : NULL, events)) { - poller_events.emplace_back (zmq_poller_event_t ()); - return true; - } - return false; + void remove(zmq::socket_t &socket) + { + if (0 != zmq_poller_remove(poller_ptr.get(), static_cast(socket))) { + throw error_t(); } + } - bool remove (zmq::socket_t &socket) - { - if (0 == zmq_poller_remove (poller_ptr, socket.ptr)) { - poller_events.pop_back (); - return true; - } - return false; + void modify(zmq::socket_t &socket, short events) + { + if (0 + != zmq_poller_modify(poller_ptr.get(), static_cast(socket), + events)) { + throw error_t(); } + } - bool wait (std::chrono::milliseconds timeout) - { - int rc = zmq_poller_wait_all (poller_ptr, poller_events.data (), static_cast (poller_events.size ()), static_cast(timeout.count ())); - if (rc >= 0) { - std::for_each (poller_events.begin (), poller_events.begin () + rc, [](zmq_poller_event_t& event) { - if (event.user_data != NULL) - (*reinterpret_cast*> (event.user_data)) (); - }); - return true; - } + size_t wait_all(std::vector &poller_events, + const std::chrono::microseconds timeout) + { + int rc = zmq_poller_wait_all(poller_ptr.get(), poller_events.data(), + static_cast(poller_events.size()), + static_cast(timeout.count())); + if (rc > 0) + return static_cast(rc); #if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 3) - if (zmq_errno () == EAGAIN) + if (zmq_errno() == EAGAIN) #else - if (zmq_errno () == ETIMEDOUT) + if (zmq_errno() == ETIMEDOUT) #endif - return false; + return 0; - throw error_t (); - } + throw error_t(); + } - private: - void *poller_ptr; - std::vector poller_events; - }; + private: + std::unique_ptr> poller_ptr{ + []() { + auto poller_new = zmq_poller_new(); + if (poller_new) + return poller_new; + throw error_t(); + }(), + [](void *ptr) { + int rc = zmq_poller_destroy(&ptr); + ZMQ_ASSERT(rc == 0); + }}; +}; #endif // defined(ZMQ_BUILD_DRAFT_API) && defined(ZMQ_CPP11) && defined(ZMQ_HAVE_POLLER) +inline std::ostream &operator<<(std::ostream &os, const message_t &msg) +{ + return os << msg.str(); } -#endif +} // namespace zmq +#endif // __ZMQ_HPP_INCLUDED__ diff --git a/src/helics/common/cppzmq/zmq_addon.hpp b/src/helics/common/cppzmq/zmq_addon.hpp index f6fc14d310..e0c0b6dcd7 100644 --- a/src/helics/common/cppzmq/zmq_addon.hpp +++ b/src/helics/common/cppzmq/zmq_addon.hpp @@ -1,6 +1,6 @@ /* Copyright (c) 2016-2017 ZeroMQ community - Copyright (c) 2016 VOCA AS / Harald Nøkland + Copyright (c) 2016 VOCA AS / Harald Nøkland Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to @@ -25,29 +25,29 @@ #define __ZMQ_ADDON_HPP_INCLUDED__ #include "zmq.hpp" + #include #include #include #include -namespace zmq { - +namespace zmq +{ #ifdef ZMQ_HAS_RVALUE_REFS /* This class handles multipart messaging. It is the C++ equivalent of zmsg.h, which is part of CZMQ (the high-level C binding). Furthermore, it is a major - improvement compared to zmsg.hpp, which is part of the examples in the ØMQ + improvement compared to zmsg.hpp, which is part of the examples in the ØMQ Guide. Unnecessary copying is avoided by using move semantics to efficiently add/remove parts. */ class multipart_t { -private: + private: std::deque m_parts; -public: - + public: typedef std::deque::iterator iterator; typedef std::deque::const_iterator const_iterator; @@ -55,147 +55,76 @@ class multipart_t typedef std::deque::const_reverse_iterator const_reverse_iterator; // Default constructor - multipart_t() - {} + multipart_t() {} // Construct from socket receive - multipart_t(socket_t& socket) - { - recv(socket); - } + multipart_t(socket_t &socket) { recv(socket); } // Construct from memory block - multipart_t(const void *src, size_t message_size) - { - addmem(src, message_size); - } + multipart_t(const void *src, size_t size) { addmem(src, size); } // Construct from string - multipart_t(const std::string& string) - { - addstr(string); - } + multipart_t(const std::string &string) { addstr(string); } // Construct from message part - multipart_t(message_t&& message) - { - add(std::move(message)); - } + multipart_t(message_t &&message) { add(std::move(message)); } // Move constructor - multipart_t(multipart_t&& other) - { - m_parts = std::move(other.m_parts); - } + multipart_t(multipart_t &&other) { m_parts = std::move(other.m_parts); } // Move assignment operator - multipart_t& operator=(multipart_t&& other) + multipart_t &operator=(multipart_t &&other) { m_parts = std::move(other.m_parts); return *this; } // Destructor - virtual ~multipart_t() - { - clear(); - } + virtual ~multipart_t() { clear(); } - message_t& operator[] (size_t n) - { - return m_parts[n]; - } + message_t &operator[](size_t n) { return m_parts[n]; } - const message_t& operator[] (size_t n) const - { - return m_parts[n]; - } + const message_t &operator[](size_t n) const { return m_parts[n]; } - message_t& at (size_t n) - { - return m_parts.at(n); - } + message_t &at(size_t n) { return m_parts.at(n); } - const message_t& at (size_t n) const - { - return m_parts.at(n); - } + const message_t &at(size_t n) const { return m_parts.at(n); } - iterator begin() - { - return m_parts.begin(); - } + iterator begin() { return m_parts.begin(); } - const_iterator begin() const - { - return m_parts.begin(); - } + const_iterator begin() const { return m_parts.begin(); } - const_iterator cbegin() const - { - return m_parts.cbegin(); - } + const_iterator cbegin() const { return m_parts.cbegin(); } - reverse_iterator rbegin() - { - return m_parts.rbegin(); - } + reverse_iterator rbegin() { return m_parts.rbegin(); } - const_reverse_iterator rbegin() const - { - return m_parts.rbegin(); - } + const_reverse_iterator rbegin() const { return m_parts.rbegin(); } - iterator end() - { - return m_parts.end(); - } + iterator end() { return m_parts.end(); } - const_iterator end() const - { - return m_parts.end(); - } + const_iterator end() const { return m_parts.end(); } - const_iterator cend() const - { - return m_parts.cend(); - } + const_iterator cend() const { return m_parts.cend(); } - reverse_iterator rend() - { - return m_parts.rend(); - } + reverse_iterator rend() { return m_parts.rend(); } - const_reverse_iterator rend() const - { - return m_parts.rend(); - } + const_reverse_iterator rend() const { return m_parts.rend(); } // Delete all parts - void clear() - { - m_parts.clear(); - } + void clear() { m_parts.clear(); } // Get number of parts - size_t size() const - { - return m_parts.size(); - } + size_t size() const { return m_parts.size(); } // Check if number of parts is zero - bool empty() const - { - return m_parts.empty(); - } + bool empty() const { return m_parts.empty(); } // Receive multipart message from socket - bool recv(socket_t& socket, int flags = 0) + bool recv(socket_t &socket, int flags = 0) { clear(); bool more = true; - while (more) - { + while (more) { message_t message; if (!socket.recv(&message, flags)) return false; @@ -206,12 +135,11 @@ class multipart_t } // Send multipart message to socket - bool send(socket_t& socket, int flags = 0) + bool send(socket_t &socket, int flags = 0) { flags &= ~(ZMQ_SNDMORE); bool more = size() > 0; - while (more) - { + while (more) { message_t message = pop(); more = size() > 0; if (!socket.send(message, (more ? ZMQ_SNDMORE : 0) | flags)) @@ -222,90 +150,81 @@ class multipart_t } // Concatenate other multipart to front - void prepend(multipart_t&& other) + void prepend(multipart_t &&other) { while (!other.empty()) push(other.remove()); } // Concatenate other multipart to back - void append(multipart_t&& other) + void append(multipart_t &&other) { while (!other.empty()) add(other.pop()); } // Push memory block to front - void pushmem(const void *src, size_t mem_size) + void pushmem(const void *src, size_t size) { - m_parts.push_front(message_t(src, mem_size)); + m_parts.push_front(message_t(src, size)); } // Push memory block to back - void addmem(const void *src, size_t mem_size) + void addmem(const void *src, size_t size) { - m_parts.push_back(message_t(src, mem_size)); + m_parts.push_back(message_t(src, size)); } // Push string to front - void pushstr(const std::string& string) + void pushstr(const std::string &string) { m_parts.push_front(message_t(string.data(), string.size())); } // Push string to back - void addstr(const std::string& string) + void addstr(const std::string &string) { m_parts.push_back(message_t(string.data(), string.size())); } // Push type (fixed-size) to front - template - void pushtyp(const T& type) + template void pushtyp(const T &type) { - static_assert(!std::is_same::value, "Use pushstr() instead of pushtyp()"); + static_assert(!std::is_same::value, + "Use pushstr() instead of pushtyp()"); m_parts.push_front(message_t(&type, sizeof(type))); } // Push type (fixed-size) to back - template - void addtyp(const T& type) + template void addtyp(const T &type) { - static_assert(!std::is_same::value, "Use addstr() instead of addtyp()"); + static_assert(!std::is_same::value, + "Use addstr() instead of addtyp()"); m_parts.push_back(message_t(&type, sizeof(type))); } // Push message part to front - void push(message_t&& message) - { - m_parts.push_front(std::move(message)); - } + void push(message_t &&message) { m_parts.push_front(std::move(message)); } // Push message part to back - void add(message_t&& message) - { - m_parts.push_back(std::move(message)); - } + void add(message_t &&message) { m_parts.push_back(std::move(message)); } // Pop string from front std::string popstr() { - if (m_parts.empty()) - return ""; std::string string(m_parts.front().data(), m_parts.front().size()); m_parts.pop_front(); return string; } // Pop type (fixed-size) from front - template - T poptyp() + template T poptyp() { - if (m_parts.empty()) - return T(); - static_assert(!std::is_same::value, "Use popstr() instead of poptyp()"); + static_assert(!std::is_same::value, + "Use popstr() instead of poptyp()"); if (sizeof(T) != m_parts.front().size()) - throw std::runtime_error("Invalid type, size does not match the message size"); + throw std::runtime_error( + "Invalid type, size does not match the message size"); T type = *m_parts.front().data(); m_parts.pop_front(); return type; @@ -314,8 +233,6 @@ class multipart_t // Pop message part from front message_t pop() { - if (m_parts.empty()) - return message_t(0); message_t message = std::move(m_parts.front()); m_parts.pop_front(); return message; @@ -324,20 +241,13 @@ class multipart_t // Pop message part from back message_t remove() { - if (m_parts.empty()) - return message_t(0); message_t message = std::move(m_parts.back()); m_parts.pop_back(); return message; } // Get pointer to a specific message part - const message_t* peek(size_t index) const - { - if (index >= size()) - return nullptr; - return &m_parts[index]; - } + const message_t *peek(size_t index) const { return &m_parts[index]; } // Get a string copy of a specific message part std::string peekstr(size_t index) const @@ -347,19 +257,19 @@ class multipart_t } // Peek type (fixed-size) from front - template - T peektyp(size_t index) const + template T peektyp(size_t index) const { - static_assert(!std::is_same::value, "Use peekstr() instead of peektyp()"); - if(sizeof(T) != m_parts[index].size()) - throw std::runtime_error("Invalid type, size does not match the message size"); + static_assert(!std::is_same::value, + "Use peekstr() instead of peektyp()"); + if (sizeof(T) != m_parts[index].size()) + throw std::runtime_error( + "Invalid type, size does not match the message size"); T type = *m_parts[index].data(); return type; } // Create multipart from type (fixed-size) - template - static multipart_t create(const T& type) + template static multipart_t create(const T &type) { multipart_t multipart; multipart.addtyp(type); @@ -379,224 +289,143 @@ class multipart_t std::string str() const { std::stringstream ss; - for (size_t i = 0; i < m_parts.size(); i++) - { - const unsigned char* data = m_parts[i].data(); - size_t numparts = m_parts[i].size(); + for (size_t i = 0; i < m_parts.size(); i++) { + const unsigned char *data = m_parts[i].data(); + size_t size = m_parts[i].size(); // Dump the message as text or binary bool isText = true; - for (size_t j = 0; j < numparts; j++) - { - if (data[j] < 32 || data[j] > 127) - { + for (size_t j = 0; j < size; j++) { + if (data[j] < 32 || data[j] > 127) { isText = false; break; } } - ss << "\n[" << std::dec << std::setw(3) << std::setfill('0') << numparts << "] "; - if (numparts >= 1000) - { + ss << "\n[" << std::dec << std::setw(3) << std::setfill('0') << size + << "] "; + if (size >= 1000) { ss << "... (to big to print)"; continue; } - for (size_t j = 0; j < numparts; j++) - { + for (size_t j = 0; j < size; j++) { if (isText) ss << static_cast(data[j]); else - ss << std::hex << std::setw(2) << std::setfill('0') << static_cast(data[j]); + ss << std::hex << std::setw(2) << std::setfill('0') + << static_cast(data[j]); } } return ss.str(); } // Check if equal to other multipart - bool equal(const multipart_t* other) const + bool equal(const multipart_t *other) const { if (size() != other->size()) return false; for (size_t i = 0; i < size(); i++) - if (!peek(i)->equal(other->peek(i))) + if (*peek(i) != *other->peek(i)) return false; return true; } - // Self test - static int test() + private: + // Disable implicit copying (moving is more efficient) + multipart_t(const multipart_t &other) ZMQ_DELETED_FUNCTION; + void operator=(const multipart_t &other) ZMQ_DELETED_FUNCTION; +}; // class multipart_t + +inline std::ostream &operator<<(std::ostream &os, const multipart_t &msg) +{ + return os << msg.str(); +} + +#endif // ZMQ_HAS_RVALUE_REFS + +#if defined(ZMQ_BUILD_DRAFT_API) && defined(ZMQ_CPP11) && defined(ZMQ_HAVE_POLLER) +class active_poller_t +{ + public: + active_poller_t() = default; + ~active_poller_t() = default; + + active_poller_t(const active_poller_t &) = delete; + active_poller_t &operator=(const active_poller_t &) = delete; + + active_poller_t(active_poller_t &&src) = default; + active_poller_t &operator=(active_poller_t &&src) = default; + + using handler_t = std::function; + + void add(zmq::socket_t &socket, short events, handler_t handler) + { + auto it = decltype(handlers)::iterator{}; + auto inserted = bool{}; + std::tie(it, inserted) = + handlers.emplace(static_cast(socket), + std::make_shared(std::move(handler))); + try { + base_poller.add(socket, events, + inserted && *(it->second) ? it->second.get() : nullptr); + need_rebuild |= inserted; + } + catch (const zmq::error_t &) { + // rollback + if (inserted) { + handlers.erase(static_cast(socket)); + } + throw; + } + } + + void remove(zmq::socket_t &socket) { - bool ok = true; (void) ok; - float num = 0; (void) num; - std::string str = ""; - message_t msg; - - // Create two PAIR sockets and connect over inproc - context_t context(1); - socket_t output(context, ZMQ_PAIR); - socket_t input(context, ZMQ_PAIR); - output.bind("inproc://multipart.test"); - input.connect("inproc://multipart.test"); - - // Test send and receive of single-frame message - multipart_t multipart; - assert(multipart.empty()); - - multipart.push(message_t("Hello", 5)); - assert(multipart.size() == 1); - - ok = multipart.send(output); - assert(multipart.empty()); - assert(ok); - - ok = multipart.recv(input); - assert(multipart.size() == 1); - assert(ok); - - msg = multipart.pop(); - assert(multipart.empty()); - assert(std::string(msg.data(), msg.size()) == "Hello"); - - // Test send and receive of multi-frame message - multipart.addstr("A"); - multipart.addstr("BB"); - multipart.addstr("CCC"); - assert(multipart.size() == 3); - - multipart_t copy = multipart.clone(); - assert(copy.size() == 3); - - ok = copy.send(output); - assert(copy.empty()); - assert(ok); - - ok = copy.recv(input); - assert(copy.size() == 3); - assert(ok); - assert(copy.equal(&multipart)); - - multipart.clear(); - assert(multipart.empty()); - - // Test message frame manipulation - multipart.add(message_t("Frame5", 6)); - multipart.addstr("Frame6"); - multipart.addstr("Frame7"); - multipart.addtyp(8.0f); - multipart.addmem("Frame9", 6); - multipart.push(message_t("Frame4", 6)); - multipart.pushstr("Frame3"); - multipart.pushstr("Frame2"); - multipart.pushtyp(1.0f); - multipart.pushmem("Frame0", 6); - assert(multipart.size() == 10); - - msg = multipart.remove(); - assert(multipart.size() == 9); - assert(std::string(msg.data(), msg.size()) == "Frame9"); - - msg = multipart.pop(); - assert(multipart.size() == 8); - assert(std::string(msg.data(), msg.size()) == "Frame0"); - - num = multipart.poptyp(); - assert(multipart.size() == 7); - assert(num == 1.0f); - - str = multipart.popstr(); - assert(multipart.size() == 6); - assert(str == "Frame2"); - - str = multipart.popstr(); - assert(multipart.size() == 5); - assert(str == "Frame3"); - - str = multipart.popstr(); - assert(multipart.size() == 4); - assert(str == "Frame4"); - - str = multipart.popstr(); - assert(multipart.size() == 3); - assert(str == "Frame5"); - - str = multipart.popstr(); - assert(multipart.size() == 2); - assert(str == "Frame6"); - - str = multipart.popstr(); - assert(multipart.size() == 1); - assert(str == "Frame7"); - - num = multipart.poptyp(); - assert(multipart.empty()); - assert(num == 8.0f); - - // Test message constructors and concatenation - multipart_t head("One", 3); - head.addstr("Two"); - assert(head.size() == 2); - - multipart_t tail("One-hundred"); - tail.pushstr("Ninety-nine"); - assert(tail.size() == 2); - - multipart_t tmp(message_t("Fifty", 5)); - assert(tmp.size() == 1); - - multipart_t mid = multipart_t::create(49.0f); - mid.append(std::move(tmp)); - assert(mid.size() == 2); - assert(tmp.empty()); - - multipart_t merged(std::move(mid)); - merged.prepend(std::move(head)); - merged.append(std::move(tail)); - assert(merged.size() == 6); - assert(head.empty()); - assert(tail.empty()); - - ok = merged.send(output); - assert(merged.empty()); - assert(ok); - - multipart_t received(input); - assert(received.size() == 6); - - str = received.popstr(); - assert(received.size() == 5); - assert(str == "One"); - - str = received.popstr(); - assert(received.size() == 4); - assert(str == "Two"); - - num = received.poptyp(); - assert(received.size() == 3); - assert(num == 49.0f); - - str = received.popstr(); - assert(received.size() == 2); - assert(str == "Fifty"); - - str = received.popstr(); - assert(received.size() == 1); - assert(str == "Ninety-nine"); - - str = received.popstr(); - assert(received.empty()); - assert(str == "One-hundred"); - - return 0; + base_poller.remove(socket); + handlers.erase(static_cast(socket)); + need_rebuild = true; } -private: - // Disable implicit copying (moving is more efficient) - multipart_t(const multipart_t& other) ZMQ_DELETED_FUNCTION; - void operator=(const multipart_t& other) ZMQ_DELETED_FUNCTION; -}; + void modify(zmq::socket_t &socket, short events) + { + base_poller.modify(socket, events); + } -#endif + size_t wait(std::chrono::milliseconds timeout) + { + if (need_rebuild) { + poller_events.resize(handlers.size()); + poller_handlers.clear(); + poller_handlers.reserve(handlers.size()); + for (const auto &handler : handlers) { + poller_handlers.push_back(handler.second); + } + need_rebuild = false; + } + const auto count = base_poller.wait_all(poller_events, timeout); + std::for_each(poller_events.begin(), poller_events.begin() + count, + [](zmq_poller_event_t &event) { + if (event.user_data != NULL) + (*reinterpret_cast(event.user_data))( + event.events); + }); + return count; + } + + bool empty() const { return handlers.empty(); } + + size_t size() const { return handlers.size(); } + + private: + bool need_rebuild{false}; + + poller_t base_poller{}; + std::unordered_map> handlers{}; + std::vector poller_events{}; + std::vector> poller_handlers{}; +}; // class active_poller_t +#endif // defined(ZMQ_BUILD_DRAFT_API) && defined(ZMQ_CPP11) && defined(ZMQ_HAVE_POLLER) -} -#endif +} // namespace zmq +#endif // __ZMQ_ADDON_HPP_INCLUDED__ diff --git a/src/helics/common/timeRepresentation.hpp b/src/helics/common/timeRepresentation.hpp index c201a42027..7f6eb624e5 100644 --- a/src/helics/common/timeRepresentation.hpp +++ b/src/helics/common/timeRepresentation.hpp @@ -308,7 +308,7 @@ class TimeRepresentation #endif public: /** default constructor*/ - TimeRepresentation () noexcept {}; + TimeRepresentation ()=default; private: /** explicit means to generate a constexpr TimeRepresentation at time 0, negTime and maxTime and min time delta*/ diff --git a/src/helics/core/CMakeLists.txt b/src/helics/core/CMakeLists.txt index eb4744a25e..75a915dfef 100644 --- a/src/helics/core/CMakeLists.txt +++ b/src/helics/core/CMakeLists.txt @@ -197,20 +197,3 @@ if (HELICS_HAVE_MPI) endif(HELICS_HAVE_MPI) install (FILES ${PUBLIC_INCLUDE_FILES} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/helics/core COMPONENT headers) - -OPTION(BUILD_BROKER "Build a helics Broker" ON) -if (BUILD_BROKER) -add_executable(helics_broker helics-broker.cpp) - target_link_libraries(helics_broker helics-static) - target_include_directories(helics_broker SYSTEM PRIVATE ${Boost_INCLUDE_DIR}) - set_target_properties (helics_broker PROPERTIES FOLDER apps) - set(HELICS_BROKER_LOC ${CMAKE_CURRENT_BINARY_DIR} CACHE INTERNAL "build folder location of the broker") - INSTALL(TARGETS helics_broker DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT applications) -foreach(keyfile IN LISTS KEY_LIBRARY_FILES) -add_custom_command(TARGET helics_broker POST_BUILD # Adds a post-build event to core tests - COMMAND ${CMAKE_COMMAND} -E copy_if_different # which executes "cmake - E copy_if_different..." - "${keyfile}" # <--this is in-file - "$/") # <--this is out-file path -endforeach(keyfile) -endif() - diff --git a/src/helics/core/core-types.hpp b/src/helics/core/core-types.hpp index acf272c315..b063de06e4 100644 --- a/src/helics/core/core-types.hpp +++ b/src/helics/core/core-types.hpp @@ -40,6 +40,7 @@ enum class core_type : int }; + /** enumeration of the possible states of convergence*/ enum class iteration_state : signed char { diff --git a/src/helics/core/helics-broker.cpp b/src/helics/core/helics-broker.cpp deleted file mode 100644 index c6ed6f3867..0000000000 --- a/src/helics/core/helics-broker.cpp +++ /dev/null @@ -1,65 +0,0 @@ -#include "helics/helics-config.h" - -#include "../common/argParser.h" -#include "BrokerFactory.hpp" -#include "CoreBroker.hpp" -#include "helicsVersion.hpp" -#include -#include - -static const helics::ArgDescriptors InfoArgs{ - {"name,n", "name of the broker"}, - {"type,t", "type of the broker (\"(zmq)\", \"ipc\", \"test\", \"mpi\", \"test\", \"tcp\", \"udp\")"}}; - -int main (int argc, char *argv[]) -{ - helics::variable_map vm; - auto exit_early = helics::argumentParser (argc, argv, vm, InfoArgs); - - if (exit_early != 0) - { - if (exit_early == helics::helpReturn) - { - helics::BrokerFactory::displayHelp (); - } - else if (exit_early == helics::versionReturn) - { - std::cout << helics::versionString << '\n'; - } - return 0; - } - - std::string name = (vm.count ("name") > 0) ? vm["name"].as () : ""; - std::string btype = (vm.count ("type") > 0) ? vm["type"].as () : "zmq"; - - helics::core_type type; - try - { - type = helics::coreTypeFromString (btype); - } - catch (std::invalid_argument &ie) - { - std::cerr << "Unable to generate broker: " << ie.what () << '\n'; - return (-2); - } - auto broker = helics::BrokerFactory::create (type, name, argc, argv); - if (broker->isConnected ()) - { - do // sleep until the broker finishes - { - std::this_thread::sleep_for (std::chrono::milliseconds (500)); - - } while (broker->isConnected ()); - } - else - { - std::cerr << "Broker is unable to connect\n"; - return (-1); - } - broker = nullptr; - while (helics::BrokerFactory::cleanUpBrokers () > 0) - { - std::this_thread::sleep_for (std::chrono::milliseconds (500)); - } - return 0; -} diff --git a/src/helics/cpp98/CMakeLists.txt b/src/helics/cpp98/CMakeLists.txt index 2ceb0865dc..e9bce3274d 100644 --- a/src/helics/cpp98/CMakeLists.txt +++ b/src/helics/cpp98/CMakeLists.txt @@ -22,6 +22,7 @@ add_library(helicsCpp98 INTERFACE) target_include_directories(helicsCpp98 INTERFACE "${PROJECT_SOURCE_DIR}/src/helics") target_link_libraries(helicsCpp98 INTERFACE helicsSharedLib) +#this is purely so the files show up nicely in an IDE, other ides might use it as well but that can be added when/if the need arises IF (MSVC) add_library(helicsCpp98_ide STATIC ${helicsCpp98_headers} ../../empty.cpp) target_include_directories(helicsCpp98_ide PRIVATE "${PROJECT_SOURCE_DIR}/src/helics") diff --git a/src/helics/shared_api_library/CMakeLists.txt b/src/helics/shared_api_library/CMakeLists.txt index fd2eb2a0e5..3caa26d5c6 100644 --- a/src/helics/shared_api_library/CMakeLists.txt +++ b/src/helics/shared_api_library/CMakeLists.txt @@ -3,13 +3,6 @@ # Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC #All rights reserved. See LICENSE file and DISCLAIMER for more details. ############################################################################## -IF(UNIX) - add_compile_options(-fvisibility=hidden) -ELSE(UNIX) - IF(MINGW) - add_compile_options(-fvisibility=hidden) - ENDIF(MINGW) -ENDIF(UNIX) set(helicsShared_headers helics.h @@ -51,6 +44,27 @@ endif() set_target_properties (helicsSharedLib PROPERTIES FOLDER interfaces) +OPTION(STATIC_STANDARD_LIB "Link against a static standard lib" OFF) + +if (STATIC_STANDARD_LIB) + if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") + if (USE_LIBCXX) + message("static linking against libc++ is not currently supported") + else(USE_LIBCXX) + target_link_libraries(helicsSharedLib -static-libgcc -static-libstdc++) + endif(USE_LIBCXX) +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + target_link_libraries(helicsSharedLib -static-libgcc -static-libstdc++) +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel") + target_link_libraries(helicsSharedLib -static-libgcc -static-libstdc++) +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") + # using Visual Studio C++ + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT") + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd") +endif() + +endif(STATIC_STANDARD_LIB) + INSTALL(TARGETS helicsSharedLib EXPORT helics-targets RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} diff --git a/tests/helics/CMakeLists.txt b/tests/helics/CMakeLists.txt index 60d81f2b52..0344f0b188 100644 --- a/tests/helics/CMakeLists.txt +++ b/tests/helics/CMakeLists.txt @@ -19,7 +19,5 @@ if (BUILD_C_SHARED_LIB OR INTERFACE_BUILD) add_subdirectory(shared_library) endif() -if(BUILD_PLAYER OR BUILD_RECORDER OR BUILD_APPS) - add_subdirectory(apps) -endif() +add_subdirectory(apps) diff --git a/tests/helics/apps/PlayerTests.cpp b/tests/helics/apps/PlayerTests.cpp index e581b4e614..b0798f5580 100644 --- a/tests/helics/apps/PlayerTests.cpp +++ b/tests/helics/apps/PlayerTests.cpp @@ -252,7 +252,7 @@ BOOST_DATA_TEST_CASE (simple_player_test_files_ext, boost::unit_test::data::make { exeTestRunner playerExe (std::string (HELICS_BIN_LOC) + "/apps/", "helics_player"); - exeTestRunner brokerExe (std::string (HELICS_BIN_LOC) + "/core/", "helics_broker"); + exeTestRunner brokerExe (std::string (HELICS_BIN_LOC) + "/apps/", "helics_broker"); BOOST_REQUIRE (playerExe.isActive ()); BOOST_REQUIRE (brokerExe.isActive ()); @@ -558,7 +558,7 @@ BOOST_AUTO_TEST_CASE (simple_player_test) { static exeTestRunner playerExe (HELICS_BIN_LOC "apps/", "helics_player"); - static exeTestRunner brokerExe (HELICS_BIN_LOC "core/", "helics_broker"); + static exeTestRunner brokerExe (HELICS_BIN_LOC "apps/", "helics_broker"); auto res = brokerExe.runAsync ("1 --type=ipc --name=ipc_broker"); std::string exampleFile = std::string (TEST_DIR) + "/test_files/example1.Player"; From bfbb13b0a33251e72f133609548f1b0e0598c51d Mon Sep 17 00:00:00 2001 From: Dheepak Krishnamurthy Date: Thu, 24 May 2018 11:51:56 -0600 Subject: [PATCH 06/10] Add helicsConfigMain.cpp (#203) * Add helicsConfigMain.cpp and helicsConfigMain.h.in Also update CMakeLists.txt to generate `helics-config` target * Pass name by reference instead * move some cmake configuration around, move broker executable to apps folder * move library cmake configuration to more sensible location * fix broken test by cmake changes * added BrokerApp, Still some work on getting it to play nicely with other apps * update HELICS config Issue #322 * update examples to use BrokerApp * a few fixes for travis builds and warnings * fix explicit issue in app constructors * fix a couple more warnings * fix gcc 4.9 warnings * try to fix more errors * allow compilation before boost 1.61 * actually use the required function for lexically_normal * clean up warning in signal generators * fix some issues with command lines so it works a little more consistently * add a system zmq only flag * try a different approach with addZeroMQ.cmake --- CMakeLists.txt | 2 +- config/cmake/addZeroMQ.cmake | 25 ++++- src/helics/apps/CMakeLists.txt | 23 +++- src/helics/apps/SignalGenerators.cpp | 2 +- src/helics/apps/SignalGenerators.hpp | 2 +- src/helics/apps/helicsConfigMain.cpp | 150 +++++++++++++++++++++++++ src/helics/apps/helicsConfigMain.h.in | 16 +++ src/helics/common/cppzmq/zmq.hpp | 11 +- src/helics/common/cppzmq/zmq_addon.hpp | 25 +++-- 9 files changed, 231 insertions(+), 25 deletions(-) create mode 100644 src/helics/apps/helicsConfigMain.cpp create mode 100644 src/helics/apps/helicsConfigMain.h.in diff --git a/CMakeLists.txt b/CMakeLists.txt index 1561ea5830..01a765b8de 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,7 +17,7 @@ set (HELICS_VERSION_BUILD 0) set (HELICS_DATE "05-09-18") set (HELICS_VERSION "${HELICS_VERSION_MAJOR}.${HELICS_VERSION_MINOR}.${HELICS_VERSION_PATCH}") -set (HELICS_VERSION_STRING "${HELICS_VERSION} ${HELICS_DATE}") +set (HELICS_VERSION_STRING "${HELICS_VERSION} (${HELICS_DATE})") #----------------------------------------------------------------------------- # set the module path and include some common macros diff --git a/config/cmake/addZeroMQ.cmake b/config/cmake/addZeroMQ.cmake index b27db47316..0be18ad36d 100644 --- a/config/cmake/addZeroMQ.cmake +++ b/config/cmake/addZeroMQ.cmake @@ -1,5 +1,8 @@ #file to include ZMQ - +OPTION(USE_SYSTEM_ZEROMQ_ONLY "only search for system zeromq libraries, bypass autobuild option" OFF) +if (USE_SYSTEM_ZEROMQ_ONLY) + find_package(ZeroMQ) +else() OPTION(ZMQ_USE_STATIC_LIBRARY "use the ZMQ static library" OFF) @@ -11,13 +14,27 @@ set(ZMQ_CMAKE_SUFFIXES cmake CMake/ZeroMQ lib/cmake) - + +if (WIN32 AND NOT MSYS) +find_package(ZeroMQ QUIET + HINTS + ${ZeroMQ_INSTALL_PATH} + ${PROJECT_BINARY_DIR}/libs/ + PATH_SUFFIXES ${ZMQ_CMAKE_SUFFIXES} + ) +else() find_package(ZeroMQ QUIET HINTS ${ZeroMQ_INSTALL_PATH} ${PROJECT_BINARY_DIR}/libs/ PATH_SUFFIXES ${ZMQ_CMAKE_SUFFIXES} + NO_SYSTEM_ENVIRONMENT_PATH + NO_CMAKE_PACKAGE_REGISTRY + NO_CMAKE_SYSTEM_PATH + NO_CMAKE_SYSTEM_PACKAGE_REGISTRY ) +endif() + if (NOT ZeroMQ_FOUND) message(STATUS "initialZMQ not found") @@ -47,4 +64,6 @@ if (NOT ZeroMQ_FOUND) ENDIF(AUTOBUILD_ZMQ) endif() endif() -endif() \ No newline at end of file +endif() + +endif() # USE_SYSTEM_ZEROMQ_ONLY \ No newline at end of file diff --git a/src/helics/apps/CMakeLists.txt b/src/helics/apps/CMakeLists.txt index 8c4bb63a26..3d934ff41a 100644 --- a/src/helics/apps/CMakeLists.txt +++ b/src/helics/apps/CMakeLists.txt @@ -3,6 +3,9 @@ # Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC #All rights reserved. See LICENSE file and DISCLAIMER for more details. ############################################################################## + +if(BUILD_PLAYER OR BUILD_RECORDER OR BUILD_APPS OR BUILD_BROKER) + set(helics_apps_public_headers Player.hpp Recorder.hpp @@ -58,7 +61,6 @@ add_executable(helics_broker helics-broker.cpp) endif() -if(BUILD_PLAYER OR BUILD_RECORDER OR BUILD_APPS OR BUILD_BROKER) add_executable(helics_app appMain.cpp) target_link_libraries(helics_app helics_apps-static) set_target_properties (helics_app PROPERTIES FOLDER apps) @@ -70,8 +72,10 @@ add_custom_command(TARGET helics_app POST_BUILD # Adds a post-build event "${keyfile}" # <--this is in-file "$/") # <--this is out-file path endforeach(keyfile) + endif() -endif() + + INSTALL(TARGETS helics_apps-static EXPORT helics-targets DESTINATION ${CMAKE_INSTALL_LIBDIR} @@ -80,3 +84,18 @@ INSTALL(TARGETS helics_apps-static EXPORT helics-targets INSTALL(FILES ${helics_apps_public_headers} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/helics/apps COMPONENT headers) +endif() #if build any app + +#configure executable app + +configure_file(helicsConfigMain.h.in ${CMAKE_CURRENT_BINARY_DIR}/helicsConfigMain.h) +add_executable(helics-config helicsConfigMain.cpp ${CMAKE_CURRENT_BINARY_DIR}/helicsConfigMain.h) + +target_include_directories(helics-config PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) +set_target_properties (helics-config PROPERTIES FOLDER apps) +target_link_libraries(helics-config PRIVATE ${Boost_LIBRARIES_core}) +target_include_directories(helics-config SYSTEM PRIVATE ${Boost_INCLUDE_DIRS}) +install(TARGETS helics-config +RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT libs +) + diff --git a/src/helics/apps/SignalGenerators.cpp b/src/helics/apps/SignalGenerators.cpp index 4914cc8aea..88611a41fd 100644 --- a/src/helics/apps/SignalGenerators.cpp +++ b/src/helics/apps/SignalGenerators.cpp @@ -168,7 +168,7 @@ defV PhasorGenerator::generate(Time signalTime) frequency += dfdt * dt; Amplitude += dAdt * dt; - rotation = std::polar(1.0, frequency*dt * (2 * pi)); + rotation = std::polar(1.0, frequency*dt * (2.0 * pi)); state *= rotation; lastTime = signalTime; return Amplitude*state+std::complex(bias_real,bias_imag); diff --git a/src/helics/apps/SignalGenerators.hpp b/src/helics/apps/SignalGenerators.hpp index 5632a29e4d..757556fcb4 100644 --- a/src/helics/apps/SignalGenerators.hpp +++ b/src/helics/apps/SignalGenerators.hpp @@ -57,7 +57,7 @@ class PhasorGenerator : public SignalGenerator double Amplitude = 0.0; double dAdt = 0.0; double dfdt = 0.0; - Time lastCycle = timeZero; + //Time lastCycle = timeZero; std::complex state{ 1.0, 0 }; std::complex rotation{ 1.0,0 }; public: diff --git a/src/helics/apps/helicsConfigMain.cpp b/src/helics/apps/helicsConfigMain.cpp new file mode 100644 index 0000000000..886d6cff7d --- /dev/null +++ b/src/helics/apps/helicsConfigMain.cpp @@ -0,0 +1,150 @@ +/* +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 "helicsConfigMain.h" +#include +#include +#include + +using namespace boost::filesystem; + +static void show_usage (std::string const &name) +{ + std::cout << "Usage: " << name << " --prefix|--includes|--libs|--flags|--bin|--version|--help\n"; + std::cout << "--prefix returns the base install location\n"; + std::cout << "--includes, -I returns the helics include location\n"; + std::cout << "--libs, -L returns the helics library location\n"; + std::cout << "--flags returns the C++ flags used for compilation\n"; + std::cout << "--install returns the install location\n"; + std::cout << "--bin return the location of the binaries\n"; + std::cout << "--version returns the helics version\n"; + std::cout << "--std returns the C++ standard flag used\n"; + std::cout << "--help, -h, -? returns this help display\n"; + +} + +path dir_path(const char *filename, const char *tail) +{ + path cfile = system_complete(path(filename)); + path bin_dir = (cfile.has_parent_path()) ? cfile.parent_path() : current_path(); + path base_dir = bin_dir.parent_path(); + path dpath; + if (is_directory(base_dir / tail)) + { + dpath = base_dir / tail; + } + else if (base_dir.has_parent_path()) + { + if (is_directory(base_dir.parent_path() / tail)) + { + dpath=base_dir.parent_path()/tail; + } + else + { + dpath = path(HELICS_INSTALL_PREFIX) /tail; + } + } + else + { + dpath = path(HELICS_INSTALL_PREFIX) / tail; + } +#if BOOST_VERSION_LEVEL>0 + dpath = dpath.lexically_normal(); +#endif + return dpath.make_preferred(); +} + +path base_path( const char *filename) +{ + path cfile = system_complete(path(filename)); + path bin_dir = (cfile.has_parent_path()) ? cfile.parent_path() : current_path(); + path base_dir = bin_dir.parent_path(); + path dpath; + if (is_directory(base_dir / HELICS_INCLUDE_SUFFIX)) + { + dpath=base_dir; + } + else if (base_dir.has_parent_path()) + { + if (is_directory(base_dir.parent_path() / HELICS_INCLUDE_SUFFIX)) + { + dpath=base_dir.parent_path(); + } + else + { + dpath= path(HELICS_INSTALL_PREFIX); + } + } + else + { + dpath = path(HELICS_INSTALL_PREFIX); + } +#if BOOST_VERSION_LEVEL>0 + dpath = dpath.lexically_normal(); +#endif + return dpath.make_preferred(); +} + +int main (int argc, char *argv[]) +{ + if (argc < 2) + { + show_usage (argv[0]); + return 1; + } + + for (int ii = 1; ii < argc; ++ii) + { + std::string arg(argv[ii]); + if ((arg == "-h") || (arg == "--help") || (arg == "-?")) + { + show_usage (argv[0]); + } + else if (arg == "--version") + { + std::cout << HELICS_VERSION << '\n'; + } + else if (arg == "--prefix") + { + path bpath = base_path(argv[0]); +#if BOOST_VERSION_LEVEL>0 + bpath=bpath.lexically_normal(); +#endif + std::cout << bpath.make_preferred() << '\n'; + } + else if ((arg == "--includes") || (arg == "-I")||(arg=="--include")) + { + std::cout << dir_path(argv[0], HELICS_INCLUDE_SUFFIX) << '\n'; + } + else if ((arg == "--libs")||(arg=="-L")||(arg=="--lib")) + { + std::cout << dir_path(argv[0], HELICS_LIB_SUFFIX) << '\n'; + } + else if ((arg == "--bin")||(arg=="--binaries")) + { + std::cout << dir_path(argv[0], HELICS_BIN_SUFFIX) << '\n'; + } + else if (arg == "--install") + { + std::cout << base_path(argv[0]) << '\n'; + } + else if (arg == "--flags") + { + std::cout << HELICS_CXX_VERSION << " " << HELICS_CXX_FLAGS << '\n'; + } + else if ((arg == "--std")||(arg=="--standard")) + { + std::cout << HELICS_CXX_VERSION <<'\n'; + } + else + { + std::cerr << "Received unknown argument: " << arg << '\n'; + show_usage (argv[0]); + } + } + + return 0; +} diff --git a/src/helics/apps/helicsConfigMain.h.in b/src/helics/apps/helicsConfigMain.h.in new file mode 100644 index 0000000000..f0668b9c4a --- /dev/null +++ b/src/helics/apps/helicsConfigMain.h.in @@ -0,0 +1,16 @@ +/* +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. +*/ +#pragma once + +#define HELICS_INCLUDE_SUFFIX "${CMAKE_INSTALL_INCLUDEDIR}" +#define HELICS_BIN_SUFFIX "${CMAKE_INSTALL_BINDIR}" +#define HELICS_LIB_SUFFIX "${CMAKE_INSTALL_LIBDIR}" + +#define HELICS_VERSION "${HELICS_VERSION_STRING}" +#define HELICS_CXX_VERSION "${VERSION_OPTION}" +#define HELICS_CXX_FLAGS "${CMAKE_CXX_FLAGS}" +#define HELICS_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}" +#define BOOST_VERSION_LEVEL ${BOOST_VERSION_LEVEL} \ No newline at end of file diff --git a/src/helics/common/cppzmq/zmq.hpp b/src/helics/common/cppzmq/zmq.hpp index 9a14e67a0a..674b5496cf 100644 --- a/src/helics/common/cppzmq/zmq.hpp +++ b/src/helics/common/cppzmq/zmq.hpp @@ -412,21 +412,22 @@ proxy_steerable(void *frontend, void *backend, void *capture, void *control) */ inline std::string str() const { - // Partly mutuated from the same method in zmq::multipart_t + // Partly mutated from the same method in zmq::multipart_t std::stringstream os; const unsigned char *msg_data = this->data(); unsigned char byte; - size_t size = this->size(); + + size_t message_size = this->size(); int is_ascii[2] = {0, 0}; os << "zmq::message_t [size " << std::dec << std::setw(3) - << std::setfill('0') << size << "] ("; + << std::setfill('0') << message_size << "] ("; // Totally arbitrary - if (size >= 1000) { + if (message_size >= 1000) { os << "... too big to print)"; } else { - while (size--) { + while (message_size--) { byte = *msg_data++; is_ascii[1] = (byte >= 33 && byte < 127); diff --git a/src/helics/common/cppzmq/zmq_addon.hpp b/src/helics/common/cppzmq/zmq_addon.hpp index e0c0b6dcd7..7b985e9979 100644 --- a/src/helics/common/cppzmq/zmq_addon.hpp +++ b/src/helics/common/cppzmq/zmq_addon.hpp @@ -1,6 +1,6 @@ /* Copyright (c) 2016-2017 ZeroMQ community - Copyright (c) 2016 VOCA AS / Harald Nøkland + Copyright (c) 2016 VOCA AS / Harald Nøkland Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to @@ -38,7 +38,7 @@ namespace zmq /* This class handles multipart messaging. It is the C++ equivalent of zmsg.h, which is part of CZMQ (the high-level C binding). Furthermore, it is a major - improvement compared to zmsg.hpp, which is part of the examples in the ØMQ + improvement compared to zmsg.hpp, which is part of the examples in the ØMQ Guide. Unnecessary copying is avoided by using move semantics to efficiently add/remove parts. */ @@ -61,7 +61,7 @@ class multipart_t multipart_t(socket_t &socket) { recv(socket); } // Construct from memory block - multipart_t(const void *src, size_t size) { addmem(src, size); } + multipart_t(const void *src, size_t message_size) { addmem(src, message_size); } // Construct from string multipart_t(const std::string &string) { addstr(string); } @@ -164,15 +164,15 @@ class multipart_t } // Push memory block to front - void pushmem(const void *src, size_t size) + void pushmem(const void *src, size_t memsize) { - m_parts.push_front(message_t(src, size)); + m_parts.push_front(message_t(src, memsize)); } // Push memory block to back - void addmem(const void *src, size_t size) + void addmem(const void *src, size_t memsize) { - m_parts.push_back(message_t(src, size)); + m_parts.push_back(message_t(src, memsize)); } // Push string to front @@ -291,23 +291,24 @@ class multipart_t std::stringstream ss; for (size_t i = 0; i < m_parts.size(); i++) { const unsigned char *data = m_parts[i].data(); - size_t size = m_parts[i].size(); + size_t message_size = m_parts[i].size(); // Dump the message as text or binary bool isText = true; - for (size_t j = 0; j < size; j++) { + for (size_t j = 0; j < message_size; j++) { if (data[j] < 32 || data[j] > 127) { isText = false; break; } } - ss << "\n[" << std::dec << std::setw(3) << std::setfill('0') << size + ss << "\n[" << std::dec << std::setw(3) << std::setfill('0') << message_size << "] "; - if (size >= 1000) { + if (message_size >= 1000) { ss << "... (to big to print)"; continue; } - for (size_t j = 0; j < size; j++) { + for (size_t j = 0; j < message_size; j++) { + if (isText) ss << static_cast(data[j]); else From 845f2d1fec154ebb55a6b18695d71fa90709ad77 Mon Sep 17 00:00:00 2001 From: Philip Top Date: Thu, 24 May 2018 12:59:50 -0700 Subject: [PATCH 07/10] Yet more cmake updates (#325) * Add helicsConfigMain.cpp and helicsConfigMain.h.in Also update CMakeLists.txt to generate `helics-config` target * Pass name by reference instead * move some cmake configuration around, move broker executable to apps folder * move library cmake configuration to more sensible location * fix broken test by cmake changes * added BrokerApp, Still some work on getting it to play nicely with other apps * update HELICS config Issue #322 * update examples to use BrokerApp * a few fixes for travis builds and warnings * fix explicit issue in app constructors * fix a couple more warnings * fix gcc 4.9 warnings * try to fix more errors * allow compilation before boost 1.61 * actually use the required function for lexically_normal * clean up warning in signal generators * fix some issues with command lines so it works a little more consistently * working on some more cmake issues particularly around the dependencies and export * try using boost targets for better exportConfig this is the first step toward improving that significantly. * fix a few things in the addBoost.cmake * rework the mpi inclusion to be a target * actually use the correct target * update to addMPI so it works a little more reliably on windows * try disabling finding C compiler in cmake for buildJAR * add shebang line to scripts * update HELICSCOnfig.cmake.in to start to include finding ZMQ * add a system zmq only flag * lots of cmake updates to get installed config to work properly * fix some issues with finding ZMQ on non MSVC builds * change path to empty.cpp since the build instructions were moved * a few other minor updates and fixes * update package installer with some new details * Fix adding MPI target and installing directories when using system libraries * restrict zmq library install to windows platforms * add alias targets and cpp98 target in install * fix incorrect target specification * update install path * Fix ALIAS name capitalization for c++98 target) --- CMakeLists.txt | 131 +++++++++---------- config/HELICSConfig.cmake.in | 53 +++++++- config/cmake/FindZeroMQ.cmake | 86 +++++++++--- config/cmake/addBoost.cmake | 114 +++++++++++++++- config/cmake/addMPI.cmake | 79 +++++++---- config/cmake/addZeroMQ.cmake | 16 ++- config/cmake/buildlibZMQ.cmake | 6 +- config/cmake/configGenerator.cmake | 12 +- scripts/build_boost_clang.sh | 2 +- scripts/build_boost_gcc.sh | 2 +- src/helics/CMakeLists.txt | 6 +- src/helics/apps/CMakeLists.txt | 8 +- src/helics/cpp98/CMakeLists.txt | 8 +- src/helics/shared_api_library/CMakeLists.txt | 19 +-- swig/java/MakeJarCMakeLists.txt.in | 2 +- tests/helics/CMakeLists.txt | 2 +- tests/helics/application_api/CMakeLists.txt | 14 -- tests/helics/common/CMakeLists.txt | 2 - tests/helics/core/CMakeLists.txt | 8 +- 19 files changed, 384 insertions(+), 186 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 01a765b8de..05e028097c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,10 +13,17 @@ project (HELICS) set (HELICS_VERSION_MAJOR 1) set (HELICS_VERSION_MINOR 1) set (HELICS_VERSION_PATCH 0) -set (HELICS_VERSION_BUILD 0) +set (HELICS_VERSION_BUILD ) set (HELICS_DATE "05-09-18") -set (HELICS_VERSION "${HELICS_VERSION_MAJOR}.${HELICS_VERSION_MINOR}.${HELICS_VERSION_PATCH}") +if (NOT HELICS_VERSION_BUILD) + set (HELICS_VERSION "${HELICS_VERSION_MAJOR}.${HELICS_VERSION_MINOR}.${HELICS_VERSION_PATCH}") + set (HELICS_VERSION_UNDERSCORE "${HELICS_VERSION_MAJOR}_${HELICS_VERSION_MINOR}_${HELICS_VERSION_PATCH}") +else() + set (HELICS_VERSION "${HELICS_VERSION_MAJOR}.${HELICS_VERSION_MINOR}.${HELICS_VERSION_PATCH}-${HELICS_VERSION_BUILD}") + set (HELICS_VERSION_UNDERSCORE "${HELICS_VERSION_MAJOR}_${HELICS_VERSION_MINOR}_${HELICS_VERSION_PATCH}-${HELICS_VERSION_BUILD}") +endif() + set (HELICS_VERSION_STRING "${HELICS_VERSION} (${HELICS_DATE})") #----------------------------------------------------------------------------- @@ -31,14 +38,19 @@ include(extraMacros) if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) if (WIN32) if (MSYS) - set (CMAKE_INSTALL_PREFIX "/usr/local/helics_${HELICS_VERSION_MAJOR}_${HELICS_VERSION_MINOR}_${HELICS_VERSION_PATCH}/" CACHE PATH "default install path" FORCE ) + set (CMAKE_INSTALL_PREFIX "/usr/local/helics_${HELICS_VERSION_UNDERSCORE}/" CACHE PATH "default install path" FORCE ) else(MSYS) - set (CMAKE_INSTALL_PREFIX "C:/local/helics_${HELICS_VERSION_MAJOR}_${HELICS_VERSION_MINOR}_${HELICS_VERSION_PATCH}/" CACHE PATH "default install path" FORCE ) + set (CMAKE_INSTALL_PREFIX "C:/local/helics_${HELICS_VERSION_UNDERSCORE}/" CACHE PATH "default install path" FORCE ) endif(MSYS) endif(WIN32) endif() +SHOW_VARIABLE(AUTOBUILD_INSTALL_PATH PATH + "location to install the autobuild libraries and Headers" "${PROJECT_BINARY_DIR}/libs") + +FILE(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/logs) + OPTION(BUILD_HELICS_TESTS "Enable the test Executables to be built" ON) # enable testing if (BUILD_HELICS_TESTS) @@ -50,7 +62,7 @@ set_property(GLOBAL PROPERTY USE_FOLDERS ON) OPTION(BUILD_HELICS_EXAMPLES "Enable the example Executables to be built" ON) OPTION(BUILD_PYTHON_INTERFACE "Build Python extension" OFF) -OPTION(BUILD_PYTHON2_INTERFACE "Build Python2.7 extension(Requires swig and will not build if python interface is active)" OFF) +OPTION(BUILD_PYTHON2_INTERFACE "Build Python2.7 extension(Requires swig and will not build if \"PYTHON_INTERFACE\" is active)" OFF) OPTION(BUILD_MATLAB_INTERFACE "Build Matlab Extension" OFF) OPTION(BUILD_OCTAVE_INTERFACE "Build Octave extension (very experimental)" OFF) OPTION(BUILD_JAVA_INTERFACE "Build Java extension" OFF) @@ -65,11 +77,8 @@ else() SHOW_VARIABLE(BUILD_C_SHARED_LIB BOOL "Build the Shared Libraries with a C interface" ON) endif() - -#IF(NOT MSVC) - OPTION(BUILD_CXX_SHARED_LIB "Build a Shared Libraries of the CXX interface" OFF) - mark_as_advanced(BUILD_CXX_SHARED_LIB) -#ENDIF() +OPTION(BUILD_CXX_SHARED_LIB "Build a Shared Libraries of the CXX interface" OFF) +mark_as_advanced(BUILD_CXX_SHARED_LIB) if (INTERFACE_BUILD OR BUILD_C_SHARED_LIB OR BUILD_CXX_SHARED_LIB) set(BUILD_SHARED_LIBS ON) @@ -111,27 +120,6 @@ IF (VERSION_OPTION) ENDIF (MSVC) ENDIF(VERSION_OPTION) -IF(UNIX) - # Since default builds of boost library under Unix don't use - # CMake, turn off using CMake build and find include/libs the - # regular way. - set(Boost_NO_BOOST_CMAKE ON) - set(Boost_USE_MULTITHREADED OFF) # Needed if MT libraries not built - option (USE_BOOST_STATIC_LIBS "Build using boost static Libraries" OFF) -ELSE(UNIX) - IF(MSYS) - option (USE_BOOST_STATIC_LIBS "Build using boost static Libraries" OFF) - ELSE(MSYS) - #this will be MSYS or stand alone Mingw - option (USE_BOOST_STATIC_LIBS "Build using boost static Libraries" ON) - ENDIF(MSYS) -ENDIF(UNIX) - -IF (USE_BOOST_STATIC_LIBS) - set(Boost_USE_STATIC_LIBS ON) - set(BOOST_STATIC ON) -ENDIF () - # ------------------------------------------------------------- # add coverage target # ------------------------------------------------------------- @@ -155,7 +143,7 @@ if(BUILD_HELICS_TESTS) # Get some configuration for C++17 as that becomes available # ------------------------------------------------------------- #message(STATUS ${CMAKE_CXX_FLAGS}) -set(CONFIGURE_TARGET_LOCATION ${PROJECT_BINARY_DIR}/libs/include/helics/) +set(CONFIGURE_TARGET_LOCATION ${AUTOBUILD_INSTALL_PATH}/include/helics/) include(configGenerator) option (GENERATE_DOXYGEN_DOC "Generate Doxygen doc target" OFF) @@ -174,17 +162,15 @@ if (GENERATE_DOXYGEN_DOC) endif(DOXYGEN_FOUND) endif (GENERATE_DOXYGEN_DOC) -FILE(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/logs) - - # ------------------------------------------------------------- # BOOST find the boost libraries # ------------------------------------------------------------- +set(BOOST_REQUIRED_LIBRARIES program_options unit_test_framework filesystem system date_time timer chrono) include(addBoost) - +target_link_libraries(helics_base INTERFACE Boostlibs::core) # ------------------------------------------------------------- # finding MPI # ------------------------------------------------------------- @@ -194,7 +180,7 @@ IF (MPI_ENABLE) include(addMPI) if (MPI_C_FOUND) set(HELICS_HAVE_MPI TRUE) - target_link_libraries(helics_base INTERFACE ${MPI_C_LIBRARIES}) + target_link_libraries(helics_base INTERFACE MPI::MPI_C) else() set(HELICS_HAVE_MPI FALSE) endif (MPI_C_FOUND) @@ -207,7 +193,9 @@ ENDIF(MPI_ENABLE) # ------------------------------------------------------------- if (NOT WIN32) set(THREADS_PREFER_PTHREAD_FLAG ON) -endif(NOT WIN32) +elseif (MSYS) + set(THREADS_PREFER_PTHREAD_FLAG ON) +endif() find_package(Threads REQUIRED) target_link_libraries(helics_base INTERFACE Threads::Threads) @@ -217,7 +205,7 @@ IF (UNIX AND NOT APPLE) ENDIF() # ------------------------------------------------------------- -# check for some things with TCP core +# check for some things with TCP core and boost # ------------------------------------------------------------- IF(MSYS) if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") @@ -257,6 +245,9 @@ IF (ZeroMQ_ENABLE) endif() #message(STATUS "zmq dep ${ZeroMQ_DEPENDENCY}") target_link_libraries(helics_base INTERFACE ${ZeroMQ_DEPENDENCY}) + #get_target_properties(ZMQ_LOC ${ZeroMQ_DEPENDENCY} INTERFACE_INCLUDE_DIRECTORIES) + #get_filename_component(ZMQ_LOC_BASE ${ZMQ_LOC} DIRECTORY) + else(ZeroMQ_FOUND) set(HELICS_HAVE_ZEROMQ FALSE) endif(ZeroMQ_FOUND) @@ -267,15 +258,14 @@ IF (ZeroMQ_ENABLE) endif() ENDIF(ZeroMQ_ENABLE) -target_link_libraries(helics_base INTERFACE ${Boost_LIBRARIES_core}) # ------------------------------------------------------------- # global include directories # ------------------------------------------------------------- target_include_directories(helics_base_includes INTERFACE $ - $ - $ + $ + $ ) target_include_directories(helics_base_includes SYSTEM INTERFACE @@ -297,7 +287,7 @@ SET(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE) SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}") -SET(CMAKE_BUILD_RPATH "${CMAKE_BINARY_DIR}/libs/bin;${CMAKE_BINARY_DIR}/libs/lib") +SET(CMAKE_BUILD_RPATH "${AUTOBUILD_INSTALL_PATH}/bin;${AUTOBUILD_INSTALL_PATH}/lib;${AUTOBUILD_INSTALL_PATH}/lib64") # add the automatically determined parts of the RPATH # which point to directories outside the build tree to the install RPATH @@ -326,8 +316,8 @@ OPTION(BUILD_RECORDER "Build a helics recorder standalone executable" ON) OPTION(BUILD_APPS "Build helics application to run various apps" ON) -FILE(GLOB KEY_LIBRARY_FILES ${PROJECT_BINARY_DIR}/libs/bin/*) -message(STATUS "key files ${KEY_LIBRARY_FILES}") +FILE(GLOB KEY_LIBRARY_FILES ${AUTOBUILD_INSTALL_PATH}/bin/*) +#message(STATUS "key files ${KEY_LIBRARY_FILES}") OPTION(DISABLE_LOGGING "disable all normal, debug, and trace logging in HELICS" OFF) if (NOT DISABLE_LOGGING) @@ -361,6 +351,16 @@ endif(BUILD_HELICS_EXAMPLES) INSTALL(FILES ${KEY_LIBRARY_FILES} DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT runtime) + +install(DIRECTORY ${AUTOBUILD_INSTALL_PATH}/lib/ DESTINATION ${CMAKE_INSTALL_LIBDIR}/ OPTIONAL) +install(DIRECTORY ${AUTOBUILD_INSTALL_PATH}/lib64/ DESTINATION ${CMAKE_INSTALL_LIBDIR}/ OPTIONAL) + +if (HELICS_HAVE_ZEROMQ) + if (WIN32 AND NOT MSYS) + install(FILES $ DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libraries) + endif() +endif() + # ------------------------------------------------------------- # Enable clang analysis and formatting tools # ------------------------------------------------------------- @@ -403,39 +403,21 @@ ENDIF() set(HELICS_CMAKECONFIG_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}" CACHE STRING "install path for HELICSConfig.cmake") install (EXPORT helics-targets - NAMESPACE Helics:: + NAMESPACE HELICS:: DESTINATION ${HELICS_CMAKECONFIG_INSTALL_DIR} COMPONENT libs ) -set(helics_dependencies ${Boost_LIBRARIES_core}) - -IF (UNIX AND NOT APPLE) - list(APPEND helics_dependencies rt) -ENDIF() - -IF(MSYS) - list(APPEND helics_dependencies wsock32 ws2_32) -ENDIF(MSYS) - -if (HELICS_HAVE_ZEROMQ) - list(APPEND helics_dependencies ${ZeroMQ_DEPENDENCY}) -endif(HELICS_HAVE_ZEROMQ) - -if (HELICS_HAVE_MPI) - list(APPEND helics_dependencies ${MPI_C_LIBRARIES}) -endif(HELICS_HAVE_MPI) - #----------------------------------------------------------------------------- # Setup configure.h file for accessing configure options #----------------------------------------------------------------------------- configure_file ( "config/helics-config.h.in" - "${PROJECT_BINARY_DIR}/libs/include/helics/helics-config.h" + "${AUTOBUILD_INSTALL_PATH}/include/helics/helics-config.h" ) - install(FILES ${PROJECT_BINARY_DIR}/libs/include/helics/helics-config.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/helics + install(FILES ${AUTOBUILD_INSTALL_PATH}/include/helics/helics-config.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/helics COMPONENT headers) - install(FILES ${PROJECT_BINARY_DIR}/libs/include/helics/compiler-config.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/helics + install(FILES ${AUTOBUILD_INSTALL_PATH}/include/helics/compiler-config.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/helics COMPONENT headers) install(DIRECTORY ThirdParty/cereal DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} COMPONENT headers) @@ -459,10 +441,13 @@ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake DESTINATION ${HELICS_CMAKECONFIG_INSTALL_DIR} COMPONENT libs) - -if (CMAKE_INSTALL_PREFIX) - message(STATUS "Using CMAKE_INSTALL_PREFIX: " ${CMAKE_INSTALL_PREFIX}) -endif() +#install required additional cmake files +install(FILES config/cmake/addMPI.cmake + config/cmake/FindZeroMQ.cmake + config/cmake/addBoost.cmake + config/cmake/extraMacros.cmake + DESTINATION ${HELICS_CMAKECONFIG_INSTALL_DIR} + COMPONENT libs) # ------------------------------------------------------------- # CPack @@ -477,6 +462,7 @@ set(CPACK_PACKAGE_VERSION "${HELICS_VERSION}") set(CPACK_PACKAGE_VERSION_MAJOR ${HELICS_VERSION_MAJOR}) set(CPACK_PACKAGE_VERSION_MINOR ${HELICS_VERSION_MINOR}) set(CPACK_PACKAGE_VERSION_PATCH ${HELICS_VERSION_PATCH}) +set(CPACK_PACKAGE_INSTALL_REGISTRY_KEY "HELICS") set(CPACK_COMPONENTS_ALL applications headers libs runtime matlab python java octave) if (WIN32) @@ -506,12 +492,13 @@ set(CPACK_COMPONENT_APPLICATIONS_DISPLAY_NAME "Application") set(CPACK_COMPONENT_LIBS_DEPENDS headers) set(CPACK_COMPONENT_RUNTIME_REQUIRED ON) - set(CPACK_PACKAGE_EXECUTABLES "helics_broker" "Helics Broker" "helics_app" "Helics app executable") + set(CPACK_PACKAGE_EXECUTABLES "helics_broker" "Helics Broker" "helics_app" "Helics app executable" "helics_recorder" "Helics recorder" "helics_player" "Helics Player") if (WIN32) set(CPACK_PACKAGE_ICON "${CMAKE_SOURCE_DIR}\\\\docs\\\\img\\\\HELICS.ico") set(CPACK_NSIS_MUI_ICON "${CMAKE_SOURCE_DIR}/docs/img/HELICS.ico") set(CPACK_NSIS_INSTALL_ROOT "C:\\\\local\\\\") set(CPACK_NSIS_URL_INFO_ABOUT "https://www.github.com/GMLC-TDC/Helics-src") + set(CPACK_NSIS_CONTACT "helicsteam@helics.org") set(CPACK_NSIS_MENU_LINKS "https://www.github.com/GMLC-TDC/Helics-src" "HELICS Github" "https://gmlc-tdc.github.io/HELICS-src/" "Helics Documentation" diff --git a/config/HELICSConfig.cmake.in b/config/HELICSConfig.cmake.in index 2e9e15478e..dfc3272d0a 100644 --- a/config/HELICSConfig.cmake.in +++ b/config/HELICSConfig.cmake.in @@ -31,8 +31,6 @@ endif() set(${PN}_STATIC_LIBRARY "${PACKAGE_PREFIX_DIR}/@CMAKE_INSTALL_LIBDIR@/@helics_static_file@") set(${PN}_STATIC_LIBRARY_DEBUG "${PACKAGE_PREFIX_DIR}/@CMAKE_INSTALL_LIBDIR@/@helics_static_file_debug@") -set(${PN}_DEPENDENCIES "@helics_dependencies@") - find_program(HELICS_PLAYER helics_player PATH ${PACKAGE_PREFIX_DIR}/@CMAKE_INSTALL_BINDIR@ NO_DEFAULT_PATH) @@ -49,10 +47,55 @@ find_program(HELICS_BROKER helics_broker PATH ${PACKAGE_PREFIX_DIR}/@CMAKE_INSTALL_BINDIR@ NO_DEFAULT_PATH) - -set(THREADS_PREFER_PTHREAD_FLAG ON) -find_package(Threads REQUIRED) +set(HELICS_HAVE_ZEROMQ @HELICS_HAVE_ZEROMQ) +set(HELICS_HAVE_MPI @HELICS_HAVE_MPI) + +set(CMAKE_MODULE_PATH ${PACKAGE_PREFIX_DIR}/@HELICS_CMAKECONFIG_INSTALL_DIR@) + +include(CMakeFindDependencyMacro) + +include(extraMacros) + +if (NOT Boostlibs::core) + include(addBoost) +endif() + +if (HELICS_HAVE_ZEROMQ) + if (NOT libzmq) + set(ZeroMQ_LIBRARY_ONLY ON) + set(ZeroMQ_INSTALL_PATH ${PACKAGE_PREFIX_DIR}) + find_dependency(ZeroMQ) + endif() +endif() + +if (HELICS_HAVE_MPI) + if (NOT MPI::MPI_C) + include(addMPI) + endif() +endif() + +#find_dependency(ZeroMQ) + +if (NOT Threads::Threads) + if (NOT WIN32) + set(THREADS_PREFER_PTHREAD_FLAG ON) + elseif (MSYS) + set(THREADS_PREFER_PTHREAD_FLAG ON) + endif() + find_dependency(Threads REQUIRED) +endif() + include(${CMAKE_CURRENT_LIST_DIR}/helics-targets.cmake) +if (HELICS::helicsSharedLib) +add_library(HELICS::helicsCpp98 INTERFACE) +target_include_directories(HELICS::helicsCpp98 INTERFACE "${PACKAGE_PREFIX_DIR}/@CMAKE_INSTALL_INCLUDEDIR@/cpp98") +target_link_libraries(HELICS::helicsCpp98 INTERFACE HELICS::helicsSharedLib) + +set_target_properties(Helics::helicsSharedLib PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${PACKAGE_PREFIX_DIR}/@CMAKE_INSTALL_INCLUDEDIR@/helics/shared_api_library" +) +endif() + check_required_components(${PN}) diff --git a/config/cmake/FindZeroMQ.cmake b/config/cmake/FindZeroMQ.cmake index 375af0a423..1b099e7727 100644 --- a/config/cmake/FindZeroMQ.cmake +++ b/config/cmake/FindZeroMQ.cmake @@ -10,6 +10,8 @@ # ZeroMQ_LIBRARY, the library needed to use ZeroMQ # ZeroMQ_FOUND, if false, you cannot build anything that requires ZeroMQ. # ZeroMQ_SHARED_LIB the shared library that needs to be associated with the executable +# adds targets for libzmq and libzmq-static + set(ZeroMQ_FOUND 0) set(ZeroMQ_REGISTRY_PATH @@ -46,22 +48,25 @@ if (MSVC) string(REGEX REPLACE "\\." "_" ZeroMQ_NAME ${ZeroMQ_NAME}) # Get Visual studio version number - #message(STATUS "toolset =${CMAKE_VS_PLATFORM_TOOLSET}") if (${ZeroMQ_NAME} MATCHES "registry") # if key was not found, the string "registry" is returned set(_ZeroMQ_VERSIONS "4_2_5" "4_2_4" "4_2_3" "4_2_2" "4_2_1" "4_2_0" "4_1_5" "4_1_4" "4_0_4" "4_0_3" "4_0_2" "4_0_1" "4_0_0") set(ZeroMQ_LIBRARY_NAME) - - foreach(ver ${_ZeroMQ_VERSIONS}) - list(APPEND ZeroMQ_LIBRARY_NAME "libzmq-${CMAKE_VS_PLATFORM_TOOLSET}-mt-${ver}") - endforeach() + foreach(ver ${_ZeroMQ_VERSIONS}) + list(APPEND ZeroMQ_LIBRARY_NAME "libzmq-${CMAKE_VS_PLATFORM_TOOLSET}-mt-${ver}") + endforeach() + foreach(ver ${_ZeroMQ_VERSIONS}) + list(APPEND ZeroMQ_DEBUG_LIBRARY_NAME "libzmq-${CMAKE_VS_PLATFORM_TOOLSET}-mt-gd-${ver}") + endforeach() else() # Format ZeroMQ library file name - - foreach(vs ${_VS_VERSIONS}) - set(ZeroMQ_LIBRARY_NAME "libzmq-v${CMAKE_VS_PLATFORM_TOOLSET}-mt-${ZeroMQ_NAME}") - endforeach() + foreach(vs ${_VS_VERSIONS}) + set(ZeroMQ_LIBRARY_NAME "libzmq-v${CMAKE_VS_PLATFORM_TOOLSET}-mt-${ZeroMQ_NAME}") + endforeach() + foreach(vs ${_VS_VERSIONS}) + set(ZeroMQ_DEBUG_LIBRARY_NAME "libzmq-v${CMAKE_VS_PLATFORM_TOOLSET}-mt-gd-${ZeroMQ_NAME}") + endforeach() endif() endif() find_library(ZeroMQ_LIBRARY @@ -72,26 +77,67 @@ find_library(ZeroMQ_LIBRARY HINTS "${ZeroMQ_ROOT_DIR}/lib" "${ZeroMQ_INSTALL_PATH}/lib" + "${ZeroMQ_INSTALL_PATH}/bin" ${ZeroMQ_PATH2}/lib "${ZeroMQ_LIBRARY_PATH}" PATHS /lib /usr/lib /usr/local/lib +) +if (MSVC) +find_library(ZeroMQ_DEBUG_LIBRARY + NAMES + ${ZeroMQ_DEBUG_LIBRARY_NAME} +HINTS + "${ZeroMQ_ROOT_DIR}/lib" + "${ZeroMQ_INSTALL_PATH}/lib" + "${ZeroMQ_INSTALL_PATH}/bin" + ${ZeroMQ_PATH2}/lib + "${ZeroMQ_LIBRARY_PATH}" + PATHS + /lib + /usr/lib + /usr/local/lib ) -if (ZeroMQ_INCLUDE_DIR AND ZeroMQ_LIBRARY AND NOT ZeroMQ_LIBRARY-NOTFOUND) - set(ZeroMQ_FOUND 1) - message(STATUS "Found ZeroMQ library: ${ZeroMQ_LIBRARY}") - message(STATUS "Found ZeroMQ headers: ${ZeroMQ_INCLUDE_DIR}") - #this is static because we are pointing to the library for the linker, not the shared object - add_library(libzmq STATIC IMPORTED) - set_target_properties(libzmq PROPERTIES IMPORTED_LOCATION "${ZeroMQ_LIBRARY}") - set_target_properties(libzmq PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${ZeroMQ_INCLUDE_DIR}") +endif() + +if (ZeroMQ_LIBRARY_ONLY) #don't worry about the header files, just need the linking library + if (ZeroMQ_LIBRARY AND NOT ZeroMQ_LIBRARY-NOTFOUND) + set(ZeroMQ_FOUND 1) + #this is static because we are pointing to the library for the linker, not the shared object + add_library(libzmq STATIC IMPORTED) + if (ZeroMQ_DEBUG_LIBRARY) + set_target_properties(libzmq PROPERTIES IMPORTED_LOCATION_RELEASE "${ZeroMQ_LIBRARY}") + set_target_properties(libzmq PROPERTIES IMPORTED_LOCATION_DEBUG "${ZeroMQ_DEBUG_LIBRARY}") + else(ZeroMQ_DEBUG_LIBRARY) + set_target_properties(libzmq PROPERTIES IMPORTED_LOCATION "${ZeroMQ_LIBRARY}") + endif(ZeroMQ_DEBUG_LIBRARY) + else() + IF(NOT ZeroMQ_FIND_QUIETLY) + message(SEND_ERROR "Could not find ZeroMQ libraries/headers! Please install ZeroMQ with libraries and headers") + ENDIF(NOT ZeroMQ_FIND_QUIETLY) + endif() else() -IF(NOT ZeroMQ_FIND_QUIETLY) - message(SEND_ERROR "Could not find ZeroMQ libraries/headers! Please install ZeroMQ with libraries and headers") - ENDIF(NOT ZeroMQ_FIND_QUIETLY) + if (ZeroMQ_INCLUDE_DIR AND ZeroMQ_LIBRARY AND NOT ZeroMQ_LIBRARY-NOTFOUND) + set(ZeroMQ_FOUND 1) + message(STATUS "Found ZeroMQ library: ${ZeroMQ_LIBRARY}") + message(STATUS "Found ZeroMQ headers: ${ZeroMQ_INCLUDE_DIR}") + #this is static because we are pointing to the library for the linker, not the shared object + add_library(libzmq STATIC IMPORTED) + if (ZeroMQ_DEBUG_LIBRARY) + set_target_properties(libzmq PROPERTIES IMPORTED_LOCATION_RELEASE "${ZeroMQ_LIBRARY}") + set_target_properties(libzmq PROPERTIES IMPORTED_LOCATION_DEBUG "${ZeroMQ_DEBUG_LIBRARY}") + else(ZeroMQ_DEBUG_LIBRARY) + set_target_properties(libzmq PROPERTIES IMPORTED_LOCATION "${ZeroMQ_LIBRARY}") + endif(ZeroMQ_DEBUG_LIBRARY) + set_target_properties(libzmq PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${ZeroMQ_INCLUDE_DIR}") + else() + IF(NOT ZeroMQ_FIND_QUIETLY) + message(SEND_ERROR "Could not find ZeroMQ libraries/headers! Please install ZeroMQ with libraries and headers") + ENDIF(NOT ZeroMQ_FIND_QUIETLY) + endif() endif() # show the ZeroMQ_INCLUDE_DIR and ZeroMQ_LIBRARY variables only in the advanced view mark_as_advanced(ZeroMQ_ROOT_DIR ZeroMQ_INCLUDE_DIR ZeroMQ_LIBRARY ZeroMQ_FOUND) diff --git a/config/cmake/addBoost.cmake b/config/cmake/addBoost.cmake index c44d28e7c3..60adaae744 100644 --- a/config/cmake/addBoost.cmake +++ b/config/cmake/addBoost.cmake @@ -1,4 +1,33 @@ +############################################################################## +#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. +############################################################################## + SHOW_VARIABLE(BOOST_INSTALL_PATH PATH "Boost root directory" "${BOOST_INSTALL_PATH}") + +IF(UNIX) + # Since default builds of boost library under Unix don't use + # CMake, turn off using CMake build and find include/libs the + # regular way. + set(Boost_NO_BOOST_CMAKE ON) + set(Boost_USE_MULTITHREADED OFF) # Needed if MT libraries not built + option (USE_BOOST_STATIC_LIBS "Build using boost static Libraries" OFF) +ELSE(UNIX) + IF(MSYS) + option (USE_BOOST_STATIC_LIBS "Build using boost static Libraries" OFF) + ELSE(MSYS) + #this will be MSYS or stand alone Mingw + option (USE_BOOST_STATIC_LIBS "Build using boost static Libraries" ON) + ENDIF(MSYS) +ENDIF(UNIX) + +IF (USE_BOOST_STATIC_LIBS) + set(Boost_USE_STATIC_LIBS ON) + set(BOOST_STATIC ON) +ENDIF () + + IF (MSVC) set (boost_versions @@ -50,12 +79,14 @@ ELSE(MSVC) set(BOOST_ROOT "${BOOST_INSTALL_PATH}") ENDIF(MSVC) - +if (NOT BOOST_REQUIRED_LIBRARIES) +set(BOOST_REQUIRED_LIBRARIES program_options unit_test_framework filesystem system date_time timer chrono) +endif() # Minimum version of Boost required for building HELICS set(BOOST_MINIMUM_VERSION 1.58) set(Boost_USE_STATIC_LIBS ${USE_BOOST_STATIC_LIBS}) -find_package(Boost ${BOOST_MINIMUM_VERSION} COMPONENTS program_options unit_test_framework filesystem system date_time timer chrono REQUIRED) +find_package(Boost ${BOOST_MINIMUM_VERSION} COMPONENTS ${BOOST_REQUIRED_LIBRARIES} REQUIRED) # Minimum version of Boost required for building test suite if (Boost_VERSION LESS 106100) @@ -85,13 +116,86 @@ foreach(loop_var ${Boost_LIBRARIES}) else() list(APPEND Boost_LIBRARIES_core ${modifier} ${loop_var}) endif() + if (${modifier} MATCHES "debug") + if(${loop_var} MATCHES "unit_test") + list(APPEND Boost_LIBRARIES_test_debug ${loop_var}) + else() + list(APPEND Boost_LIBRARIES_core_debug ${loop_var}) + endif() + else() + if(${loop_var} MATCHES "unit_test") + list(APPEND Boost_LIBRARIES_test_release ${loop_var}) + else() + list(APPEND Boost_LIBRARIES_core_release ${loop_var}) + endif() + endif() list(LENGTH modifier modifier_size) if (modifier_size GREATER 0) - list(REMOVE_AT modifier -1) + list(REMOVE_AT modifier -1) endif() endif() endforeach(loop_var) -#message(STATUS "Using Boost core libraries : ${Boost_LIBRARIES_core}") -#message(STATUS "Using Boost test libraries : ${Boost_LIBRARIES_test}") +############################################################ +# Add boost targets to use +##################################################### + +if (${Boost_USE_STATIC_LIBS}) + add_library(Boostlibs::core STATIC IMPORTED) + add_library(Boostlibs::test STATIC IMPORTED) +else() + add_library(Boostlibs::core UNKNOWN IMPORTED) + add_library(Boostlibs::test UNKNOWN IMPORTED) +endif() + +list(LENGTH Boost_LIBRARIES_core_debug core_debug_size) +list(LENGTH Boost_LIBRARIES_core_release core_release_size) + +math(EXPR rng "${core_release_size} - 1") + +if (core_debug_size EQUAL 0) + list(GET Boost_LIBRARIES_core_release 0 first_lib) + set_target_properties(Boostlibs::core PROPERTIES IMPORTED_LOCATION ${first_lib}) + + foreach(item RANGE 1 ${rng}) + list(GET Boost_LIBRARIES_core_release ${item} next_lib) + string(RANDOM LENGTH 7 rand_name) + if (${Boost_USE_STATIC_LIBS}) + add_library(Boostlibs::${rand_name} STATIC IMPORTED) + else() + add_library(Boostlibs::${rand_name} UNKNOWN IMPORTED) + endif() + set_target_properties(Boostlibs::${rand_name} PROPERTIES IMPORTED_LOCATION ${next_lib}) + list(APPEND boost_core_deps Boostlibs::${rand_name}) + endforeach() +else() + list(GET Boost_LIBRARIES_core_release 0 first_lib_r) + list(GET Boost_LIBRARIES_core_debug 0 first_lib_d) + set_target_properties(Boostlibs::core PROPERTIES IMPORTED_LOCATION_DEBUG ${first_lib_d} IMPORTED_LOCATION_RELEASE ${first_lib_r}) + + foreach(item RANGE 1 ${rng}) + list(GET Boost_LIBRARIES_core_release ${item} next_lib_r) + list(GET Boost_LIBRARIES_core_debug ${item} next_lib_d) + string(RANDOM LENGTH 7 rand_name) + if (${Boost_USE_STATIC_LIBS}) + add_library(Boostlibs::${rand_name} STATIC IMPORTED) + else() + add_library(Boostlibs::${rand_name} UNKNOWN IMPORTED) + endif() + set_target_properties(Boostlibs::${rand_name} PROPERTIES IMPORTED_LOCATION_DEBUG ${next_lib_d} IMPORTED_LOCATION_RELEASE ${next_lib_r}) + list(APPEND boost_core_deps Boostlibs::${rand_name}) + endforeach() +endif() + +set_target_properties(Boostlibs::core Boostlibs::test PROPERTIES INTERFACE_SYSTEM_INCLUDE_DIRECTORIES ${Boost_INCLUDE_DIR}) +set_target_properties(Boostlibs::core PROPERTIES INTERFACE_LINK_LIBRARIES "${boost_core_deps}") + +if (Boost_LIBRARIES_test_debug) + set_target_properties(Boostlibs::test PROPERTIES IMPORTED_LOCATION_DEBUG "${Boost_LIBRARIES_test_debug}" IMPORTED_LOCATION_RELEASE "${Boost_LIBRARIES_test_release}") +else() + set_target_properties(Boostlibs::test PROPERTIES IMPORTED_LOCATION "${Boost_LIBRARIES_test_release}") +endif() + +#message(STATUS "Using Boost core debug libraries : ${Boost_LIBRARIES_core_debug}") +#message(STATUS "Using Boost core release libraries : ${Boost_LIBRARIES_core_release}") diff --git a/config/cmake/addMPI.cmake b/config/cmake/addMPI.cmake index 5e7eeb5f65..42f71b0c20 100644 --- a/config/cmake/addMPI.cmake +++ b/config/cmake/addMPI.cmake @@ -15,37 +15,62 @@ #All rights reserved. See LICENSE file and DISCLAIMER for more details. ############################################################################## find_package(MPI) -if(MSVC) +if (NOT MPI_C_FOUND) +if(MSVC) #the cmake find MPI doesn't completely work for visual studio 2017 if (NOT MPI_CXX_COMPILER) message(STATUS "not mpi cxx compiler") # For building MPI programs the selected Visual Studio compiler is used, #namely cl.exe. # So there is no need to set a specific MPI compiler. - set(MPI_CXX_COMPILER "${CMAKE_CXX_COMPILER}" CACHE FILEPATH "Mpi cxx compiler" FORCE) - set(MPI_C_COMPILER "${CMAKE_C_COMPILER}" CACHE FILEPATH "Mpi c compiler" FORCE) + set(MPI_CXX_COMPILER "${CMAKE_CXX_COMPILER}" CACHE FILEPATH "Mpi CXX compiler" FORCE) + set(MPI_C_COMPILER "${CMAKE_C_COMPILER}" CACHE FILEPATH "Mpi C compiler" FORCE) endif(NOT MPI_CXX_COMPILER) - - #message(STATUS "mpi lib ${MPI_C_LIBRARIES} CXX ${MPI_CXX_LIBRARIES}") - #This is for finding MS-MPI. - #set(_MPI_PREFIX_PATH) - #list(APPEND _MPI_PREFIX_PATH - #"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\MPI;Path]/..") - # set(MPIEXEC "C:/Program Files/Microsoft MPI/Bin/mpiexec.exe") - - - #set(MPI_CXX_INCLUDE_PATH "C:/Program Files (x86)/Microsoft SDKs/MPI/Include") - # Make sure the correct libraries (64-bit or 32-bit) are selected. - # Decide between 32-bit and 64-bit libraries for Microsoft's MPI - # if("${CMAKE_SIZEOF_VOID_P}" EQUAL 8) - # set(MS_MPI_ARCH_DIR x64) - #else() - # set(MS_MPI_ARCH_DIR x86) - # endif() - #set(MPI_CXX_LIBRARIES "C:/Program Files (x86)/Microsoft SDKs/MPI/Lib/${MS_MPI_ARCH_DIR}/msmpi.lib") - - # set(MPI_C_LIBRARIES "{${MPI_CXX_LIBRARIES}") -# set(MPI_C_FOUND YES) - #set(MPI_CXX_FOUND YES) -# endif() -endif() \ No newline at end of file + if (MPIEXEC_EXECUTABLE) #if we found this then the target was found + if (NOT MPI_C_LIBRARIES) + if (MPI_msmpi_LIBRARY) + set(MPI_C_LIBRARIES ${MPI_msmpi_LIBRARY} CACHE STRING "MPI C libraries" FORCE) + else() + #TODO not sure how MPICH libraries are laid out on Windows + endif() + endif() + set(MPI_C_FOUND TRUE CACHE BOOL "MPI C FOUND" FORCE) + endif() +endif() +endif() +############################################################ +# Add targets to use +############################################################ +if (NOT MPI::MPI_C) + if (NOT TARGET MPI::MPI_C) + if(MPI_C_LIBRARIES) + + add_library(MPI::MPI_C STATIC IMPORTED) + + set_property(TARGET MPI::MPI_C PROPERTY INTERFACE_LINK_LIBRARIES "") + if(MPI_C_LINK_FLAGS) + set_property(TARGET MPI::MPI_C APPEND PROPERTY INTERFACE_LINK_LIBRARIES "${MPI_C_LINK_FLAGS}") + endif() + set_target_properties(MPI::MPI_C PROPERTIES IMPORT_LOCATION "${MPI_C_LIBRARIES}") + else() + add_library(MPI::MPI_C INTERFACE IMPORTED) + + set_property(TARGET MPI::MPI_C PROPERTY INTERFACE_LINK_LIBRARIES "") + if(MPI_C_LINK_FLAGS) + set_property(TARGET MPI::MPI_C APPEND PROPERTY INTERFACE_LINK_LIBRARIES "${MPI_C_LINK_FLAGS}") + endif() + endif() + else() + set_target_properties(MPI::MPI_C PROPERTIES INTERFACE_LINK_LIBRARIES "") + if(MPI_C_LINK_FLAGS) + set_property(TARGET MPI::MPI_C APPEND PROPERTY INTERFACE_LINK_LIBRARIES "${MPI_C_LINK_FLAGS}") + endif() + if(MPI_C_LIBRARIES) + set_property(TARGET MPI::MPI_C APPEND PROPERTY INTERFACE_LINK_LIBRARIES "${MPI_C_LIBRARIES}") + endif() + endif() + set_target_properties(MPI::MPI_C PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${MPI_C_INCLUDE_DIR};${MPI_C_HEADER_DIR};${MPI_C_ADDITIONAL_INCLUDE_DIRS}") + set_target_properties(MPI::MPI_C PROPERTIES INTERFACE_COMPILE_OPTIONS "${MPI_C_COMPILE_OPTIONS}") + set_target_properties(MPI::MPI_C PROPERTIES INTERFACE_COMPILE_DEFINITIONS "${MPI_C_COMPILE_DEFINITIONS}") + +endif() diff --git a/config/cmake/addZeroMQ.cmake b/config/cmake/addZeroMQ.cmake index 0be18ad36d..1260271ab0 100644 --- a/config/cmake/addZeroMQ.cmake +++ b/config/cmake/addZeroMQ.cmake @@ -7,7 +7,7 @@ OPTION(ZMQ_USE_STATIC_LIBRARY "use the ZMQ static library" OFF) SHOW_VARIABLE(ZeroMQ_INSTALL_PATH PATH - "path to the zmq libraries" "${PROJECT_BINARY_DIR}/libs") + "path to the zmq libraries" "${AUTOBUILD_INSTALL_PATH}") set(ZMQ_CMAKE_SUFFIXES cmake/ZeroMQ @@ -26,7 +26,7 @@ else() find_package(ZeroMQ QUIET HINTS ${ZeroMQ_INSTALL_PATH} - ${PROJECT_BINARY_DIR}/libs/ + ${AUTOBUILD_INSTALL_PATH} PATH_SUFFIXES ${ZMQ_CMAKE_SUFFIXES} NO_SYSTEM_ENVIRONMENT_PATH NO_CMAKE_PACKAGE_REGISTRY @@ -37,28 +37,32 @@ endif() if (NOT ZeroMQ_FOUND) - message(STATUS "initialZMQ not found") + #message(STATUS "initialZMQ not found") if (ZMQ_USE_STATIC_LIBRARY OR AUTOBUILD_ZMQ) include(buildlibZMQ) build_libzmq() find_package(ZeroMQ HINTS ${ZeroMQ_INSTALL_PATH} - ${PROJECT_BINARY_DIR}/libs/ + ${AUTOBUILD_INSTALL_PATH} PATH_SUFFIXES ${ZMQ_CMAKE_SUFFIXES} ) else() set(ZeroMQ_FIND_QUIETLY ON) find_package(ZeroMQ) if (NOT ZeroMQ_FOUND) - OPTION(AUTOBUILD_ZMQ "enable ZMQ to automatically download and build" ON) + if (WIN32 AND NOT MSYS) + OPTION(AUTOBUILD_ZMQ "enable ZMQ to automatically download and build" ON) + else() + OPTION(AUTOBUILD_ZMQ "enable ZMQ to automatically download and build" OFF) + endif() IF (AUTOBUILD_ZMQ) include(buildlibZMQ) build_libzmq() find_package(ZeroMQ HINTS ${ZeroMQ_INSTALL_PATH} - ${PROJECT_BINARY_DIR}/libs/ + ${AUTOBUILD_INSTALL_PATH} PATH_SUFFIXES ${ZMQ_CMAKE_SUFFIXES} ) ENDIF(AUTOBUILD_ZMQ) diff --git a/config/cmake/buildlibZMQ.cmake b/config/cmake/buildlibZMQ.cmake index babf7040ff..9866eb81e9 100644 --- a/config/cmake/buildlibZMQ.cmake +++ b/config/cmake/buildlibZMQ.cmake @@ -3,7 +3,7 @@ # Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC #All rights reserved. See LICENSE file and DISCLAIMER for more details. ############################################################################## -# This function is used to force a build on a dependant project at cmake configuration phase. +# This function is used to force a build on a dependent project at CMAKE configuration phase. # function (build_libzmq) @@ -61,7 +61,7 @@ ExternalProject_Add(libzmq CMAKE_ARGS -DCMAKE_CXX_COMPILER=${cxx_compiler_string} -DCMAKE_C_COMPILER=${c_compiler_string} - -DCMAKE_INSTALL_PREFIX=${PROJECT_BINARY_DIR}/libs + -DCMAKE_INSTALL_PREFIX=${AUTOBUILD_INSTALL_PATH} -DCMAKE_BUILD_TYPE=\$\{CMAKE_BUILD_TYPE\} -DZMQ_BUILD_TESTS=OFF -DENABLE_CURVE=OFF @@ -73,7 +73,7 @@ ExternalProject_Add(libzmq -DENABLE_CPACK=OFF -DLIBZMQ_PEDANTIC=OFF -DWITH_PERF_TOOL=OFF - -DZEROMQ_CMAKECONFIG_INSTALL_DIR=${PROJECT_BINARY_DIR}/libs/cmake/ZeroMQ + -DZEROMQ_CMAKECONFIG_INSTALL_DIR=${AUTOBUILD_INSTALL_PATH}/cmake/ZeroMQ INSTALL_DIR ${PROJECT_BINARY_DIR}/libs )") diff --git a/config/cmake/configGenerator.cmake b/config/cmake/configGenerator.cmake index a1609b6b9a..9cb75dff34 100644 --- a/config/cmake/configGenerator.cmake +++ b/config/cmake/configGenerator.cmake @@ -11,7 +11,7 @@ if ( MSVC ) set(WERROR_FLAG "/W4 /WX") else( MSVC ) -set(WERROR_FLAG "-Werror") + set(WERROR_FLAG "-Werror") endif ( MSVC ) @@ -95,11 +95,11 @@ endif() if (NOT NO_CONFIG_GENERATION) -if (CONFIGURE_TARGET_LOCATION) -CONFIGURE_FILE(${CMAKE_CURRENT_LIST_DIR}/compiler-config.h.in ${CONFIGURE_TARGET_LOCATION}/compiler-config.h) -else() -CONFIGURE_FILE(${CMAKE_CURRENT_LIST_DIR}/compiler-config.h.in ${PROJECT_BINARY_DIR}/compiler-config.h) -endif() + if (CONFIGURE_TARGET_LOCATION) + CONFIGURE_FILE(${CMAKE_CURRENT_LIST_DIR}/compiler-config.h.in ${CONFIGURE_TARGET_LOCATION}/compiler-config.h) + else() + CONFIGURE_FILE(${CMAKE_CURRENT_LIST_DIR}/compiler-config.h.in ${PROJECT_BINARY_DIR}/compiler-config.h) + endif() endif(NOT NO_CONFIG_GENERATION) diff --git a/scripts/build_boost_clang.sh b/scripts/build_boost_clang.sh index 800305c311..b72a202ee0 100755 --- a/scripts/build_boost_clang.sh +++ b/scripts/build_boost_clang.sh @@ -1,4 +1,4 @@ - +#!/usr/bin/env bash localdir=$(pwd) #change to wherever boost was downloaded diff --git a/scripts/build_boost_gcc.sh b/scripts/build_boost_gcc.sh index 1d1650cd82..660ef1d063 100755 --- a/scripts/build_boost_gcc.sh +++ b/scripts/build_boost_gcc.sh @@ -1,4 +1,4 @@ -#!/usr/bin/sh +#!/usr/bin/env bash localdir=$(pwd) diff --git a/src/helics/CMakeLists.txt b/src/helics/CMakeLists.txt index b39e7dbd7c..b0386ac614 100644 --- a/src/helics/CMakeLists.txt +++ b/src/helics/CMakeLists.txt @@ -19,19 +19,21 @@ add_library(helics-static STATIC ) target_link_libraries(helics-static PUBLIC helics_base) - +#add and alias library to match the find_package +add_library(HELICS::helics-static ALIAS helics-static) IF(BUILD_CXX_SHARED_LIB) #if (BUILD_C_SHARED_LIB OR INTERFACE_BUILD) # message(WARNING "Building the CXX shared library and C shared library in the same build is not advisable due to conflicting symbol visibility guidelines and is unlikely to work very well") #endif() add_library(helics-shared SHARED - src/empty.cpp + ../empty.cpp $ $ $ ) + add_library(HELICS::helics-shared ALIAS helics-shared) target_link_libraries(helics-shared PRIVATE helics_base) if (WIN32) diff --git a/src/helics/apps/CMakeLists.txt b/src/helics/apps/CMakeLists.txt index 3d934ff41a..7c11c31bb6 100644 --- a/src/helics/apps/CMakeLists.txt +++ b/src/helics/apps/CMakeLists.txt @@ -36,6 +36,8 @@ set(helics_apps_library_files add_library(helics_apps-static STATIC ${helics_apps_library_files} ${helics_apps_public_headers} ${helics_apps_private_headers}) target_link_libraries(helics_apps-static PUBLIC helics-static) +#add and alias library to match the find_package +add_library(HELICS::helics_apps-static ALIAS helics_apps-static) if (BUILD_PLAYER) add_executable(helics_player playerMain.cpp) @@ -93,8 +95,10 @@ add_executable(helics-config helicsConfigMain.cpp ${CMAKE_CURRENT_BINARY_DIR}/he target_include_directories(helics-config PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) set_target_properties (helics-config PROPERTIES FOLDER apps) -target_link_libraries(helics-config PRIVATE ${Boost_LIBRARIES_core}) -target_include_directories(helics-config SYSTEM PRIVATE ${Boost_INCLUDE_DIRS}) + +target_link_libraries(helics-config PUBLIC Boostlibs::core) +target_include_directories(helics-config SYSTEM PRIVATE ${Boost_INCLUDE_DIR}) + install(TARGETS helics-config RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT libs ) diff --git a/src/helics/cpp98/CMakeLists.txt b/src/helics/cpp98/CMakeLists.txt index e9bce3274d..dda6599e30 100644 --- a/src/helics/cpp98/CMakeLists.txt +++ b/src/helics/cpp98/CMakeLists.txt @@ -22,11 +22,13 @@ add_library(helicsCpp98 INTERFACE) target_include_directories(helicsCpp98 INTERFACE "${PROJECT_SOURCE_DIR}/src/helics") target_link_libraries(helicsCpp98 INTERFACE helicsSharedLib) +add_library(HELICS::helicsCpp98 ALIAS helicsCpp98) + #this is purely so the files show up nicely in an IDE, other ides might use it as well but that can be added when/if the need arises IF (MSVC) -add_library(helicsCpp98_ide STATIC ${helicsCpp98_headers} ../../empty.cpp) -target_include_directories(helicsCpp98_ide PRIVATE "${PROJECT_SOURCE_DIR}/src/helics") -set_target_properties (helicsCpp98_ide PROPERTIES FOLDER interfaces) + add_library(helicsCpp98_ide STATIC ${helicsCpp98_headers} ../../empty.cpp) + target_include_directories(helicsCpp98_ide PRIVATE "${PROJECT_SOURCE_DIR}/src/helics") + set_target_properties (helicsCpp98_ide PROPERTIES FOLDER interfaces) ENDIF(MSVC) install(FILES ${helicsCpp98_headers} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/cpp98 COMPONENT headers) diff --git a/src/helics/shared_api_library/CMakeLists.txt b/src/helics/shared_api_library/CMakeLists.txt index 3caa26d5c6..6f768b8d3f 100644 --- a/src/helics/shared_api_library/CMakeLists.txt +++ b/src/helics/shared_api_library/CMakeLists.txt @@ -27,6 +27,7 @@ include(GenerateExportHeader) add_library(helicsSharedLib SHARED ${helicsShared_sources} ${helicsShared_headers}) +add_library(HELICS::helicsSharedLib ALIAS helicsSharedLib) generate_export_header(helicsSharedLib BASE_NAME helics) @@ -53,15 +54,15 @@ if (STATIC_STANDARD_LIB) else(USE_LIBCXX) target_link_libraries(helicsSharedLib -static-libgcc -static-libstdc++) endif(USE_LIBCXX) -elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") - target_link_libraries(helicsSharedLib -static-libgcc -static-libstdc++) -elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel") - target_link_libraries(helicsSharedLib -static-libgcc -static-libstdc++) -elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") - # using Visual Studio C++ - set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT") - set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd") -endif() + elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + target_link_libraries(helicsSharedLib -static-libgcc -static-libstdc++) + elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel") + target_link_libraries(helicsSharedLib -static-libgcc -static-libstdc++) + elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") + # using Visual Studio C++ + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT") + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd") + endif() endif(STATIC_STANDARD_LIB) diff --git a/swig/java/MakeJarCMakeLists.txt.in b/swig/java/MakeJarCMakeLists.txt.in index 8440de1f05..cd184e7aad 100644 --- a/swig/java/MakeJarCMakeLists.txt.in +++ b/swig/java/MakeJarCMakeLists.txt.in @@ -1,5 +1,5 @@ cmake_minimum_required (VERSION 3.4) -project (HELICSJAR) +project (HELICSJAR LANGUAGES NONE) FIND_PACKAGE(Java REQUIRED) INCLUDE(UseJava) diff --git a/tests/helics/CMakeLists.txt b/tests/helics/CMakeLists.txt index 0344f0b188..03367de968 100644 --- a/tests/helics/CMakeLists.txt +++ b/tests/helics/CMakeLists.txt @@ -7,7 +7,7 @@ #add a baseline library for underlying dependencies and flags for test executables add_library(helics_test_base INTERFACE) -target_link_libraries(helics_test_base INTERFACE ${Boost_LIBRARIES_test}) +target_link_libraries(helics_test_base INTERFACE Boostlibs::test) target_link_libraries(helics_test_base INTERFACE helics_base_includes) add_subdirectory(common) diff --git a/tests/helics/application_api/CMakeLists.txt b/tests/helics/application_api/CMakeLists.txt index 0c82d9ccfc..d018715f7b 100644 --- a/tests/helics/application_api/CMakeLists.txt +++ b/tests/helics/application_api/CMakeLists.txt @@ -38,10 +38,6 @@ heat-transfer-tests.cpp ValueFederateExtendedTests.cpp ) -include_directories( SYSTEM ${Boost_INCLUDE_DIR}) -include_directories(SYSTEM ${PROJECT_SOURCE_DIR}/ThirdParty) -include_directories(${PROJECT_SOURCE_DIR}/src) - # QUICK API TESTS add_executable(application-api-tests ${application_api_test_sources} ${application_api_test_headers}) @@ -59,16 +55,6 @@ target_link_libraries(extended-api-tests helics-static helics_test_base) set_target_properties (application-api-tests extended-api-tests key-tests PROPERTIES FOLDER tests) - -#add a bigobj indicator for this project -#IF(MINGW) -# target_compile_options(application-api-tests PRIVATE "-Wa,-mbig-obj") -#ENDIF(MINGW) - -#if (MSVC) -# target_compile_options(application-api-tests PRIVATE /bigobj) -#endif(MSVC) - target_compile_definitions(application-api-tests PRIVATE "-DHELICS_BROKER_LOCATION=\"${HELICS_BROKER_LOC}\"") target_compile_definitions(application-api-tests PRIVATE "-DHELICS_INSTALL_LOCATION=\"${CMAKE_INSTALL_PREFIX}\"") diff --git a/tests/helics/common/CMakeLists.txt b/tests/helics/common/CMakeLists.txt index 2d7349915d..b46c324018 100644 --- a/tests/helics/common/CMakeLists.txt +++ b/tests/helics/common/CMakeLists.txt @@ -29,8 +29,6 @@ TimeTests.cpp add_executable(common-tests ${common_test_sources} ${common_test_headers} ) target_link_libraries(common-tests PRIVATE helics-static helics_test_base) -target_include_directories(common-tests PRIVATE ${PROJECT_SOURCE_DIR}/src) - add_test(NAME common-tests COMMAND common-tests --log_level=message --report_level=short) set_target_properties (common-tests PROPERTIES FOLDER tests) diff --git a/tests/helics/core/CMakeLists.txt b/tests/helics/core/CMakeLists.txt index 96fd2f036c..6a04e29290 100644 --- a/tests/helics/core/CMakeLists.txt +++ b/tests/helics/core/CMakeLists.txt @@ -30,9 +30,9 @@ ForwardingTimeCoordinatorTests.cpp TimeCoordinatorTests.cpp networkInfoTests.cpp ) -if (HELICS_HAVE_ZMQ) +if (HELICS_HAVE_ZEROMQ) list(APPEND core_test_sources ZeromqCore-tests.cpp) -endif(HELICS_HAVE_ZMQ) +endif(HELICS_HAVE_ZEROMQ) if (NOT DISABLE_TCP_CORE) list(APPEND core_test_sources TcpCore-tests.cpp) @@ -47,10 +47,6 @@ target_link_libraries(core-tests helics-static helics_test_base) target_include_directories(core-tests PRIVATE ${PROJECT_SOURCE_DIR}/src) -if (HELICS_HAVE_ZEROMQ) - target_include_directories (core-tests PRIVATE "${ZeroMQ_INCLUDE_DIR}") -endif (HELICS_HAVE_ZEROMQ) - add_test(NAME core-tests COMMAND core-tests --log_level=message --report_level=short) set_target_properties (core-tests PROPERTIES FOLDER tests) From 88cf361314373220448437f147242d93247ba431 Mon Sep 17 00:00:00 2001 From: Philip Top Date: Thu, 24 May 2018 14:24:29 -0700 Subject: [PATCH 08/10] C interface error handling (#326) * use error handler function in the C interface * switch endpoints to use unique_ptrs in C interface * change publication/subscription/endpoint/filter creation in the C interface to use unique_ptr internally --- CMakeLists.txt | 4 +- config/HELICSConfig.cmake.in | 1 - config/cmake/addMPI.cmake | 3 +- config/cmake/addZeroMQ.cmake | 2 +- .../shared_api_library/FederateExport.cpp | 334 ++++-- .../MessageFederateExport.cpp | 198 ++-- .../MessageFiltersExport.cpp | 178 ++-- .../ValueFederateExport.cpp | 969 +++++++++++------- .../shared_api_library/helicsCallbacks.cpp | 63 +- .../shared_api_library/helicsExport.cpp | 325 ++++-- .../shared_api_library/internal/api_objects.h | 12 +- 11 files changed, 1332 insertions(+), 757 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 05e028097c..9a512cfcea 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,7 +23,6 @@ else() set (HELICS_VERSION "${HELICS_VERSION_MAJOR}.${HELICS_VERSION_MINOR}.${HELICS_VERSION_PATCH}-${HELICS_VERSION_BUILD}") set (HELICS_VERSION_UNDERSCORE "${HELICS_VERSION_MAJOR}_${HELICS_VERSION_MINOR}_${HELICS_VERSION_PATCH}-${HELICS_VERSION_BUILD}") endif() - set (HELICS_VERSION_STRING "${HELICS_VERSION} (${HELICS_DATE})") #----------------------------------------------------------------------------- @@ -289,6 +288,7 @@ SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}") SET(CMAKE_BUILD_RPATH "${AUTOBUILD_INSTALL_PATH}/bin;${AUTOBUILD_INSTALL_PATH}/lib;${AUTOBUILD_INSTALL_PATH}/lib64") + # add the automatically determined parts of the RPATH # which point to directories outside the build tree to the install RPATH SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) @@ -420,7 +420,7 @@ configure_file ( install(FILES ${AUTOBUILD_INSTALL_PATH}/include/helics/compiler-config.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/helics COMPONENT headers) install(DIRECTORY ThirdParty/cereal DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} - COMPONENT headers) + COMPONENT headers) install(DIRECTORY ThirdParty/helics_includes DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} COMPONENT headers) diff --git a/config/HELICSConfig.cmake.in b/config/HELICSConfig.cmake.in index dfc3272d0a..b2bd8fb9f9 100644 --- a/config/HELICSConfig.cmake.in +++ b/config/HELICSConfig.cmake.in @@ -53,7 +53,6 @@ set(HELICS_HAVE_MPI @HELICS_HAVE_MPI) set(CMAKE_MODULE_PATH ${PACKAGE_PREFIX_DIR}/@HELICS_CMAKECONFIG_INSTALL_DIR@) include(CMakeFindDependencyMacro) - include(extraMacros) if (NOT Boostlibs::core) diff --git a/config/cmake/addMPI.cmake b/config/cmake/addMPI.cmake index 42f71b0c20..4a11383020 100644 --- a/config/cmake/addMPI.cmake +++ b/config/cmake/addMPI.cmake @@ -10,7 +10,7 @@ ############################################################################## -# Copyright © 2017-2018, +# 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. ############################################################################## @@ -74,3 +74,4 @@ if (NOT MPI::MPI_C) set_target_properties(MPI::MPI_C PROPERTIES INTERFACE_COMPILE_DEFINITIONS "${MPI_C_COMPILE_DEFINITIONS}") endif() + diff --git a/config/cmake/addZeroMQ.cmake b/config/cmake/addZeroMQ.cmake index 1260271ab0..a99546cb94 100644 --- a/config/cmake/addZeroMQ.cmake +++ b/config/cmake/addZeroMQ.cmake @@ -19,7 +19,7 @@ if (WIN32 AND NOT MSYS) find_package(ZeroMQ QUIET HINTS ${ZeroMQ_INSTALL_PATH} - ${PROJECT_BINARY_DIR}/libs/ + ${AUTOBUILD_INSTALL_PATH} PATH_SUFFIXES ${ZMQ_CMAKE_SUFFIXES} ) else() diff --git a/src/helics/shared_api_library/FederateExport.cpp b/src/helics/shared_api_library/FederateExport.cpp index 9ccab27fda..25334192eb 100644 --- a/src/helics/shared_api_library/FederateExport.cpp +++ b/src/helics/shared_api_library/FederateExport.cpp @@ -92,16 +92,16 @@ std::shared_ptr getMessageFedSharedPtr (helics_federate /* Creation and destruction of Federates */ helics_federate helicsCreateValueFederate (const helics_federate_info_t fi) { - auto FedI = std::make_unique(); + auto FedI = std::make_unique (); try { if (fi == nullptr) { - FedI->fedptr = std::make_shared(helics::FederateInfo()); + FedI->fedptr = std::make_shared (helics::FederateInfo ()); } else { - FedI->fedptr = std::make_shared(*reinterpret_cast (fi)); + FedI->fedptr = std::make_shared (*reinterpret_cast (fi)); } } catch (const helics::RegistrationFailure &) @@ -110,17 +110,17 @@ helics_federate helicsCreateValueFederate (const helics_federate_info_t fi) } FedI->type = helics::vtype::valueFed; FedI->valid = fedValidationIdentifier; - auto fed = reinterpret_cast(FedI.get()); - getMasterHolder()->addFed(std::move(FedI)); - return (fed); + auto fed = reinterpret_cast (FedI.get ()); + getMasterHolder ()->addFed (std::move (FedI)); + return (fed); } helics_federate helicsCreateValueFederateFromJson (const char *json) { - auto FedI = std::make_unique(); + auto FedI = std::make_unique (); try { - FedI->fedptr = std::make_shared((json != nullptr) ? std::string(json) : std::string()); + FedI->fedptr = std::make_shared ((json != nullptr) ? std::string (json) : std::string ()); } catch (const helics::RegistrationFailure &) { @@ -128,24 +128,24 @@ helics_federate helicsCreateValueFederateFromJson (const char *json) } FedI->type = helics::vtype::valueFed; FedI->valid = fedValidationIdentifier; - auto fed = reinterpret_cast(FedI.get()); - getMasterHolder()->addFed(std::move(FedI)); - return (fed); + auto fed = reinterpret_cast (FedI.get ()); + getMasterHolder ()->addFed (std::move (FedI)); + return (fed); } /* Creation and destruction of Federates */ helics_federate helicsCreateMessageFederate (const helics_federate_info_t fi) { - auto FedI = std::make_unique(); + auto FedI = std::make_unique (); try { if (fi == nullptr) { - FedI->fedptr = std::make_shared(helics::FederateInfo()); + FedI->fedptr = std::make_shared (helics::FederateInfo ()); } else { - FedI->fedptr = std::make_shared(*reinterpret_cast (fi)); + FedI->fedptr = std::make_shared (*reinterpret_cast (fi)); } } catch (const helics::RegistrationFailure &) @@ -154,18 +154,18 @@ helics_federate helicsCreateMessageFederate (const helics_federate_info_t fi) } FedI->type = helics::vtype::messageFed; FedI->valid = fedValidationIdentifier; - auto fed = reinterpret_cast(FedI.get()); - getMasterHolder()->addFed(std::move(FedI)); - return (fed); + auto fed = reinterpret_cast (FedI.get ()); + getMasterHolder ()->addFed (std::move (FedI)); + return (fed); } helics_federate helicsCreateMessageFederateFromJson (const char *json) { - auto FedI = std::make_unique(); - + auto FedI = std::make_unique (); + try { - FedI->fedptr = std::make_shared((json != nullptr) ? std::string(json) : std::string()); + FedI->fedptr = std::make_shared ((json != nullptr) ? std::string (json) : std::string ()); } catch (const helics::RegistrationFailure &) { @@ -173,24 +173,24 @@ helics_federate helicsCreateMessageFederateFromJson (const char *json) } FedI->type = helics::vtype::messageFed; FedI->valid = fedValidationIdentifier; - auto fed = reinterpret_cast(FedI.get()); - getMasterHolder()->addFed(std::move(FedI)); - return (fed); + auto fed = reinterpret_cast (FedI.get ()); + getMasterHolder ()->addFed (std::move (FedI)); + return (fed); } /* Creation and destruction of Federates */ helics_federate helicsCreateCombinationFederate (const helics_federate_info_t fi) { - auto FedI = std::make_unique(); + auto FedI = std::make_unique (); try { if (fi == nullptr) { - FedI->fedptr = std::make_shared(helics::FederateInfo()); + FedI->fedptr = std::make_shared (helics::FederateInfo ()); } else { - FedI->fedptr = std::make_shared(*reinterpret_cast (fi)); + FedI->fedptr = std::make_shared (*reinterpret_cast (fi)); } } catch (const helics::RegistrationFailure &) @@ -199,28 +199,28 @@ helics_federate helicsCreateCombinationFederate (const helics_federate_info_t fi } FedI->type = helics::vtype::combinationFed; FedI->valid = fedValidationIdentifier; - auto fed = reinterpret_cast(FedI.get()); - getMasterHolder()->addFed(std::move(FedI)); - return (fed); + auto fed = reinterpret_cast (FedI.get ()); + getMasterHolder ()->addFed (std::move (FedI)); + return (fed); } helics_federate helicsCreateCombinationFederateFromJson (const char *json) { - auto FedI = std::make_unique(); + auto FedI = std::make_unique (); try { - FedI->fedptr = std::make_shared((json != nullptr) ? std::string(json) : std::string()); + FedI->fedptr = std::make_shared ((json != nullptr) ? std::string (json) : std::string ()); } catch (const helics::RegistrationFailure &) { return nullptr; } - + FedI->type = helics::vtype::combinationFed; FedI->valid = fedValidationIdentifier; - auto fed = reinterpret_cast(FedI.get()); - getMasterHolder()->addFed(std::move(FedI)); - return (fed); + auto fed = reinterpret_cast (FedI.get ()); + getMasterHolder ()->addFed (std::move (FedI)); + return (fed); } helics_federate helicsFederateClone (helics_federate fed) @@ -230,14 +230,14 @@ helics_federate helicsFederateClone (helics_federate fed) return nullptr; } auto *fedObj = reinterpret_cast (fed); - auto fedClone = std::make_unique(); + auto fedClone = std::make_unique (); fedClone->fedptr = fedObj->fedptr; - + fedClone->type = fedObj->type; fedClone->valid = fedObj->valid; - auto fedB = reinterpret_cast(fedClone.get()); - getMasterHolder()->addFed(std::move(fedClone)); - return (fedB); + auto fedB = reinterpret_cast (fedClone.get ()); + getMasterHolder ()->addFed (std::move (fedClone)); + return (fedB); } helics_core helicsFederateGetCoreObject (helics_federate fed) @@ -247,11 +247,11 @@ helics_core helicsFederateGetCoreObject (helics_federate fed) { return nullptr; } - auto core = std::make_unique(); + auto core = std::make_unique (); core->valid = fedValidationIdentifier; core->coreptr = fedObj->getCorePointer (); - auto retcore = reinterpret_cast (core.get()); - getMasterHolder()->addCore(std::move(core)); + auto retcore = reinterpret_cast (core.get ()); + getMasterHolder ()->addCore (std::move (core)); return retcore; } @@ -262,9 +262,15 @@ helics_status helicsFederateFinalize (helics_federate fed) { return helics_invalid_object; } - fedObj->finalize (); - - return helics_ok; + try + { + fedObj->finalize (); + return helics_ok; + } + catch (...) + { + return helicsErrorHandler (); + } } /* initialization, execution, and time requests */ @@ -280,9 +286,9 @@ helics_status helicsFederateEnterInitializationMode (helics_federate fed) fedObj->enterInitializationState (); return helics_ok; } - catch (helics::InvalidFunctionCall &) + catch (...) { - return helics_invalid_state_transition; + return helicsErrorHandler (); } } @@ -298,9 +304,9 @@ helics_status helicsFederateEnterInitializationModeAsync (helics_federate fed) fedObj->enterInitializationStateAsync (); return helics_ok; } - catch (helics::InvalidFunctionCall &) + catch (...) { - return helics_invalid_state_transition; + return helicsErrorHandler (); } } @@ -326,9 +332,9 @@ helics_status helicsFederateEnterInitializationModeComplete (helics_federate fed fedObj->enterInitializationStateComplete (); return helics_ok; } - catch (helics::InvalidFunctionCall &) + catch (...) { - return helics_invalid_state_transition; + return helicsErrorHandler (); } } @@ -345,10 +351,9 @@ helics_status helicsFederateEnterExecutionMode (helics_federate fed) fedObj->enterExecutionState (); return helics_ok; } - catch (helics::InvalidFunctionCall &) + catch (...) { - // printf("current state=%d\n", static_cast(fedObj->getCurrentState())); - return helics_invalid_state_transition; + return helicsErrorHandler (); } } @@ -400,9 +405,9 @@ helicsFederateEnterExecutionModeIterative (helics_federate fed, helics_iteration } return helics_ok; } - catch (helics::InvalidFunctionCall &) + catch (...) { - return helics_error; + return helicsErrorHandler (); } } @@ -418,9 +423,9 @@ helics_status helicsFederateEnterExecutionModeAsync (helics_federate fed) fedObj->enterExecutionStateAsync (); return helics_ok; } - catch (helics::InvalidFunctionCall &) + catch (...) { - return helics_error; + return helicsErrorHandler (); } } @@ -436,9 +441,9 @@ helics_status helicsFederateEnterExecutionModeIterativeAsync (helics_federate fe fedObj->enterExecutionStateAsync (getIterationRequest (iterate)); return helics_ok; } - catch (helics::InvalidFunctionCall &) + catch (...) { - return helics_error; + return helicsErrorHandler (); } } @@ -454,9 +459,9 @@ helics_status helicsFederateEnterExecutionModeComplete (helics_federate fed) fedObj->enterExecutionStateComplete (); return helics_ok; } - catch (helics::InvalidFunctionCall &) + catch (...) { - return helics_error; + return helicsErrorHandler (); } } helics_status helicsFederateEnterExecutionModeIterativeComplete (helics_federate fed, helics_iteration_status *outConverged) @@ -475,9 +480,9 @@ helics_status helicsFederateEnterExecutionModeIterativeComplete (helics_federate } return helics_ok; } - catch (helics::InvalidFunctionCall &) + catch (...) { - return helics_error; + return helicsErrorHandler (); } } @@ -488,8 +493,15 @@ helics_status helicsFederateRequestTime (helics_federate fed, helics_time_t requ { return helics_invalid_object; } - *timeOut = static_cast (fedObj->requestTime (requestTime)); - return helics_ok; + try + { + *timeOut = static_cast (fedObj->requestTime (requestTime)); + return helics_ok; + } + catch (...) + { + return helicsErrorHandler (); + } } helics_status helicsFederateRequestTimeIterative (helics_federate fed, @@ -503,15 +515,21 @@ helics_status helicsFederateRequestTimeIterative (helics_federate fed, { return helics_invalid_object; } - - auto val = fedObj->requestTimeIterative (requestTime, getIterationRequest (iterate)); - if (val.state == helics::iteration_result::error) + try { - return helics_error; + auto val = fedObj->requestTimeIterative (requestTime, getIterationRequest (iterate)); + if (val.state == helics::iteration_result::error) + { + return helics_error; + } + *outIteration = getIterationStatus (val.state); + *timeOut = static_cast (val.grantedTime); + return helics_ok; + } + catch (...) + { + return helicsErrorHandler (); } - *outIteration = getIterationStatus (val.state); - *timeOut = static_cast (val.grantedTime); - return helics_ok; } helics_status helicsFederateRequestTimeAsync (helics_federate fed, helics_time_t requestTime) @@ -521,8 +539,15 @@ helics_status helicsFederateRequestTimeAsync (helics_federate fed, helics_time_t { return helics_invalid_object; } - fedObj->requestTimeAsync (requestTime); - return helics_ok; + try + { + fedObj->requestTimeAsync (requestTime); + return helics_ok; + } + catch (...) + { + return helicsErrorHandler (); + } } helics_status helicsFederateRequestTimeIterativeAsync (helics_federate fed, helics_time_t requestTime, helics_iteration_request iterate) @@ -537,9 +562,9 @@ helics_status helicsFederateRequestTimeIterativeAsync (helics_federate fed, heli fedObj->requestTimeIterative (requestTime, getIterationRequest (iterate)); return helics_ok; } - catch (helics::InvalidFunctionCall &) + catch (...) { - return helics_error; + return helicsErrorHandler (); } } helics_status helicsFederateRequestTimeComplete (helics_federate fed, helics_time_t *timeOut) @@ -549,8 +574,15 @@ helics_status helicsFederateRequestTimeComplete (helics_federate fed, helics_tim { return helics_invalid_object; } - *timeOut = fedObj->requestTimeComplete (); - return helics_ok; + try + { + *timeOut = fedObj->requestTimeComplete (); + return helics_ok; + } + catch (...) + { + return helicsErrorHandler (); + } } static const std::map stateEnumConversions{ @@ -575,9 +607,16 @@ helics_status helicsFederateGetState (helics_federate fed, federate_state *state { return helics_discard; } - auto FedState = fedObj->getCurrentState (); - *state = stateEnumConversions.at (FedState); - return helics_ok; + try + { + auto FedState = fedObj->getCurrentState (); + *state = stateEnumConversions.at (FedState); + return helics_ok; + } + catch (...) + { + return helicsErrorHandler (); + } } helics_status helicsFederateGetName (helics_federate fed, char *outputString, int maxlen) @@ -591,17 +630,24 @@ helics_status helicsFederateGetName (helics_federate fed, char *outputString, in { return helics_discard; } - auto &ident = fedObj->getName (); - if (static_cast (ident.size ()) > maxlen) + try { - strncpy (outputString, ident.c_str (), maxlen); - outputString[maxlen - 1] = 0; + auto &ident = fedObj->getName (); + if (static_cast (ident.size ()) > maxlen) + { + strncpy (outputString, ident.c_str (), maxlen); + outputString[maxlen - 1] = 0; + } + else + { + strcpy (outputString, ident.c_str ()); + } + return helics_ok; } - else + catch (...) { - strcpy (outputString, ident.c_str ()); + return helicsErrorHandler (); } - return helics_ok; } helics_status helicsFederateSetTimeDelta (helics_federate fed, helics_time_t time) @@ -611,8 +657,15 @@ helics_status helicsFederateSetTimeDelta (helics_federate fed, helics_time_t tim { return helics_invalid_object; } - fedObj->setTimeDelta (time); - return helics_ok; + try + { + fedObj->setTimeDelta (time); + return helics_ok; + } + catch (...) + { + return helicsErrorHandler (); + } } helics_status helicsFederateSetOutputDelay (helics_federate fed, helics_time_t outputDelay) @@ -622,8 +675,15 @@ helics_status helicsFederateSetOutputDelay (helics_federate fed, helics_time_t o { return helics_invalid_object; } - fedObj->setOutputDelay (outputDelay); - return helics_ok; + try + { + fedObj->setOutputDelay (outputDelay); + return helics_ok; + } + catch (...) + { + return helicsErrorHandler (); + } } helics_status helicsFederateSetInputDelay (helics_federate fed, helics_time_t inputDelay) @@ -633,8 +693,15 @@ helics_status helicsFederateSetInputDelay (helics_federate fed, helics_time_t in { return helics_invalid_object; } - fedObj->setInputDelay (inputDelay); - return helics_ok; + try + { + fedObj->setInputDelay (inputDelay); + return helics_ok; + } + catch (...) + { + return helicsErrorHandler (); + } } helics_status helicsFederateSetPeriod (helics_federate fed, helics_time_t period, helics_time_t offset) { @@ -643,8 +710,15 @@ helics_status helicsFederateSetPeriod (helics_federate fed, helics_time_t period { return helics_invalid_object; } - fedObj->setPeriod (period, offset); - return helics_ok; + try + { + fedObj->setPeriod (period, offset); + return helics_ok; + } + catch (...) + { + return helicsErrorHandler (); + } } helics_status helicsFederateSetFlag (helics_federate fed, int flag, helics_bool_t flagValue) { @@ -653,8 +727,15 @@ helics_status helicsFederateSetFlag (helics_federate fed, int flag, helics_bool_ { return helics_invalid_object; } - fedObj->setFlag (flag, (flagValue != helics_false)); - return helics_ok; + try + { + fedObj->setFlag (flag, (flagValue != helics_false)); + return helics_ok; + } + catch (...) + { + return helicsErrorHandler (); + } } helics_status helicsFederateSetLoggingLevel (helics_federate fed, int loggingLevel) @@ -664,8 +745,15 @@ helics_status helicsFederateSetLoggingLevel (helics_federate fed, int loggingLev { return helics_invalid_object; } - fedObj->setLoggingLevel (loggingLevel); - return helics_ok; + try + { + fedObj->setLoggingLevel (loggingLevel); + return helics_ok; + } + catch (...) + { + return helicsErrorHandler (); + } } helics_status helicsFederateSetMaxIterations (helics_federate fed, int maxIterations) @@ -675,8 +763,15 @@ helics_status helicsFederateSetMaxIterations (helics_federate fed, int maxIterat { return helics_invalid_object; } - fedObj->setMaxIterations (maxIterations); - return helics_ok; + try + { + fedObj->setMaxIterations (maxIterations); + return helics_ok; + } + catch (...) + { + return helicsErrorHandler (); + } } /** get the current time of the federate @@ -691,8 +786,15 @@ helics_status helicsFederateGetCurrentTime (helics_federate fed, helics_time_t * { return helics_invalid_object; } - *time = static_cast (fedObj->getCurrentTime ()); - return helics_ok; + try + { + *time = static_cast (fedObj->getCurrentTime ()); + return helics_ok; + } + catch (...) + { + return helicsErrorHandler (); + } } helics_status @@ -703,13 +805,19 @@ helicsFederateRequestTimeIterativeComplete (helics_federate fed, helics_time_t * { return helics_invalid_object; } - - auto val = fedObj->requestTimeIterativeComplete (); - if (val.state == helics::iteration_result::error) + try + { + auto val = fedObj->requestTimeIterativeComplete (); + if (val.state == helics::iteration_result::error) + { + return helics_error; + } + *outIteration = getIterationStatus (val.state); + *timeOut = static_cast (val.grantedTime); + return helics_ok; + } + catch (...) { - return helics_error; + return helicsErrorHandler (); } - *outIteration = getIterationStatus (val.state); - *timeOut = static_cast (val.grantedTime); - return helics_ok; } diff --git a/src/helics/shared_api_library/MessageFederateExport.cpp b/src/helics/shared_api_library/MessageFederateExport.cpp index c4f4c80fe3..534c730b3b 100644 --- a/src/helics/shared_api_library/MessageFederateExport.cpp +++ b/src/helics/shared_api_library/MessageFederateExport.cpp @@ -13,10 +13,10 @@ All rights reserved. See LICENSE file and DISCLAIMER for more details. #include #include -static inline void addEndpoint (helics_federate fed, helics::EndpointObject *ept) +static inline void addEndpoint (helics_federate fed, std::unique_ptr ept) { auto fedObj = reinterpret_cast (fed); - fedObj->epts.push_back (ept); + fedObj->epts.push_back (std::move(ept)); } static const std::string nullStr; @@ -28,19 +28,19 @@ helics_endpoint helicsFederateRegisterEndpoint (helics_federate fed, const char { return nullptr; } - helics::EndpointObject *end = nullptr; try { - end = new helics::EndpointObject (); + auto end = std::make_unique (); end->endptr = std::make_unique (fedObj.get (), (name != nullptr) ? std::string (name) : nullStr, (type == nullptr) ? nullStr : std::string (type)); end->fedptr = std::move (fedObj); - addEndpoint (fed, end); - return reinterpret_cast (end); + auto ret = reinterpret_cast (end.get()); + addEndpoint (fed, std::move(end)); + return ret; } catch (const helics::InvalidFunctionCall &) { - delete end; + return nullptr; } return nullptr; } @@ -53,19 +53,19 @@ helics_endpoint helicsFederateRegisterGlobalEndpoint (helics_federate fed, const { return nullptr; } - helics::EndpointObject *end = nullptr; try { - end = new helics::EndpointObject (); + auto end = std::make_unique(); end->endptr = std::make_unique (helics::GLOBAL, fedObj.get (), (name != nullptr) ? std::string (name) : nullStr, (type == nullptr) ? nullStr : std::string (type)); end->fedptr = std::move (fedObj); - addEndpoint (fed, end); - return reinterpret_cast (end); + auto ret = reinterpret_cast (end.get()); + addEndpoint(fed, std::move(end)); + return ret; } - catch (const helics::InvalidFunctionCall &) + catch (...) { - delete end; + return nullptr; } return nullptr; } @@ -76,9 +76,16 @@ helics_status helicsEndpointSetDefaultDestination (helics_endpoint endpoint, con { return helics_invalid_object; } - auto endObj = reinterpret_cast (endpoint); - endObj->endptr->setTargetDestination (dest); - return helics_ok; + try + { + auto endObj = reinterpret_cast (endpoint); + endObj->endptr->setTargetDestination (dest); + return helics_ok; + } + catch (...) + { + return helicsErrorHandler (); + } } helics_status helicsEndpointSendMessageRaw (helics_endpoint endpoint, const char *dest, const void *data, int inputDataLength) @@ -87,31 +94,38 @@ helics_status helicsEndpointSendMessageRaw (helics_endpoint endpoint, const char { return helics_invalid_object; } - auto endObj = reinterpret_cast (endpoint); - if ((data == nullptr) || (inputDataLength <= 0)) + try { - if ((dest == nullptr) || (std::string (dest).empty ())) + auto endObj = reinterpret_cast (endpoint); + if ((data == nullptr) || (inputDataLength <= 0)) { - endObj->endptr->send (std::string ()); + if ((dest == nullptr) || (std::string (dest).empty ())) + { + endObj->endptr->send (std::string ()); + } + else + { + endObj->endptr->send (dest, std::string ()); + } } else { - endObj->endptr->send (dest, std::string ()); + if ((dest == nullptr) || (std::string (dest).empty ())) + { + endObj->endptr->send ((const char *)data, inputDataLength); + } + else + { + endObj->endptr->send (dest, (const char *)data, inputDataLength); + } } + + return helics_ok; } - else + catch (...) { - if ((dest == nullptr) || (std::string (dest).empty ())) - { - endObj->endptr->send ((const char *)data, inputDataLength); - } - else - { - endObj->endptr->send (dest, (const char *)data, inputDataLength); - } + return helicsErrorHandler (); } - - return helics_ok; } helics_status @@ -121,31 +135,38 @@ helicsEndpointSendEventRaw (helics_endpoint endpoint, const char *dest, const vo { return helics_invalid_object; } - auto endObj = reinterpret_cast (endpoint); - if ((data == nullptr) || (inputDataLength <= 0)) + try { - if ((dest == nullptr) || (std::string (dest).empty ())) + auto endObj = reinterpret_cast (endpoint); + if ((data == nullptr) || (inputDataLength <= 0)) { - endObj->endptr->send (std::string (), time); + if ((dest == nullptr) || (std::string (dest).empty ())) + { + endObj->endptr->send (std::string (), time); + } + else + { + endObj->endptr->send (dest, std::string (), time); + } } else { - endObj->endptr->send (dest, std::string (), time); + if ((dest == nullptr) || (std::string (dest).empty ())) + { + endObj->endptr->send ((const char *)data, inputDataLength, time); + } + else + { + endObj->endptr->send (dest, (const char *)data, inputDataLength, time); + } } + + return helics_ok; } - else + catch (...) { - if ((dest == nullptr) || (std::string (dest).empty ())) - { - endObj->endptr->send ((const char *)data, inputDataLength, time); - } - else - { - endObj->endptr->send (dest, (const char *)data, inputDataLength, time); - } + return helicsErrorHandler (); } - - return helics_ok; } helics_status helicsEndpointSendMessage (helics_endpoint endpoint, message_t *message) @@ -158,18 +179,24 @@ helics_status helicsEndpointSendMessage (helics_endpoint endpoint, message_t *me { return helics_invalid_object; } - - auto endObj = reinterpret_cast (endpoint); - // TODO this isn't correct yet (need to translate to a Message_view if origSrc is not this name - if (message->dest == nullptr) + try { - endObj->endptr->send (message->data, message->length, message->time); + auto endObj = reinterpret_cast (endpoint); + // TODO this isn't correct yet (need to translate to a Message_view if origSrc is not this name + if (message->dest == nullptr) + { + endObj->endptr->send (message->data, message->length, message->time); + } + else + { + endObj->endptr->send (message->dest, message->data, message->length, message->time); + } + return helics_ok; } - else + catch (...) { - endObj->endptr->send (message->dest, message->data, message->length, message->time); + return helicsErrorHandler (); } - return helics_ok; } helics_status helicsEndpointSubscribe (helics_endpoint endpoint, const char *key, const char *type) @@ -178,10 +205,17 @@ helics_status helicsEndpointSubscribe (helics_endpoint endpoint, const char *key { return helics_error; } - auto endObj = reinterpret_cast (endpoint); + try + { + auto endObj = reinterpret_cast (endpoint); - endObj->endptr->subscribe (key, (type == nullptr) ? nullStr : std::string (type)); - return helics_ok; + endObj->endptr->subscribe (key, (type == nullptr) ? nullStr : std::string (type)); + return helics_ok; + } + catch (...) + { + return helicsErrorHandler (); + } } helics_bool_t helicsFederateHasMessage (helics_federate fed) @@ -311,18 +345,25 @@ helics_status helicsEndpointGetType (helics_endpoint endpoint, char *outputStrin { return helics_invalid_argument; } - auto endObj = reinterpret_cast (endpoint); - auto type = endObj->endptr->getType (); - if (static_cast (type.size ()) > maxlen) + try { - strncpy (outputString, type.c_str (), maxlen); - outputString[maxlen - 1] = 0; + auto endObj = reinterpret_cast (endpoint); + auto type = endObj->endptr->getType (); + if (static_cast (type.size ()) > maxlen) + { + strncpy (outputString, type.c_str (), maxlen); + outputString[maxlen - 1] = 0; + } + else + { + strcpy (outputString, type.c_str ()); + } + return helics_ok; } - else + catch (...) { - strcpy (outputString, type.c_str ()); + return helicsErrorHandler (); } - return helics_ok; } helics_status helicsEndpointGetName (helics_endpoint endpoint, char *outputString, int maxlen) @@ -335,18 +376,25 @@ helics_status helicsEndpointGetName (helics_endpoint endpoint, char *outputStrin { return helics_invalid_argument; } - auto endObj = reinterpret_cast (endpoint); - auto type = endObj->endptr->getName (); - if (static_cast (type.size ()) > maxlen) + try { - strncpy (outputString, type.c_str (), maxlen); - outputString[maxlen - 1] = 0; + auto endObj = reinterpret_cast (endpoint); + auto type = endObj->endptr->getName (); + if (static_cast (type.size ()) > maxlen) + { + strncpy (outputString, type.c_str (), maxlen); + outputString[maxlen - 1] = 0; + } + else + { + strcpy (outputString, type.c_str ()); + } + return helics_ok; } - else + catch (...) { - strcpy (outputString, type.c_str ()); + return helicsErrorHandler (); } - return helics_ok; } int helicsFederateGetEndpointCount (helics_federate fed) diff --git a/src/helics/shared_api_library/MessageFiltersExport.cpp b/src/helics/shared_api_library/MessageFiltersExport.cpp index 17e3df2b76..fe0cd9bdec 100644 --- a/src/helics/shared_api_library/MessageFiltersExport.cpp +++ b/src/helics/shared_api_library/MessageFiltersExport.cpp @@ -18,16 +18,16 @@ static const std::string nullstr; /** this is a random identifier put in place when the federate or core or broker gets created*/ static const int filterValidationIdentifier = 0xEC26'0127; -static inline void federateAddFilter (helics_federate fed, helics::FilterObject *filt) +static inline void federateAddFilter (helics_federate fed, std::unique_ptrfilt) { auto fedObj = reinterpret_cast (fed); - fedObj->filters.push_back (filt); + fedObj->filters.push_back (std::move(filt)); } -static inline void coreAddFilter (helics_core core, helics::FilterObject *filt) +static inline void coreAddFilter (helics_core core, std::unique_ptrfilt) { auto coreObj = reinterpret_cast (core); - coreObj->filters.push_back (filt); + coreObj->filters.push_back (std::move(filt)); } helics_filter helicsFederateRegisterSourceFilter (helics_federate fed, helics_filter_type_t type, const char *target, const char *name) @@ -43,21 +43,20 @@ helics_filter helicsFederateRegisterSourceFilter (helics_federate fed, helics_fi return nullptr; } - helics::FilterObject *filt = nullptr; try { - filt = new helics::FilterObject (); + auto filt = std::make_unique (); filt->filtptr = helics::make_source_filter (static_cast (type), fedObj.get (), std::string (target), (name != nullptr) ? std::string (name) : nullstr); filt->fedptr = std::move (fedObj); filt->type = helics::ftype::source; filt->valid = filterValidationIdentifier; - federateAddFilter (fed, filt); - return reinterpret_cast (filt); + auto ret = reinterpret_cast (filt.get()); + federateAddFilter (fed, std::move(filt)); + return ret; } catch (const helics::InvalidFunctionCall &) { - delete filt; } return nullptr; } @@ -70,21 +69,20 @@ helics_filter helicsFederateRegisterDestinationFilter (helics_federate fed, heli { return nullptr; } - helics::FilterObject *filt = nullptr; try { - filt = new helics::FilterObject (); + auto filt = std::make_unique(); filt->filtptr = helics::make_destination_filter (static_cast (type), fedObj.get (), std::string (target), (name != nullptr) ? std::string (name) : nullstr); filt->fedptr = std::move (fedObj); filt->type = helics::ftype::dest; filt->valid = filterValidationIdentifier; - federateAddFilter (fed, filt); - return reinterpret_cast (filt); + auto ret = reinterpret_cast (filt.get()); + federateAddFilter (fed, std::move(filt)); + return ret; } catch (const helics::InvalidFunctionCall &) { - delete filt; } return nullptr; } @@ -100,21 +98,20 @@ helics_filter helicsCoreRegisterSourceFilter (helics_core cr, helics_filter_type { return nullptr; } - helics::FilterObject *filt = nullptr; try { - filt = new helics::FilterObject (); + auto filt = std::make_unique(); filt->filtptr = helics::make_source_filter (static_cast (type), core.get (), std::string (target), (name != nullptr) ? std::string (name) : nullstr); filt->corePtr = std::move (core); filt->type = helics::ftype::source; filt->valid = filterValidationIdentifier; - coreAddFilter (cr, filt); - return reinterpret_cast (filt); + auto ret = reinterpret_cast (filt.get()); + coreAddFilter (cr, std::move(filt)); + return ret; } catch (const helics::InvalidFunctionCall &) { - delete filt; } return nullptr; } @@ -131,21 +128,20 @@ helics_filter helicsCoreRegisterDestinationFilter (helics_core cr, helics_filter return nullptr; } - helics::FilterObject *filt = nullptr; try { - filt = new helics::FilterObject (); + auto filt = std::make_unique(); filt->filtptr = helics::make_destination_filter (static_cast (type), core.get (), std::string (target), (name != nullptr) ? std::string (name) : nullstr); filt->corePtr = std::move (core); filt->type = helics::ftype::dest; filt->valid = filterValidationIdentifier; - coreAddFilter (cr, filt); - return reinterpret_cast (filt); + auto ret = reinterpret_cast (filt.get()); + coreAddFilter (cr, std::move(filt)); + return ret; } catch (const helics::InvalidFunctionCall &) { - delete filt; } return nullptr; } @@ -158,10 +154,9 @@ helics_filter helicsFederateRegisterCloningFilter (helics_federate fed, const ch return nullptr; } - helics::FilterObject *filt = nullptr; try { - filt = new helics::FilterObject (); + auto filt = std::make_unique(); auto filtptr = std::make_unique (fedObj.get ()); if (deliveryEndpoint != nullptr) { @@ -171,12 +166,12 @@ helics_filter helicsFederateRegisterCloningFilter (helics_federate fed, const ch filt->fedptr = std::move (fedObj); filt->type = helics::ftype::clone; filt->valid = filterValidationIdentifier; - federateAddFilter (fed, filt); - return reinterpret_cast (filt); + auto ret = reinterpret_cast (filt.get()); + federateAddFilter (fed, std::move(filt)); + return ret; } catch (const helics::InvalidFunctionCall &) { - delete filt; } return nullptr; } @@ -188,10 +183,9 @@ helics_filter helicsCoreRegisterCloningFilter (helics_core cr, const char *deliv { return nullptr; } - helics::FilterObject *filt = nullptr; try { - filt = new helics::FilterObject (); + auto filt = std::make_unique(); auto filtptr = std::make_unique (core.get ()); if (deliveryEndpoint != nullptr) { @@ -201,12 +195,12 @@ helics_filter helicsCoreRegisterCloningFilter (helics_core cr, const char *deliv filt->corePtr = std::move (core); filt->type = helics::ftype::clone; filt->valid = filterValidationIdentifier; - coreAddFilter (cr, filt); - return reinterpret_cast (filt); + auto ret = reinterpret_cast (filt.get()); + coreAddFilter (cr, std::move(filt)); + return ret; } catch (const helics::InvalidFunctionCall &) { - delete filt; } return nullptr; } @@ -251,15 +245,22 @@ helics_status helicsFilterGetTarget (helics_filter filt, char *outputString, int { return helics_invalid_object; } - auto target = filter->getTarget (); - if (static_cast (target.size ()) > maxlen) + try + { + auto target = filter->getTarget (); + if (static_cast (target.size ()) > maxlen) + { + strncpy (outputString, target.c_str (), maxlen); + outputString[maxlen - 1] = 0; + return helics_warning; + } + strcpy (outputString, target.c_str ()); + return helics_ok; + } + catch (...) { - strncpy (outputString, target.c_str (), maxlen); - outputString[maxlen - 1] = 0; - return helics_warning; + return helicsErrorHandler (); } - strcpy (outputString, target.c_str ()); - return helics_ok; } /** get the name of the filter*/ @@ -270,15 +271,22 @@ helics_status helicsFilterGetName (helics_filter filt, char *outputString, int m { return helics_invalid_object; } - auto name = filter->getTarget (); - if (static_cast (name.size ()) > maxlen) + try + { + auto name = filter->getTarget (); + if (static_cast (name.size ()) > maxlen) + { + strncpy (outputString, name.c_str (), maxlen); + outputString[maxlen - 1] = 0; + return helics_warning; + } + strcpy (outputString, name.c_str ()); + return helics_ok; + } + catch (...) { - strncpy (outputString, name.c_str (), maxlen); - outputString[maxlen - 1] = 0; - return helics_warning; + return helicsErrorHandler (); } - strcpy (outputString, name.c_str ()); - return helics_ok; } helics_status helicsFilterSet (helics_filter filt, const char *property, double val) @@ -292,8 +300,15 @@ helics_status helicsFilterSet (helics_filter filt, const char *property, double { return helics_invalid_argument; } - filter->set (property, val); - return helics_ok; + try + { + filter->set (property, val); + return helics_ok; + } + catch (...) + { + return helicsErrorHandler (); + } } helics_status helicsFilterSetString (helics_filter filt, const char *property, const char *val) @@ -307,8 +322,15 @@ helics_status helicsFilterSetString (helics_filter filt, const char *property, c { return helics_invalid_argument; } - filter->setString (property, val); - return helics_ok; + try + { + filter->setString (property, val); + return helics_ok; + } + catch (...) + { + return helicsErrorHandler (); + } } helics_status helicsFilterAddDestinationTarget (helics_filter filt, const char *dest) @@ -327,9 +349,9 @@ helics_status helicsFilterAddDestinationTarget (helics_filter filt, const char * cfilt->addDestinationTarget (dest); return helics_ok; } - catch (const helics::InvalidFunctionCall &ifc) + catch (...) { - return helics_invalid_function_call; + return helicsErrorHandler (); } } @@ -349,9 +371,9 @@ helics_status helicsFilterAddSourceTarget (helics_filter filt, const char *src) cfilt->addSourceTarget (src); return helics_ok; } - catch (const helics::InvalidFunctionCall &ifc) + catch (...) { - return helics_invalid_function_call; + return helicsErrorHandler (); } } @@ -366,8 +388,15 @@ helics_status helicsFilterAddDeliveryEndpoint (helics_filter filt, const char *d { return helics_invalid_argument; } - cfilt->addDeliveryEndpoint (delivery); - return helics_ok; + try + { + cfilt->addDeliveryEndpoint (delivery); + return helics_ok; + } + catch (...) + { + return helicsErrorHandler (); + } } helics_status helicsFilterRemoveDestinationTarget (helics_filter filt, const char *dest) @@ -381,8 +410,15 @@ helics_status helicsFilterRemoveDestinationTarget (helics_filter filt, const cha { return helics_invalid_argument; } - cfilt->removeDestinationTarget (dest); - return helics_ok; + try + { + cfilt->removeDestinationTarget (dest); + return helics_ok; + } + catch (...) + { + return helicsErrorHandler (); + } } helics_status helicsFilterRemoveSourceTarget (helics_filter filt, const char *source) @@ -396,8 +432,15 @@ helics_status helicsFilterRemoveSourceTarget (helics_filter filt, const char *so { return helics_invalid_argument; } - cfilt->removeSourceTarget (source); - return helics_ok; + try + { + cfilt->removeSourceTarget (source); + return helics_ok; + } + catch (...) + { + return helicsErrorHandler (); + } } helics_status helicsFilterRemoveDeliveryEndpoint (helics_filter filt, const char *delivery) @@ -411,6 +454,13 @@ helics_status helicsFilterRemoveDeliveryEndpoint (helics_filter filt, const char { return helics_invalid_argument; } - cfilt->removeDeliveryEndpoint (delivery); - return helics_ok; + try + { + cfilt->removeDeliveryEndpoint (delivery); + return helics_ok; + } + catch (...) + { + return helicsErrorHandler (); + } } diff --git a/src/helics/shared_api_library/ValueFederateExport.cpp b/src/helics/shared_api_library/ValueFederateExport.cpp index b83afacd17..15e6fb5cc3 100644 --- a/src/helics/shared_api_library/ValueFederateExport.cpp +++ b/src/helics/shared_api_library/ValueFederateExport.cpp @@ -12,16 +12,16 @@ All rights reserved. See LICENSE file and DISCLAIMER for more details. #include #include -static inline void addSubscription (helics_federate fed, helics::SubscriptionObject *sub) +static inline void addSubscription (helics_federate fed, std::unique_ptr sub) { auto fedObj = reinterpret_cast (fed); - fedObj->subs.push_back (sub); + fedObj->subs.push_back (std::move (sub)); } -static inline void addPublication (helics_federate fed, helics::PublicationObject *pub) +static inline void addPublication (helics_federate fed, std::unique_ptr pub) { auto fedObj = reinterpret_cast (fed); - fedObj->pubs.push_back (pub); + fedObj->pubs.push_back (std::move (pub)); } const std::string nullStr; @@ -36,11 +36,19 @@ helics_subscription helicsFederateRegisterSubscription (helics_federate fed, con { return nullptr; } - auto *sub = new helics::SubscriptionObject (); - sub->subptr = std::make_unique (fedObj, key, (units == nullptr) ? nullStr : std::string (units)); - sub->fedptr = std::move (fedObj); - addSubscription (fed, sub); - return reinterpret_cast (sub); + try + { + auto sub = std::make_unique (); + sub->subptr = std::make_unique (fedObj, key, (units == nullptr) ? nullStr : std::string (units)); + sub->fedptr = std::move (fedObj); + auto ret = reinterpret_cast (sub.get ()); + addSubscription (fed, std::move (sub)); + return ret; + } + catch (const helics::InvalidFunctionCall &) + { + } + return nullptr; } auto htype = helics::getTypeFromString (type); if (htype != helics::helics_type_t::helicsInvalid) @@ -53,19 +61,18 @@ helics_subscription helicsFederateRegisterSubscription (helics_federate fed, con { return nullptr; } - helics::SubscriptionObject *sub = nullptr; try { - sub = new helics::SubscriptionObject (); + auto sub = std::make_unique (); sub->id = fedObj->registerRequiredSubscription (key, type, (units == nullptr) ? nullStr : std::string (units)); sub->rawOnly = true; sub->fedptr = std::move (fedObj); - addSubscription (fed, sub); - return reinterpret_cast (sub); + auto ret = reinterpret_cast (sub.get ()); + addSubscription (fed, std::move (sub)); + return ret; } catch (const helics::InvalidFunctionCall &) { - delete sub; } return nullptr; } @@ -85,19 +92,18 @@ helics_subscription helicsFederateRegisterTypeSubscription (helics_federate fed, return nullptr; } - helics::SubscriptionObject *sub = nullptr; try { - sub = new helics::SubscriptionObject (); + auto sub = std::make_unique (); sub->subptr = std::make_unique (fedObj.get (), key, static_cast (type), (units == nullptr) ? nullStr : std::string (units)); sub->fedptr = std::move (fedObj); - addSubscription (fed, sub); - return reinterpret_cast (sub); + auto ret = reinterpret_cast (sub.get ()); + addSubscription (fed, std::move (sub)); + return ret; } catch (const helics::InvalidFunctionCall &) { - delete sub; } return nullptr; } @@ -112,12 +118,20 @@ helics_subscription helicsFederateRegisterOptionalSubscription (helics_federate { return nullptr; } - auto *sub = new helics::SubscriptionObject (); - sub->subptr = - std::make_unique (helics::OPTIONAL, fedObj.get (), key, (units == nullptr) ? nullStr : std::string (units)); - sub->fedptr = std::move (fedObj); - addSubscription (fed, sub); - return reinterpret_cast (sub); + try + { + auto sub = std::make_unique (); + sub->subptr = std::make_unique (helics::OPTIONAL, fedObj.get (), key, + (units == nullptr) ? nullStr : std::string (units)); + sub->fedptr = std::move (fedObj); + auto ret = reinterpret_cast (sub.get ()); + addSubscription (fed, std::move (sub)); + return ret; + } + catch (const helics::InvalidFunctionCall &) + { + } + return nullptr; } auto htype = helics::getTypeFromString (type); if (htype != helics::helics_type_t::helicsInvalid) @@ -130,19 +144,18 @@ helics_subscription helicsFederateRegisterOptionalSubscription (helics_federate { return nullptr; } - helics::SubscriptionObject *sub = nullptr; try { - sub = new helics::SubscriptionObject (); + auto sub = std::make_unique (); sub->id = fedObj->registerOptionalSubscription (key, type, (units == nullptr) ? nullStr : std::string (units)); sub->rawOnly = true; sub->fedptr = std::move (fedObj); - addSubscription (fed, sub); - return reinterpret_cast (sub); + auto ret = reinterpret_cast (sub.get ()); + addSubscription (fed, std::move (sub)); + return ret; } catch (const helics::InvalidFunctionCall &) { - delete sub; } return nullptr; } @@ -163,19 +176,18 @@ helics_subscription helicsFederateRegisterOptionalTypeSubscription (helics_feder return nullptr; } - helics::SubscriptionObject *sub = nullptr; try { - sub = new helics::SubscriptionObject (); + auto sub = std::make_unique (); sub->subptr = std::make_unique (fedObj.get (), key, static_cast (type), (units == nullptr) ? nullStr : std::string (units)); sub->fedptr = std::move (fedObj); - addSubscription (fed, sub); - return reinterpret_cast (sub); + auto ret = reinterpret_cast (sub.get ()); + addSubscription (fed, std::move (sub)); + return ret; } catch (const helics::InvalidFunctionCall &) { - delete sub; } return nullptr; } @@ -193,20 +205,19 @@ helics_publication helicsFederateRegisterPublication (helics_federate fed, const { return nullptr; } - helics::PublicationObject *pub = nullptr; try { - pub = new helics::PublicationObject (); + auto pub = std::make_unique (); pub->id = fedObj->registerPublication (key, (type == nullptr) ? nullStr : std::string (type), (units == nullptr) ? nullStr : std::string (units)); pub->rawOnly = true; pub->fedptr = std::move (fedObj); - addPublication (fed, pub); - return reinterpret_cast (pub); + auto ret = reinterpret_cast (pub.get ()); + addPublication (fed, std::move (pub)); + return ret; } catch (const helics::InvalidFunctionCall &) { - delete pub; } return nullptr; } @@ -225,19 +236,18 @@ helics_publication helicsFederateRegisterTypePublication (helics_federate fed, c { return nullptr; } - helics::PublicationObject *pub = nullptr; try { - pub = new helics::PublicationObject (); + auto pub = std::make_unique (); pub->pubptr = std::make_unique (fedObj.get (), key, static_cast (type), (units == nullptr) ? nullStr : std::string (units)); pub->fedptr = std::move (fedObj); - addPublication (fed, pub); - return reinterpret_cast (pub); + auto ret = reinterpret_cast (pub.get ()); + addPublication (fed, std::move (pub)); + return ret; } catch (const helics::InvalidFunctionCall &) { - delete pub; } return nullptr; } @@ -255,20 +265,19 @@ helics_publication helicsFederateRegisterGlobalPublication (helics_federate fed, { return nullptr; } - helics::PublicationObject *pub = nullptr; try { - pub = new helics::PublicationObject (); + auto pub = std::make_unique (); pub->id = fedObj->registerGlobalPublication (key, (type == nullptr) ? nullStr : std::string (type), (units == nullptr) ? nullStr : std::string (units)); pub->rawOnly = true; pub->fedptr = std::move (fedObj); - addPublication (fed, pub); - return reinterpret_cast (pub); + auto ret = reinterpret_cast (pub.get ()); + addPublication (fed, std::move (pub)); + return ret; } catch (const helics::InvalidFunctionCall &) { - delete pub; } return nullptr; } @@ -288,19 +297,18 @@ helics_publication helicsFederateRegisterGlobalTypePublication (helics_federate { return nullptr; } - helics::PublicationObject *pub = nullptr; try { - pub = new helics::PublicationObject (); + auto pub = std::make_unique (); pub->pubptr = std::make_unique (helics::GLOBAL, fedObj.get (), key, static_cast (type), (units == nullptr) ? nullStr : std::string (units)); pub->fedptr = std::move (fedObj); - addPublication (fed, pub); - return reinterpret_cast (pub); + auto ret = reinterpret_cast (pub.get ()); + addPublication (fed, std::move (pub)); + return ret; } catch (const helics::InvalidFunctionCall &) { - delete pub; } return nullptr; } @@ -312,16 +320,23 @@ helics_status helicsPublicationPublishRaw (helics_publication pub, const void *d { return helics_error; } - auto pubObj = reinterpret_cast (pub); - if (pubObj->rawOnly) + try { - pubObj->fedptr->publish (pubObj->id, (const char *)data, datalen); + auto pubObj = reinterpret_cast (pub); + if (pubObj->rawOnly) + { + pubObj->fedptr->publish (pubObj->id, (const char *)data, datalen); + } + else + { + pubObj->fedptr->publish (pubObj->pubptr->getID (), (const char *)data, datalen); + } + return helics_ok; } - else + catch (...) { - pubObj->fedptr->publish (pubObj->pubptr->getID (), (const char *)data, datalen); + return helicsErrorHandler (); } - return helics_ok; } helics_status helicsPublicationPublishString (helics_publication pub, const char *str) @@ -330,16 +345,23 @@ helics_status helicsPublicationPublishString (helics_publication pub, const char { return helics_error; } - auto pubObj = reinterpret_cast (pub); - if (pubObj->rawOnly) + try { - pubObj->fedptr->publish (pubObj->id, (str != nullptr) ? str : ""); + auto pubObj = reinterpret_cast (pub); + if (pubObj->rawOnly) + { + pubObj->fedptr->publish (pubObj->id, (str != nullptr) ? str : ""); + } + else + { + pubObj->pubptr->publish ((str != nullptr) ? str : ""); + } + return helics_ok; } - else + catch (...) { - pubObj->pubptr->publish ((str != nullptr) ? str : ""); + return helicsErrorHandler (); } - return helics_ok; } helics_status helicsPublicationPublishInteger (helics_publication pub, int64_t val) @@ -348,34 +370,48 @@ helics_status helicsPublicationPublishInteger (helics_publication pub, int64_t v { return helics_error; } - auto pubObj = reinterpret_cast (pub); - if (pubObj->rawOnly) + try { - pubObj->fedptr->publish (pubObj->id, val); + auto pubObj = reinterpret_cast (pub); + if (pubObj->rawOnly) + { + pubObj->fedptr->publish (pubObj->id, val); + } + else + { + pubObj->pubptr->publish (val); + } + return helics_ok; } - else + catch (...) { - pubObj->pubptr->publish (val); + return helicsErrorHandler (); } - return helics_ok; } -helics_status helicsPublicationPublishBoolean(helics_publication pub, helics_bool_t val) +helics_status helicsPublicationPublishBoolean (helics_publication pub, helics_bool_t val) { if (pub == nullptr) { return helics_error; } - auto pubObj = reinterpret_cast (pub); - if (pubObj->rawOnly) + try { - pubObj->fedptr->publish(pubObj->id, (val!=helics_false)?"0":"1"); + auto pubObj = reinterpret_cast (pub); + if (pubObj->rawOnly) + { + pubObj->fedptr->publish (pubObj->id, (val != helics_false) ? "0" : "1"); + } + else + { + pubObj->pubptr->publish ((val != helics_false) ? true : false); + } + return helics_ok; } - else + catch (...) { - pubObj->pubptr->publish((val!=helics_false)?true:false); + return helicsErrorHandler (); } - return helics_ok; } helics_status helicsPublicationPublishDouble (helics_publication pub, double val) @@ -384,16 +420,23 @@ helics_status helicsPublicationPublishDouble (helics_publication pub, double val { return helics_error; } - auto pubObj = reinterpret_cast (pub); - if (pubObj->rawOnly) + try { - pubObj->fedptr->publish (pubObj->id, val); + auto pubObj = reinterpret_cast (pub); + if (pubObj->rawOnly) + { + pubObj->fedptr->publish (pubObj->id, val); + } + else + { + pubObj->pubptr->publish (val); + } + return helics_ok; } - else + catch (...) { - pubObj->pubptr->publish (val); + return helicsErrorHandler (); } - return helics_ok; } helics_status helicsPublicationPublishComplex (helics_publication pub, double real, double imag) @@ -402,16 +445,23 @@ helics_status helicsPublicationPublishComplex (helics_publication pub, double re { return helics_error; } - auto pubObj = reinterpret_cast (pub); - if (pubObj->rawOnly) + try { - pubObj->fedptr->publish (pubObj->id, std::complex (real, imag)); + auto pubObj = reinterpret_cast (pub); + if (pubObj->rawOnly) + { + pubObj->fedptr->publish (pubObj->id, std::complex (real, imag)); + } + else + { + pubObj->pubptr->publish (std::complex (real, imag)); + } + return helics_ok; } - else + catch (...) { - pubObj->pubptr->publish (std::complex (real, imag)); + return helicsErrorHandler (); } - return helics_ok; } helics_status helicsPublicationPublishVector (helics_publication pub, const double *vectorInput, int vectorlength) @@ -420,63 +470,76 @@ helics_status helicsPublicationPublishVector (helics_publication pub, const doub { return helics_invalid_object; } - auto pubObj = reinterpret_cast (pub); - if ((vectorInput == nullptr) || (vectorlength <= 0)) + try { - if (pubObj->rawOnly) + auto pubObj = reinterpret_cast (pub); + if ((vectorInput == nullptr) || (vectorlength <= 0)) { - pubObj->fedptr->publish(pubObj->id,std::vector()); + if (pubObj->rawOnly) + { + pubObj->fedptr->publish (pubObj->id, std::vector ()); + } + else + { + pubObj->pubptr->publish (std::vector ()); + } } else { - pubObj->pubptr->publish(std::vector()); + if (pubObj->rawOnly) + { + pubObj->fedptr->publish (pubObj->id, std::vector (vectorInput, vectorInput + vectorlength)); + } + else + { + pubObj->pubptr->publish (std::vector (vectorInput, vectorInput + vectorlength)); + } } - + return helics_ok; } - else + catch (...) { - if (pubObj->rawOnly) - { - pubObj->fedptr->publish (pubObj->id, std::vector (vectorInput, vectorInput + vectorlength)); - } - else - { - pubObj->pubptr->publish (std::vector (vectorInput, vectorInput + vectorlength)); - } + return helicsErrorHandler (); } - return helics_ok; } -helics_status helicsPublicationPublishNamedPoint(helics_publication pub, const char *str, double val) +helics_status helicsPublicationPublishNamedPoint (helics_publication pub, const char *str, double val) { if (pub == nullptr) { return helics_invalid_object; } - auto pubObj = reinterpret_cast (pub); - if (str == nullptr) + try { - if (pubObj->rawOnly) + auto pubObj = reinterpret_cast (pub); + if (str == nullptr) { - pubObj->fedptr->publish(pubObj->id, helics::named_point(std::string(), val)); + if (pubObj->rawOnly) + { + pubObj->fedptr->publish (pubObj->id, helics::named_point (std::string (), val)); + } + else + { + pubObj->pubptr->publish (std::string (), val); + } } else { - pubObj->pubptr->publish(std::string(), val); + if (pubObj->rawOnly) + { + pubObj->fedptr->publish (pubObj->id, helics::named_point (str, val)); + } + else + { + pubObj->pubptr->publish (str, val); + } } + return helics_ok; } - else + catch (...) { - if (pubObj->rawOnly) - { - pubObj->fedptr->publish(pubObj->id, helics::named_point(str,val)); - } - else - { - pubObj->pubptr->publish(str,val); - } + return helicsErrorHandler (); } - return helics_ok; } int helicsSubscriptionGetValueSize (helics_subscription sub) @@ -506,38 +569,45 @@ helics_status helicsSubscriptionGetRawValue (helics_subscription sub, void *data { return helics_invalid_argument; } - auto subObj = reinterpret_cast (sub); - if (subObj->rawOnly) + try { - auto dv = subObj->fedptr->getValueRaw (subObj->id); - if (maxDatalen > static_cast (dv.size ())) + auto subObj = reinterpret_cast (sub); + if (subObj->rawOnly) { - memcpy (data, dv.data (), dv.size ()); + auto dv = subObj->fedptr->getValueRaw (subObj->id); + if (maxDatalen > static_cast (dv.size ())) + { + memcpy (data, dv.data (), dv.size ()); + if (actualSize != nullptr) + { + *actualSize = static_cast (dv.size ()); + } + + return helics_ok; + } + memcpy (data, dv.data (), maxDatalen); if (actualSize != nullptr) { - *actualSize = static_cast (dv.size ()); + *actualSize = maxDatalen; } - - return helics_ok; + return helics_warning; } - memcpy (data, dv.data (), maxDatalen); - if (actualSize != nullptr) + + auto str = subObj->subptr->getValue (); + if (maxDatalen > static_cast (str.size ())) { - *actualSize = maxDatalen; + memcpy (data, str.data (), static_cast (str.size ())); + *actualSize = static_cast (str.size ()); + return helics_ok; } + memcpy (data, str.data (), maxDatalen); + *actualSize = maxDatalen; return helics_warning; } - - auto str = subObj->subptr->getValue (); - if (maxDatalen > static_cast (str.size ())) + catch (...) { - memcpy (data, str.data (), static_cast (str.size ())); - *actualSize = static_cast (str.size ()); - return helics_ok; + return helicsErrorHandler (); } - memcpy (data, str.data (), maxDatalen); - *actualSize = maxDatalen; - return helics_warning; } helics_status helicsSubscriptionGetString (helics_subscription sub, char *outputString, int maxlen, int *actualLength) @@ -551,16 +621,22 @@ helics_status helicsSubscriptionGetString (helics_subscription sub, char *output { return helics_invalid_argument; } - - auto res = helicsSubscriptionGetRawValue (sub, outputString, maxlen, actualLength); - // make sure we have a null terminator - if (*actualLength == maxlen) + try { - outputString[maxlen - 1] = '\0'; - return helics_warning; + auto res = helicsSubscriptionGetRawValue (sub, outputString, maxlen, actualLength); + // make sure we have a null terminator + if (*actualLength == maxlen) + { + outputString[maxlen - 1] = '\0'; + return helics_warning; + } + outputString[*actualLength] = '\0'; + return res; + } + catch (...) + { + return helicsErrorHandler (); } - outputString[*actualLength] = '\0'; - return res; } helics_status helicsSubscriptionGetInteger (helics_subscription sub, int64_t *val) @@ -573,19 +649,26 @@ helics_status helicsSubscriptionGetInteger (helics_subscription sub, int64_t *va { return helics_invalid_argument; } - auto subObj = reinterpret_cast (sub); - if (subObj->rawOnly) + try { - *val = subObj->fedptr->getValue (subObj->id); + auto subObj = reinterpret_cast (sub); + if (subObj->rawOnly) + { + *val = subObj->fedptr->getValue (subObj->id); + } + else + { + subObj->subptr->getValue (*val); + } + return helics_ok; } - else + catch (...) { - subObj->subptr->getValue (*val); + return helicsErrorHandler (); } - return helics_ok; } -helics_status helicsSubscriptionGetBoolean(helics_subscription sub, helics_bool_t *val) +helics_status helicsSubscriptionGetBoolean (helics_subscription sub, helics_bool_t *val) { if (sub == nullptr) { @@ -595,31 +678,38 @@ helics_status helicsSubscriptionGetBoolean(helics_subscription sub, helics_bool_ { return helics_invalid_argument; } - auto subObj = reinterpret_cast (sub); - bool boolval; - if (subObj->rawOnly) + try { - auto str = subObj->fedptr->getValue(subObj->id); - if (str.size() == 1) - { - boolval = (str[0] != '0'); - } - else if (str.size() == 9) + auto subObj = reinterpret_cast (sub); + bool boolval; + if (subObj->rawOnly) { - auto ival= subObj->fedptr->getValue(subObj->id); - boolval = (ival != 0); + auto str = subObj->fedptr->getValue (subObj->id); + if (str.size () == 1) + { + boolval = (str[0] != '0'); + } + else if (str.size () == 9) + { + auto ival = subObj->fedptr->getValue (subObj->id); + boolval = (ival != 0); + } + else + { + boolval = true; + } } else { - boolval = true; + boolval = subObj->subptr->getValue (); } + *val = (boolval) ? helics_true : helics_false; + return helics_ok; } - else + catch (...) { - boolval=subObj->subptr->getValue(); + return helicsErrorHandler (); } - *val = (boolval) ? helics_true : helics_false; - return helics_ok; } helics_status helicsSubscriptionGetDouble (helics_subscription sub, double *val) @@ -632,16 +722,23 @@ helics_status helicsSubscriptionGetDouble (helics_subscription sub, double *val) { return helics_invalid_argument; } - auto subObj = reinterpret_cast (sub); - if (subObj->rawOnly) + try { - *val = subObj->fedptr->getValue (subObj->id); + auto subObj = reinterpret_cast (sub); + if (subObj->rawOnly) + { + *val = subObj->fedptr->getValue (subObj->id); + } + else + { + *val = subObj->subptr->getValue (); + } + return helics_ok; } - else + catch (...) { - *val = subObj->subptr->getValue (); + return helicsErrorHandler (); } - return helics_ok; } helics_status helicsSubscriptionGetComplex (helics_subscription sub, double *real, double *imag) @@ -654,21 +751,27 @@ helics_status helicsSubscriptionGetComplex (helics_subscription sub, double *rea { return helics_invalid_argument; } - - auto subObj = reinterpret_cast (sub); - if (subObj->rawOnly) + try { - auto cval = subObj->fedptr->getValue> (subObj->id); - *real = cval.real (); - *imag = cval.imag (); + auto subObj = reinterpret_cast (sub); + if (subObj->rawOnly) + { + auto cval = subObj->fedptr->getValue> (subObj->id); + *real = cval.real (); + *imag = cval.imag (); + } + else + { + auto cval = subObj->subptr->getValue> (); + *real = cval.real (); + *imag = cval.imag (); + } + return helics_ok; } - else + catch (...) { - auto cval = subObj->subptr->getValue> (); - *real = cval.real (); - *imag = cval.imag (); + return helicsErrorHandler (); } - return helics_ok; } int helicsSubscriptionGetVectorSize (helics_subscription sub) @@ -698,10 +801,22 @@ helics_status helicsSubscriptionGetVector (helics_subscription sub, double data[ { return helics_invalid_argument; } - auto subObj = reinterpret_cast (sub); - if (subObj->rawOnly) + try { - auto V = subObj->fedptr->getValue> (subObj->id); + auto subObj = reinterpret_cast (sub); + if (subObj->rawOnly) + { + auto V = subObj->fedptr->getValue> (subObj->id); + int length = std::min (static_cast (V.size ()), maxlen); + std::copy (V.data (), V.data () + length, data); + if (actualSize != nullptr) + { + *actualSize = length; + } + return (length < maxlen) ? helics_ok : helics_warning; + } + + auto V = subObj->subptr->getValue> (); int length = std::min (static_cast (V.size ()), maxlen); std::copy (V.data (), V.data () + length, data); if (actualSize != nullptr) @@ -710,18 +825,14 @@ helics_status helicsSubscriptionGetVector (helics_subscription sub, double data[ } return (length < maxlen) ? helics_ok : helics_warning; } - - auto V = subObj->subptr->getValue> (); - int length = std::min (static_cast (V.size ()), maxlen); - std::copy (V.data (), V.data () + length, data); - if (actualSize != nullptr) + catch (...) { - *actualSize = length; + return helicsErrorHandler (); } - return (length < maxlen) ? helics_ok : helics_warning; } -helics_status helicsSubscriptionGetNamedPoint(helics_subscription sub, char *outputString, int maxStringlen, int *actualLength, double *val) +helics_status +helicsSubscriptionGetNamedPoint (helics_subscription sub, char *outputString, int maxStringlen, int *actualLength, double *val) { if (sub == nullptr) { @@ -731,19 +842,21 @@ helics_status helicsSubscriptionGetNamedPoint(helics_subscription sub, char *out { return helics_invalid_argument; } - auto subObj = reinterpret_cast (sub); - helics::named_point np; - if (subObj->rawOnly) - { - np = subObj->fedptr->getValue(subObj->id); - } - else + try { - np = subObj->subptr->getValue(); - } - int length = std::min(static_cast (np.name.size()), maxStringlen); - memcpy(outputString, np.name.data(), length); - + auto subObj = reinterpret_cast (sub); + helics::named_point np; + if (subObj->rawOnly) + { + np = subObj->fedptr->getValue (subObj->id); + } + else + { + np = subObj->subptr->getValue (); + } + int length = std::min (static_cast (np.name.size ()), maxStringlen); + memcpy (outputString, np.name.data (), length); + if (length == maxStringlen) { outputString[maxStringlen - 1] = '\0'; @@ -761,7 +874,11 @@ helics_status helicsSubscriptionGetNamedPoint(helics_subscription sub, char *out *val = np.value; } return (length < maxStringlen) ? helics_ok : helics_warning; - + } + catch (...) + { + return helicsErrorHandler (); + } } helics_status helicsSubscriptionSetDefaultRaw (helics_subscription sub, const void *data, int dataLen) @@ -770,18 +887,25 @@ helics_status helicsSubscriptionSetDefaultRaw (helics_subscription sub, const vo { return helics_invalid_object; } - auto subObj = reinterpret_cast (sub); - - if ((data == nullptr) || (dataLen <= 0)) + try { - subObj->fedptr->setDefaultValue (subObj->id, std::string ()); + auto subObj = reinterpret_cast (sub); + + if ((data == nullptr) || (dataLen <= 0)) + { + subObj->fedptr->setDefaultValue (subObj->id, std::string ()); + } + else + { + subObj->fedptr->setDefaultValue (subObj->id, helics::data_view ((const char *)data, dataLen)); + } + + return helics_ok; } - else + catch (...) { - subObj->fedptr->setDefaultValue (subObj->id, helics::data_view ((const char *)data, dataLen)); + return helicsErrorHandler (); } - - return helics_ok; } helics_status helicsSubscriptionSetDefaultString (helics_subscription sub, const char *str) @@ -790,16 +914,23 @@ helics_status helicsSubscriptionSetDefaultString (helics_subscription sub, const { return helics_invalid_object; } - auto subObj = reinterpret_cast (sub); - if (subObj->rawOnly) + try { - subObj->fedptr->setDefaultValue (subObj->id, helics::data_view ((str == nullptr) ? str : "")); + auto subObj = reinterpret_cast (sub); + if (subObj->rawOnly) + { + subObj->fedptr->setDefaultValue (subObj->id, helics::data_view ((str == nullptr) ? str : "")); + } + else + { + subObj->subptr->setDefault (str); + } + return helics_ok; } - else + catch (...) { - subObj->subptr->setDefault (str); + return helicsErrorHandler (); } - return helics_ok; } helics_status helicsSubscriptionSetDefaultInteger (helics_subscription sub, int64_t val) @@ -808,34 +939,48 @@ helics_status helicsSubscriptionSetDefaultInteger (helics_subscription sub, int6 { return helics_invalid_object; } - auto subObj = reinterpret_cast (sub); - if (subObj->rawOnly) + try { - subObj->fedptr->setDefaultValue (subObj->id, val); + auto subObj = reinterpret_cast (sub); + if (subObj->rawOnly) + { + subObj->fedptr->setDefaultValue (subObj->id, val); + } + else + { + subObj->subptr->setDefault (val); + } + return helics_ok; } - else + catch (...) { - subObj->subptr->setDefault (val); + return helicsErrorHandler (); } - return helics_ok; } -helics_status helicsSubscriptionSetDefaultBoolean(helics_subscription sub, helics_bool_t val) +helics_status helicsSubscriptionSetDefaultBoolean (helics_subscription sub, helics_bool_t val) { if (sub == nullptr) { return helics_invalid_object; } - auto subObj = reinterpret_cast (sub); - if (subObj->rawOnly) + try { - subObj->fedptr->setDefaultValue(subObj->id, helics::data_view((val!=helics_false)?"1":"0")); + auto subObj = reinterpret_cast (sub); + if (subObj->rawOnly) + { + subObj->fedptr->setDefaultValue (subObj->id, helics::data_view ((val != helics_false) ? "1" : "0")); + } + else + { + subObj->subptr->setDefault ((val != helics_false) ? true : false); + } + return helics_ok; } - else + catch (...) { - subObj->subptr->setDefault((val != helics_false) ? true : false); + return helicsErrorHandler (); } - return helics_ok; } helics_status helicsSubscriptionSetDefaultDouble (helics_subscription sub, double val) @@ -844,16 +989,23 @@ helics_status helicsSubscriptionSetDefaultDouble (helics_subscription sub, doubl { return helics_invalid_object; } - auto subObj = reinterpret_cast (sub); - if (subObj->rawOnly) + try { - subObj->fedptr->setDefaultValue (subObj->id, val); + auto subObj = reinterpret_cast (sub); + if (subObj->rawOnly) + { + subObj->fedptr->setDefaultValue (subObj->id, val); + } + else + { + subObj->subptr->setDefault (val); + } + return helics_ok; } - else + catch (...) { - subObj->subptr->setDefault (val); + return helicsErrorHandler (); } - return helics_ok; } helics_status helicsSubscriptionSetDefaultComplex (helics_subscription sub, double real, double imag) { @@ -861,16 +1013,23 @@ helics_status helicsSubscriptionSetDefaultComplex (helics_subscription sub, doub { return helics_invalid_object; } - auto subObj = reinterpret_cast (sub); - if (subObj->rawOnly) + try { - subObj->fedptr->setDefaultValue (subObj->id, std::complex (real, imag)); + auto subObj = reinterpret_cast (sub); + if (subObj->rawOnly) + { + subObj->fedptr->setDefaultValue (subObj->id, std::complex (real, imag)); + } + else + { + subObj->subptr->setDefault (std::complex (real, imag)); + } + return helics_ok; } - else + catch (...) { - subObj->subptr->setDefault (std::complex (real, imag)); + return helicsErrorHandler (); } - return helics_ok; } helics_status helicsSubscriptionSetDefaultVector (helics_subscription sub, const double *vectorInput, int vectorlength) @@ -879,49 +1038,63 @@ helics_status helicsSubscriptionSetDefaultVector (helics_subscription sub, const { return helics_invalid_object; } - auto subObj = reinterpret_cast (sub); - if ((vectorInput == nullptr) || (vectorlength <= 0)) + try { - if (subObj->rawOnly) + auto subObj = reinterpret_cast (sub); + if ((vectorInput == nullptr) || (vectorlength <= 0)) { - subObj->fedptr->setDefaultValue (subObj->id, std::vector{}); + if (subObj->rawOnly) + { + subObj->fedptr->setDefaultValue (subObj->id, std::vector{}); + } + else + { + subObj->subptr->setDefault (std::vector{}); + } } else { - subObj->subptr->setDefault (std::vector{}); + if (subObj->rawOnly) + { + subObj->fedptr->setDefaultValue (subObj->id, std::vector (vectorInput, vectorInput + vectorlength)); + } + else + { + subObj->subptr->setDefault (std::vector (vectorInput, vectorInput + vectorlength)); + } } + + return helics_ok; } - else + catch (...) { - if (subObj->rawOnly) - { - subObj->fedptr->setDefaultValue (subObj->id, std::vector (vectorInput, vectorInput + vectorlength)); - } - else - { - subObj->subptr->setDefault (std::vector (vectorInput, vectorInput + vectorlength)); - } + return helicsErrorHandler (); } - - return helics_ok; } -helics_status helicsSubscriptionSetDefaultNamedPoint(helics_subscription sub, const char *str, double val) +helics_status helicsSubscriptionSetDefaultNamedPoint (helics_subscription sub, const char *str, double val) { if (sub == nullptr) { return helics_invalid_object; } - auto subObj = reinterpret_cast (sub); - if (subObj->rawOnly) + try { - subObj->fedptr->setDefaultValue(subObj->id, helics::named_point((str != nullptr) ? str : "",val)); + auto subObj = reinterpret_cast (sub); + if (subObj->rawOnly) + { + subObj->fedptr->setDefaultValue (subObj->id, helics::named_point ((str != nullptr) ? str : "", val)); + } + else + { + subObj->subptr->setDefault (helics::named_point ((str != nullptr) ? str : "", val)); + } + return helics_ok; } - else + catch (...) { - subObj->subptr->setDefault(helics::named_point((str != nullptr) ? str : "",val)); + return helicsErrorHandler (); } - return helics_ok; } helics_status helicsSubscriptionGetType (helics_subscription sub, char *outputString, int maxlen) @@ -934,26 +1107,33 @@ helics_status helicsSubscriptionGetType (helics_subscription sub, char *outputSt { return helics_invalid_argument; } - auto subObj = reinterpret_cast (sub); - std::string type; - if (subObj->rawOnly) - { - type = subObj->fedptr->getSubscriptionType (subObj->id); - } - else - { - type = subObj->subptr->getType (); - } - if (static_cast (type.size ()) > maxlen) + try { - strncpy (outputString, type.c_str (), maxlen); - outputString[maxlen - 1] = 0; + auto subObj = reinterpret_cast (sub); + std::string type; + if (subObj->rawOnly) + { + type = subObj->fedptr->getSubscriptionType (subObj->id); + } + else + { + type = subObj->subptr->getType (); + } + if (static_cast (type.size ()) > maxlen) + { + strncpy (outputString, type.c_str (), maxlen); + outputString[maxlen - 1] = 0; + } + else + { + strcpy (outputString, type.c_str ()); + } + return helics_ok; } - else + catch (...) { - strcpy (outputString, type.c_str ()); + return helicsErrorHandler (); } - return helics_ok; } helics_status helicsPublicationGetType (helics_publication pub, char *outputString, int maxlen) @@ -966,26 +1146,33 @@ helics_status helicsPublicationGetType (helics_publication pub, char *outputStri { return helics_invalid_argument; } - auto pubObj = reinterpret_cast (pub); - std::string type; - if (pubObj->rawOnly) - { - type = pubObj->fedptr->getPublicationType (pubObj->id); - } - else - { - type = pubObj->pubptr->getType (); - } - if (static_cast (type.size ()) > maxlen) + try { - strncpy (outputString, type.c_str (), maxlen); - outputString[maxlen - 1] = 0; + auto pubObj = reinterpret_cast (pub); + std::string type; + if (pubObj->rawOnly) + { + type = pubObj->fedptr->getPublicationType (pubObj->id); + } + else + { + type = pubObj->pubptr->getType (); + } + if (static_cast (type.size ()) > maxlen) + { + strncpy (outputString, type.c_str (), maxlen); + outputString[maxlen - 1] = 0; + } + else + { + strcpy (outputString, type.c_str ()); + } + return helics_ok; } - else + catch (...) { - strcpy (outputString, type.c_str ()); + return helicsErrorHandler (); } - return helics_ok; } helics_status helicsSubscriptionGetKey (helics_subscription sub, char *outputString, int maxlen) @@ -998,26 +1185,33 @@ helics_status helicsSubscriptionGetKey (helics_subscription sub, char *outputStr { return helics_invalid_argument; } - auto subObj = reinterpret_cast (sub); - std::string type; - if (subObj->rawOnly) - { - type = subObj->fedptr->getSubscriptionKey (subObj->id); - } - else - { - type = subObj->subptr->getKey (); - } - if (static_cast (type.size ()) > maxlen) + try { - strncpy (outputString, type.c_str (), maxlen); - outputString[maxlen - 1] = 0; + auto subObj = reinterpret_cast (sub); + std::string type; + if (subObj->rawOnly) + { + type = subObj->fedptr->getSubscriptionKey (subObj->id); + } + else + { + type = subObj->subptr->getKey (); + } + if (static_cast (type.size ()) > maxlen) + { + strncpy (outputString, type.c_str (), maxlen); + outputString[maxlen - 1] = 0; + } + else + { + strcpy (outputString, type.c_str ()); + } + return helics_ok; } - else + catch (...) { - strcpy (outputString, type.c_str ()); + return helicsErrorHandler (); } - return helics_ok; } helics_status helicsPublicationGetKey (helics_publication pub, char *outputString, int maxlen) @@ -1030,26 +1224,33 @@ helics_status helicsPublicationGetKey (helics_publication pub, char *outputStrin { return helics_invalid_argument; } - auto pubObj = reinterpret_cast (pub); - std::string type; - if (pubObj->rawOnly) - { - type = pubObj->fedptr->getPublicationKey (pubObj->id); - } - else - { - type = pubObj->pubptr->getKey (); - } - if (static_cast (type.size ()) > maxlen) + try { - strncpy (outputString, type.c_str (), maxlen); - outputString[maxlen - 1] = 0; + auto pubObj = reinterpret_cast (pub); + std::string type; + if (pubObj->rawOnly) + { + type = pubObj->fedptr->getPublicationKey (pubObj->id); + } + else + { + type = pubObj->pubptr->getKey (); + } + if (static_cast (type.size ()) > maxlen) + { + strncpy (outputString, type.c_str (), maxlen); + outputString[maxlen - 1] = 0; + } + else + { + strcpy (outputString, type.c_str ()); + } + return helics_ok; } - else + catch (...) { - strcpy (outputString, type.c_str ()); + return helicsErrorHandler (); } - return helics_ok; } helics_status helicsSubscriptionGetUnits (helics_subscription sub, char *outputString, int maxlen) @@ -1062,26 +1263,33 @@ helics_status helicsSubscriptionGetUnits (helics_subscription sub, char *outputS { return helics_invalid_argument; } - auto subObj = reinterpret_cast (sub); - std::string type; - if (subObj->rawOnly) - { - type = subObj->fedptr->getSubscriptionUnits (subObj->id); - } - else - { - type = subObj->subptr->getUnits (); - } - if (static_cast (type.size ()) > maxlen) + try { - strncpy (outputString, type.c_str (), maxlen); - outputString[maxlen - 1] = 0; + auto subObj = reinterpret_cast (sub); + std::string type; + if (subObj->rawOnly) + { + type = subObj->fedptr->getSubscriptionUnits (subObj->id); + } + else + { + type = subObj->subptr->getUnits (); + } + if (static_cast (type.size ()) > maxlen) + { + strncpy (outputString, type.c_str (), maxlen); + outputString[maxlen - 1] = 0; + } + else + { + strcpy (outputString, type.c_str ()); + } + return helics_ok; } - else + catch (...) { - strcpy (outputString, type.c_str ()); + return helicsErrorHandler (); } - return helics_ok; } helics_status helicsPublicationGetUnits (helics_publication pub, char *outputString, int maxlen) @@ -1094,33 +1302,40 @@ helics_status helicsPublicationGetUnits (helics_publication pub, char *outputStr { return helics_invalid_argument; } - auto pubObj = reinterpret_cast (pub); - std::string type; - if (pubObj->rawOnly) - { - type = pubObj->fedptr->getPublicationUnits (pubObj->id); - } - else - { - type = pubObj->pubptr->getUnits (); - } - if (static_cast (type.size ()) > maxlen) + try { - strncpy (outputString, type.c_str (), maxlen); - outputString[maxlen - 1] = 0; + auto pubObj = reinterpret_cast (pub); + std::string type; + if (pubObj->rawOnly) + { + type = pubObj->fedptr->getPublicationUnits (pubObj->id); + } + else + { + type = pubObj->pubptr->getUnits (); + } + if (static_cast (type.size ()) > maxlen) + { + strncpy (outputString, type.c_str (), maxlen); + outputString[maxlen - 1] = 0; + } + else + { + strcpy (outputString, type.c_str ()); + } + return helics_ok; } - else + catch (...) { - strcpy (outputString, type.c_str ()); + return helicsErrorHandler (); } - return helics_ok; } helics_bool_t helicsSubscriptionIsUpdated (helics_subscription sub) { if (sub == nullptr) { - return helics_invalid_object; + return helics_false; } auto subObj = reinterpret_cast (sub); if (subObj->rawOnly) @@ -1131,7 +1346,7 @@ helics_bool_t helicsSubscriptionIsUpdated (helics_subscription sub) else { auto val = subObj->subptr->isUpdated (); - return (val) ? 1 : 0; + return (val) ? helics_true : helics_false; } } @@ -1139,7 +1354,7 @@ helics_time_t helicsSubscriptionLastUpdateTime (helics_subscription sub) { if (sub == nullptr) { - return helics_invalid_object; + return 1e-37; } auto subObj = reinterpret_cast (sub); if (subObj->rawOnly) diff --git a/src/helics/shared_api_library/helicsCallbacks.cpp b/src/helics/shared_api_library/helicsCallbacks.cpp index c0f0a588f1..217f1abf91 100644 --- a/src/helics/shared_api_library/helicsCallbacks.cpp +++ b/src/helics/shared_api_library/helicsCallbacks.cpp @@ -22,15 +22,22 @@ helics_status helicsBrokerAddLoggingCallback (helics_broker broker, void (*logge { return helics_invalid_object; } - auto brk = getBroker (broker); - if (brk == nullptr) + try { - return helics_invalid_object; + auto brk = getBroker (broker); + if (brk == nullptr) + { + return helics_invalid_object; + } + brk->setLoggingCallback ([logger](int loglevel, const std::string &ident, const std::string &message) { + logger (loglevel, ident.c_str (), message.c_str ()); + }); + return helics_ok; + } + catch (...) + { + return helicsErrorHandler (); } - brk->setLoggingCallback ([logger](int loglevel, const std::string &ident, const std::string &message) { - logger (loglevel, ident.c_str (), message.c_str ()); - }); - return helics_ok; } helics_status helicsCoreAddLoggingCallback (helics_core core, void (*logger) (int, const char *, const char *)) @@ -39,15 +46,22 @@ helics_status helicsCoreAddLoggingCallback (helics_core core, void (*logger) (in { return helics_invalid_object; } - auto cr = getCore (core); - if (cr == nullptr) + try { - return helics_invalid_object; + auto cr = getCore (core); + if (cr == nullptr) + { + return helics_invalid_object; + } + cr->setLoggingCallback (0, [logger](int loglevel, const std::string &ident, const std::string &message) { + logger (loglevel, ident.c_str (), message.c_str ()); + }); + return helics_ok; + } + catch (...) + { + return helicsErrorHandler (); } - cr->setLoggingCallback (0, [logger](int loglevel, const std::string &ident, const std::string &message) { - logger (loglevel, ident.c_str (), message.c_str ()); - }); - return helics_ok; } helics_status helicsFederateAddLoggingCallback (helics_federate fed, void (*logger) (int, const char *, const char *)) @@ -56,13 +70,20 @@ helics_status helicsFederateAddLoggingCallback (helics_federate fed, void (*logg { return helics_invalid_object; } - auto fedptr = getFed (fed); - if (fedptr == nullptr) + try { - return helics_invalid_object; + auto fedptr = getFed (fed); + if (fedptr == nullptr) + { + return helics_invalid_object; + } + fedptr->setLoggingCallback ([logger](int loglevel, const std::string &ident, const std::string &message) { + logger (loglevel, ident.c_str (), message.c_str ()); + }); + return helics_ok; + } + catch (...) + { + return helicsErrorHandler (); } - fedptr->setLoggingCallback ([logger](int loglevel, const std::string &ident, const std::string &message) { - logger (loglevel, ident.c_str (), message.c_str ()); - }); - return helics_ok; } diff --git a/src/helics/shared_api_library/helicsExport.cpp b/src/helics/shared_api_library/helicsExport.cpp index a34d538c1f..263160f279 100644 --- a/src/helics/shared_api_library/helicsExport.cpp +++ b/src/helics/shared_api_library/helicsExport.cpp @@ -16,6 +16,8 @@ All rights reserved. See LICENSE file and DISCLAIMER for more details. #include #include +#include "../core/core-exceptions.hpp" + #include "../core/helicsVersion.hpp" #include "helics/helics-config.h" #if HELICS_HAVE_ZEROMQ > 0 @@ -41,6 +43,60 @@ helics_federate_info_t helicsFederateInfoCreate () return reinterpret_cast (fi); } +// typedef enum { + +// helics_ok = 0, /*!< the function executed successfully */ +// helics_invalid_object, /*!< indicator that the object used was not a valid object */ +// helics_invalid_argument, /*!< the parameter passed was invalid and unable to be used*/ +// helics_discard, /*!< the input was discarded and not used for some reason */ +// helics_terminated, /*!< the federate has terminated and the call cannot be completed*/ +// helics_warning, /*!< the function issued a warning of some kind */ +// helics_invalid_state_transition, /*!< error issued when an invalid state transition occurred */ +// helics_invalid_function_call, /*!< the call made was invalid in the present state of the calling object*/ +// helics_error /*!< the function produced an error */ +//} helics_status; + +/** this function is based on the lippencott function template +http://cppsecrets.blogspot.com/2013/12/using-lippincott-function-for.html +*/ +helics_status helicsErrorHandler () noexcept +{ + try + { + try + { + if (std::exception_ptr eptr = std::current_exception ()) + { + std::rethrow_exception (eptr); + } + else + { + return helics_error; + } + } + catch (const helics::InvalidIdentifier &) + { + return helics_invalid_object; + } + catch (const helics::InvalidFunctionCall &) + { + return helics_invalid_function_call; + } + catch (const helics::InvalidParameter &) + { + return helics_invalid_argument; + } + catch (...) + { + return helics_error; + } + } + catch (...) + { + return helics_error; + } +} + void helicsFederateInfoFree (helics_federate_info_t fi) { delete reinterpret_cast (fi); } static const std::string nullstr; @@ -52,8 +108,15 @@ helics_status helicsFederateInfoLoadFromArgs (helics_federate_info_t fi, int arg return helics_discard; } auto hfi = reinterpret_cast (fi); - hfi->loadInfoFromArgs (argc, argv); - return helics_ok; + try + { + hfi->loadInfoFromArgs (argc, argv); + return helics_ok; + } + catch (...) + { + return helicsErrorHandler (); + } } helics_status helicsFederateInfoSetFederateName (helics_federate_info_t fi, const char *name) @@ -63,8 +126,15 @@ helics_status helicsFederateInfoSetFederateName (helics_federate_info_t fi, cons return helics_invalid_object; } auto hfi = reinterpret_cast (fi); - hfi->name = (name != nullptr) ? std::string (name) : nullstr; - return helics_ok; + try + { + hfi->name = (name != nullptr) ? std::string (name) : nullstr; + return helics_ok; + } + catch (...) + { + return helicsErrorHandler (); + } } helics_status helicsFederateInfoSetCoreName (helics_federate_info_t fi, const char *corename) { @@ -73,9 +143,16 @@ helics_status helicsFederateInfoSetCoreName (helics_federate_info_t fi, const ch return helics_invalid_object; } auto hfi = reinterpret_cast (fi); - hfi->coreName = (corename != nullptr) ? std::string (corename) : nullstr; + try + { + hfi->coreName = (corename != nullptr) ? std::string (corename) : nullstr; - return helics_ok; + return helics_ok; + } + catch (...) + { + return helicsErrorHandler (); + } } helics_status helicsFederateInfoSetCoreInitString (helics_federate_info_t fi, const char *coreinit) @@ -85,8 +162,15 @@ helics_status helicsFederateInfoSetCoreInitString (helics_federate_info_t fi, co return helics_invalid_object; } auto hfi = reinterpret_cast (fi); - hfi->coreInitString = (coreinit != nullptr) ? std::string (coreinit) : nullstr; - return helics_ok; + try + { + hfi->coreInitString = (coreinit != nullptr) ? std::string (coreinit) : nullstr; + return helics_ok; + } + catch (...) + { + return helicsErrorHandler (); + } } helics_status helicsFederateInfoSetCoreType (helics_federate_info_t fi, int coretype) @@ -117,12 +201,12 @@ helics_status helicsFederateInfoSetCoreTypeFromString (helics_federate_info_t fi { hfi->coreType = helics::coreTypeFromString (coretype); } + return helics_ok; } - catch (const std::invalid_argument &ie) + catch (...) { - return helics_error; + return helicsErrorHandler (); } - return helics_ok; } helics_status helicsFederateInfoSetFlag (helics_federate_info_t fi, int flag, helics_bool_t value) @@ -169,6 +253,10 @@ helics_status helicsFederateInfoSetOutputDelay (helics_federate_info_t fi, helic { return helics_invalid_object; } + if (outputDelay < helics_time_zero) + { + return helics_invalid_argument; + } auto hfi = reinterpret_cast (fi); hfi->outputDelay = outputDelay; return helics_ok; @@ -180,6 +268,10 @@ helics_status helicsFederateInfoSetTimeDelta (helics_federate_info_t fi, helics_ { return helics_invalid_object; } + if (timeDelta < helics_time_zero) + { + return helics_invalid_argument; + } auto hfi = reinterpret_cast (fi); hfi->timeDelta = timeDelta; return helics_ok; @@ -191,6 +283,10 @@ helics_status helicsFederateInfoSetInputDelay (helics_federate_info_t fi, helics { return helics_invalid_object; } + if (inputDelay < helics_time_zero) + { + return helics_invalid_argument; + } auto hfi = reinterpret_cast (fi); hfi->inputDelay = inputDelay; return helics_ok; @@ -212,9 +308,9 @@ helics_status helicsFederateInfoSetPeriod (helics_federate_info_t fi, helics_tim return helics_invalid_object; } auto hfi = reinterpret_cast (fi); - if (period < 0) + if (period < helics_time_zero) { - return helics_discard; + return helics_invalid_argument; } hfi->period = period; return helics_ok; @@ -237,6 +333,10 @@ helics_status helicsFederateInfoSetMaxIterations (helics_federate_info_t fi, int { return helics_invalid_object; } + if (maxIterations < 0) + { + maxIterations = 10'000'000; + } auto hfi = reinterpret_cast (fi); hfi->maxIterations = maxIterations; return helics_ok; @@ -293,13 +393,13 @@ helics_core helicsCreateCore (const char *type, const char *name, const char *in { return nullptr; } - auto core = std::make_unique(); + auto core = std::make_unique (); core->valid = coreValidationIdentifier; core->coreptr = helics::CoreFactory::FindOrCreate (ct, (name != nullptr) ? std::string (name) : nullstr, (initString != nullptr) ? std::string (initString) : nullstr); - auto retcore = reinterpret_cast (core.get()); - getMasterHolder()->addCore(std::move(core)); - + auto retcore = reinterpret_cast (core.get ()); + getMasterHolder ()->addCore (std::move (core)); + return retcore; } @@ -314,13 +414,13 @@ helics_core helicsCreateCoreFromArgs (const char *type, const char *name, int ar { return nullptr; } - auto core = std::make_unique(); - + auto core = std::make_unique (); + core->valid = coreValidationIdentifier; core->coreptr = helics::CoreFactory::FindOrCreate (ct, (name != nullptr) ? std::string (name) : nullstr, argc, argv); - auto retcore = reinterpret_cast (core.get()); - getMasterHolder()->addCore(std::move(core)); - + auto retcore = reinterpret_cast (core.get ()); + getMasterHolder ()->addCore (std::move (core)); + return retcore; } @@ -331,12 +431,12 @@ helics_core helicsCoreClone (helics_core core) return nullptr; } auto *coreObj = reinterpret_cast (core); - auto coreClone = std::make_unique(); + auto coreClone = std::make_unique (); coreClone->valid = coreValidationIdentifier; coreClone->coreptr = coreObj->coreptr; - auto retcore = reinterpret_cast (coreClone.get()); - getMasterHolder()->addCore(std::move(coreClone)); - + auto retcore = reinterpret_cast (coreClone.get ()); + getMasterHolder ()->addCore (std::move (coreClone)); + return retcore; } @@ -361,12 +461,12 @@ helics_broker helicsCreateBroker (const char *type, const char *name, const char { return nullptr; } - auto broker = std::make_unique(); + auto broker = std::make_unique (); broker->valid = brokerValidationIdentifier; broker->brokerptr = helics::BrokerFactory::create (ct, (name != nullptr) ? std::string (name) : nullstr, (initString != nullptr) ? std::string (initString) : nullstr); - auto retbroker = reinterpret_cast (broker.get()); - getMasterHolder()->addBroker(std::move(broker)); + auto retbroker = reinterpret_cast (broker.get ()); + getMasterHolder ()->addBroker (std::move (broker)); return retbroker; } @@ -381,11 +481,11 @@ helics_broker helicsCreateBrokerFromArgs (const char *type, const char *name, in { return nullptr; } - auto broker = std::make_unique(); + auto broker = std::make_unique (); broker->valid = brokerValidationIdentifier; broker->brokerptr = helics::BrokerFactory::create (ct, (name != nullptr) ? std::string (name) : nullstr, argc, argv); - auto retbroker = reinterpret_cast (broker.get()); - getMasterHolder()->addBroker(std::move(broker)); + auto retbroker = reinterpret_cast (broker.get ()); + getMasterHolder ()->addBroker (std::move (broker)); return retbroker; } @@ -396,11 +496,11 @@ helics_broker helicsBrokerClone (helics_broker broker) return nullptr; } auto *brokerObj = reinterpret_cast (broker); - auto brokerClone = std::make_unique(); + auto brokerClone = std::make_unique (); brokerClone->valid = brokerValidationIdentifier; brokerClone->brokerptr = brokerObj->brokerptr; - auto retbroker = reinterpret_cast (brokerClone.get()); - getMasterHolder()->addBroker(std::move(brokerClone)); + auto retbroker = reinterpret_cast (brokerClone.get ()); + getMasterHolder ()->addBroker (std::move (brokerClone)); return retbroker; } @@ -443,17 +543,24 @@ helics_status helicsBrokerGetIdentifier (helics_broker broker, char *identifier, { return helics_invalid_object; } - auto &ident = brk->getIdentifier (); - if (static_cast (ident.size ()) > maxlen) + try { - strncpy (identifier, ident.c_str (), maxlen); - identifier[maxlen - 1] = 0; + auto &ident = brk->getIdentifier (); + if (static_cast (ident.size ()) > maxlen) + { + strncpy (identifier, ident.c_str (), maxlen); + identifier[maxlen - 1] = '\0'; + } + else + { + strcpy (identifier, ident.c_str ()); + } + return helics_ok; } - else + catch (...) { - strcpy (identifier, ident.c_str ()); + return helicsErrorHandler (); } - return helics_ok; } helics_status helicsCoreGetIdentifier (helics_core core, char *identifier, int maxlen) @@ -467,18 +574,25 @@ helics_status helicsCoreGetIdentifier (helics_core core, char *identifier, int m { return helics_invalid_object; } - auto &ident = cr->getIdentifier (); - - if (static_cast (ident.size ()) > maxlen) + try { - strncpy (identifier, ident.c_str (), maxlen); - identifier[maxlen - 1] = 0; + auto &ident = cr->getIdentifier (); + + if (static_cast (ident.size ()) > maxlen) + { + strncpy (identifier, ident.c_str (), maxlen); + identifier[maxlen - 1] = 0; + } + else + { + strcpy (identifier, ident.c_str ()); + } + return helics_ok; } - else + catch (...) { - strcpy (identifier, ident.c_str ()); + return helicsErrorHandler (); } - return helics_ok; } helics_status helicsBrokerGetAddress (helics_broker broker, char *address, int maxlen) @@ -492,17 +606,24 @@ helics_status helicsBrokerGetAddress (helics_broker broker, char *address, int m { return helics_invalid_object; } - auto ident = brk->getAddress (); - if (static_cast (ident.size ()) > maxlen) + try { - strncpy (address, ident.c_str (), maxlen); - address[maxlen - 1] = 0; + auto ident = brk->getAddress (); + if (static_cast (ident.size ()) > maxlen) + { + strncpy (address, ident.c_str (), maxlen); + address[maxlen - 1] = 0; + } + else + { + strcpy (address, ident.c_str ()); + } + return helics_ok; } - else + catch (...) { - strcpy (address, ident.c_str ()); + return helicsErrorHandler (); } - return helics_ok; } helics_status helicsCoreSetReadyToInit (helics_core core) @@ -532,8 +653,15 @@ helics_status helicsCoreDisconnect (helics_core core) return helics_invalid_object; } - cr->disconnect (); - return helics_ok; + try + { + cr->disconnect (); + return helics_ok; + } + catch (...) + { + return helicsErrorHandler (); + } } helics_status helicsBrokerDisconnect (helics_broker broker) @@ -547,8 +675,15 @@ helics_status helicsBrokerDisconnect (helics_broker broker) { return helics_invalid_object; } - brk->disconnect (); - return helics_ok; + try + { + brk->disconnect (); + return helics_ok; + } + catch (...) + { + return helicsErrorHandler (); + } } void helicsCoreFree (helics_core core) @@ -584,31 +719,18 @@ void helicsFederateFree (helics_federate fed) helics::FedObject::~FedObject () { - for (auto sub : subs) - { - delete sub; - } - for (auto pub : pubs) - { - delete pub; - } - for (auto ept : epts) - { - delete ept; - } - for (auto filt : filters) - { - delete filt; - } + //we want to remove the values in the arrays before deleting the fedptr + // and we want to do it inside this function to ensure it does so in a consistent manner + subs.clear(); + pubs.clear(); + epts.clear(); + filters.clear(); fedptr = nullptr; } helics::CoreObject::~CoreObject () { - for (auto filt : filters) - { - delete filt; - } + filters.clear(); coreptr = nullptr; } @@ -636,20 +758,22 @@ helics_query helicsCreateQuery (const char *target, const char *query) return reinterpret_cast (queryObj); } +constexpr auto invalidStringConst = "#invalid"; + const char *helicsQueryExecute (helics_query query, helics_federate fed) { if (fed == nullptr) { - return nullptr; + return invalidStringConst; } if (query == nullptr) { - return nullptr; + return invalidStringConst; } auto fedObj = getFed (fed); if (fedObj == nullptr) { - return nullptr; + return invalidStringConst; } auto queryObj = reinterpret_cast (query); @@ -681,18 +805,25 @@ helics_status helicsQueryExecuteAsync (helics_query query, helics_federate fed) return helics_invalid_object; } - auto queryObj = reinterpret_cast (query); - if (queryObj->target.empty ()) + try { - queryObj->asyncIndexCode = fedObj->queryAsync (queryObj->query); + auto queryObj = reinterpret_cast (query); + if (queryObj->target.empty ()) + { + queryObj->asyncIndexCode = fedObj->queryAsync (queryObj->query); + } + else + { + queryObj->asyncIndexCode = fedObj->queryAsync (queryObj->target, queryObj->query); + } + queryObj->activeAsync = true; + queryObj->activeFed = fedObj; + return helics_ok; } - else + catch (...) { - queryObj->asyncIndexCode = fedObj->queryAsync (queryObj->target, queryObj->query); + return helicsErrorHandler (); } - queryObj->activeAsync = true; - queryObj->activeFed = fedObj; - return helics_ok; } const char *helicsQueryExecuteComplete (helics_query query) @@ -713,7 +844,7 @@ const char *helicsQueryExecuteComplete (helics_query query) return queryObj->response.c_str (); } -HELICS_EXPORT helics_bool_t helicsQueryIsCompleted (helics_query query) +helics_bool_t helicsQueryIsCompleted (helics_query query) { if (query == nullptr) { @@ -758,7 +889,7 @@ int MasterObjectHolder::addBroker (std::unique_ptr broker) auto handle = brokers.lock (); auto index = static_cast (handle->size ()); broker->index = index; - handle->push_back (std::move(broker)); + handle->push_back (std::move (broker)); return index; } @@ -767,7 +898,7 @@ int MasterObjectHolder::addCore (std::unique_ptr core) auto handle = cores.lock (); auto index = static_cast (handle->size ()); core->index = index; - handle->push_back (std::move(core)); + handle->push_back (std::move (core)); return index; } @@ -776,7 +907,7 @@ int MasterObjectHolder::addFed (std::unique_ptr fed) auto handle = feds.lock (); auto index = static_cast (handle->size ()); fed->index = index; - handle->push_back (std::move(fed)); + handle->push_back (std::move (fed)); return index; } @@ -789,7 +920,7 @@ helics::FedObject *MasterObjectHolder::findFed (const std::string &fedName) { if (fed->fedptr->getName () == fedName) { - return fed.get(); + return fed.get (); } } } diff --git a/src/helics/shared_api_library/internal/api_objects.h b/src/helics/shared_api_library/internal/api_objects.h index ba184a6dea..b989e474c0 100644 --- a/src/helics/shared_api_library/internal/api_objects.h +++ b/src/helics/shared_api_library/internal/api_objects.h @@ -55,7 +55,7 @@ namespace helics { public: std::shared_ptr coreptr; - std::vector filters; //!< list of filters created directly through the core + std::vector> filters; //!< list of filters created directly through the core int index; int valid; CoreObject() = default; @@ -78,10 +78,10 @@ namespace helics int index; std::shared_ptr fedptr; std::unique_ptr lastMessage; - std::vector subs; - std::vector pubs; - std::vector epts; - std::vector filters; + std::vector> subs; + std::vector> pubs; + std::vector> epts; + std::vector> filters; FedObject() = default; ~FedObject(); }; @@ -160,6 +160,8 @@ std::shared_ptr getFedSharedPtr(helics_federate fed); std::shared_ptr getValueFedSharedPtr(helics_federate fed); std::shared_ptr getMessageFedSharedPtr(helics_federate fed); std::shared_ptr getCoreSharedPtr(helics_core core); +/**centralized error handler for the C interface*/ +helics_status helicsErrorHandler() noexcept; /** class for containing all the objects associated with a federation*/ class MasterObjectHolder From 05c4b863238c83514914c43c43a0571a0de3d0cf Mon Sep 17 00:00:00 2001 From: Philip Top Date: Fri, 25 May 2018 11:54:28 -0700 Subject: [PATCH 09/10] Subscription update (#330) * change publication/subscription/endpoint/filter creation in the C interface to use unique_ptr internally * add getXXXSize functions to Subscriptions, not implemented yet. * add additional subpub object test * update subscriptions and getSize functions * some fixes for the size functions * fix some warnings, and an error when running a few MPI tests on windows, and few low level changes and corresponding tests * update changelog and roadmap --- CHANGELOG.md | 14 +- CMakeLists.txt | 29 ++-- ROADMAP.md | 14 +- ThirdParty/libguarded/shared_guarded.hpp | 37 +++-- ThirdParty/libguarded/staged_guarded.hpp | 6 +- appveyor.yml | 2 +- config/HELICSConfig.cmake.in | 31 ++-- .../application_api/HelicsPrimaryTypes.hpp | 36 +---- src/helics/application_api/Subscriptions.cpp | 87 ++++++++++- src/helics/application_api/Subscriptions.hpp | 14 +- .../application_api/ValueFederateManager.cpp | 140 +++++++++--------- .../application_api/ValueFederateManager.hpp | 9 +- src/helics/common/DualMappedPointerVector.hpp | 108 ++++++++------ src/helics/common/DualMappedVector.hpp | 60 ++++---- src/helics/common/GuardedTypes.hpp | 3 +- src/helics/core/CommonCore.cpp | 8 +- src/helics/core/CoreBroker.cpp | 3 +- src/helics/core/mpi/MpiCore.cpp | 4 +- .../ValueFederateExport.cpp | 7 +- .../PrimaryTypeConversionTests.cpp | 3 +- .../application_api/subPubObjectTests.cpp | 111 +++++++++++++- 21 files changed, 463 insertions(+), 263 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 81665a9286..26d8a210e4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,19 +4,31 @@ 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.1.1] - 2018-05-25 ### Added - BrokerApp as a slightly more convenient runner to Brokers + - getXXSize functions directly in the Subscription object instead of a roundabout call in the C api + - more complete error catching for the C library + - added helics-config executable for getting paths and links and used flags + - added a broker app that can start up a broker easily ### Changed - upgrade autobuild ZMQ version to 4.2.5 and change CMake scripts to use zmq target + - updated HELICSConfig.cmake install file to link properly to external libraries and find them if necessary, also included some find functions. The find_package(HELICS) should work properly now + - changed boost inclusion to use targets instead of files directly + - changed MPI inclusion to work better on windows and use targets instead of direct links - update cereal library with latest bug fixes - update jsoncpp with latest version + - update cppzmq with the latest version - moved helics_broker executable code to the apps repository - the CXX shared library can now be built alongside the C shared library and can be built on Windows. ### Fixed - compilation issue with Xcode 8.0 + - inconsistent numerical conversion from vectors to doubles in subscriptions + +### Removed + - installation of HELICSImport.cmake this is now redundant with updated HELICSConfig.cmake ## [1.1.0] - 2018-05-09 ### Added diff --git a/CMakeLists.txt b/CMakeLists.txt index 9a512cfcea..c78dcc486c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,9 +12,9 @@ project (HELICS) #----------------------------------------------------------------------------- set (HELICS_VERSION_MAJOR 1) set (HELICS_VERSION_MINOR 1) -set (HELICS_VERSION_PATCH 0) +set (HELICS_VERSION_PATCH 1) set (HELICS_VERSION_BUILD ) -set (HELICS_DATE "05-09-18") +set (HELICS_DATE "05-25-18") if (NOT HELICS_VERSION_BUILD) set (HELICS_VERSION "${HELICS_VERSION_MAJOR}.${HELICS_VERSION_MINOR}.${HELICS_VERSION_PATCH}") @@ -37,11 +37,10 @@ include(extraMacros) if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) if (WIN32) if (MSYS) - set (CMAKE_INSTALL_PREFIX "/usr/local/helics_${HELICS_VERSION_UNDERSCORE}/" CACHE PATH "default install path" FORCE ) + set (CMAKE_INSTALL_PREFIX "/usr/local/helics_${HELICS_VERSION_UNDERSCORE}/" CACHE PATH "default install path" FORCE ) else(MSYS) set (CMAKE_INSTALL_PREFIX "C:/local/helics_${HELICS_VERSION_UNDERSCORE}/" CACHE PATH "default install path" FORCE ) endif(MSYS) - endif(WIN32) endif() @@ -76,8 +75,8 @@ else() SHOW_VARIABLE(BUILD_C_SHARED_LIB BOOL "Build the Shared Libraries with a C interface" ON) endif() -OPTION(BUILD_CXX_SHARED_LIB "Build a Shared Libraries of the CXX interface" OFF) -mark_as_advanced(BUILD_CXX_SHARED_LIB) + OPTION(BUILD_CXX_SHARED_LIB "Build a Shared Libraries of the CXX interface" OFF) + mark_as_advanced(BUILD_CXX_SHARED_LIB) if (INTERFACE_BUILD OR BUILD_C_SHARED_LIB OR BUILD_CXX_SHARED_LIB) set(BUILD_SHARED_LIBS ON) @@ -85,7 +84,6 @@ else() OPTION(USE_POSITION_INDEPENDENT_CODE "Build the libraries with Position independent code Useful if only building the static library and it will be used later in a shared library" OFF) endif() - IF(BUILD_SHARED_LIBS OR USE_POSITION_INDEPENDENT_CODE) SET(CMAKE_POSITION_INDEPENDENT_CODE ON) ENDIF() @@ -106,7 +104,7 @@ add_library(helics_base_includes INTERFACE) target_link_libraries(helics_base INTERFACE helics_base_includes) # Prohibit in-source build IF("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}") - message(FATAL_ERROR "In-source build is not supported. Please, use an empty directory for building the project.") + message(FATAL_ERROR "In-source build is not supported. Please, use an empty directory for building the project.") ENDIF() include(compiler_flags) @@ -231,7 +229,7 @@ ENDIF(MSYS) OPTION(ZeroMQ_ENABLE "Enable ZeroMQ networking library" ON) # If ZeroMQ library is enabled try to locate it and link against it -IF (ZeroMQ_ENABLE) +if (ZeroMQ_ENABLE) include(addZeroMQ) if (ZeroMQ_FOUND) @@ -244,18 +242,15 @@ IF (ZeroMQ_ENABLE) endif() #message(STATUS "zmq dep ${ZeroMQ_DEPENDENCY}") target_link_libraries(helics_base INTERFACE ${ZeroMQ_DEPENDENCY}) - #get_target_properties(ZMQ_LOC ${ZeroMQ_DEPENDENCY} INTERFACE_INCLUDE_DIRECTORIES) - #get_filename_component(ZMQ_LOC_BASE ${ZMQ_LOC} DIRECTORY) - else(ZeroMQ_FOUND) set(HELICS_HAVE_ZEROMQ FALSE) endif(ZeroMQ_FOUND) - ELSE(ZeroMQ_ENABLE) + else(ZeroMQ_ENABLE) set(HELICS_HAVE_ZEROMQ FALSE) if (ZeroMQ_ENABLE) - message(WARNING "ZeroMQ not found") + message(WARNING "ZeroMQ not found") endif() -ENDIF(ZeroMQ_ENABLE) +endif(ZeroMQ_ENABLE) # ------------------------------------------------------------- @@ -392,7 +387,7 @@ ELSE (BUILD_CXX_SHARED_LIB) set(helics_cxx_shared_file_debug ) ENDIF(BUILD_CXX_SHARED_LIB) -IF(BUILD_C_SHARED_LIB OR BUILD_PYTHON_INTERFACE OR BUILD_MATLAB_INTERFACE OR BUILD_JAVA_INTERFACE OR BUILD_OCTAVE_INTERFACE) +IF(BUILD_C_SHARED_LIB OR INTERFACE_BUILD) set(helics_c_shared_file "${CMAKE_SHARED_LIBRARY_PREFIX}helicsSharedLib${CMAKE_SHARED_LIBRARY_SUFFIX}") set(helics_c_shared_file_debug "${CMAKE_SHARED_LIBRARY_PREFIX}helicsSharedLib${CMAKE_DEBUG_POSTFIX}${CMAKE_SHARED_LIBRARY_SUFFIX}") ELSE() @@ -434,7 +429,7 @@ configure_package_config_file(config/${PROJECT_NAME}Config.cmake.in "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" INSTALL_DESTINATION ${HELICS_CMAKECONFIG_INSTALL_DIR}) write_basic_package_version_file(${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake - VERSION ${HELICS_VERSION_MAJOR}.${HELICS_VERSION_MINOR}.${HELICS_VERSION_PATCH}-${HELICS_VERSION_BUILD} + VERSION ${HELICS_VERSION} COMPATIBILITY SameMajorVersion) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake diff --git a/ROADMAP.md b/ROADMAP.md index c77f9daff4..268d956b3b 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -1,28 +1,28 @@ # RoadMap -This document contains tentative plans for changes and improvements of note in upcoming versions of the HELICS library. All dates are approximate and subject to change +This document contains tentative plans for changes and improvements of note in upcoming versions of the HELICS library. All dates are approximate and subject to change. see the [projects](https://github.com/GMLC-TDC/HELICS-src/projects) for additional details -## [1.X] ~ 2018-06-13 Improvements planned before the 2.0 release +## [1.2] ~ 2018-06-13 + - see [HELICS 1.2](https://github.com/GMLC-TDC/HELICS-src/projects/6) for up to date information + +## [1.3] ~ 2018-07-16 Improvements planned before the 2.0 release ### Features - Support for TOML configuration - Octave support - - addition of more convenient broker initialization so brokers can be easily added to executables - + - add a control point type for N to 1 control of federates this new interface will be symmetric with the publication and subscriptions interface which is a 1 to N fanout. ### Improvements - some initial performance testing and improvements - increased testing of queries and timing - more detail and testing in the C++ wrapper around the C interface - - initial performance testing - general code refactoring for threading and better modularity ## [2.0 Beta] ~ 2018-08-23 ### Features - targeted integration with package managers for 2.0 so Beta version will start that process - - add a control point type for N to 1 control of federates this new interface will be symmetric with the publication and subscriptions interface which is a 1 to N fanout. - a routing broker to connect different communication types and brokers together in the same federation ### Improvements - Major API changes based on feedback and initial broader usage - Change C interface to use an error object instead of return code and corresponding updates to the Interface API's - Initial performance and scalability testing - - relaxed subscription registration requirements + - relaxed subscription/endpoint registration requirements diff --git a/ThirdParty/libguarded/shared_guarded.hpp b/ThirdParty/libguarded/shared_guarded.hpp index 1cd36363a1..557954e1a7 100644 --- a/ThirdParty/libguarded/shared_guarded.hpp +++ b/ThirdParty/libguarded/shared_guarded.hpp @@ -92,19 +92,19 @@ class shared_guarded public: using pointer = T *; - deleter(M & mutex) : m_deleter_mutex(mutex) + deleter(M & mutex) : m_deleter_mutex(&mutex) { } void operator()(T * ptr) { if (ptr) { - m_deleter_mutex.unlock(); + m_deleter_mutex->unlock(); } } private: - M & m_deleter_mutex; + M * m_deleter_mutex; }; class shared_deleter @@ -112,19 +112,19 @@ class shared_guarded public: using pointer = const T *; - shared_deleter(M & mutex) : m_deleter_mutex(mutex) + shared_deleter(M & mutex) : m_deleter_mutex(&mutex) { } void operator()(const T * ptr) { if (ptr) { - m_deleter_mutex.unlock_shared(); + m_deleter_mutex->unlock_shared(); } } private: - M & m_deleter_mutex; + M * m_deleter_mutex; }; T m_obj; @@ -253,19 +253,18 @@ class shared_guarded public: using pointer = T *; - deleter(std::mutex & mutex) : m_deleter_mutex(mutex) + deleter(std::mutex & mutex) : m_deleter_mutex(&mutex) { } - void operator()(T * ptr) { if (ptr) { - m_deleter_mutex.unlock(); + m_deleter_mutex->unlock(); } } private: - std::mutex & m_deleter_mutex; + std::mutex * m_deleter_mutex; }; class shared_deleter @@ -273,19 +272,19 @@ class shared_guarded public: using pointer = const T *; - shared_deleter(std::mutex & mutex) : m_deleter_mutex(mutex) + shared_deleter(std::mutex & mutex) : m_deleter_mutex(&mutex) { } void operator()(const T * ptr) { if (ptr) { - m_deleter_mutex.unlock(); + m_deleter_mutex->unlock(); } } private: - std::mutex & m_deleter_mutex; + std::mutex * m_deleter_mutex; }; T m_obj; @@ -386,19 +385,19 @@ class shared_guarded public: using pointer = T *; - deleter(std::timed_mutex & mutex) : m_deleter_mutex(mutex) + deleter(std::timed_mutex & mutex) : m_deleter_mutex(&mutex) { } void operator()(T * ptr) { if (ptr) { - m_deleter_mutex.unlock(); + m_deleter_mutex->unlock(); } } private: - std::timed_mutex & m_deleter_mutex; + std::timed_mutex * m_deleter_mutex; }; class shared_deleter @@ -406,19 +405,19 @@ class shared_guarded public: using pointer = const T *; - shared_deleter(std::timed_mutex & mutex) : m_deleter_mutex(mutex) + shared_deleter(std::timed_mutex & mutex) : m_deleter_mutex(&mutex) { } void operator()(const T * ptr) { if (ptr) { - m_deleter_mutex.unlock(); + m_deleter_mutex->unlock(); } } private: - std::timed_mutex & m_deleter_mutex; + std::timed_mutex * m_deleter_mutex; }; T m_obj; diff --git a/ThirdParty/libguarded/staged_guarded.hpp b/ThirdParty/libguarded/staged_guarded.hpp index 91ad1fed6e..98f11f49d6 100644 --- a/ThirdParty/libguarded/staged_guarded.hpp +++ b/ThirdParty/libguarded/staged_guarded.hpp @@ -44,7 +44,7 @@ namespace libguarded copyable. */ template -class guarded +class staged_guarded { private: class deleter; @@ -175,7 +175,7 @@ class guarded template template -staged_guarded::guarded (Us &&... data) : m_obj (std::forward (data)...) +staged_guarded::staged_guarded (Us &&... data) : m_obj (std::forward (data)...) { } @@ -227,7 +227,7 @@ auto staged_guarded::try_lock () -> handle template -auto staged_guarded::try_lock_shared() -> shared_handle +auto staged_guarded::try_lock_shared() const -> shared_handle { if (!constant) { diff --git a/appveyor.yml b/appveyor.yml index e41258a5bc..382cd691e0 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,6 +1,6 @@ shallow_clone: true -version: 1.1.0.{build} +version: 1.1.1.{build} image: Visual Studio 2015 diff --git a/config/HELICSConfig.cmake.in b/config/HELICSConfig.cmake.in index b2bd8fb9f9..bb51c87653 100644 --- a/config/HELICSConfig.cmake.in +++ b/config/HELICSConfig.cmake.in @@ -47,20 +47,22 @@ find_program(HELICS_BROKER helics_broker PATH ${PACKAGE_PREFIX_DIR}/@CMAKE_INSTALL_BINDIR@ NO_DEFAULT_PATH) -set(HELICS_HAVE_ZEROMQ @HELICS_HAVE_ZEROMQ) -set(HELICS_HAVE_MPI @HELICS_HAVE_MPI) +set(HELICS_HAVE_ZEROMQ @HELICS_HAVE_ZEROMQ@) +set(HELICS_HAVE_MPI @HELICS_HAVE_MPI@) set(CMAKE_MODULE_PATH ${PACKAGE_PREFIX_DIR}/@HELICS_CMAKECONFIG_INSTALL_DIR@) include(CMakeFindDependencyMacro) include(extraMacros) -if (NOT Boostlibs::core) +if (TARGET Boostlibs::core) +else() include(addBoost) endif() if (HELICS_HAVE_ZEROMQ) - if (NOT libzmq) + if (TARGET libzmq) + else() set(ZeroMQ_LIBRARY_ONLY ON) set(ZeroMQ_INSTALL_PATH ${PACKAGE_PREFIX_DIR}) find_dependency(ZeroMQ) @@ -68,14 +70,16 @@ if (HELICS_HAVE_ZEROMQ) endif() if (HELICS_HAVE_MPI) - if (NOT MPI::MPI_C) + if (TARGET MPI::MPI_C) + else() include(addMPI) endif() endif() #find_dependency(ZeroMQ) -if (NOT Threads::Threads) +if (TARGET Threads::Threads) +else() if (NOT WIN32) set(THREADS_PREFER_PTHREAD_FLAG ON) elseif (MSYS) @@ -86,14 +90,15 @@ endif() include(${CMAKE_CURRENT_LIST_DIR}/helics-targets.cmake) -if (HELICS::helicsSharedLib) -add_library(HELICS::helicsCpp98 INTERFACE) -target_include_directories(HELICS::helicsCpp98 INTERFACE "${PACKAGE_PREFIX_DIR}/@CMAKE_INSTALL_INCLUDEDIR@/cpp98") -target_link_libraries(HELICS::helicsCpp98 INTERFACE HELICS::helicsSharedLib) +if (TARGET HELICS::helicsSharedLib) + add_library(HELICS::helicsCpp98 INTERFACE IMPORTED) + set_property(TARGET HELICS::helicsCpp98 PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${PACKAGE_PREFIX_DIR}/include/cpp98") -set_target_properties(Helics::helicsSharedLib PROPERTIES - INTERFACE_INCLUDE_DIRECTORIES "${PACKAGE_PREFIX_DIR}/@CMAKE_INSTALL_INCLUDEDIR@/helics/shared_api_library" -) + set_property(TARGET HELICS::helicsCpp98 PROPERTY INTERFACE_LINK_LIBRARIES HELICS::helicsSharedLib) + + set_target_properties(HELICS::helicsSharedLib PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${PACKAGE_PREFIX_DIR}/include/helics/shared_api_library" + ) endif() check_required_components(${PN}) diff --git a/src/helics/application_api/HelicsPrimaryTypes.hpp b/src/helics/application_api/HelicsPrimaryTypes.hpp index 50a4396b82..9bbf912514 100644 --- a/src/helics/application_api/HelicsPrimaryTypes.hpp +++ b/src/helics/application_api/HelicsPrimaryTypes.hpp @@ -117,34 +117,13 @@ std::enable_if_t::value> valueExtract (const defV &dv, X & case vectorLoc: // vector { auto &vec = mpark::get> (dv); - if (!vec.empty ()) - { - if (vec.size () == 2) - { - val = static_cast (std::hypot (vec[0], vec[1])); - } - else - { - val = static_cast (vec.front ()); - } - } - else - { - val = X (0); - } + val = static_cast (vectorNorm(vec)); break; } case complexVectorLoc: // complex vector { auto &vec = mpark::get>> (dv); - if (!vec.empty ()) - { - val = static_cast (std::abs (vec.front ())); - } - else - { - val = X (0); - } + val = static_cast (vectorNorm(vec)); break; } case namedPointLoc: @@ -250,14 +229,7 @@ std::enable_if_t::value> valueExtract (const data_view &dv case helics_type_t::helicsVector: { auto V = ValueConverter>::interpret (dv); - if (V.size () == 2) - { - val = static_cast (std::hypot (V[0], V[1])); - } - else - { - val = (V.empty ()) ? X (0) : static_cast (V.front ()); - } + val = static_cast(vectorNorm(V)); break; } case helics_type_t::helicsComplex: @@ -269,7 +241,7 @@ std::enable_if_t::value> valueExtract (const data_view &dv case helics_type_t::helicsComplexVector: { auto V = ValueConverter>>::interpret (dv); - val = (!V.empty ()) ? static_cast (std::abs (V.front ())) : 0.0; + val = static_cast(vectorNorm(V)); break; } case helics_type_t::helicsInvalid: diff --git a/src/helics/application_api/Subscriptions.cpp b/src/helics/application_api/Subscriptions.cpp index d16ef53bb3..117c91927f 100644 --- a/src/helics/application_api/Subscriptions.cpp +++ b/src/helics/application_api/Subscriptions.cpp @@ -81,13 +81,98 @@ void Subscription::handleCallback (Time time) bool Subscription::isUpdated () const { + if (hasUpdate) + { + return true; + } if (changeDetectionEnabled) { - return SubscriptionBase::isUpdated (); + if (SubscriptionBase::isUpdated ()) + { + if (type == helics_type_t::helicsInvalid) + { + return true; + } + auto dv = fed->getValueRaw(id); + auto visitor = [&](auto &&arg) -> bool { + std::remove_const_t> newVal; + (void)arg; //suppress VS2015 warning + valueExtract (dv, type, newVal); + return (changeDetected(lastValue, newVal, delta)); + }; + return mpark::visit (visitor, lastValue); + } + return false; } else { return SubscriptionBase::isUpdated (); } } + +bool Subscription::getAndCheckForUpdate () +{ + if (hasUpdate) + { + return true; + } + if (changeDetectionEnabled) + { + if (SubscriptionBase::isUpdated ()) + { + auto dv = fed->getValueRaw (id); + if (type == helics_type_t::helicsInvalid) + { + type = getTypeFromString (fed->getPublicationType (id)); + } + if (type != helics_type_t::helicsInvalid) + { + auto visitor = [&](auto &&arg) { + std::remove_reference_t newVal; + (void)arg; //suppress VS2015 warning + valueExtract (dv, type, newVal); + if (changeDetected (lastValue, newVal, delta)) + { + lastValue = newVal; + hasUpdate = true; + } + }; + mpark::visit (visitor, lastValue); + } + } + } + else + { + hasUpdate = SubscriptionBase::isUpdated (); + } + + return hasUpdate; +} + +size_t Subscription::getRawSize () +{ + getAndCheckForUpdate(); + auto dv=fed->getValueRaw(id); + if (dv.empty()) + { + auto out = getValue(); + return out.size(); + } + return dv.size(); +} + +size_t Subscription::getStringSize () +{ + getAndCheckForUpdate(); + auto out = getValue(); + return out.size()+1; +} + +size_t Subscription::getVectorSize () +{ + getAndCheckForUpdate(); + auto out = getValue>(); + return out.size(); +} + } // namespace helics diff --git a/src/helics/application_api/Subscriptions.hpp b/src/helics/application_api/Subscriptions.hpp index 192f166e8d..cf838d1553 100644 --- a/src/helics/application_api/Subscriptions.hpp +++ b/src/helics/application_api/Subscriptions.hpp @@ -104,7 +104,7 @@ class Subscription : public SubscriptionBase mutable helics_type_t type = helics_type_t::helicsInvalid; //!< the underlying type the publication is using bool changeDetectionEnabled = false; //!< the change detection is enabled - // bool hasUpdate = false; //!< the value has been updated + bool hasUpdate = false; //!< the value has been updated defV lastValue; //!< the last value updated double delta = -1.0; //!< the minimum difference public: @@ -148,6 +148,8 @@ class Subscription : public SubscriptionBase Subscription (ValueFederate *valueFed, int subIndex) : SubscriptionBase (valueFed, subIndex) {} /** check if the value has been updated*/ virtual bool isUpdated () const override; + /** check if the value has been updated and load the value into buffer*/ + bool getAndCheckForUpdate(); using SubscriptionBase::registerCallback; /** register a callback for the update @@ -201,7 +203,7 @@ class Subscription : public SubscriptionBase template void getValue_impl (std::true_type /*V*/, X &out) { - if (fed->isUpdated (id)) + if (fed->isUpdated (id)||(hasUpdate && !changeDetectionEnabled)) { auto dv = fed->getValueRaw (id); if (type == helics_type_t::helicsInvalid) @@ -236,6 +238,7 @@ class Subscription : public SubscriptionBase { valueExtract (lastValue, out); } + hasUpdate = false; } template void getValue_impl (std::false_type /*V*/, X &out) @@ -280,6 +283,13 @@ class Subscription : public SubscriptionBase return getValue_impl (std::conditional_t<(helicsType () != helics_type_t::helicsInvalid), std::true_type, std::false_type> ()); } + /** get the size of the raw data*/ + size_t getRawSize(); + /** get the size of the data if it were a string*/ + size_t getStringSize(); + /** get the number of elements in the data if it were a vector*/ + size_t getVectorSize(); + }; /** class to handle a subscription diff --git a/src/helics/application_api/ValueFederateManager.cpp b/src/helics/application_api/ValueFederateManager.cpp index a91c0852bd..e7f1c9a36b 100644 --- a/src/helics/application_api/ValueFederateManager.cpp +++ b/src/helics/application_api/ValueFederateManager.cpp @@ -37,13 +37,13 @@ publication_id_t ValueFederateManager::registerPublication (const std::string &k auto sz = getTypeSize (type); auto coreID = coreObject->registerPublication (fedID, key, type, units); - std::lock_guard publock (publication_mutex); - publication_id_t id = static_cast (publications.size ()); + auto pubHandle = publications.lock(); + publication_id_t id = static_cast (pubHandle->size ()); ++publicationCount; - publications.insert (key, key, type, units); - publications.back ().id = id; - publications.back ().size = sz; - publications.back ().coreID = coreID; + pubHandle->insert (key, key, type, units); + pubHandle->back ().id = id; + pubHandle->back ().size = sz; + pubHandle->back ().coreID = coreID; return id; } @@ -52,12 +52,12 @@ subscription_id_t ValueFederateManager::registerRequiredSubscription (const std: const std::string &units) { auto coreID = coreObject->registerSubscription (fedID, key, type, units, handle_check_mode::required); - std::lock_guard sublock (subscription_mutex); - subscription_id_t id = static_cast (subscriptions.size ()); + auto subHandle = subscriptions.lock(); + subscription_id_t id = static_cast (subHandle->size ()); ++subscriptionCount; - subscriptions.insert (key, coreID, key, type, units); - subscriptions.back ().id = id; - subscriptions.back ().coreID = coreID; + subHandle->insert (key, coreID, key, type, units); + subHandle->back ().id = id; + subHandle->back ().coreID = coreID; lastData.resize (id.value () + 1); return id; } @@ -67,12 +67,12 @@ subscription_id_t ValueFederateManager::registerOptionalSubscription (const std: const std::string &units) { auto coreID = coreObject->registerSubscription (fedID, key, type, units, handle_check_mode::optional); - std::lock_guard sublock (subscription_mutex); - subscription_id_t id = static_cast (subscriptions.size ()); + auto subHandle = subscriptions.lock(); + subscription_id_t id = static_cast (subHandle->size ()); ++subscriptionCount; - subscriptions.insert (key, coreID, key, type, units); - subscriptions.back ().id = id; - subscriptions.back ().coreID = coreID; + subHandle->insert (key, coreID, key, type, units); + subHandle->back ().id = id; + subHandle->back ().coreID = coreID; lastData.resize (id.value () + 1); return id; } @@ -81,8 +81,8 @@ void ValueFederateManager::addSubscriptionShortcut (subscription_id_t subid, con { if (subid.value () < subscriptionCount) { - std::lock_guard sublock (subscription_mutex); - subscriptions.addSearchTermForIndex (shortcutName, subid.value ()); + auto subHandle = subscriptions.lock(); + subHandle->addSearchTermForIndex (shortcutName, subid.value ()); } else { @@ -94,10 +94,10 @@ void ValueFederateManager::setDefaultValue (subscription_id_t id, const data_vie { if (id.value () < subscriptionCount) { - std::lock_guard sublock (subscription_mutex); + auto subHandle = subscriptions.lock(); /** copy the data first since we are not entirely sure of the lifetime of the data_view*/ lastData[id.value ()] = data_view (std::make_shared (block.data (), block.size ())); - subscriptions[id.value ()].lastUpdate = CurrentTime; + (*subHandle)[id.value ()].lastUpdate = CurrentTime; } else { @@ -109,12 +109,12 @@ void ValueFederateManager::setDefaultValue (subscription_id_t id, const data_vie void ValueFederateManager::getUpdateFromCore (Core::handle_id_t updatedHandle) { auto data = coreObject->getValue (updatedHandle); - + auto subHandle = subscriptions.lock(); /** find the id*/ - auto fid = subscriptions.find (updatedHandle); - if (fid != subscriptions.end ()) + auto fid = subHandle->find (updatedHandle); + if (fid != subHandle->end ()) { // assign the data - std::lock_guard sublock (subscription_mutex); + lastData[fid->id.value ()] = data_view (std::move (data)); fid->lastUpdate = CurrentTime; } @@ -124,9 +124,9 @@ data_view ValueFederateManager::getValue (subscription_id_t id) { if (id.value () < subscriptionCount) { - std::lock_guard sublock (subscription_mutex); - subscriptions[id.value ()].lastQuery = CurrentTime; - subscriptions[id.value ()].hasUpdate = false; + auto subHandle = subscriptions.lock(); + (*subHandle)[id.value ()].lastQuery = CurrentTime; + (*subHandle)[id.value ()].hasUpdate = false; return lastData[id.value ()]; } else @@ -145,9 +145,10 @@ void ValueFederateManager::publish (publication_id_t id, const data_view &block) { if (id.value () < publicationCount) { // send directly to the core - if (isBlockSizeValid (static_cast (block.size ()), publications[id.value ()])) + auto pubHandle = publications.lock(); + if (isBlockSizeValid (static_cast (block.size ()), (*pubHandle)[id.value ()])) { - coreObject->setValue (publications[id.value ()].coreID, block.data (), block.size ()); + coreObject->setValue ((*pubHandle)[id.value ()].coreID, block.data (), block.size ()); } else { @@ -164,8 +165,8 @@ bool ValueFederateManager::queryUpdate (subscription_id_t sub_id) const { if (sub_id.value () < subscriptionCount) { - std::lock_guard sublock (subscription_mutex); - return subscriptions[sub_id.value ()].hasUpdate; + auto subHandle = subscriptions.lock_shared(); + return (*subHandle)[sub_id.value ()].hasUpdate; } return false; } @@ -174,8 +175,8 @@ Time ValueFederateManager::queryLastUpdate (subscription_id_t sub_id) const { if (sub_id.value () < subscriptionCount) { - std::lock_guard sublock (subscription_mutex); - return subscriptions[sub_id.value ()].lastUpdate; + auto subHandle = subscriptions.lock_shared(); + return (*subHandle)[sub_id.value ()].lastUpdate; } return false; } @@ -185,12 +186,12 @@ void ValueFederateManager::updateTime (Time newTime, Time /*oldTime*/) CurrentTime = newTime; auto handles = coreObject->getValueUpdates (fedID); // lock the data updates - std::unique_lock sublock (subscription_mutex); + auto subHandle = subscriptions.lock(); for (auto handle : handles) { /** find the id*/ - auto fid = subscriptions.find (handle); - if (fid != subscriptions.end ()) + auto fid = subHandle->find (handle); + if (fid != subHandle->end ()) { // assign the data auto data = coreObject->getValue (handle); @@ -203,19 +204,19 @@ void ValueFederateManager::updateTime (Time newTime, Time /*oldTime*/) { // first copy the callback in case it gets changed via another operation auto callbackFunction = callbacks[fid->callbackIndex]; - sublock.unlock (); + subHandle = nullptr; //need to free the lock // callbacks can do all sorts of things, best not to have it locked during the callback callbackFunction (fid->id, CurrentTime); - sublock.lock (); + subHandle = subscriptions.lock(); } else if (allCallbackIndex >= 0) { // first copy the callback in case it gets changed via another operation auto allCallBackFunction = callbacks[allCallbackIndex]; - sublock.unlock (); + subHandle = nullptr; //need to free the lock // callbacks can do all sorts of strange things, best not to have it locked during the callback allCallBackFunction (fid->id, CurrentTime); - sublock.lock (); + subHandle = subscriptions.lock(); } } } @@ -225,7 +226,8 @@ void ValueFederateManager::startupToInitializeStateTransition () { lastData.resize (subscriptionCount); // get the actual publication types - subscriptions.apply ([this](auto &sub) { sub.pubtype = coreObject->getType (sub.coreID); }); + auto subHandle = subscriptions.lock(); + subHandle->apply ([this](auto &sub) { sub.pubtype = coreObject->getType (sub.coreID); }); } void ValueFederateManager::initializeToExecuteStateTransition () { updateTime (0.0, 0.0); } @@ -233,8 +235,8 @@ void ValueFederateManager::initializeToExecuteStateTransition () { updateTime (0 std::vector ValueFederateManager::queryUpdates () { std::vector updates; - std::lock_guard sublock (subscription_mutex); - for (auto &sub : subscriptions) + auto subHandle = subscriptions.lock_shared(); + for (auto &sub : *subHandle) { if (sub.hasUpdate) { @@ -248,15 +250,15 @@ static const std::string nullStr; std::string ValueFederateManager::getSubscriptionKey (subscription_id_t sub_id) const { - std::lock_guard sublock (subscription_mutex); - return (sub_id.value () < subscriptions.size ()) ? subscriptions[sub_id.value ()].name : nullStr; + auto subHandle = subscriptions.lock_shared(); + return (sub_id.value () < subHandle->size ()) ? (*subHandle)[sub_id.value ()].name : nullStr; } subscription_id_t ValueFederateManager::getSubscriptionId (const std::string &key) const { - std::lock_guard sublock (subscription_mutex); - auto sub = subscriptions.find (key); - if (sub != subscriptions.end ()) + auto subHandle = subscriptions.lock_shared(); + auto sub = subHandle->find (key); + if (sub != subHandle->end ()) { return sub->id; } @@ -265,15 +267,15 @@ subscription_id_t ValueFederateManager::getSubscriptionId (const std::string &ke std::string ValueFederateManager::getPublicationKey (publication_id_t pub_id) const { - std::lock_guard publock (publication_mutex); - return (pub_id.value () < publications.size ()) ? publications[pub_id.value ()].name : nullStr; + auto pubHandle = publications.lock_shared(); + return (pub_id.value () < pubHandle->size ()) ? (*pubHandle)[pub_id.value ()].name : nullStr; } publication_id_t ValueFederateManager::getPublicationId (const std::string &key) const { - std::lock_guard publock (publication_mutex); - auto pub = publications.find (key); - if (pub != publications.end ()) + auto pubHandle = publications.lock_shared(); + auto pub = pubHandle->find (key); + if (pub != pubHandle->end ()) { return pub->id; } @@ -283,32 +285,32 @@ publication_id_t ValueFederateManager::getPublicationId (const std::string &key) std::string ValueFederateManager::getSubscriptionUnits (subscription_id_t sub_id) const { - std::lock_guard sublock (subscription_mutex); - return (sub_id.value () < subscriptions.size ()) ? subscriptions[sub_id.value ()].units : nullStr; + auto subHandle = subscriptions.lock_shared(); + return (sub_id.value () < subHandle->size ()) ? (*subHandle)[sub_id.value ()].units : nullStr; } std::string ValueFederateManager::getPublicationUnits (publication_id_t pub_id) const { - std::lock_guard publock (publication_mutex); - return (pub_id.value () < publications.size ()) ? publications[pub_id.value ()].units : nullStr; + auto pubHandle = publications.lock_shared(); + return (pub_id.value () < pubHandle->size ()) ? (*pubHandle)[pub_id.value ()].units : nullStr; } std::string ValueFederateManager::getSubscriptionType (subscription_id_t sub_id) const { - std::lock_guard sublock (subscription_mutex); - return (sub_id.value () < subscriptions.size ()) ? subscriptions[sub_id.value ()].type : nullStr; + auto subHandle = subscriptions.lock_shared(); + return (sub_id.value () < subHandle->size ()) ? (*subHandle)[sub_id.value ()].type : nullStr; } std::string ValueFederateManager::getPublicationType (subscription_id_t sub_id) const { - std::lock_guard sublock (subscription_mutex); - return (sub_id.value () < subscriptions.size ()) ? subscriptions[sub_id.value ()].pubtype : nullStr; + auto subHandle = subscriptions.lock_shared(); + return (sub_id.value () < subHandle->size ()) ? (*subHandle)[sub_id.value ()].pubtype : nullStr; } std::string ValueFederateManager::getPublicationType (publication_id_t pub_id) const { - std::lock_guard publock (publication_mutex); - return (pub_id.value () < publications.size ()) ? publications[pub_id.value ()].type : nullStr; + auto pubHandle = publications.lock_shared(); + return (pub_id.value () < pubHandle->size ()) ? (*pubHandle)[pub_id.value ()].type : nullStr; } /** get a count of the number publications registered*/ @@ -318,7 +320,7 @@ int ValueFederateManager::getSubscriptionCount () const { return static_cast callback) { - std::lock_guard sublock (subscription_mutex); + auto subHandle = subscriptions.lock(); if (allCallbackIndex >= 0) { callbacks[allCallbackIndex] = std::move (callback); @@ -335,8 +337,8 @@ void ValueFederateManager::registerCallback (subscription_id_t id, { if (id.value () < subscriptionCount) { - std::lock_guard sublock (subscription_mutex); - subscriptions[id.value ()].callbackIndex = static_cast (callbacks.size ()); + auto subHandle = subscriptions.lock(); + (*subHandle)[id.value ()].callbackIndex = static_cast (callbacks.size ()); callbacks.emplace_back (std::move (callback)); } else @@ -348,14 +350,14 @@ void ValueFederateManager::registerCallback (subscription_id_t id, void ValueFederateManager::registerCallback (const std::vector &ids, std::function callback) { - std::lock_guard sublock (subscription_mutex); + auto subHandle = subscriptions.lock(); int ind = static_cast (callbacks.size ()); callbacks.emplace_back (std::move (callback)); for (auto id : ids) { - if (id.value () < subscriptions.size ()) + if (id.value () < subHandle->size ()) { - subscriptions[id.value ()].callbackIndex = ind; + (*subHandle)[id.value ()].callbackIndex = ind; } } } diff --git a/src/helics/application_api/ValueFederateManager.hpp b/src/helics/application_api/ValueFederateManager.hpp index 0d71b62271..5675d0b855 100644 --- a/src/helics/application_api/ValueFederateManager.hpp +++ b/src/helics/application_api/ValueFederateManager.hpp @@ -11,7 +11,7 @@ All rights reserved. See LICENSE file and DISCLAIMER for more details. #include "data_view.hpp" #include "helicsTypes.hpp" #include -#include +#include "../common/GuardedTypes.hpp" namespace helics { @@ -179,8 +179,8 @@ class ValueFederateManager int getSubscriptionCount () const; private: - DualMappedVector subscriptions; - MappedVector publications; + shared_guarded_m> subscriptions; + shared_guarded_m> publications; std::atomic publicationCount{0}; //!< the count of actual endpoints std::vector> callbacks; //!< the all callback function std::vector lastData; //!< the last data to arrive @@ -189,9 +189,6 @@ class ValueFederateManager Core::federate_id_t fedID; //!< the federation ID from the core API std::atomic subscriptionCount{0}; //!< the count of actual endpoints int allCallbackIndex = -1; //!< index of the allCallback function - - mutable std::mutex subscription_mutex; //!< mutex protecting the subscription information - mutable std::mutex publication_mutex; //!< mutex protecting the publication information private: void getUpdateFromCore (Core::handle_id_t handle); }; diff --git a/src/helics/common/DualMappedPointerVector.hpp b/src/helics/common/DualMappedPointerVector.hpp index f63c047c31..bf56946116 100644 --- a/src/helics/common/DualMappedPointerVector.hpp +++ b/src/helics/common/DualMappedPointerVector.hpp @@ -34,13 +34,17 @@ class DualMappedPointerVector auto fnd = lookup1.find (searchValue1); if (fnd != lookup1.end ()) { - return stx::nullopt; + auto fnd2 = lookup2.find(searchValue2); + if (fnd2 != lookup2.end()) + { + return stx::nullopt; + } } - auto index = dataStorage.size (); - dataStorage.emplace_back (std::move (ptr)); - lookup1.emplace (searchValue1, index); - lookup2.emplace (searchValue2, index); - return index; + auto index = dataStorage.size (); + dataStorage.emplace_back (std::move (ptr)); + lookup1.emplace (searchValue1, index); + lookup2.emplace (searchValue2, index); + return index; } /** insert a new element into the vector*/ template @@ -49,13 +53,17 @@ class DualMappedPointerVector auto fnd = lookup1.find (searchValue1); if (fnd != lookup1.end ()) { - return stx::nullopt; + auto fnd2 = lookup2.find(searchValue2); + if (fnd2 != lookup2.end()) + { + return stx::nullopt; + } } - auto index = dataStorage.size (); - dataStorage.emplace_back (std::make_unique (std::forward (data)...)); - lookup1.emplace (searchValue1, index); - lookup2.emplace (searchValue2, index); - return index; + auto index = dataStorage.size (); + dataStorage.emplace_back (std::make_unique (std::forward (data)...)); + lookup1.emplace (searchValue1, index); + lookup2.emplace (searchValue2, index); + return index; } /** insert a new element into the vector*/ @@ -67,10 +75,10 @@ class DualMappedPointerVector { return stx::nullopt; } - auto index = dataStorage.size (); - dataStorage.emplace_back (std::make_unique (std::forward (data)...)); - lookup1.emplace (searchValue1, index); - return index; + auto index = dataStorage.size (); + dataStorage.emplace_back (std::make_unique (std::forward (data)...)); + lookup1.emplace (searchValue1, index); + return index; } /** insert a new element into the vector*/ @@ -82,10 +90,10 @@ class DualMappedPointerVector { return stx::nullopt; } - auto index = dataStorage.size (); - dataStorage.emplace_back (std::make_unique (std::forward (data)...)); - lookup2.emplace (searchValue2, index); - return index; + auto index = dataStorage.size (); + dataStorage.emplace_back (std::make_unique (std::forward (data)...)); + lookup2.emplace (searchValue2, index); + return index; } /** insert a new element into the vector directly from an existing unique ptr*/ @@ -96,15 +104,21 @@ class DualMappedPointerVector auto fnd = lookup1.find (searchValue1); if (fnd != lookup1.end ()) { - dataStorage[fnd->second] = std::move (ptr); - lookup2[searchValue2] = fnd->second; - return fnd->second; + auto fnd2 = lookup2.find(searchValue2); + if (fnd2 != lookup2.end()) + { + if (fnd2->second == fnd->second) + { + dataStorage[fnd->second] = std::move(ptr); + return fnd->second; + } + } } - auto index = dataStorage.size (); - dataStorage.emplace_back (std::move (ptr)); - lookup1.emplace (searchValue1, index); - lookup2.emplace (searchValue2, index); - return index; + auto index = dataStorage.size (); + dataStorage.emplace_back (std::move (ptr)); + lookup1[searchValue1] = index; + lookup2[searchValue2] = index; + return index; } /** insert a new element into the vector*/ template @@ -113,15 +127,21 @@ class DualMappedPointerVector auto fnd = lookup1.find (searchValue1); if (fnd != lookup1.end ()) { - dataStorage[fnd->second] = std::make_unique (std::forward (data)...); - lookup2[searchValue2] = fnd->second; - return fnd->second; + auto fnd2 = lookup2.find(searchValue2); + if (fnd2 != lookup2.end()) + { + if (fnd2->second == fnd->second) + { + dataStorage[fnd->second] = std::make_unique(std::forward(data)...); + return fnd->second; + } + } } - auto index = dataStorage.size (); - dataStorage.emplace_back (std::make_unique (std::forward (data)...)); - lookup1.emplace (searchValue1, index); - lookup2.emplace (searchValue2, index); - return index; + auto index = dataStorage.size (); + dataStorage.emplace_back (std::make_unique (std::forward (data)...)); + lookup1[searchValue1] = index; + lookup2[searchValue2] = index; + return index; } /** insert a new element into the vector*/ @@ -134,10 +154,10 @@ class DualMappedPointerVector dataStorage[fnd->second] = std::make_unique (std::forward (data)...); return fnd->second; } - auto index = dataStorage.size (); - dataStorage.emplace_back (std::make_unique (std::forward (data)...)); - lookup1.emplace (searchValue1, index); - return index; + auto index = dataStorage.size (); + dataStorage.emplace_back (std::make_unique (std::forward (data)...)); + lookup1.emplace (searchValue1, index); + return index; } /** insert a new element into the vector*/ @@ -150,10 +170,10 @@ class DualMappedPointerVector dataStorage[fnd->second] = std::make_unique (std::forward (data)...); return fnd->second; } - auto index = dataStorage.size (); - dataStorage.emplace_back (std::make_unique (std::forward (data)...)); - lookup2.emplace (searchValue2, index); - return index; + auto index = dataStorage.size (); + dataStorage.emplace_back (std::make_unique (std::forward (data)...)); + lookup2.emplace (searchValue2, index); + return index; } /** find an element based on the search value diff --git a/src/helics/common/DualMappedVector.hpp b/src/helics/common/DualMappedVector.hpp index 89f50f06a6..13a94b8f53 100644 --- a/src/helics/common/DualMappedVector.hpp +++ b/src/helics/common/DualMappedVector.hpp @@ -29,17 +29,18 @@ class DualMappedVector bool insert (const searchType1 &searchValue1, const searchType2 &searchValue2, Us &&... data) { auto fnd = lookup1.find (searchValue1); - if (fnd != lookup1.end ()) - { - return false; - } - else + if (fnd != lookup1.end()) { - auto index = dataStorage.size (); - dataStorage.emplace_back (std::forward (data)...); - lookup1.emplace (searchValue1, index); - lookup2.emplace (searchValue2, index); + auto fnd2 = lookup2.find(searchValue2); + if (fnd2 != lookup2.end()) + { + return false; + } } + auto index = dataStorage.size(); + dataStorage.emplace_back(std::forward(data)...); + lookup1[searchValue1] = index; + lookup2[searchValue2] = index; return true; } @@ -54,12 +55,9 @@ class DualMappedVector { return false; } - else - { - auto index = dataStorage.size (); - dataStorage.emplace_back (std::forward (data)...); - lookup1.emplace (searchValue1, index); - } + auto index = dataStorage.size (); + dataStorage.emplace_back (std::forward (data)...); + lookup1.emplace (searchValue1, index); return true; } @@ -74,12 +72,9 @@ class DualMappedVector { return false; } - else - { - auto index = dataStorage.size (); - dataStorage.emplace_back (std::forward (data)...); - lookup2.emplace (searchValue2, index); - } + auto index = dataStorage.size (); + dataStorage.emplace_back (std::forward (data)...); + lookup2.emplace (searchValue2, index); return true; } @@ -92,16 +87,18 @@ class DualMappedVector auto fnd = lookup1.find (searchValue1); if (fnd != lookup1.end ()) { - dataStorage[fnd->second] = VType (std::forward (data)...); - lookup2[searchValue2] = fnd->second; - } - else - { - auto index = dataStorage.size (); - dataStorage.emplace_back (std::forward (data)...); - lookup1.emplace (searchValue1, index); - lookup2.emplace (searchValue2, index); + auto fnd2 = lookup2.find(searchValue2); + if (fnd2 != lookup2.end()) + { + dataStorage[fnd->second] = VType(std::forward(data)...); + lookup2[searchValue2] = fnd->second; + return; + } } + auto index = dataStorage.size (); + dataStorage.emplace_back (std::forward (data)...); + lookup1[searchValue1] = index; + lookup2[searchValue2] = index; } /** insert a new element into the vector @@ -141,7 +138,8 @@ class DualMappedVector lookup2.emplace (searchValue2, index); } } - /** add an additional index term for searching*/ + /** add an additional index term for searching + this function does not override existing values*/ bool addSearchTermForIndex (const searchType1 &searchValue, size_t index) { if (index < dataStorage.size ()) diff --git a/src/helics/common/GuardedTypes.hpp b/src/helics/common/GuardedTypes.hpp index 2003758884..0f5dcb12a7 100644 --- a/src/helics/common/GuardedTypes.hpp +++ b/src/helics/common/GuardedTypes.hpp @@ -3,7 +3,6 @@ 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. */ - #pragma once #include "helics/compiler-config.h" @@ -16,7 +15,7 @@ All rights reserved. See LICENSE file and DISCLAIMER for more details. #include #include #include - +//#include template diff --git a/src/helics/core/CommonCore.cpp b/src/helics/core/CommonCore.cpp index 36dec05652..860b945368 100644 --- a/src/helics/core/CommonCore.cpp +++ b/src/helics/core/CommonCore.cpp @@ -873,11 +873,13 @@ const std::string &CommonCore::getType (handle_id_t handle) const { auto fed = getFederateAt (handleInfo->local_fed_id); auto subInfo = fed->getSubscription (handleInfo->handle); - if (subInfo->pubType.empty ()) + if (subInfo != nullptr) { - return handleInfo->type; + if (!subInfo->pubType.empty()) + { + return subInfo->pubType; + } } - return subInfo->pubType; } return handleInfo->type; } diff --git a/src/helics/core/CoreBroker.cpp b/src/helics/core/CoreBroker.cpp index a250010536..a8892c6cca 100644 --- a/src/helics/core/CoreBroker.cpp +++ b/src/helics/core/CoreBroker.cpp @@ -210,7 +210,7 @@ void CoreBroker::processPriorityCommand (ActionMessage &&command) transmit (getRoute (command.source_id), badInit); return; } - if (!_federates.insert (command.name, static_cast (_federates.size ()), command.name)) + if (_federates.find(command.name)!=_federates.end()) { ActionMessage badName (CMD_FED_ACK); setActionFlag (badName, error_flag); @@ -220,6 +220,7 @@ void CoreBroker::processPriorityCommand (ActionMessage &&command) transmit (getRoute (command.source_id), badName); return; } + _federates.insert(command.name, static_cast (_federates.size()), command.name); _federates.back ().route_id = getRoute (command.source_id); if (!_isRoot) { diff --git a/src/helics/core/mpi/MpiCore.cpp b/src/helics/core/mpi/MpiCore.cpp index abcdc45f92..63401f380b 100644 --- a/src/helics/core/mpi/MpiCore.cpp +++ b/src/helics/core/mpi/MpiCore.cpp @@ -17,7 +17,7 @@ namespace mpi MpiCore::MpiCore () noexcept {} // MpiCore::~MpiCore () = default; -MpiCore::~MpiCore () { std::cout << "MpiCore destructor for " << getAddress () << std::endl; } +MpiCore::~MpiCore () { std::cout << "MpiCore destructor for " << MpiCore::getAddress () << std::endl; } MpiCore::MpiCore (const std::string &core_name) : CommsBroker (core_name) {} using namespace std::string_literals; @@ -70,7 +70,7 @@ bool MpiCore::brokerConnect () return res; } -std::string MpiCore::getAddress () const { return comms->getAddress (); } +std::string MpiCore::getAddress () const { return (comms)?(comms->getAddress ()): brokerAddress; } } // namespace mpi } // namespace helics diff --git a/src/helics/shared_api_library/ValueFederateExport.cpp b/src/helics/shared_api_library/ValueFederateExport.cpp index 15e6fb5cc3..bcc6a8eb43 100644 --- a/src/helics/shared_api_library/ValueFederateExport.cpp +++ b/src/helics/shared_api_library/ValueFederateExport.cpp @@ -554,9 +554,7 @@ int helicsSubscriptionGetValueSize (helics_subscription sub) auto dv = subObj->fedptr->getValueRaw (subObj->id); return static_cast (dv.size ()); } - - auto str = subObj->subptr->getValue (); - return static_cast (str.size ()); + return static_cast (subObj->subptr->getRawSize()); } helics_status helicsSubscriptionGetRawValue (helics_subscription sub, void *data, int maxDatalen, int *actualSize) @@ -787,8 +785,7 @@ int helicsSubscriptionGetVectorSize (helics_subscription sub) return static_cast (V.size ()); } - auto V = subObj->subptr->getValue> (); - return static_cast (V.size ()); + return static_cast (subObj->subptr->getVectorSize()); } helics_status helicsSubscriptionGetVector (helics_subscription sub, double data[], int maxlen, int *actualSize) diff --git a/tests/helics/application_api/PrimaryTypeConversionTests.cpp b/tests/helics/application_api/PrimaryTypeConversionTests.cpp index 586d28e0a6..c339c9ec82 100644 --- a/tests/helics/application_api/PrimaryTypeConversionTests.cpp +++ b/tests/helics/application_api/PrimaryTypeConversionTests.cpp @@ -36,12 +36,13 @@ BOOST_AUTO_TEST_CASE (vectorNorm_tests) { using c = std::complex; using cv = std::vector; - + BOOST_CHECK_EQUAL(vectorNorm(std::vector()), 0.0); BOOST_CHECK_EQUAL (vectorNorm (std::vector{4.0}), 4.0); BOOST_CHECK_EQUAL (vectorNorm (std::vector{3.0, 4.0}), 5.0); BOOST_CHECK_EQUAL (vectorNorm (std::vector{-3.0, -4.0}), 5.0); BOOST_CHECK_EQUAL (vectorNorm (std::vector{-3.0, -3.0, -3.0, -3.0, -3.0}), std::sqrt (9.0 * 5.0)); + BOOST_CHECK_EQUAL(vectorNorm(cv()), 0.0); BOOST_CHECK_EQUAL (vectorNorm (cv{c (4.0, 0)}), 4.0); BOOST_CHECK_EQUAL (vectorNorm (cv{c (3.0, 4.0)}), 5.0); BOOST_CHECK_EQUAL (vectorNorm (cv{c (-3.0, -4.0)}), 5.0); diff --git a/tests/helics/application_api/subPubObjectTests.cpp b/tests/helics/application_api/subPubObjectTests.cpp index 5cf21cc6dc..9f98c0cf8c 100644 --- a/tests/helics/application_api/subPubObjectTests.cpp +++ b/tests/helics/application_api/subPubObjectTests.cpp @@ -245,7 +245,7 @@ BOOST_AUTO_TEST_CASE (subscriptionObject_vector_tests) SKIPTEST runPubSubTypeTests (c{0.0, 2}, v{0, 2}); - SKIPTEST runPubSubTypeTests (tvec1, 12.4); + SKIPTEST runPubSubTypeTests (tvec1, sqrt(12.4*12.4+0.3*0.3+0.7*0.7)); SKIPTEST runPubSubTypeTests (0.34, v{0.34}); @@ -292,13 +292,118 @@ BOOST_AUTO_TEST_CASE (subscriptionObject_complex_vector_tests) SKIPTEST runPubSubTypeTests (c{0.0, 2}, vc{c{0, 2}}); - SKIPTEST runPubSubTypeTests (tcvec2, 5.0); + SKIPTEST runPubSubTypeTests (tcvec2, helics::vectorNorm(tcvec2)); SKIPTEST runPubSubTypeTests (0.34, vc{c{0.34}}); - SKIPTEST runPubSubTypeTests (tcvec2, 5); + SKIPTEST runPubSubTypeTests (tcvec2, 51); SKIPTEST runPubSubTypeTests (56, vc{c{56}}); } +BOOST_AUTO_TEST_CASE(subscriptionChangedDetection_tests) +{ + helics::FederateInfo fi("test1"); + fi.coreType = CORE_TYPE_TO_TEST; + fi.coreInitString = "1"; + + auto vFed = std::make_shared(fi); + // register the publications + auto pubObj = helics::make_publication(helics::GLOBAL, vFed.get(), std::string("pub1")); + + auto subObj1 = helics::Subscription(vFed.get(), "pub1"); + auto subObj2 = helics::Subscription(vFed.get(), "pub1"); + subObj2.setMinimumChange(0.1); + vFed->setTimeDelta(1.0); + vFed->enterExecutionState(); + // publish string1 at time=0.0; + pubObj->publish(23.7); + auto gtime = vFed->requestTime(1.0); + + BOOST_CHECK_EQUAL(gtime, 1.0); + BOOST_CHECK(subObj1.isUpdated()); + BOOST_CHECK(subObj2.isUpdated()); + //check a second time + BOOST_CHECK(subObj1.isUpdated()); + BOOST_CHECK(subObj2.isUpdated()); + auto val1 = subObj1.getValue(); + auto val2 = subObj2.getValue(); + //now that we got the value it should not be updated + BOOST_CHECK(!subObj1.isUpdated()); + BOOST_CHECK(!subObj2.isUpdated()); + BOOST_CHECK_EQUAL(val1, val2); + BOOST_CHECK_EQUAL(val1, 23.7); + // publish a second string + pubObj->publish(23.61); + // advance time + gtime = vFed->requestTime(2.0); + + BOOST_CHECK(subObj1.isUpdated()); + BOOST_CHECK(!subObj2.isUpdated()); + + vFed->finalize(); +} + + +BOOST_AUTO_TEST_CASE(subscriptionstringSize_tests) +{ + helics::FederateInfo fi("test1"); + fi.coreType = CORE_TYPE_TO_TEST; + fi.coreInitString = "1"; + + auto vFed = std::make_shared(fi); + // register the publications + auto pubObj = helics::make_publication < std::string > (helics::GLOBAL, vFed.get(), std::string("pub1")); + + auto subObj = helics::Subscription(vFed.get(), "pub1"); + + vFed->setTimeDelta(1.0); + vFed->enterExecutionState(); + // publish string1 at time=0.0; + std::string str("this is a string test"); + pubObj->publish(str); + auto gtime = vFed->requestTime(1.0); + + BOOST_CHECK_EQUAL(gtime, 1.0); + BOOST_CHECK(subObj.isUpdated()); + BOOST_CHECK_EQUAL(subObj.getStringSize(), str.size()+1); + BOOST_CHECK_EQUAL(subObj.getRawSize(), str.size()); + auto val1 = subObj.getValue(); + //now that we got the value it should not be updated + BOOST_CHECK(!subObj.isUpdated()); + BOOST_CHECK_EQUAL(val1, str); + vFed->finalize(); +} + + + +BOOST_AUTO_TEST_CASE(subscriptionVectorSize_tests) +{ + helics::FederateInfo fi("test1"); + fi.coreType = CORE_TYPE_TO_TEST; + fi.coreInitString = "1"; + + auto vFed = std::make_shared(fi); + // register the publications + auto pubObj = helics::make_publication < std::vector >(helics::GLOBAL, vFed.get(), std::string("pub1")); + + auto subObj = helics::Subscription(vFed.get(), "pub1"); + + vFed->setTimeDelta(1.0); + vFed->enterExecutionState(); + // publish string1 at time=0.0; + std::vector tvec{ 5,7,234.23,99.1,1e7,0.0 }; + pubObj->publish(tvec); + auto gtime = vFed->requestTime(1.0); + + BOOST_CHECK_EQUAL(gtime, 1.0); + BOOST_CHECK(subObj.isUpdated()); + BOOST_CHECK_EQUAL(subObj.getVectorSize(), tvec.size()); + + auto val1 = subObj.getValue>(); + //now that we got the value it should not be updated + BOOST_CHECK(!subObj.isUpdated()); + BOOST_CHECK(val1==tvec); + vFed->finalize(); +} BOOST_AUTO_TEST_SUITE_END () From 3be39e76c1c47de9e3f82e0dc242b13dbc3495c9 Mon Sep 17 00:00:00 2001 From: Dheepak Krishnamurthy Date: Fri, 25 May 2018 15:06:59 -0600 Subject: [PATCH 10/10] Fix mac linux python extension (#331) * Fix Python extension -rpath issue --- swig/python/CMakeLists.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/swig/python/CMakeLists.txt b/swig/python/CMakeLists.txt index 37aa97295c..b154ecc740 100644 --- a/swig/python/CMakeLists.txt +++ b/swig/python/CMakeLists.txt @@ -1,5 +1,5 @@ ############################################################################## -#Copyright © 2017-2018, +#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. ############################################################################## @@ -44,6 +44,7 @@ SET(CMAKE_SWIG_FLAGS "-py3") set(CMAKE_MACOSX_RPATH 1) set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}") +set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}") SET_PROPERTY(SOURCE ../helics.i PROPERTY SWIG_MODULE_NAME helics) @@ -83,7 +84,7 @@ add_custom_command(TARGET _helics POST_BUILD # Adds a post-build event to COMMAND ${CMAKE_COMMAND} -E copy_if_different # which executes "cmake - E copy_if_different..." "$" # <--this is in-file "$/") # <--this is out-file path - + ENDIF ()