diff --git a/.circleci/config.yml b/.circleci/config.yml index 4db624cc8ca8..373266a51e98 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -244,6 +244,7 @@ jobs: -DHPX_WITH_TESTS_DEBUG_LOG_DESTINATION=/hpx/build/debug-log.txt \ -DHPX_WITH_SPINLOCK_DEADLOCK_DETECTION=On \ -DHPX_WITH_CHECK_MODULE_DEPENDENCIES=On \ + -DHPX_LOGGING_WITH_SEPARATE_DESTINATIONS=Off \ -DCMAKE_EXPORT_COMPILE_COMMANDS=On \ -DHPX_WITH_DOCUMENTATION=On \ -DHPX_WITH_DOCUMENTATION_OUTPUT_FORMATS="${DOCUMENTATION_OUTPUT_FORMATS}" diff --git a/cmake/HPX_AddDefinitions.cmake b/cmake/HPX_AddDefinitions.cmake index b9c367719e7a..d2a9f3373ad8 100644 --- a/cmake/HPX_AddDefinitions.cmake +++ b/cmake/HPX_AddDefinitions.cmake @@ -185,7 +185,7 @@ function(write_config_defines_file) if(NOT OPTION_TEMPLATE) string(TOUPPER ${OPTION_NAMESPACE} NAMESPACE_UPPER) set(PREAMBLE - "// Copyright (c) 2019-2020 STE||AR Group\n" + "// Copyright (c) 2019-2023 STE||AR Group\n" "//\n" "// SPDX-License-Identifier: BSL-1.0\n" "// Distributed under the Boost Software License, Version 1.0. (See accompanying\n" @@ -193,7 +193,7 @@ function(write_config_defines_file) "\n" "// Do not edit this file! It has been generated by the cmake configuration step.\n" "\n" - "#pragma once" + "#pragma once\n" ) set(TEMP_FILENAME "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${NAMESPACE_UPPER}" diff --git a/libs/core/assertion/include/hpx/modules/assertion.hpp b/libs/core/assertion/include/hpx/modules/assertion.hpp index 0213e053c8a7..6efad0a0e304 100644 --- a/libs/core/assertion/include/hpx/modules/assertion.hpp +++ b/libs/core/assertion/include/hpx/modules/assertion.hpp @@ -67,7 +67,7 @@ namespace hpx::assertion { #define HPX_ASSERT_LOCKED_(l, expr, msg) \ (!!(expr) ? void() : \ - (l.unlock(), \ + ((l).unlock(), \ ::hpx::assertion::detail::handle_assert( \ HPX_CURRENT_SOURCE_LOCATION(), HPX_PP_STRINGIZE(expr), \ msg))) /**/ diff --git a/libs/core/command_line_handling_local/include/hpx/command_line_handling_local/command_line_handling_local.hpp b/libs/core/command_line_handling_local/include/hpx/command_line_handling_local/command_line_handling_local.hpp index 9159a50f2879..6dc26a88747d 100644 --- a/libs/core/command_line_handling_local/include/hpx/command_line_handling_local/command_line_handling_local.hpp +++ b/libs/core/command_line_handling_local/include/hpx/command_line_handling_local/command_line_handling_local.hpp @@ -63,7 +63,8 @@ namespace hpx::local::detail { hpx::program_options::variables_map& vm, std::vector& ini_config); - void enable_logging_settings(hpx::program_options::variables_map& vm, + static void enable_logging_settings( + hpx::program_options::variables_map& vm, std::vector& ini_config); void store_command_line(int argc, char** argv); @@ -85,8 +86,8 @@ namespace hpx::local::detail { hpx::program_options::variables_map& prevm); void handle_high_priority_threads( - hpx::program_options::variables_map& vm, - std::vector& ini_config); + hpx::program_options::variables_map const& vm, + std::vector& ini_config) const; }; /////////////////////////////////////////////////////////////////////////// @@ -98,8 +99,9 @@ namespace hpx::local::detail { HPX_CORE_EXPORT std::string convert_to_log_file(std::string const& dest); - HPX_CORE_EXPORT std::size_t handle_num_cores(util::manage_config& cfgmap, - hpx::program_options::variables_map& vm, std::size_t num_threads, + HPX_CORE_EXPORT std::size_t handle_num_cores_default( + util::manage_config& cfgmap, + hpx::program_options::variables_map const& vm, std::size_t num_threads, std::size_t num_default_cores); HPX_CORE_EXPORT std::size_t get_number_of_default_threads( diff --git a/libs/core/command_line_handling_local/src/command_line_handling_local.cpp b/libs/core/command_line_handling_local/src/command_line_handling_local.cpp index 105af2c0f510..6dab0322fed0 100644 --- a/libs/core/command_line_handling_local/src/command_line_handling_local.cpp +++ b/libs/core/command_line_handling_local/src/command_line_handling_local.cpp @@ -1,10 +1,12 @@ -// Copyright (c) 2007-2022 Hartmut Kaiser +// Copyright (c) 2007-2023 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #include +#include + #include #include #include @@ -17,10 +19,11 @@ #include #include #include -#include -#include #include #include +#if defined(HPX_HAVE_MAX_CPU_COUNT) +#include +#endif #include #include @@ -110,8 +113,9 @@ namespace hpx::local::detail { return "file(" + dest + ")"; } - std::string handle_queuing(util::manage_config& cfgmap, - hpx::program_options::variables_map& vm, std::string const& default_) + std::string handle_queuing(util::manage_config const& cfgmap, + hpx::program_options::variables_map const& vm, + std::string const& default_) { // command line options is used preferred if (vm.count("hpx:queuing")) @@ -121,8 +125,9 @@ namespace hpx::local::detail { return cfgmap.get_value("hpx.scheduler", default_); } - std::string handle_affinity(util::manage_config& cfgmap, - hpx::program_options::variables_map& vm, std::string const& default_) + std::string handle_affinity(util::manage_config const& cfgmap, + hpx::program_options::variables_map const& vm, + std::string const& default_) { // command line options is used preferred if (vm.count("hpx:affinity")) @@ -132,15 +137,16 @@ namespace hpx::local::detail { return cfgmap.get_value("hpx.affinity", default_); } - std::string handle_affinity_bind(util::manage_config& cfgmap, - hpx::program_options::variables_map& vm, std::string const& default_) + std::string handle_affinity_bind(util::manage_config const& cfgmap, + hpx::program_options::variables_map const& vm, + std::string const& default_) { // command line options is used preferred if (vm.count("hpx:bind")) { std::string affinity_desc; - std::vector bind_affinity = + std::vector const bind_affinity = vm["hpx:bind"].as>(); for (std::string const& s : bind_affinity) { @@ -156,8 +162,8 @@ namespace hpx::local::detail { return cfgmap.get_value("hpx.bind", default_); } - std::size_t handle_pu_step(util::manage_config& cfgmap, - hpx::program_options::variables_map& vm, std::size_t default_) + std::size_t handle_pu_step(util::manage_config const& cfgmap, + hpx::program_options::variables_map const& vm, std::size_t default_) { // command line options is used preferred if (vm.count("hpx:pu-step")) @@ -167,8 +173,8 @@ namespace hpx::local::detail { return cfgmap.get_value("hpx.pu_step", default_); } - std::size_t handle_pu_offset(util::manage_config& cfgmap, - hpx::program_options::variables_map& vm, std::size_t default_) + std::size_t handle_pu_offset(util::manage_config const& cfgmap, + hpx::program_options::variables_map const& vm, std::size_t default_) { // command line options is used preferred if (vm.count("hpx:pu-offset")) @@ -178,12 +184,12 @@ namespace hpx::local::detail { return cfgmap.get_value("hpx.pu_offset", default_); } - std::size_t handle_numa_sensitive(util::manage_config& cfgmap, - hpx::program_options::variables_map& vm, std::size_t default_) + std::size_t handle_numa_sensitive(util::manage_config const& cfgmap, + hpx::program_options::variables_map const& vm, std::size_t default_) { if (vm.count("hpx:numa-sensitive") != 0) { - std::size_t numa_sensitive = + std::size_t const numa_sensitive = vm["hpx:numa-sensitive"].as(); if (numa_sensitive > 2) { @@ -203,7 +209,7 @@ namespace hpx::local::detail { { if (use_process_mask) { - threads::topology& top = threads::create_topology(); + threads::topology const& top = threads::create_topology(); return threads::count(top.get_cpubind_mask()); } return static_cast(threads::hardware_concurrency()); @@ -211,13 +217,12 @@ namespace hpx::local::detail { std::size_t get_number_of_default_cores(bool use_process_mask) { - threads::topology& top = threads::create_topology(); - - std::size_t num_cores = top.get_number_of_cores(); + threads::topology const& top = threads::create_topology(); + std::size_t const num_cores = top.get_number_of_cores(); if (use_process_mask) { - threads::mask_type proc_mask = top.get_cpubind_mask(); + threads::mask_type const proc_mask = top.get_cpubind_mask(); std::size_t num_cores_proc_mask = 0; for (std::size_t num_core = 0; num_core < num_cores; ++num_core) @@ -237,9 +242,9 @@ namespace hpx::local::detail { } /////////////////////////////////////////////////////////////////////// - std::size_t handle_num_threads(util::manage_config& cfgmap, + std::size_t handle_num_threads(util::manage_config const& cfgmap, hpx::util::runtime_configuration const& rtcfg, - hpx::program_options::variables_map& vm, bool use_process_mask) + hpx::program_options::variables_map const& vm, bool use_process_mask) { // If using the process mask we override "cores" and "all" options but // keep explicit numeric values. @@ -248,11 +253,10 @@ namespace hpx::local::detail { std::size_t const init_cores = get_number_of_default_cores(use_process_mask); - std::string threads_str = cfgmap.get_value( - "hpx.os_threads", + auto threads_str = cfgmap.get_value("hpx.os_threads", rtcfg.get_entry("hpx.os_threads", std::to_string(init_threads))); - std::size_t threads = 0; + std::size_t threads; if ("cores" == threads_str) { threads = init_cores; @@ -303,7 +307,7 @@ namespace hpx::local::detail { } // make sure minimal requested number of threads is observed - std::size_t min_os_threads = + auto min_os_threads = cfgmap.get_value("hpx.force_min_os_threads", threads); if (min_os_threads == 0) @@ -328,17 +332,17 @@ namespace hpx::local::detail { return threads; } - std::size_t handle_num_cores(util::manage_config& cfgmap, - hpx::program_options::variables_map& vm, std::size_t num_threads, + std::size_t handle_num_cores_default(util::manage_config& cfgmap, + hpx::program_options::variables_map const& vm, std::size_t num_threads, std::size_t num_default_cores) { - std::string cores_str = cfgmap.get_value("hpx.cores", ""); + auto cores_str = cfgmap.get_value("hpx.cores", ""); if ("all" == cores_str) { cfgmap.config_["hpx.cores"] = std::to_string(num_default_cores); } - std::size_t num_cores = + auto num_cores = cfgmap.get_value("hpx.cores", num_threads); if (vm.count("hpx:cores")) { @@ -357,10 +361,10 @@ namespace hpx::local::detail { } std::size_t handle_num_cores(util::manage_config& cfgmap, - hpx::program_options::variables_map& vm, std::size_t num_threads, + hpx::program_options::variables_map const& vm, std::size_t num_threads, bool use_process_mask) { - return handle_num_cores(cfgmap, vm, num_threads, + return handle_num_cores_default(cfgmap, vm, num_threads, get_number_of_default_cores(use_process_mask)); } @@ -386,7 +390,7 @@ namespace hpx::local::detail { , num_threads_(1) , num_cores_(1) , pu_step_(1) - , pu_offset_(std::size_t(-1)) + , pu_offset_(static_cast(-1)) , numa_sensitive_(0) , use_process_mask_(false) , cmd_line_parsed_(false) @@ -418,7 +422,8 @@ namespace hpx::local::detail { return; } - if (!(pu_offset_ == std::size_t(-1) || pu_offset_ == std::size_t(0)) || + if (!(pu_offset_ == static_cast(-1) || + pu_offset_ == static_cast(0)) || pu_step_ != 1 || affinity_domain_ != "pu") { throw hpx::detail::command_line_error( @@ -429,7 +434,7 @@ namespace hpx::local::detail { void command_line_handling::check_pu_offset() const { - if (pu_offset_ != std::size_t(-1) && + if (pu_offset_ != static_cast(-1) && pu_offset_ >= static_cast(hpx::threads::hardware_concurrency())) { @@ -454,14 +459,14 @@ namespace hpx::local::detail { } void command_line_handling::handle_high_priority_threads( - hpx::program_options::variables_map& vm, - std::vector& ini_config) + hpx::program_options::variables_map const& vm, + std::vector& ini_config) const { if (vm_.count("hpx:high-priority-threads")) { - std::size_t num_high_priority_queues = + std::size_t const num_high_priority_queues = vm["hpx:high-priority-threads"].as(); - if (num_high_priority_queues != std::size_t(-1) && + if (num_high_priority_queues != static_cast(-1) && num_high_priority_queues > num_threads_) { throw hpx::detail::command_line_error( @@ -488,7 +493,7 @@ namespace hpx::local::detail { hpx::program_options::variables_map& vm, std::vector& ini_config) { - bool debug_clp = vm.count("hpx:debug-clp"); + bool const debug_clp = vm.count("hpx:debug-clp"); if (vm.count("hpx:ini")) { @@ -554,10 +559,11 @@ namespace hpx::local::detail { check_pu_step(); - pu_offset_ = detail::handle_pu_offset(cfgmap, vm, std::size_t(-1)); + pu_offset_ = + detail::handle_pu_offset(cfgmap, vm, static_cast(-1)); // NOLINTNEXTLINE(bugprone-branch-clone) - if (pu_offset_ != std::size_t(-1)) + if (pu_offset_ != static_cast(-1)) { #if defined(__APPLE__) std::cerr << "Warning: PU offset set to \"" << pu_offset_ @@ -585,7 +591,7 @@ namespace hpx::local::detail { // default affinity mode is now 'balanced' (only if no pu-step or // pu-offset is given) - if (pu_step_ == 1 && pu_offset_ == std::size_t(-1) && + if (pu_step_ == 1 && pu_offset_ == static_cast(-1) && affinity_bind_.empty()) { #if defined(__APPLE__) @@ -640,6 +646,7 @@ namespace hpx::local::detail { ini_config.emplace_back("hpx.logging.level=5"); } +#if defined(HPX_LOGGING_HAVE_SEPARATE_DESTINATIONS) if (vm.count("hpx:debug-timing-log")) { ini_config.emplace_back("hpx.logging.console.timing.destination=" + @@ -651,7 +658,15 @@ namespace hpx::local::detail { ini_config.emplace_back("hpx.logging.console.timing.level=1"); ini_config.emplace_back("hpx.logging.timing.level=1"); } - +#else + if (vm.count("hpx:debug-timing-log")) + { + throw hpx::detail::command_line_error( + "Command line option error: can't enable logging while it was " + "disabled at configuration time. Please re-configure HPX using " + "the option -DHPX_LOGGING_WITH_SEPARATE_DESTINATIONS=On."); + } +#endif if (vm.count("hpx:debug-app-log")) { ini_config.emplace_back( @@ -721,13 +736,12 @@ namespace hpx::local::detail { if (!unregistered_options.empty()) { - typedef std::vector::const_iterator iterator_type; - - iterator_type end = unregistered_options.end(); - for (iterator_type it = unregistered_options.begin(); it != end; - ++it) + auto const end = unregistered_options.end(); + for (auto it = unregistered_options.begin(); it != end; ++it) + { unregistered_options_cmd_line += " " + detail::encode_and_enquote(*it); + } ini_config_.emplace_back("hpx.unknown_cmd_line!=" + detail::encode_and_enquote(cmd_name) + @@ -746,7 +760,7 @@ namespace hpx::local::detail { { if (vm_.count("hpx:help")) { - std::string help_option(vm_["hpx:help"].as()); + std::string const help_option(vm_["hpx:help"].as()); if (0 == std::string("minimal").find(help_option)) { // print static help only @@ -780,7 +794,8 @@ namespace hpx::local::detail { #if defined(_POSIX_VERSION) || defined(HPX_WINDOWS) if (vm_.count("hpx:attach-debugger")) { - std::string option = vm_["hpx:attach-debugger"].as(); + std::string const option = + vm_["hpx:attach-debugger"].as(); if (option != "off" && option != "startup" && option != "exception" && option != "test-failure") { @@ -812,8 +827,9 @@ namespace hpx::local::detail { // extract all command line arguments from configuration settings and // remove them from this list - auto it = std::stable_partition(ini_config_.begin(), ini_config_.end(), - [](std::string const& e) { return e.find("--hpx:") != 0; }); + auto const it = + std::stable_partition(ini_config_.begin(), ini_config_.end(), + [](std::string const& e) { return e.find("--hpx:") != 0; }); std::move(it, ini_config_.end(), std::back_inserter(options)); ini_config_.erase(it, ini_config_.end()); @@ -850,7 +866,7 @@ namespace hpx::local::detail { } hpx::string_util::escaped_list_separator sep('\\', ' ', '\"'); - hpx::string_util::tokenizer tok(options, sep); + hpx::string_util::tokenizer const tok(options, sep); std::vector result(tok.begin(), tok.end()); std::move(args.begin(), args.end(), std::back_inserter(result)); diff --git a/libs/core/command_line_handling_local/src/parse_command_line_local.cpp b/libs/core/command_line_handling_local/src/parse_command_line_local.cpp index 1befcfa1b423..09cafec8d687 100644 --- a/libs/core/command_line_handling_local/src/parse_command_line_local.cpp +++ b/libs/core/command_line_handling_local/src/parse_command_line_local.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2022 Hartmut Kaiser +// Copyright (c) 2007-2023 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -9,30 +9,27 @@ #include #include #include -#include -#include #include #include #include -#include #include #include #include /////////////////////////////////////////////////////////////////////////////// -namespace hpx { namespace local { namespace detail { +namespace hpx::local::detail { /////////////////////////////////////////////////////////////////////// std::string trim_whitespace(std::string const& s) { using size_type = std::string::size_type; - size_type first = s.find_first_not_of(" \t"); + size_type const first = s.find_first_not_of(" \t"); if (std::string::npos == first) - return std::string(); + return {}; - size_type last = s.find_last_not_of(" \t"); + size_type const last = s.find_last_not_of(" \t"); return s.substr(first, last - first + 1); } @@ -178,7 +175,7 @@ namespace hpx { namespace local { namespace detail { using hpx::local::detail::trim_whitespace; // skip empty lines - std::string::size_type pos = line.find_first_not_of(" \t"); + std::string::size_type const pos = line.find_first_not_of(" \t"); if (pos == std::string::npos) continue; @@ -188,7 +185,7 @@ namespace hpx { namespace local { namespace detail { // skip comment lines if ('#' != line[0]) { - std::string::size_type p1 = line.find_first_of(" \t"); + std::string::size_type const p1 = line.find_first_of(" \t"); if (p1 != std::string::npos) { // rebuild the line connecting the parts with a '=' @@ -217,9 +214,9 @@ namespace hpx { namespace local { namespace detail { using hpx::program_options::store; using hpx::program_options::command_line_style::unix_style; - util::commandline_error_mode mode = + util::commandline_error_mode const mode = error_mode & util::commandline_error_mode::ignore_aliases; - util::commandline_error_mode notmode = + util::commandline_error_mode const notmode = error_mode & util::commandline_error_mode::ignore_aliases; store(get_commandline_parser( @@ -248,22 +245,21 @@ namespace hpx { namespace local { namespace detail { return; filesystem::path dir(filesystem::initial_path()); - filesystem::path app(appname); + filesystem::path const app(appname); appname = filesystem::basename(app.filename()); // walk up the hierarchy, trying to find a file .cfg while (!dir.empty()) { filesystem::path filename = dir / (appname + ".cfg"); - util::commandline_error_mode mode = error_mode & + util::commandline_error_mode const mode = error_mode & ~util::commandline_error_mode::report_missing_config_file; std::vector options = read_config_file_options(filename.string(), mode); - bool result = handle_config_file_options( - options, desc_cfgfile, vm, ini, mode); - if (result) + if (handle_config_file_options( + options, desc_cfgfile, vm, ini, mode)) { break; // break on the first options file found } @@ -291,7 +287,7 @@ namespace hpx { namespace local { namespace detail { using hpx::program_options::options_description; if (vm.count("hpx:options-file")) { - std::vector const& cfg_files = + auto const& cfg_files = vm["hpx:options-file"].as>(); for (std::string const& cfg_file : cfg_files) @@ -310,7 +306,7 @@ namespace hpx { namespace local { namespace detail { { for (auto const& opt : opts) { - std::string::size_type p = opt.find("--hpx:"); + std::string::size_type const p = opt.find("--hpx:"); if (p != std::string::npos) { throw hpx::detail::command_line_error( @@ -356,19 +352,19 @@ namespace hpx { namespace local { namespace detail { pd.add("hpx:positional", -1); // parse command line, allow for unregistered options this point - util::commandline_error_mode mode = + util::commandline_error_mode const mode = error_mode & util::commandline_error_mode::ignore_aliases; - util::commandline_error_mode notmode = + util::commandline_error_mode const notmode = error_mode & ~util::commandline_error_mode::ignore_aliases; - parsed_options opts(get_commandline_parser( + parsed_options const opts(get_commandline_parser( command_line_parser(args) .options(all_options[options_type::desc_cmdline]) .positional(pd) .style(unix_style) .extra_parser(option_parser(rtcfg, as_bool(mode))), notmode) - .run()); + .run()); // collect unregistered options, if needed if (unregistered_options) @@ -386,18 +382,18 @@ namespace hpx { namespace local { namespace detail { else { // parse command line, allow for unregistered options this point - util::commandline_error_mode mode = + util::commandline_error_mode const mode = error_mode & util::commandline_error_mode::ignore_aliases; - util::commandline_error_mode notmode = + util::commandline_error_mode const notmode = error_mode & ~util::commandline_error_mode::ignore_aliases; - parsed_options opts(get_commandline_parser( + parsed_options const opts(get_commandline_parser( command_line_parser(args) .options(all_options[options_type::desc_cmdline]) .style(unix_style) .extra_parser(option_parser(rtcfg, as_bool(mode))), notmode) - .run()); + .run()); // collect unregistered options, if needed if (unregistered_options) @@ -604,8 +600,9 @@ namespace hpx { namespace local { namespace detail { compose_all_options(app_options, all_options); - bool result = parse_commandline(rtcfg, all_options, app_options, - args, vm, error_mode, visible, unregistered_options); + bool const result = + parse_commandline(rtcfg, all_options, app_options, args, vm, + error_mode, visible, unregistered_options); handle_generic_config_options(arg0, vm, all_options[options_type::desc_cfgfile], rtcfg, error_mode); @@ -631,7 +628,7 @@ namespace hpx { namespace local { namespace detail { std::string extract_arg0(std::string const& cmdline) { - std::string::size_type p = cmdline.find_first_of(" \t"); + std::string::size_type const p = cmdline.find_first_of(" \t"); if (p != std::string::npos) { return cmdline.substr(0, p); @@ -661,7 +658,8 @@ namespace hpx { namespace local { namespace detail { /////////////////////////////////////////////////////////////////////////// std::string embed_in_quotes(std::string const& s) { - char quote = (s.find_first_of('"') != std::string::npos) ? '\'' : '"'; + char const quote = + (s.find_first_of('"') != std::string::npos) ? '\'' : '"'; if (s.find_first_of("\t ") != std::string::npos) return quote + s + quote; @@ -718,4 +716,4 @@ namespace hpx { namespace local { namespace detail { } return command_line; } -}}} // namespace hpx::local::detail +} // namespace hpx::local::detail diff --git a/libs/core/init_runtime_local/include/hpx/init_runtime_local/detail/init_logging.hpp b/libs/core/init_runtime_local/include/hpx/init_runtime_local/detail/init_logging.hpp index 67daf03598b2..54b1d2fc7aec 100644 --- a/libs/core/init_runtime_local/include/hpx/init_runtime_local/detail/init_logging.hpp +++ b/libs/core/init_runtime_local/include/hpx/init_runtime_local/detail/init_logging.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2021 Hartmut Kaiser +// Copyright (c) 2007-2023 Hartmut Kaiser // Copyright (c) 2011 Bryce Lelbach // // SPDX-License-Identifier: BSL-1.0 @@ -15,7 +15,7 @@ #if defined(HPX_HAVE_LOGGING) /////////////////////////////////////////////////////////////////////////////// -namespace hpx { namespace util { +namespace hpx::util { /// \cond NOINTERNAL @@ -23,7 +23,8 @@ namespace hpx { namespace util { // custom log destination: send generated strings to console struct HPX_CORE_EXPORT console_local : logging::destination::manipulator { - console_local(logging::level level, logging_destination dest) + constexpr console_local( + logging::level level, logging_destination dest) noexcept : level_(level) , dest_(dest) { @@ -31,8 +32,8 @@ namespace hpx { namespace util { void operator()(logging::message const& msg) override; - friend bool operator==( - console_local const& lhs, console_local const& rhs) + friend constexpr bool operator==( + console_local const& lhs, console_local const& rhs) noexcept { return lhs.dest_ == rhs.dest_; } @@ -78,12 +79,12 @@ namespace hpx { namespace util { std::string logformat = ""); /// Disable all logging for the given destination - HPX_CORE_EXPORT void disable_logging(logging_destination dest); -}} // namespace hpx::util + HPX_CORE_EXPORT void disable_logging(logging_destination dest) noexcept; +} // namespace hpx::util #else // HPX_HAVE_LOGGING -namespace hpx { namespace util { +namespace hpx::util { namespace detail { HPX_CORE_EXPORT void warn_if_logging_requested(runtime_configuration&); @@ -94,7 +95,7 @@ namespace hpx { namespace util { std::string const& lvl = "5", std::string logdest = "", std::string logformat = ""); - HPX_CORE_EXPORT void disable_logging(logging_destination dest); -}} // namespace hpx::util + HPX_CORE_EXPORT void disable_logging(logging_destination dest) noexcept; +} // namespace hpx::util #endif // HPX_HAVE_LOGGING diff --git a/libs/core/init_runtime_local/src/init_logging.cpp b/libs/core/init_runtime_local/src/init_logging.cpp index 96cb043f0060..d9bca2288d32 100644 --- a/libs/core/init_runtime_local/src/init_logging.cpp +++ b/libs/core/init_runtime_local/src/init_logging.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2021 Hartmut Kaiser +// Copyright (c) 2007-2023 Hartmut Kaiser // Copyright (c) 2011 Bryce Lelbach // // SPDX-License-Identifier: BSL-1.0 @@ -8,6 +8,8 @@ #include #if defined(HPX_HAVE_LOGGING) +#include + #include #include #include @@ -17,7 +19,6 @@ #include #include #include -#include #include #if defined(ANDROID) || defined(__ANDROID__) @@ -25,7 +26,7 @@ #endif /////////////////////////////////////////////////////////////////////////////// -namespace hpx { namespace util { +namespace hpx::util { using logger_writer_type = logging::writer::named_write; @@ -36,9 +37,9 @@ namespace hpx { namespace util { void operator()(std::ostream& to) const override { error_code ec(throwmode::lightweight); - std::size_t thread_num = hpx::get_worker_thread_num(ec); + std::size_t const thread_num = hpx::get_worker_thread_num(ec); - if (std::size_t(-1) != thread_num) + if (static_cast(-1) != thread_num) { util::format_to(to, "{:016x}", thread_num); } @@ -55,7 +56,7 @@ namespace hpx { namespace util { { void operator()(std::ostream& to) const override { - std::uint32_t locality_id = hpx::get_locality_id(); + std::uint32_t const locality_id = hpx::get_locality_id(); if (~static_cast(0) != locality_id) { @@ -75,14 +76,14 @@ namespace hpx { namespace util { { void operator()(std::ostream& to) const override { - threads::thread_self* self = threads::get_self_ptr(); + threads::thread_self const* self = threads::get_self_ptr(); if (nullptr != self) { // called from inside a HPX thread - threads::thread_id_type id = threads::get_self_id(); + threads::thread_id_type const id = threads::get_self_id(); if (id != threads::invalid_thread_id) { - std::ptrdiff_t value = + auto const value = reinterpret_cast(id.get()); util::format_to(to, "{:016x}", value); return; @@ -100,11 +101,11 @@ namespace hpx { namespace util { { void operator()(std::ostream& to) const override { - threads::thread_self* self = threads::get_self_ptr(); + threads::thread_self const* self = threads::get_self_ptr(); if (nullptr != self) { // called from inside a HPX thread - std::size_t phase = self->get_thread_phase(); + std::size_t const phase = self->get_thread_phase(); if (0 != phase) { util::format_to(to, "{:04x}", self->get_thread_phase()); @@ -123,7 +124,7 @@ namespace hpx { namespace util { { void operator()(std::ostream& to) const override { - std::uint32_t parent_locality_id = + std::uint32_t const parent_locality_id = threads::get_parent_locality_id(); if (~static_cast(0) != parent_locality_id) { @@ -144,11 +145,11 @@ namespace hpx { namespace util { { void operator()(std::ostream& to) const override { - threads::thread_id_type parent_id = threads::get_parent_id(); + threads::thread_id_type const parent_id = threads::get_parent_id(); if (nullptr != parent_id) { // called from inside a HPX thread - std::ptrdiff_t value = + auto const value = reinterpret_cast(parent_id.get()); util::format_to(to, "{:016x}", value); } @@ -166,7 +167,7 @@ namespace hpx { namespace util { { void operator()(std::ostream& to) const override { - std::size_t parent_phase = threads::get_parent_phase(); + std::size_t const parent_phase = threads::get_parent_phase(); if (0 != parent_phase) { // called from inside a HPX thread @@ -219,7 +220,7 @@ namespace hpx { namespace util { { switch (dest_) { - default: + // NOLINTNEXTLINE(bugprone-branch-clone) case logging_destination::hpx: LHPX_CONSOLE_(level_) << msg; break; @@ -252,10 +253,10 @@ namespace hpx { namespace util { std::string unescape(std::string const& value) { std::string result; - std::string::size_type pos = 0; - std::string::size_type pos1 = value.find_first_of('\\', 0); - if (std::string::npos != pos1) + if (std::string::size_type pos1 = value.find_first_of('\\', 0); + std::string::npos != pos1) { + std::string::size_type pos = 0; do { switch (value[pos1 + 1]) @@ -338,6 +339,7 @@ namespace hpx { namespace util { writer.set_destination(name, console_local(lvl, dest)); } +#if defined(HPX_LOGGING_HAVE_SEPARATE_DESTINATIONS) /////////////////////////////////////////////////////////////////////// // initialize logging for AGAS void init_agas_log(logging::level lvl, std::string logdest, @@ -372,7 +374,7 @@ namespace hpx { namespace util { agas_logger()->set_enabled(lvl); } - void init_agas_log(runtime_configuration& ini, bool isconsole, + void init_agas_log(runtime_configuration const& ini, bool isconsole, void (*set_console_dest)(logger_writer_type&, char const*, logging::level, logging_destination), void (*define_formatters)(logging::writer::named_write&)) @@ -422,7 +424,7 @@ namespace hpx { namespace util { parcel_logger()->set_enabled(lvl); } - void init_parcel_log(runtime_configuration& ini, bool isconsole, + void init_parcel_log(runtime_configuration const& ini, bool isconsole, void (*set_console_dest)(logger_writer_type&, char const*, logging::level, logging_destination), void (*define_formatters)(logging::writer::named_write&)) @@ -473,7 +475,7 @@ namespace hpx { namespace util { timing_logger()->set_enabled(lvl); } - void init_timing_log(runtime_configuration& ini, bool isconsole, + void init_timing_log(runtime_configuration const& ini, bool isconsole, void (*set_console_dest)(logger_writer_type&, char const*, logging::level, logging_destination), void (*define_formatters)(logging::writer::named_write&)) @@ -488,6 +490,7 @@ namespace hpx { namespace util { HPX_MOVE(settings.format_), isconsole, set_console_dest, define_formatters); } +#endif /////////////////////////////////////////////////////////////////////// void init_hpx_log(logging::level lvl, std::string logdest, @@ -559,7 +562,7 @@ namespace hpx { namespace util { } } - void init_hpx_log(runtime_configuration& ini, bool isconsole, + void init_hpx_log(runtime_configuration const& ini, bool isconsole, void (*set_console_dest)(logger_writer_type&, char const*, logging::level, logging_destination), void (*define_formatters)(logging::writer::named_write&)) @@ -609,7 +612,7 @@ namespace hpx { namespace util { app_logger()->set_enabled(lvl); } - void init_app_log(runtime_configuration& ini, bool isconsole, + void init_app_log(runtime_configuration const& ini, bool isconsole, void (*set_console_dest)(logger_writer_type&, char const*, logging::level, logging_destination), void (*define_formatters)(logging::writer::named_write&)) @@ -660,7 +663,7 @@ namespace hpx { namespace util { debuglog_logger()->set_enabled(lvl); } - void init_debuglog_log(runtime_configuration& ini, bool isconsole, + void init_debuglog_log(runtime_configuration const& ini, bool isconsole, void (*set_console_dest)(logger_writer_type&, char const*, logging::level, logging_destination), void (*define_formatters)(logging::writer::named_write&)) @@ -677,6 +680,7 @@ namespace hpx { namespace util { define_formatters); } +#if defined(HPX_LOGGING_HAVE_SEPARATE_DESTINATIONS) /////////////////////////////////////////////////////////////////////// void init_agas_console_log( logging::level lvl, std::string logdest, std::string logformat) @@ -795,6 +799,7 @@ namespace hpx { namespace util { init_timing_console_log( lvl, HPX_MOVE(settings.dest_), HPX_MOVE(settings.format_)); } +#endif /////////////////////////////////////////////////////////////////////// void init_hpx_console_log( @@ -935,21 +940,25 @@ namespace hpx { namespace util { default_set_console_dest = set_console_dest; default_define_formatters = define_formatters; +#if defined(HPX_LOGGING_HAVE_SEPARATE_DESTINATIONS) // initialize normal logs init_agas_log(ini, isconsole, set_console_dest, define_formatters); init_parcel_log( ini, isconsole, set_console_dest, define_formatters); init_timing_log( ini, isconsole, set_console_dest, define_formatters); +#endif init_hpx_log(ini, isconsole, set_console_dest, define_formatters); init_app_log(ini, isconsole, set_console_dest, define_formatters); init_debuglog_log( ini, isconsole, set_console_dest, define_formatters); // initialize console logs +#if defined(HPX_LOGGING_HAVE_SEPARATE_DESTINATIONS) init_agas_console_log(ini); init_parcel_console_log(ini); init_timing_console_log(ini); +#endif init_hpx_console_log(ini); init_app_console_log(ini); init_debuglog_console_log(ini); @@ -963,15 +972,11 @@ namespace hpx { namespace util { } // namespace detail /////////////////////////////////////////////////////////////////////////// - void disable_logging(logging_destination dest) + void disable_logging(logging_destination dest) noexcept { switch (dest) { - case logging_destination::hpx: - hpx_logger()->set_enabled(logging::level::disable_all); - hpx_console_logger()->set_enabled(logging::level::disable_all); - break; - +#if defined(HPX_LOGGING_HAVE_SEPARATE_DESTINATIONS) case logging_destination::timing: timing_logger()->set_enabled(logging::level::disable_all); timing_console_logger()->set_enabled(logging::level::disable_all); @@ -986,6 +991,17 @@ namespace hpx { namespace util { parcel_logger()->set_enabled(logging::level::disable_all); parcel_console_logger()->set_enabled(logging::level::disable_all); break; +#else + case logging_destination::agas: + case logging_destination::timing: + case logging_destination::parcel: + [[fallthrough]]; +#endif + + case logging_destination::hpx: + hpx_logger()->set_enabled(logging::level::disable_all); + hpx_console_logger()->set_enabled(logging::level::disable_all); + break; case logging_destination::app: app_logger()->set_enabled(logging::level::disable_all); @@ -1010,14 +1026,7 @@ namespace hpx { namespace util { switch (dest) { - case logging_destination::hpx: - detail::init_hpx_log(lvl, logdest, logformat, - detail::default_isconsole, detail::default_set_console_dest, - detail::default_define_formatters); - detail::init_hpx_console_log( - lvl, HPX_MOVE(logdest), HPX_MOVE(logformat)); - break; - +#if defined(HPX_LOGGING_HAVE_SEPARATE_DESTINATIONS) case logging_destination::timing: detail::init_timing_log(lvl, logdest, logformat, detail::default_isconsole, detail::default_set_console_dest, @@ -1041,6 +1050,20 @@ namespace hpx { namespace util { detail::init_parcel_console_log( lvl, HPX_MOVE(logdest), HPX_MOVE(logformat)); break; +#else + case logging_destination::agas: + case logging_destination::timing: + case logging_destination::parcel: + [[fallthrough]]; +#endif + + case logging_destination::hpx: + detail::init_hpx_log(lvl, logdest, logformat, + detail::default_isconsole, detail::default_set_console_dest, + detail::default_define_formatters); + detail::init_hpx_console_log( + lvl, HPX_MOVE(logdest), HPX_MOVE(logformat)); + break; case logging_destination::app: detail::init_app_log(lvl, logdest, logformat, @@ -1059,7 +1082,7 @@ namespace hpx { namespace util { break; } } -}} // namespace hpx::util +} // namespace hpx::util #else @@ -1070,15 +1093,15 @@ namespace hpx { namespace util { #include #include -namespace hpx { namespace util { +namespace hpx::util { ////////////////////////////////////////////////////////////////////////// - void enable_logging( - logging_destination, std::string const&, std::string, std::string) + void enable_logging(logging_destination, std::string const&, + std::string const&, std::string const&) { } - void disable_logging(logging_destination) {} + void disable_logging(logging_destination) noexcept {} ////////////////////////////////////////////////////////////////////////// namespace detail { @@ -1103,6 +1126,6 @@ namespace hpx { namespace util { } } } // namespace detail -}} // namespace hpx::util +} // namespace hpx::util #endif // HPX_HAVE_LOGGING diff --git a/libs/core/logging/CMakeLists.txt b/libs/core/logging/CMakeLists.txt index 632b5433e313..0fba9551fdb0 100644 --- a/libs/core/logging/CMakeLists.txt +++ b/libs/core/logging/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2019 The STE||AR-Group +# Copyright (c) 2019-2023 The STE||AR-Group # # SPDX-License-Identifier: BSL-1.0 # Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -6,6 +6,23 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") +# Compatibility with various Boost types, introduced in V1.4.0 +hpx_option( + HPX_LOGGING_WITH_SEPARATE_DESTINATIONS + BOOL + "Enable separate logging channels for AGAS, timing, and parcel transport. (default: ON)" + ON + ADVANCED + CATEGORY "Modules" + MODULE LOGGING +) + +if(HPX_LOGGING_WITH_SEPARATE_DESTINATIONS) + hpx_add_config_define_namespace( + DEFINE HPX_LOGGING_HAVE_SEPARATE_DESTINATIONS NAMESPACE LOGGING + ) +endif() + # Default location is $HPX_ROOT/libs/logging/include set(logging_headers hpx/modules/logging.hpp @@ -67,5 +84,6 @@ add_hpx_module( hpx_preprocessor hpx_timing hpx_thread_support + hpx_type_support CMAKE_SUBDIRS examples tests ) diff --git a/libs/core/logging/include/hpx/logging/detail/logger.hpp b/libs/core/logging/include/hpx/logging/detail/logger.hpp index 65f5a29702a3..dce86781ad32 100644 --- a/libs/core/logging/include/hpx/logging/detail/logger.hpp +++ b/libs/core/logging/include/hpx/logging/detail/logger.hpp @@ -168,7 +168,7 @@ namespace hpx::util::logging { } public: - HPX_CORE_EXPORT void turn_cache_off(); + HPX_CORE_EXPORT void turn_cache_off() const; // called after all data has been gathered void write(message msg) const diff --git a/libs/core/logging/include/hpx/logging/message.hpp b/libs/core/logging/include/hpx/logging/message.hpp index 190cb0bf8ad5..17777176bb95 100644 --- a/libs/core/logging/include/hpx/logging/message.hpp +++ b/libs/core/logging/include/hpx/logging/message.hpp @@ -18,6 +18,7 @@ #include #include +#include #include #include @@ -28,14 +29,14 @@ namespace hpx::util::logging { /** - @brief Optimizes the formatting for prepending and/or appending + @brief Optimizes the formatting for pre-pending and/or appending strings to the original message It keeps all the modified message in one string. Useful if some formatter needs to access the whole string at once. - reserve() - the size that is reserved for prepending + reserve() - the size that is reserved for pre-pending (similar to string::reserve function) Note : as strings are prepended, reserve() shrinks. @@ -48,12 +49,13 @@ namespace hpx::util::logging { /** @param msg - the message that is originally cached */ - explicit message([[maybe_unused]] std::stringstream msg) noexcept + explicit message(std::stringstream msg) noexcept : m_full_msg_computed(false) #if defined(HPX_COMPUTE_HOST_CODE) , m_str(HPX_MOVE(msg)) #endif { + HPX_UNUSED(msg); } message(message&& other) noexcept diff --git a/libs/core/logging/include/hpx/modules/logging.hpp b/libs/core/logging/include/hpx/modules/logging.hpp index 1b90aa4aed27..3d438adfe43c 100644 --- a/libs/core/logging/include/hpx/modules/logging.hpp +++ b/libs/core/logging/include/hpx/modules/logging.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2022 Hartmut Kaiser +// Copyright (c) 2007-2023 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -7,6 +7,7 @@ #pragma once #include +#include namespace hpx { @@ -84,8 +85,30 @@ namespace hpx::util { std::string const& env, bool allow_always = false); } + //////////////////////////////////////////////////////////////////////////// + HPX_CORE_EXPORT HPX_DECLARE_LOG(hpx) + HPX_CORE_EXPORT HPX_DECLARE_LOG(hpx_console) + +#define LHPX_(lvl, cat) \ + HPX_LOG_FORMAT(hpx::util::hpx, ::hpx::util::logging::level::lvl, "{}{}", \ + ::hpx::util::logging::level::lvl, (cat)) /**/ + +#define LHPX_ENABLED(lvl) \ + hpx::util::hpx_logger()->is_enabled(::hpx::util::logging::level::lvl) /**/ + + //////////////////////////////////////////////////////////////////////////// + // errors are logged in a special manner (always to cerr and additionally, + // if enabled to 'normal' logging destination as well) + HPX_CORE_EXPORT HPX_DECLARE_LOG(hpx_error) + +#define LFATAL_ \ + HPX_LOG_FORMAT(hpx::util::hpx_error, ::hpx::util::logging::level::fatal, \ + "{} [ERR] ", ::hpx::util::logging::level::fatal) + +#if defined(HPX_LOGGING_HAVE_SEPARATE_DESTINATIONS) /////////////////////////////////////////////////////////////////////////// HPX_CORE_EXPORT HPX_DECLARE_LOG(agas) + HPX_CORE_EXPORT HPX_DECLARE_LOG(agas_console) #define LAGAS_(lvl) \ HPX_LOG_FORMAT(hpx::util::agas, ::hpx::util::logging::level::lvl, "{} ", \ @@ -96,6 +119,7 @@ namespace hpx::util { //////////////////////////////////////////////////////////////////////////// HPX_CORE_EXPORT HPX_DECLARE_LOG(parcel) + HPX_CORE_EXPORT HPX_DECLARE_LOG(parcel_console) #define LPT_(lvl) \ HPX_LOG_FORMAT(hpx::util::parcel, ::hpx::util::logging::level::lvl, "{} ", \ @@ -107,6 +131,7 @@ namespace hpx::util { //////////////////////////////////////////////////////////////////////////// HPX_CORE_EXPORT HPX_DECLARE_LOG(timing) + HPX_CORE_EXPORT HPX_DECLARE_LOG(timing_console) #define LTIM_(lvl) \ HPX_LOG_FORMAT(hpx::util::timing, ::hpx::util::logging::level::lvl, "{} ", \ @@ -119,18 +144,24 @@ namespace hpx::util { hpx::util::timing_logger()->is_enabled( \ ::hpx::util::logging::level::lvl) /**/ - //////////////////////////////////////////////////////////////////////////// - HPX_CORE_EXPORT HPX_DECLARE_LOG(hpx) +#else -#define LHPX_(lvl, cat) \ - HPX_LOG_FORMAT(hpx::util::hpx, ::hpx::util::logging::level::lvl, "{}{}", \ - ::hpx::util::logging::level::lvl, (cat)) /**/ +#define LAGAS_(lvl) LHPX_(lvl, "[AGAS] ") +#define LAGAS_ENABLED(lvl) LHPX_ENABLED(lvl) -#define LHPX_ENABLED(lvl) \ - hpx::util::hpx_logger()->is_enabled(::hpx::util::logging::level::lvl) /**/ +#define LPT_(lvl) LHPX_(lvl, " [PT] ") +#define LPT_ENABLED(lvl) LHPX_ENABLED(lvl) + +#define LTIM_(lvl) LHPX_(lvl, " [TIM] ") +#define LPROGRESS_ LTIM_(fatal) +#define LTIM_ENABLED(lvl) LHPX_ENABLED(lvl) + +#endif //////////////////////////////////////////////////////////////////////////// + // Application specific logging HPX_CORE_EXPORT HPX_DECLARE_LOG(app) + HPX_CORE_EXPORT HPX_DECLARE_LOG(app_console) #define LAPP_(lvl) \ HPX_LOG_FORMAT(hpx::util::app, ::hpx::util::logging::level::lvl, "{} ", \ @@ -142,6 +173,7 @@ namespace hpx::util { //////////////////////////////////////////////////////////////////////////// // special debug logging channel HPX_CORE_EXPORT HPX_DECLARE_LOG(debuglog) + HPX_CORE_EXPORT HPX_DECLARE_LOG(debuglog_console) #define LDEB_ \ HPX_LOG_FORMAT(hpx::util::debuglog, ::hpx::util::logging::level::error, \ @@ -151,27 +183,10 @@ namespace hpx::util { hpx::util::debuglog_logger()->is_enabled( \ ::hpx::util::logging::level::error) /**/ - //////////////////////////////////////////////////////////////////////////// - // errors are logged in a special manner (always to cerr and additionally, - // if enabled to 'normal' logging destination as well) - HPX_CORE_EXPORT HPX_DECLARE_LOG(hpx_error) - -#define LFATAL_ \ - HPX_LOG_FORMAT(hpx::util::hpx_error, ::hpx::util::logging::level::fatal, \ - "{} [ERR] ", ::hpx::util::logging::level::fatal) - - HPX_CORE_EXPORT HPX_DECLARE_LOG(agas_console) - HPX_CORE_EXPORT HPX_DECLARE_LOG(parcel_console) - HPX_CORE_EXPORT HPX_DECLARE_LOG(timing_console) - HPX_CORE_EXPORT HPX_DECLARE_LOG(hpx_console) - HPX_CORE_EXPORT HPX_DECLARE_LOG(app_console) - - // special debug logging channel - HPX_CORE_EXPORT HPX_DECLARE_LOG(debuglog_console) - // clang-format on } // namespace hpx::util +#if defined(HPX_LOGGING_HAVE_SEPARATE_DESTINATIONS) /////////////////////////////////////////////////////////////////////////////// #define LAGAS_CONSOLE_(lvl) \ HPX_LOG_USE_LOG(hpx::util::agas_console, \ @@ -187,6 +202,11 @@ namespace hpx::util { HPX_LOG_USE_LOG(hpx::util::timing_console, \ static_cast<::hpx::util::logging::level>(lvl)) \ /**/ +#else +#define LAGAS_CONSOLE_(lvl) LHPX_CONSOLE_(lvl) +#define LPT_CONSOLE_(lvl) LHPX_CONSOLE_(lvl) +#define LTIM_CONSOLE_(lvl) LHPX_CONSOLE_(lvl) +#endif #define LHPX_CONSOLE_(lvl) \ HPX_LOG_USE_LOG( \ diff --git a/libs/core/logging/src/logging.cpp b/libs/core/logging/src/logging.cpp index 31077de5b41a..f3a4997b3dc4 100644 --- a/libs/core/logging/src/logging.cpp +++ b/libs/core/logging/src/logging.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2022 Hartmut Kaiser +// Copyright (c) 2007-2023 Hartmut Kaiser // Copyright (c) 2011 Bryce Lelbach // // SPDX-License-Identifier: BSL-1.0 @@ -8,13 +8,12 @@ #include #if defined(HPX_HAVE_LOGGING) +#include + #include #include #include -#include -#include -#include #include #include #include @@ -22,8 +21,6 @@ /////////////////////////////////////////////////////////////////////////////// namespace hpx::util { - HPX_DEFINE_LOG(agas, disable_all) - HPX_DEFINE_LOG(agas_console, disable_all) HPX_DEFINE_LOG(app, disable_all) HPX_DEFINE_LOG(app_console, disable_all) HPX_DEFINE_LOG(app_error, fatal) @@ -33,10 +30,15 @@ namespace hpx::util { HPX_DEFINE_LOG(hpx, disable_all) HPX_DEFINE_LOG(hpx_console, disable_all) HPX_DEFINE_LOG(hpx_error, fatal) + +#if defined(HPX_LOGGING_HAVE_SEPARATE_DESTINATIONS) + HPX_DEFINE_LOG(agas, disable_all) + HPX_DEFINE_LOG(agas_console, disable_all) HPX_DEFINE_LOG(parcel, disable_all) HPX_DEFINE_LOG(parcel_console, disable_all) HPX_DEFINE_LOG(timing, disable_all) HPX_DEFINE_LOG(timing_console, disable_all) +#endif namespace detail { @@ -45,7 +47,7 @@ namespace hpx::util { { try { - int env_val = hpx::util::from_string(env); + int const env_val = hpx::util::from_string(env); if (env_val < 0) return hpx::util::logging::level::disable_all; @@ -81,7 +83,7 @@ namespace hpx::util { namespace hpx::util::logging { - void logger::turn_cache_off() + void logger::turn_cache_off() const { if (m_is_caching_off) return; // already turned off diff --git a/libs/core/mpi_base/include/hpx/mpi_base/mpi_environment.hpp b/libs/core/mpi_base/include/hpx/mpi_base/mpi_environment.hpp index d01d27cb4151..c8746f39d59f 100644 --- a/libs/core/mpi_base/include/hpx/mpi_base/mpi_environment.hpp +++ b/libs/core/mpi_base/include/hpx/mpi_base/mpi_environment.hpp @@ -29,16 +29,16 @@ namespace hpx::util { static int init(int* argc, char*** argv, int const minimal, int const required, int& provided); static void init(int* argc, char*** argv, runtime_configuration& cfg); - static void finalize(); + static void finalize() noexcept; - static bool enabled(); - static bool multi_threaded(); - static bool has_called_init(); + static bool enabled() noexcept; + static bool multi_threaded() noexcept; + static bool has_called_init() noexcept; - static int rank(); - static int size(); + static int rank() noexcept; + static int size() noexcept; - static MPI_Comm& communicator(); + static MPI_Comm& communicator() noexcept; static std::string get_processor_name(); @@ -54,7 +54,13 @@ namespace hpx::util { ~scoped_lock(); - static void unlock(); + constexpr bool owns_lock() const noexcept + { + return locked; + } + + void unlock(); + bool locked; }; struct HPX_CORE_EXPORT scoped_try_lock @@ -69,6 +75,11 @@ namespace hpx::util { ~scoped_try_lock(); + constexpr bool owns_lock() const noexcept + { + return locked; + } + void unlock(); bool locked; }; diff --git a/libs/core/mpi_base/src/mpi_environment.cpp b/libs/core/mpi_base/src/mpi_environment.cpp index d50590c57d9e..3fe15d7a1d20 100644 --- a/libs/core/mpi_base/src/mpi_environment.cpp +++ b/libs/core/mpi_base/src/mpi_environment.cpp @@ -16,10 +16,11 @@ #include #include +#include #include /////////////////////////////////////////////////////////////////////////////// -namespace hpx { namespace util { +namespace hpx::util { namespace detail { @@ -39,7 +40,7 @@ namespace hpx { namespace util { mpi_environment_strings, sep); for (auto const& tok : tokens) { - if (char* env = std::getenv(tok.c_str())) + if (char const* env = std::getenv(tok.c_str())) { LBT_(debug) << "Found MPI environment variable: " << tok << "=" @@ -91,12 +92,12 @@ namespace hpx { namespace util { return false; #endif } -}} // namespace hpx::util +} // namespace hpx::util #if (defined(HPX_HAVE_NETWORKING) && defined(HPX_HAVE_PARCELPORT_MPI)) || \ defined(HPX_HAVE_MODULE_MPI_BASE) -namespace hpx { namespace util { +namespace hpx::util { mpi_environment::mutex_type mpi_environment::mtx_; bool mpi_environment::enabled_ = false; @@ -119,6 +120,7 @@ namespace hpx { namespace util { { return retval; } + if (!is_initialized) { retval = MPI_Init_thread(nullptr, nullptr, required, &provided); @@ -174,12 +176,12 @@ namespace hpx { namespace util { rtcfg.add_entry("hpx.parcel.bootstrap", "mpi"); - int required = MPI_THREAD_SINGLE; + int required = MPI_THREAD_SERIALIZED; #if defined(HPX_HAVE_PARCELPORT_MPI_MULTITHREADED) required = (get_entry_as(rtcfg, "hpx.parcel.mpi.multithreaded", 1) != 0) ? MPI_THREAD_MULTIPLE : - MPI_THREAD_SINGLE; + MPI_THREAD_SERIALIZED; #if defined(MVAPICH2_VERSION) && defined(_POSIX_SOURCE) // This enables multi threading support in MVAPICH2 if requested. @@ -216,9 +218,9 @@ namespace hpx { namespace util { MPI_Comm_dup(MPI_COMM_WORLD, &communicator_); - if (provided_threading_flag_ < MPI_THREAD_SERIALIZED) + if (provided_threading_flag_ <= MPI_THREAD_SERIALIZED) { - // explicitly disable mpi if not run by mpirun + // explicitly disable multi-threaded mpi if needed rtcfg.add_entry("hpx.parcel.mpi.multithreaded", "0"); } @@ -230,8 +232,8 @@ namespace hpx { namespace util { "mpi_environment::init: MPI_Init_thread: " "The underlying MPI implementation only supports " "MPI_THREAD_FUNNELED. This mode is not supported by HPX. " - "Please pass -Ihpx.parcel.mpi.multithreaded=0 to explicitly " - "disable MPI multi-threading."); + "Please pass -hpx:ini=hpx.parcel.mpi.multithreaded=0 to " + "explicitly disable MPI multi-threading."); } this_rank = rank(); @@ -257,17 +259,21 @@ namespace hpx { namespace util { std::string mpi_environment::get_processor_name() { + scoped_lock l; + char name[MPI_MAX_PROCESSOR_NAME + 1] = {'\0'}; int len = 0; MPI_Get_processor_name(name, &len); - return name; + return {name}; } - void mpi_environment::finalize() + void mpi_environment::finalize() noexcept { if (enabled() && has_called_init()) { + scoped_lock l; + int is_finalized = 0; MPI_Finalized(&is_finalized); if (!is_finalized) @@ -277,43 +283,50 @@ namespace hpx { namespace util { } } - bool mpi_environment::enabled() + bool mpi_environment::enabled() noexcept { return enabled_; } - bool mpi_environment::multi_threaded() + bool mpi_environment::multi_threaded() noexcept { - return provided_threading_flag_ >= MPI_THREAD_SERIALIZED; + return provided_threading_flag_ > MPI_THREAD_SERIALIZED; } - bool mpi_environment::has_called_init() + bool mpi_environment::has_called_init() noexcept { return has_called_init_; } - int mpi_environment::size() + int mpi_environment::size() noexcept { int res(-1); if (enabled()) + { + scoped_lock l; MPI_Comm_size(communicator(), &res); + } return res; } - int mpi_environment::rank() + int mpi_environment::rank() noexcept { int res(-1); if (enabled()) + { + scoped_lock l; MPI_Comm_rank(communicator(), &res); + } return res; } - MPI_Comm& mpi_environment::communicator() + MPI_Comm& mpi_environment::communicator() noexcept { return communicator_; } mpi_environment::scoped_lock::scoped_lock() + : locked(true) { if (!multi_threaded()) mtx_.lock(); @@ -322,13 +335,19 @@ namespace hpx { namespace util { mpi_environment::scoped_lock::~scoped_lock() { if (!multi_threaded()) + { + locked = false; mtx_.unlock(); + } } void mpi_environment::scoped_lock::unlock() { if (!multi_threaded()) + { + locked = false; mtx_.unlock(); + } } mpi_environment::scoped_try_lock::scoped_try_lock() @@ -343,7 +362,10 @@ namespace hpx { namespace util { mpi_environment::scoped_try_lock::~scoped_try_lock() { if (!multi_threaded() && locked) + { + locked = false; mtx_.unlock(); + } } void mpi_environment::scoped_try_lock::unlock() @@ -354,6 +376,6 @@ namespace hpx { namespace util { mtx_.unlock(); } } -}} // namespace hpx::util +} // namespace hpx::util #endif diff --git a/libs/core/runtime_local/src/runtime_local.cpp b/libs/core/runtime_local/src/runtime_local.cpp index d77231ca487d..fc00acfc3d7c 100644 --- a/libs/core/runtime_local/src/runtime_local.cpp +++ b/libs/core/runtime_local/src/runtime_local.cpp @@ -1348,19 +1348,22 @@ namespace hpx { if (call_startup) { call_startup_functions(true); - lbt_ << "(3rd stage) run_helper: ran pre-startup functions"; + lbt_ << "(3rd stage, local) runtime::run_helper: ran " + "pre-startup functions"; call_startup_functions(false); - lbt_ << "(4th stage) run_helper: ran startup functions"; + lbt_ << "(4th stage, local) runtime::run_helper: ran startup " + "functions"; } - lbt_ << "(4th stage) runtime::run_helper: bootstrap complete"; + lbt_ + << "(4th stage, local) runtime::run_helper: bootstrap complete"; set_state(hpx::state::running); // Now, execute the user supplied thread function (hpx_main) if (!!func) { - lbt_ << "(last stage) runtime::run_helper: about to " + lbt_ << "(last stage, local) runtime::run_helper: about to " "invoke hpx_main"; // Change our thread description, as we're about to call hpx_main diff --git a/libs/core/thread_pools/include/hpx/thread_pools/scheduling_loop.hpp b/libs/core/thread_pools/include/hpx/thread_pools/scheduling_loop.hpp index b0b807485533..117a24baffcf 100644 --- a/libs/core/thread_pools/include/hpx/thread_pools/scheduling_loop.hpp +++ b/libs/core/thread_pools/include/hpx/thread_pools/scheduling_loop.hpp @@ -186,12 +186,15 @@ namespace hpx::threads::detail { std::shared_ptr background_running; thread_id_ref_type background_thread; - - if (scheduler.has_scheduler_mode( + bool const do_background_work = + scheduler.has_scheduler_mode( policies::scheduler_mode::do_background_work) && num_thread < params.max_background_threads_ && - !params.background_.empty()) + !params.background_.empty(); + + if (do_background_work) { + // do background work in parcel layer and in agas background_thread = create_background_thread(scheduler, num_thread, params, background_running, idle_loop_count); } @@ -543,11 +546,14 @@ namespace hpx::threads::detail { continue; } - // do background work in parcel layer and in agas - call_and_create_background_thread(background_thread, next_thrd, - scheduler, num_thread, bg_work_exec_time_init, - context_storage, params, background_running, - idle_loop_count); + if (do_background_work) + { + // do background work in parcel layer and in agas + call_and_create_background_thread(background_thread, + next_thrd, scheduler, num_thread, + bg_work_exec_time_init, context_storage, params, + background_running, idle_loop_count); + } // call back into invoking context if (!params.inner_.empty()) @@ -575,11 +581,14 @@ namespace hpx::threads::detail { { busy_loop_count = 0; - // do background work in parcel layer and in agas - call_and_create_background_thread(background_thread, next_thrd, - scheduler, num_thread, bg_work_exec_time_init, - context_storage, params, background_running, - idle_loop_count); + if (do_background_work) + { + // do background work in parcel layer and in agas + call_and_create_background_thread(background_thread, + next_thrd, scheduler, num_thread, + bg_work_exec_time_init, context_storage, params, + background_running, idle_loop_count); + } } else if (idle_loop_count > params.max_idle_loop_count_ || may_exit) { diff --git a/libs/core/thread_pools/src/detail/background_thread.cpp b/libs/core/thread_pools/src/detail/background_thread.cpp index 6bd914a768d5..6906b05a9b65 100644 --- a/libs/core/thread_pools/src/detail/background_thread.cpp +++ b/libs/core/thread_pools/src/detail/background_thread.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -67,6 +68,11 @@ namespace hpx::threads::detail { scheduler_base.increment_background_thread_count(); + LTM_(debug).format("create_background_thread: pool({}), " + "scheduler({}), worker_thread({}), thread({})", + scheduler_base.get_parent_pool(), scheduler_base, num_thread, + get_thread_id_data(background_thread)); + // We can now set the state to pending get_thread_id_data(background_thread) ->set_state(thread_schedule_state::pending); @@ -180,7 +186,12 @@ namespace hpx::threads::detail { hpx::execution_base::this_thread::detail::agent_storage* context_storage) { - if (HPX_UNLIKELY(background_thread)) + LTM_(debug).format("call_background_thread: pool({}), " + "scheduler({}), worker_thread({}), thread({})", + scheduler_base.get_parent_pool(), scheduler_base, num_thread, + get_thread_id_data(background_thread)); + + if (HPX_LIKELY(background_thread)) { auto* thrdptr = get_thread_id_data(background_thread); thread_state state = thrdptr->get_state(); @@ -236,11 +247,23 @@ namespace hpx::threads::detail { } else if (thread_schedule_state::terminated == state_val) { + LTM_(debug).format( + "call_background_thread terminated: pool({}), " + "scheduler({}), worker_thread({}), thread({})", + scheduler_base.get_parent_pool(), scheduler_base, + num_thread, get_thread_id_data(background_thread)); + scheduler_base.decrement_background_thread_count(); background_thread = thread_id_type(); } else if (thread_schedule_state::suspended == state_val) { + LTM_(debug).format( + "call_background_thread suspended: pool({}), " + "scheduler({}), worker_thread({}), thread({})", + scheduler_base.get_parent_pool(), scheduler_base, + num_thread, get_thread_id_data(background_thread)); + return false; } } diff --git a/libs/full/agas/src/route.cpp b/libs/full/agas/src/route.cpp index 3355ddb163de..3fde16520a9f 100644 --- a/libs/full/agas/src/route.cpp +++ b/libs/full/agas/src/route.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2011 Vinay C Amatya -// Copyright (c) 2007-2021 Hartmut Kaiser +// Copyright (c) 2007-2023 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -43,6 +43,8 @@ namespace hpx::agas::server { void primary_namespace::route(parcelset::parcel&& p) { + LPT_(debug).format("primary_namespace::route: {}", p.parcel_id()); + util::scoped_timer> update( counter_data_.route_.time_, counter_data_.route_.enabled_); counter_data_.increment_route_count(); @@ -92,7 +94,7 @@ namespace hpx::agas::server { addr.address_ = g.lva(); } - hpx::id_type source = p.source_id(); + hpx::id_type const source = p.source_id(); // either send the parcel on its way or execute actions locally if (naming::get_locality_id_from_gid(addr.locality_) == @@ -113,21 +115,21 @@ namespace hpx::agas::server { hpx::parcelset::put_parcel(HPX_MOVE(p)); } - runtime& rt = get_runtime(); + runtime const& rt = get_runtime(); if (rt.get_state() < hpx::state::pre_shutdown) { - // asynchronously update cache on source locality - // update remote cache if the id is not flagged otherwise + // asynchronously update cache on source locality update remote + // cache if the id is not flagged otherwise naming::gid_type const& id = hpx::get<0>(cache_address); if (id && naming::detail::store_in_cache(id)) { gva const& g = hpx::get<1>(cache_address); - naming::address addr(g.prefix, g.type, g.lva()); + naming::address address(g.prefix, g.type, g.lva()); HPX_ASSERT(naming::is_locality(source)); hpx::post( - source, id, addr, g.count, g.offset); + source, id, address, g.count, g.offset); } } } diff --git a/libs/full/command_line_handling/include/hpx/command_line_handling/command_line_handling.hpp b/libs/full/command_line_handling/include/hpx/command_line_handling/command_line_handling.hpp index 173ae0002a71..55ed47532afd 100644 --- a/libs/full/command_line_handling/include/hpx/command_line_handling/command_line_handling.hpp +++ b/libs/full/command_line_handling/include/hpx/command_line_handling/command_line_handling.hpp @@ -49,7 +49,8 @@ namespace hpx::util { std::vector& ini_config, std::size_t& node, bool initial = false); - void enable_logging_settings(hpx::program_options::variables_map& vm, + static void enable_logging_settings( + hpx::program_options::variables_map& vm, std::vector& ini_config); }; } // namespace hpx::util diff --git a/libs/full/command_line_handling/src/command_line_handling.cpp b/libs/full/command_line_handling/src/command_line_handling.cpp index 5c08e36f6b07..a04e3073bd8d 100644 --- a/libs/full/command_line_handling/src/command_line_handling.cpp +++ b/libs/full/command_line_handling/src/command_line_handling.cpp @@ -5,6 +5,8 @@ // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #include +#include + #include #include #include @@ -700,9 +702,9 @@ namespace hpx::util { num_threads_ = detail::handle_num_threads(cfgmap, rtcfg_, vm, env, using_nodelist, initial, use_process_mask_); - num_cores_ = - hpx::local::detail::handle_num_cores(cfgmap, vm, num_threads_, - detail::get_number_of_default_cores(env, use_process_mask_)); + num_cores_ = hpx::local::detail::handle_num_cores_default(cfgmap, vm, + num_threads_, + detail::get_number_of_default_cores(env, use_process_mask_)); // Set number of cores and OS threads in configuration. ini_config.emplace_back( @@ -866,7 +868,7 @@ namespace hpx::util { { base_type::enable_logging_settings(vm, ini_config); -#if defined(HPX_HAVE_LOGGING) +#if defined(HPX_HAVE_LOGGING) && defined(HPX_LOGGING_HAVE_SEPARATE_DESTINATIONS) if (vm.count("hpx:debug-agas-log")) { ini_config.emplace_back("hpx.logging.console.agas.destination=" + @@ -893,12 +895,11 @@ namespace hpx::util { #else if (vm.count("hpx:debug-agas-log") || vm.count("hpx:debug-parcel-log")) { - // clang-format off throw hpx::detail::command_line_error( - "Command line option error: can't enable logging while it " - "was disabled at configuration time. Please re-configure " - "HPX using the option -DHPX_WITH_LOGGING=On."); - // clang-format on + "Command line option error: can't enable logging while it was " + "disabled at configuration time. Please re-configure HPX using " + "the options -DHPX_WITH_LOGGING=On and " + "-DHPX_LOGGING_WITH_SEPARATE_DESTINATIONS=On."); } #endif } diff --git a/libs/full/command_line_handling/src/parse_command_line.cpp b/libs/full/command_line_handling/src/parse_command_line.cpp index 0b882ec84373..a2a6a0a4896e 100644 --- a/libs/full/command_line_handling/src/parse_command_line.cpp +++ b/libs/full/command_line_handling/src/parse_command_line.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2022 Hartmut Kaiser +// Copyright (c) 2007-2023 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying diff --git a/libs/full/init_runtime/src/pre_main.cpp b/libs/full/init_runtime/src/pre_main.cpp index 5a2dda3a80c0..a9b9e77f5995 100644 --- a/libs/full/init_runtime/src/pre_main.cpp +++ b/libs/full/init_runtime/src/pre_main.cpp @@ -196,7 +196,7 @@ namespace hpx { namespace detail { // all user code, including startup functions, are only run after the // component tables are populated. distributed::barrier::synchronize(); - lbt_ << "(5th stage) pre_main: passed 4th stage boot barrier"; + lbt_ << "(5th stage) pre_main: passed 5th stage boot barrier"; } // Enable logging. Even if we terminate at this point we will see all diff --git a/libs/full/parcelport_mpi/include/hpx/parcelport_mpi/header.hpp b/libs/full/parcelport_mpi/include/hpx/parcelport_mpi/header.hpp index 6b5d011cf029..953609bbb0ac 100644 --- a/libs/full/parcelport_mpi/include/hpx/parcelport_mpi/header.hpp +++ b/libs/full/parcelport_mpi/include/hpx/parcelport_mpi/header.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2013-2021 Hartmut Kaiser +// Copyright (c) 2013-2023 Hartmut Kaiser // Copyright (c) 2013-2015 Thomas Heller // // SPDX-License-Identifier: BSL-1.0 @@ -11,7 +11,7 @@ #if defined(HPX_HAVE_NETWORKING) && defined(HPX_HAVE_PARCELPORT_MPI) #include - +#include #include #include @@ -37,30 +37,35 @@ namespace hpx::parcelset::policies::mpi { pos_piggy_back_data = 5 * sizeof(value_type) + 1 }; - static constexpr int data_size_ = 512; + static constexpr std::int32_t data_size_ = 512; template header(Buffer const& buffer, int tag) noexcept { - std::int64_t size = static_cast(buffer.size_); - std::int64_t numbytes = - static_cast(buffer.data_size_); + init(buffer, tag); + } + + template + void init(Buffer const& buffer, int tag) noexcept + { + auto const size = static_cast(buffer.size_); + auto const numbytes = static_cast(buffer.data_size_); HPX_ASSERT(size <= (std::numeric_limits::max)()); HPX_ASSERT(numbytes <= (std::numeric_limits::max)()); - set(tag); - set(static_cast(size)); - set(static_cast(numbytes)); - set( + set(pos_tag, tag); + set(pos_size, static_cast(size)); + set(pos_numbytes, static_cast(numbytes)); + set(pos_numchunks_first, static_cast(buffer.num_chunks_.first)); - set( + set(pos_numchunks_second, static_cast(buffer.num_chunks_.second)); if (buffer.data_.size() <= (data_size_ - pos_piggy_back_data)) { data_[pos_piggy_back_flag] = 1; - std::memcpy(&data_[pos_piggy_back_data], &buffer.data_[0], + std::memcpy(&data_[pos_piggy_back_data], buffer.data_.data(), buffer.data_.size()); } else @@ -76,11 +81,11 @@ namespace hpx::parcelset::policies::mpi { void reset() noexcept { - std::memset(&data_[0], static_cast(-1), data_size_); + std::memset(data_.data(), static_cast(-1), data_size_); data_[pos_piggy_back_flag] = 1; } - bool valid() const noexcept + [[nodiscard]] constexpr bool valid() const noexcept { return data_[0] != static_cast(-1); } @@ -96,31 +101,32 @@ namespace hpx::parcelset::policies::mpi { constexpr char* data() noexcept { - return &data_[0]; + return data_.data(); } - value_type tag() const noexcept + [[nodiscard]] constexpr value_type tag() const noexcept { - return get(); + return get(pos_tag); } - value_type size() const noexcept + [[nodiscard]] constexpr value_type size() const noexcept { - return get(); + return get(pos_size); } - value_type numbytes() const noexcept + [[nodiscard]] constexpr value_type numbytes() const noexcept { - return get(); + return get(pos_numbytes); } - std::pair num_chunks() const noexcept + [[nodiscard]] constexpr std::pair num_chunks() + const noexcept { return std::make_pair( - get(), get()); + get(pos_numchunks_first), get(pos_numchunks_second)); } - constexpr char* piggy_back() noexcept + [[nodiscard]] constexpr char* piggy_back() noexcept { if (data_[pos_piggy_back_flag]) return &data_[pos_piggy_back_data]; @@ -130,18 +136,14 @@ namespace hpx::parcelset::policies::mpi { private: std::array data_; - template - void set(T const& t) noexcept + constexpr void set(std::size_t Pos, value_type const& t) noexcept { - std::memcpy(&data_[Pos], &t, sizeof(t)); + *hpx::bit_cast(&data_[Pos]) = t; } - template - value_type get() const noexcept + [[nodiscard]] constexpr value_type get(std::size_t Pos) const noexcept { - value_type res; - std::memcpy(&res, &data_[Pos], sizeof(res)); - return res; + return *hpx::bit_cast(&data_[Pos]); } }; } // namespace hpx::parcelset::policies::mpi diff --git a/libs/full/parcelport_mpi/include/hpx/parcelport_mpi/locality.hpp b/libs/full/parcelport_mpi/include/hpx/parcelport_mpi/locality.hpp index ac0bd60ff7dc..0d2e3983485b 100644 --- a/libs/full/parcelport_mpi/include/hpx/parcelport_mpi/locality.hpp +++ b/libs/full/parcelport_mpi/include/hpx/parcelport_mpi/locality.hpp @@ -13,6 +13,7 @@ #include #include +#include namespace hpx::parcelset::policies::mpi { @@ -29,17 +30,17 @@ namespace hpx::parcelset::policies::mpi { { } - constexpr std::int32_t rank() const noexcept + [[nodiscard]] constexpr std::int32_t rank() const noexcept { return rank_; } - static constexpr const char* type() noexcept + [[nodiscard]] static constexpr const char* type() noexcept { return "mpi"; } - explicit constexpr operator bool() const noexcept + [[nodiscard]] explicit constexpr operator bool() const noexcept { return rank_ != -1; } @@ -48,13 +49,14 @@ namespace hpx::parcelset::policies::mpi { HPX_EXPORT void load(serialization::input_archive& ar); private: - friend bool operator==( + friend constexpr bool operator==( locality const& lhs, locality const& rhs) noexcept { return lhs.rank_ == rhs.rank_; } - friend bool operator<(locality const& lhs, locality const& rhs) noexcept + friend constexpr bool operator<( + locality const& lhs, locality const& rhs) noexcept { return lhs.rank_ < rhs.rank_; } diff --git a/libs/full/parcelport_mpi/include/hpx/parcelport_mpi/receiver.hpp b/libs/full/parcelport_mpi/include/hpx/parcelport_mpi/receiver.hpp index 1d630dce65fd..eb9805513edb 100644 --- a/libs/full/parcelport_mpi/include/hpx/parcelport_mpi/receiver.hpp +++ b/libs/full/parcelport_mpi/include/hpx/parcelport_mpi/receiver.hpp @@ -12,21 +12,18 @@ #if defined(HPX_HAVE_NETWORKING) && defined(HPX_HAVE_PARCELPORT_MPI) #include #include - +#include #include #include #include #include -#include #include #include #include #include #include -#include - namespace hpx::parcelset::policies::mpi { template @@ -47,7 +44,9 @@ namespace hpx::parcelset::policies::mpi { void run() noexcept { util::mpi_environment::scoped_lock l; - new_header(); + + [[maybe_unused]] header h; + new_header(l, h); } bool background_work() noexcept @@ -59,7 +58,7 @@ namespace hpx::parcelset::policies::mpi { // already accepted ones. if (!connection) { - std::unique_lock l(connections_mtx_, std::try_to_lock); + std::unique_lock const l(connections_mtx_, std::try_to_lock); if (l.owns_lock() && !connections_.empty()) { connection = HPX_MOVE(connections_.front()); @@ -80,7 +79,7 @@ namespace hpx::parcelset::policies::mpi { { if (!connection->receive()) { - std::unique_lock l(connections_mtx_); + std::unique_lock const l(connections_mtx_); connections_.push_back(HPX_MOVE(connection)); } } @@ -98,7 +97,8 @@ namespace hpx::parcelset::policies::mpi { template connection_ptr accept_locked(Lock& header_lock) { - connection_ptr res; + HPX_ASSERT_OWNS_LOCK(header_lock); + util::mpi_environment::scoped_try_lock l; // Caller failing to hold lock 'header_lock' before calling function @@ -110,14 +110,16 @@ namespace hpx::parcelset::policies::mpi { if (l.locked) { MPI_Status status; - if (request_done_locked(hdr_request_, &status)) + if (request_done_locked(l, hdr_request_, &status)) { - header h = new_header(); + header h; + new_header(l, h); + l.unlock(); header_lock.unlock(); - res.reset(new connection_type(status.MPI_SOURCE, h, pp_)); - return res; + return std::make_shared( + status.MPI_SOURCE, h, pp_); } } @@ -125,19 +127,21 @@ namespace hpx::parcelset::policies::mpi { #pragma warning(pop) #endif - return res; //-V614 + return {}; } - header new_header() noexcept + template + void new_header([[maybe_unused]] Lock& l, header& h) noexcept { - header h = rcv_header_; - rcv_header_.reset(); + HPX_ASSERT_OWNS_LOCK(l); - MPI_Irecv(rcv_header_.data(), rcv_header_.data_size_, MPI_BYTE, - MPI_ANY_SOURCE, 0, util::mpi_environment::communicator(), - &hdr_request_); + h = rcv_header_; + rcv_header_.reset(); - return h; + [[maybe_unused]] int const ret = MPI_Irecv(rcv_header_.data(), + header::data_size_, MPI_BYTE, MPI_ANY_SOURCE, 0, + util::mpi_environment::communicator(), &hdr_request_); + HPX_ASSERT_LOCKED(l, ret == MPI_SUCCESS); } Parcelport& pp_; @@ -152,17 +156,17 @@ namespace hpx::parcelset::policies::mpi { hpx::spinlock connections_mtx_; connection_list connections_; - bool request_done_locked(MPI_Request& r, MPI_Status* status) noexcept + template + static bool request_done_locked([[maybe_unused]] Lock& l, + MPI_Request& r, MPI_Status* status) noexcept { + HPX_ASSERT_OWNS_LOCK(l); + int completed = 0; - int ret = MPI_Test(&r, &completed, status); - HPX_ASSERT(ret == MPI_SUCCESS); - (void) ret; - if (completed) - { - return true; - } - return false; + [[maybe_unused]] int const ret = MPI_Test(&r, &completed, status); + HPX_ASSERT_LOCKED(l, ret == MPI_SUCCESS); + + return completed ? true : false; } }; } // namespace hpx::parcelset::policies::mpi diff --git a/libs/full/parcelport_mpi/include/hpx/parcelport_mpi/receiver_connection.hpp b/libs/full/parcelport_mpi/include/hpx/parcelport_mpi/receiver_connection.hpp index 3893e7b78ce8..f831c3339370 100644 --- a/libs/full/parcelport_mpi/include/hpx/parcelport_mpi/receiver_connection.hpp +++ b/libs/full/parcelport_mpi/include/hpx/parcelport_mpi/receiver_connection.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2014-2015 Thomas Heller -// Copyright (c) 2007-2021 Hartmut Kaiser +// Copyright (c) 2007-2023 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -12,11 +12,12 @@ #if defined(HPX_HAVE_NETWORKING) && defined(HPX_HAVE_PARCELPORT_MPI) #include #include -#include - #include #include #include +#if defined(HPX_HAVE_PARCELPORT_COUNTERS) +#include +#endif #include #include @@ -24,8 +25,6 @@ #include #include -#include - namespace hpx::parcelset::policies::mpi { template @@ -45,7 +44,7 @@ namespace hpx::parcelset::policies::mpi { using buffer_type = parcel_buffer; public: - receiver_connection(int src, header h, Parcelport& pp) noexcept + receiver_connection(int src, header const& h, Parcelport& pp) noexcept : state_(initialized) , src_(src) , tag_(h.tag()) @@ -93,9 +92,9 @@ namespace hpx::parcelset::policies::mpi { bool receive_transmission_chunks(std::size_t num_thread = -1) { // determine the size of the chunk buffer - std::size_t num_zero_copy_chunks = static_cast( + auto const num_zero_copy_chunks = static_cast( static_cast(buffer_.num_chunks_.first)); - std::size_t num_non_zero_copy_chunks = static_cast( + auto const num_non_zero_copy_chunks = static_cast( static_cast(buffer_.num_chunks_.second)); buffer_.transmission_chunks_.resize( num_zero_copy_chunks + num_non_zero_copy_chunks); @@ -104,11 +103,15 @@ namespace hpx::parcelset::policies::mpi { buffer_.chunks_.resize(num_zero_copy_chunks); { util::mpi_environment::scoped_lock l; - MPI_Irecv(buffer_.transmission_chunks_.data(), + + [[maybe_unused]] int const ret = MPI_Irecv( + buffer_.transmission_chunks_.data(), static_cast(buffer_.transmission_chunks_.size() * sizeof(buffer_type::transmission_chunk_type)), MPI_BYTE, src_, tag_, util::mpi_environment::communicator(), &request_); + HPX_ASSERT_LOCKED(l, ret == MPI_SUCCESS); + request_ptr_ = &request_; } } @@ -125,18 +128,20 @@ namespace hpx::parcelset::policies::mpi { return false; } - char* piggy_back = header_.piggy_back(); - if (piggy_back) + if (char const* piggy_back = header_.piggy_back()) { std::memcpy( - &buffer_.data_[0], piggy_back, buffer_.data_.size()); + buffer_.data_.data(), piggy_back, buffer_.data_.size()); } else { util::mpi_environment::scoped_lock l; - MPI_Irecv(buffer_.data_.data(), + + [[maybe_unused]] int const ret = MPI_Irecv(buffer_.data_.data(), static_cast(buffer_.data_.size()), MPI_BYTE, src_, tag_, util::mpi_environment::communicator(), &request_); + HPX_ASSERT_LOCKED(l, ret == MPI_SUCCESS); + request_ptr_ = &request_; } @@ -154,17 +159,20 @@ namespace hpx::parcelset::policies::mpi { return false; } - std::size_t idx = chunks_idx_++; - std::size_t chunk_size = + std::size_t const idx = chunks_idx_++; + std::size_t const chunk_size = buffer_.transmission_chunks_[idx].second; data_type& c = buffer_.chunks_[idx]; c.resize(chunk_size); { util::mpi_environment::scoped_lock l; - MPI_Irecv(c.data(), static_cast(c.size()), MPI_BYTE, - src_, tag_, util::mpi_environment::communicator(), - &request_); + + [[maybe_unused]] int const ret = MPI_Irecv(c.data(), + static_cast(c.size()), MPI_BYTE, src_, tag_, + util::mpi_environment::communicator(), &request_); + HPX_ASSERT_LOCKED(l, ret == MPI_SUCCESS); + request_ptr_ = &request_; } } @@ -180,14 +188,18 @@ namespace hpx::parcelset::policies::mpi { { return false; } + #if defined(HPX_HAVE_PARCELPORT_COUNTERS) parcelset::data_point& data = buffer_.data_point_; data.time_ = timer_.elapsed_nanoseconds() - data.time_; #endif { util::mpi_environment::scoped_lock l; - MPI_Isend(&tag_, 1, MPI_INT, src_, 1, - util::mpi_environment::communicator(), &request_); + + [[maybe_unused]] int const ret = MPI_Isend(&tag_, 1, MPI_INT, + src_, 1, util::mpi_environment::communicator(), &request_); + HPX_ASSERT_LOCKED(l, ret == MPI_SUCCESS); + request_ptr_ = &request_; } @@ -217,10 +229,10 @@ namespace hpx::parcelset::policies::mpi { } int completed = 0; - int ret = 0; - ret = MPI_Test(request_ptr_, &completed, MPI_STATUS_IGNORE); - HPX_ASSERT(ret == MPI_SUCCESS); - (void) ret; + [[maybe_unused]] int const ret = + MPI_Test(request_ptr_, &completed, MPI_STATUS_IGNORE); + HPX_ASSERT_LOCKED(l, ret == MPI_SUCCESS); + if (completed) { request_ptr_ = nullptr; diff --git a/libs/full/parcelport_mpi/include/hpx/parcelport_mpi/sender.hpp b/libs/full/parcelport_mpi/include/hpx/parcelport_mpi/sender.hpp index bf656a882bbf..c6927ece6ec4 100644 --- a/libs/full/parcelport_mpi/include/hpx/parcelport_mpi/sender.hpp +++ b/libs/full/parcelport_mpi/include/hpx/parcelport_mpi/sender.hpp @@ -14,7 +14,7 @@ #include #include #include - +#include #include #include @@ -25,8 +25,6 @@ #include #include -#include - namespace hpx::parcelset::policies::mpi { struct sender @@ -46,7 +44,8 @@ namespace hpx::parcelset::policies::mpi { void run() noexcept { - get_next_free_tag(); + util::mpi_environment::scoped_lock l; + get_next_free_tag(l); } connection_ptr create_connection(int dest, parcelset::parcelport* pp) @@ -70,7 +69,7 @@ namespace hpx::parcelset::policies::mpi { // Check if sending has been completed.... if (connection->send()) { - error_code ec(throwmode::lightweight); + error_code const ec(throwmode::lightweight); hpx::move_only_function postprocess_handler; @@ -89,7 +88,7 @@ namespace hpx::parcelset::policies::mpi { { connection_ptr connection; { - std::unique_lock l(connections_mtx_, std::try_to_lock); + std::unique_lock const l(connections_mtx_, std::try_to_lock); if (l && !connections_.empty()) { connection = HPX_MOVE(connections_.front()); @@ -117,7 +116,7 @@ namespace hpx::parcelset::policies::mpi { std::unique_lock l(next_free_tag_mtx_, std::try_to_lock); if (l.owns_lock()) { - next_free = next_free_tag_locked(); + next_free = next_free_tag_locked(l); } } @@ -128,30 +127,39 @@ namespace hpx::parcelset::policies::mpi { } } - int next_free_tag_locked() noexcept + template + int next_free_tag_locked([[maybe_unused]] Lock& lock) noexcept { + HPX_ASSERT_OWNS_LOCK(lock); + util::mpi_environment::scoped_try_lock l; if (l.locked) { - MPI_Status status; int completed = 0; - int ret = - MPI_Test(&next_free_tag_request_, &completed, &status); + [[maybe_unused]] int const ret = MPI_Test( + &next_free_tag_request_, &completed, MPI_STATUS_IGNORE); HPX_ASSERT(ret == MPI_SUCCESS); - (void) ret; - if (completed) // && status->MPI_ERROR != MPI_ERR_PENDING) + + if (completed) { - return get_next_free_tag(); + return get_next_free_tag(l); } } return -1; } - int get_next_free_tag() noexcept + template + int get_next_free_tag([[maybe_unused]] Lock& l) noexcept { - int next_free = next_free_tag_; - MPI_Irecv(&next_free_tag_, 1, MPI_INT, MPI_ANY_SOURCE, 1, + HPX_ASSERT_OWNS_LOCK(l); + + int const next_free = next_free_tag_; + + [[maybe_unused]] int const ret = MPI_Irecv(&next_free_tag_, 1, + MPI_INT, MPI_ANY_SOURCE, 1, util::mpi_environment::communicator(), &next_free_tag_request_); + HPX_ASSERT_LOCKED(l, ret == MPI_SUCCESS); + return next_free; } diff --git a/libs/full/parcelport_mpi/include/hpx/parcelport_mpi/sender_connection.hpp b/libs/full/parcelport_mpi/include/hpx/parcelport_mpi/sender_connection.hpp index e37f79a8af5e..5a1b85ea21f4 100644 --- a/libs/full/parcelport_mpi/include/hpx/parcelport_mpi/sender_connection.hpp +++ b/libs/full/parcelport_mpi/include/hpx/parcelport_mpi/sender_connection.hpp @@ -13,23 +13,23 @@ #include #include #include -#include - #include #include #include #include #include #include +#if defined(HPX_HAVE_PARCELPORT_COUNTERS) +#include +#endif #include +#include #include #include #include #include -#include - namespace hpx::parcelset::policies::mpi { struct sender; @@ -76,13 +76,13 @@ namespace hpx::parcelset::policies::mpi { { } - parcelset::locality const& destination() const noexcept + constexpr parcelset::locality const& destination() const noexcept { return there_; } - constexpr void verify_( - parcelset::locality const& /* parcel_locality_id */) const noexcept + static constexpr void verify_( + parcelset::locality const& /* parcel_locality_id */) noexcept { } @@ -95,13 +95,13 @@ namespace hpx::parcelset::policies::mpi { HPX_ASSERT(!buffer_.data_.empty()); #if defined(HPX_HAVE_PARCELPORT_COUNTERS) - buffer_.data_point_.time_ = - hpx::chrono::high_resolution_clock::now(); + buffer_.data_point_.time_ = static_cast( + hpx::chrono::high_resolution_clock::now()); #endif request_ptr_ = nullptr; chunks_idx_ = 0; tag_ = acquire_tag(sender_); - header_ = header(buffer_, tag_); + header_.init(buffer_, tag_); header_.assert_valid(); state_ = initialized; @@ -153,8 +153,12 @@ namespace hpx::parcelset::policies::mpi { util::mpi_environment::scoped_lock l; HPX_ASSERT(state_ == initialized); HPX_ASSERT(request_ptr_ == nullptr); - MPI_Isend(header_.data(), header_.data_size_, MPI_BYTE, dst_, 0, + + [[maybe_unused]] int const ret = MPI_Isend(header_.data(), + header::data_size_, MPI_BYTE, dst_, 0, util::mpi_environment::communicator(), &request_); + HPX_ASSERT_LOCKED(l, ret == MPI_SUCCESS); + request_ptr_ = &request_; } @@ -173,16 +177,18 @@ namespace hpx::parcelset::policies::mpi { HPX_ASSERT(request_ptr_ == nullptr); - std::vector& - chunks = buffer_.transmission_chunks_; + auto const& chunks = buffer_.transmission_chunks_; if (!chunks.empty()) { util::mpi_environment::scoped_lock l; - MPI_Isend(chunks.data(), + + [[maybe_unused]] int const ret = MPI_Isend(chunks.data(), static_cast(chunks.size() * sizeof(parcel_buffer_type::transmission_chunk_type)), MPI_BYTE, dst_, tag_, util::mpi_environment::communicator(), &request_); + HPX_ASSERT_LOCKED(l, ret == MPI_SUCCESS); + request_ptr_ = &request_; } @@ -201,9 +207,12 @@ namespace hpx::parcelset::policies::mpi { if (!header_.piggy_back()) { util::mpi_environment::scoped_lock l; - MPI_Isend(buffer_.data_.data(), + + [[maybe_unused]] int const ret = MPI_Isend(buffer_.data_.data(), static_cast(buffer_.data_.size()), MPI_BYTE, dst_, tag_, util::mpi_environment::communicator(), &request_); + HPX_ASSERT_LOCKED(l, ret == MPI_SUCCESS); + request_ptr_ = &request_; } state_ = sent_data; @@ -217,8 +226,7 @@ namespace hpx::parcelset::policies::mpi { while (chunks_idx_ < buffer_.chunks_.size()) { - serialization::serialization_chunk& c = - buffer_.chunks_[chunks_idx_]; + auto const& c = buffer_.chunks_[chunks_idx_]; if (c.type_ == serialization::chunk_type::chunk_type_pointer) { if (!request_done()) @@ -227,13 +235,17 @@ namespace hpx::parcelset::policies::mpi { } util::mpi_environment::scoped_lock l; - MPI_Isend(const_cast(c.data_.cpos_), - static_cast(c.size_), MPI_BYTE, dst_, tag_, - util::mpi_environment::communicator(), &request_); + + [[maybe_unused]] int const ret = + MPI_Isend(const_cast(c.data_.cpos_), + static_cast(c.size_), MPI_BYTE, dst_, tag_, + util::mpi_environment::communicator(), &request_); + HPX_ASSERT_LOCKED(l, ret == MPI_SUCCESS); + request_ptr_ = &request_; } - chunks_idx_++; + ++chunks_idx_; } state_ = sent_chunks; @@ -248,12 +260,13 @@ namespace hpx::parcelset::policies::mpi { return false; } - error_code ec(throwmode::lightweight); + error_code const ec(throwmode::lightweight); handler_(ec); handler_.reset(); #if defined(HPX_HAVE_PARCELPORT_COUNTERS) buffer_.data_point_.time_ = - hpx::chrono::high_resolution_clock::now() - + static_cast( + hpx::chrono::high_resolution_clock::now()) - buffer_.data_point_.time_; pp_->add_sent_data(buffer_.data_point_); #endif @@ -271,16 +284,16 @@ namespace hpx::parcelset::policies::mpi { return true; } - util::mpi_environment::scoped_try_lock l; + util::mpi_environment::scoped_try_lock const l; if (!l.locked) { return false; } int completed = 0; - int ret = MPI_Test(request_ptr_, &completed, MPI_STATUS_IGNORE); + [[maybe_unused]] int const ret = + MPI_Test(request_ptr_, &completed, MPI_STATUS_IGNORE); HPX_ASSERT(ret == MPI_SUCCESS); - (void) ret; if (completed) { request_ptr_ = nullptr; @@ -293,10 +306,14 @@ namespace hpx::parcelset::policies::mpi { sender_type* sender_; int tag_; int dst_; - hpx::move_only_function handler_; - hpx::move_only_function)> - postprocess_handler_; + + using handler_type = hpx::move_only_function; + handler_type handler_; + + using post_handler_type = hpx::move_only_function)>; + post_handler_type postprocess_handler_; header header_; diff --git a/libs/full/parcelport_mpi/include/hpx/parcelport_mpi/tag_provider.hpp b/libs/full/parcelport_mpi/include/hpx/parcelport_mpi/tag_provider.hpp index aa0eb7ce5a91..4d0ecede5ff2 100644 --- a/libs/full/parcelport_mpi/include/hpx/parcelport_mpi/tag_provider.hpp +++ b/libs/full/parcelport_mpi/include/hpx/parcelport_mpi/tag_provider.hpp @@ -20,12 +20,12 @@ namespace hpx::parcelset::policies::mpi { struct tag_provider { - tag_provider() noexcept + tag_provider() : next_tag_(2) { } - int acquire() noexcept + [[nodiscard]] int acquire() noexcept { int tag = -1; std::lock_guard l(mtx_); diff --git a/libs/full/parcelport_mpi/src/locality.cpp b/libs/full/parcelport_mpi/src/locality.cpp index f32a01d388bd..4a8cd82f8485 100644 --- a/libs/full/parcelport_mpi/src/locality.cpp +++ b/libs/full/parcelport_mpi/src/locality.cpp @@ -10,9 +10,10 @@ #if defined(HPX_HAVE_NETWORKING) && defined(HPX_HAVE_PARCELPORT_MPI) #include #include - #include +#include + namespace hpx::parcelset::policies::mpi { void locality::save(serialization::output_archive& ar) const diff --git a/libs/full/parcelport_mpi/src/parcelport_mpi.cpp b/libs/full/parcelport_mpi/src/parcelport_mpi.cpp index 35f3fa7a85a1..632c1edd3f77 100644 --- a/libs/full/parcelport_mpi/src/parcelport_mpi.cpp +++ b/libs/full/parcelport_mpi/src/parcelport_mpi.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2022 Hartmut Kaiser +// Copyright (c) 2007-2023 Hartmut Kaiser // Copyright (c) 2014-2015 Thomas Heller // Copyright (c) 2020 Google // @@ -21,7 +21,6 @@ #include #include -#include #include #include #include @@ -31,10 +30,8 @@ #include #include -#include #include #include -#include #include #include @@ -121,7 +118,12 @@ namespace hpx::parcelset { { } - ~parcelport() + parcelport(parcelport const&) = delete; + parcelport(parcelport&&) = delete; + parcelport& operator=(parcelport const&) = delete; + parcelport& operator=(parcelport&&) = delete; + + ~parcelport() override { util::mpi_environment::finalize(); } @@ -134,8 +136,8 @@ namespace hpx::parcelset { for (std::size_t i = 0; i != io_service_pool_.size(); ++i) { - io_service_pool_.get_io_service(int(i)).post( - hpx::bind(&parcelport::io_service_work, this)); + io_service_pool_.get_io_service(static_cast(i)) + .post(hpx::bind(&parcelport::io_service_work, this)); } return true; } @@ -146,12 +148,22 @@ namespace hpx::parcelset { while (do_background_work(0, parcelport_background_mode_all)) { if (threads::get_self_ptr()) + { hpx::this_thread::suspend( hpx::threads::thread_schedule_state::pending, "mpi::parcelport::do_stop"); + } + } + + bool expected = false; + if (stopped_.compare_exchange_strong(expected, true)) + { + util::mpi_environment::scoped_lock l; + + [[maybe_unused]] int const ret = + MPI_Barrier(util::mpi_environment::communicator()); + HPX_ASSERT_LOCKED(l, ret == MPI_SUCCESS); } - stopped_ = true; - MPI_Barrier(util::mpi_environment::communicator()); } /// Return the name of this locality @@ -163,7 +175,7 @@ namespace hpx::parcelset { std::shared_ptr create_connection( parcelset::locality const& l, error_code&) { - int dest_rank = l.get().rank(); + int const dest_rank = l.get().rank(); return sender_.create_connection(dest_rank, this); } @@ -182,7 +194,8 @@ namespace hpx::parcelset { bool background_work( std::size_t num_thread, parcelport_background_mode mode) { - if (stopped_ || num_thread >= background_threads_) + if (stopped_.load(std::memory_order_acquire) || + num_thread >= background_threads_) { return false; } @@ -235,69 +248,64 @@ namespace hpx::parcelset { #include -namespace hpx::traits { - - // Inject additional configuration data into the factory registry for this - // type. This information ends up in the system wide configuration database - // under the plugin specific section: - // - // [hpx.parcel.mpi] - // ... - // priority = 100 - // - template <> - struct plugin_config_data +// Inject additional configuration data into the factory registry for this +// type. This information ends up in the system wide configuration database +// under the plugin specific section: +// +// [hpx.parcel.mpi] +// ... +// priority = 100 +// +template <> +struct hpx::traits::plugin_config_data< + hpx::parcelset::policies::mpi::parcelport> +{ + static constexpr char const* priority() noexcept { - static constexpr char const* priority() noexcept - { - return "100"; - } + return "100"; + } - static void init( - int* argc, char*** argv, util::command_line_handling& cfg) - { - util::mpi_environment::init(argc, argv, cfg.rtcfg_); - cfg.num_localities_ = - static_cast(util::mpi_environment::size()); - cfg.node_ = static_cast(util::mpi_environment::rank()); - } + static void init(int* argc, char*** argv, util::command_line_handling& cfg) + { + util::mpi_environment::init(argc, argv, cfg.rtcfg_); + cfg.num_localities_ = + static_cast(util::mpi_environment::size()); + cfg.node_ = static_cast(util::mpi_environment::rank()); + } - // by default no additional initialization using the resource - // partitioner is required - static constexpr void init(hpx::resource::partitioner&) noexcept {} + // by default no additional initialization using the resource + // partitioner is required + static constexpr void init(hpx::resource::partitioner&) noexcept {} - static void destroy() - { - util::mpi_environment::finalize(); - } + static void destroy() noexcept + { + util::mpi_environment::finalize(); + } - static constexpr char const* call() noexcept - { - return + static constexpr char const* call() noexcept + { + return #if defined(HPX_HAVE_PARCELPORT_MPI_ENV) - "env = " - "${HPX_HAVE_PARCELPORT_MPI_ENV:" HPX_HAVE_PARCELPORT_MPI_ENV - "}\n" + "env = ${HPX_HAVE_PARCELPORT_MPI_ENV:" HPX_HAVE_PARCELPORT_MPI_ENV + "}\n" #else - "env = ${HPX_HAVE_PARCELPORT_MPI_ENV:" - "MV2_COMM_WORLD_RANK,PMIX_RANK,PMI_RANK,OMPI_COMM_WORLD_SIZE," - "ALPS_APP_PE,PALS_NODEID" - "}\n" + "env = ${HPX_HAVE_PARCELPORT_MPI_ENV:" + "MV2_COMM_WORLD_RANK,PMIX_RANK,PMI_RANK,OMPI_COMM_WORLD_SIZE," + "ALPS_APP_PE,PALS_NODEID}\n" #endif #if defined(HPX_HAVE_PARCELPORT_MPI_MULTITHREADED) - "multithreaded = ${HPX_HAVE_PARCELPORT_MPI_MULTITHREADED:1}\n" + "multithreaded = ${HPX_HAVE_PARCELPORT_MPI_MULTITHREADED:1}\n" #else - "multithreaded = ${HPX_HAVE_PARCELPORT_MPI_MULTITHREADED:0}\n" + "multithreaded = ${HPX_HAVE_PARCELPORT_MPI_MULTITHREADED:0}\n" #endif - "max_connections = " - "${HPX_HAVE_PARCELPORT_MPI_MAX_CONNECTIONS:8192}\n" - - // number of cores that do background work, default: all - "background_threads = " - "${HPX_HAVE_PARCELPORT_MPI_BACKGROUND_THREADS:-1}\n"; - } - }; -} // namespace hpx::traits + "max_connections = " + "${HPX_HAVE_PARCELPORT_MPI_MAX_CONNECTIONS:8192}\n" + + // number of cores that do background work, default: all + "background_threads = " + "${HPX_HAVE_PARCELPORT_MPI_BACKGROUND_THREADS:-1}\n"; + } +}; // namespace hpx::traits HPX_REGISTER_PARCELPORT(hpx::parcelset::policies::mpi::parcelport, mpi) diff --git a/libs/full/parcelset/include/hpx/parcelset/connection_cache.hpp b/libs/full/parcelset/include/hpx/parcelset/connection_cache.hpp index 6a40234e9ea0..f1b1b533e22c 100644 --- a/libs/full/parcelset/include/hpx/parcelset/connection_cache.hpp +++ b/libs/full/parcelset/include/hpx/parcelset/connection_cache.hpp @@ -37,12 +37,11 @@ #include /////////////////////////////////////////////////////////////////////////////// -namespace hpx { namespace util { +namespace hpx::util { /////////////////////////////////////////////////////////////////////////// /// This class implements an LRU cache to hold connections. It includes /// entries checked out from the cache in its cache size. - // TODO: investigate usage of boost.cache. template class connection_cache { @@ -640,6 +639,6 @@ namespace hpx { namespace util { std::int64_t misses_; std::int64_t reclaims_; }; -}} // namespace hpx::util +} // namespace hpx::util #endif diff --git a/libs/full/parcelset/include/hpx/parcelset/decode_parcels.hpp b/libs/full/parcelset/include/hpx/parcelset/decode_parcels.hpp index 89b01ee515d4..308291d4cf07 100644 --- a/libs/full/parcelset/include/hpx/parcelset/decode_parcels.hpp +++ b/libs/full/parcelset/include/hpx/parcelset/decode_parcels.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2021 Hartmut Kaiser +// Copyright (c) 2007-2023 Hartmut Kaiser // Copyright (c) 2014-2021 Thomas Heller // // SPDX-License-Identifier: BSL-1.0 @@ -19,7 +19,6 @@ #include #include -#include #include #include #include @@ -55,20 +54,21 @@ namespace hpx::parcelset { data.num_zchunks_ += buffer.chunks_.size(); data.num_zchunks_per_msg_max_ = (std::max)(data.num_zchunks_per_msg_max_, - (std::int64_t) buffer.chunks_.size()); + static_cast(buffer.chunks_.size())); for (auto& chunk : buffer.chunks_) { data.size_zchunks_total_ += chunk.size(); - data.size_zchunks_max_ = - (std::max)(data.size_zchunks_max_, (std::int64_t) chunk.size()); + data.size_zchunks_max_ = (std::max)(data.size_zchunks_max_, + static_cast(chunk.size())); } #endif if (num_zero_copy_chunks != 0) { // decode chunk information - std::size_t num_non_zero_copy_chunks = static_cast( - static_cast(buffer.num_chunks_.second)); + std::size_t const num_non_zero_copy_chunks = + static_cast( + static_cast(buffer.num_chunks_.second)); chunks.resize(num_zero_copy_chunks + num_non_zero_copy_chunks); @@ -76,9 +76,9 @@ namespace hpx::parcelset { for (std::size_t i = 0; i != num_zero_copy_chunks; ++i) { transmission_chunk_type& c = buffer.transmission_chunks_[i]; - std::size_t first = static_cast( + auto const first = static_cast( static_cast(c.first)); - std::size_t second = static_cast( + auto second = static_cast( static_cast(c.second)); HPX_ASSERT(buffer.chunks_[i].size() == second); @@ -92,9 +92,9 @@ namespace hpx::parcelset { i != num_zero_copy_chunks + num_non_zero_copy_chunks; ++i) { transmission_chunk_type& c = buffer.transmission_chunks_[i]; - std::size_t first = static_cast( + auto const first = static_cast( static_cast(c.first)); - std::size_t second = static_cast( + auto const second = static_cast( static_cast(c.second)); // find next free entry @@ -126,7 +126,7 @@ namespace hpx::parcelset { std::vector& chunks, std::size_t num_thread = -1) { - std::size_t inbound_data_size = static_cast( + auto inbound_data_size = static_cast( static_cast(buffer.data_size_)); // protect from unhandled exceptions bubbling up @@ -136,7 +136,7 @@ namespace hpx::parcelset { { // mark start of serialization #if defined(HPX_HAVE_PARCELPORT_COUNTERS) - hpx::chrono::high_resolution_timer timer; + hpx::chrono::high_resolution_timer const timer; std::int64_t overall_add_parcel_time = 0; parcelset::data_point& data = buffer.data_point_; #endif @@ -161,8 +161,8 @@ namespace hpx::parcelset { #if defined(HPX_HAVE_PARCELPORT_COUNTERS) && \ defined(HPX_HAVE_PARCELPORT_ACTION_COUNTERS) - std::size_t archive_pos = archive.current_pos(); - std::int64_t serialize_time = + std::size_t const archive_pos = archive.current_pos(); + std::int64_t const serialize_time = timer.elapsed_nanoseconds(); #endif // de-serialize parcel and add it to incoming parcel queue @@ -173,11 +173,11 @@ namespace hpx::parcelset { // one parcel to decode, deferred_schedule will be // preset to false and the direct action will be called // directly - bool migrated = p.load_schedule( + bool const migrated = p.load_schedule( archive, num_thread, deferred_schedule); #if defined(HPX_HAVE_PARCELPORT_COUNTERS) - std::int64_t add_parcel_time = + std::int64_t const add_parcel_time = timer.elapsed_nanoseconds(); #endif @@ -192,7 +192,7 @@ namespace hpx::parcelset { pp.add_received_data(p.get_action_name(), action_data); #endif // make sure this parcel ended up on the right locality - std::uint32_t here = agas::get_locality_id(); + std::uint32_t const here = agas::get_locality_id(); if (hpx::get_runtime_ptr() && here != naming::invalid_locality_id && (naming::get_locality_id_from_gid( @@ -203,7 +203,6 @@ namespace hpx::parcelset { "parcel destination does not match locality " "which received the parcel ({}), {}", here, p); - return; } if (migrated) @@ -235,11 +234,15 @@ namespace hpx::parcelset { for (std::size_t i = 1; i != deferred_parcels.size(); ++i) { + LPT_(debug).format( + "decode_message_with_chunks: received: {}", + deferred_parcels[i].parcel_id()); + auto f = [num_thread](parcelset::parcel&& p) { if (p.schedule_action(num_thread)) { - // route this parcel as the object - // was migrated + // route this parcel as the object was + // migrated agas::route(HPX_MOVE(p), &parcelset::detail:: parcel_route_handler, @@ -248,7 +251,7 @@ namespace hpx::parcelset { }; // schedule all but the first parcel on a new thread. - hpx::threads::thread_init_data data( + hpx::threads::thread_init_data init_data( hpx::threads::make_thread_function_nullary( util::deferred_call(HPX_MOVE(f), HPX_MOVE(deferred_parcels[i]))), @@ -258,11 +261,15 @@ namespace hpx::parcelset { static_cast(num_thread)), threads::thread_stacksize::default_, threads::thread_schedule_state::pending, true); - hpx::threads::register_thread(data); + hpx::threads::register_thread(init_data); } // If we are the first deferred parcel, we don't need to spin // up a new thread... + LPT_(debug).format( + "decode_message_with_chunks: received: {}", + deferred_parcels[0].parcel_id()); + if (deferred_parcels[0].schedule_action(num_thread)) { // route this parcel as the object was migrated diff --git a/libs/full/parcelset/include/hpx/parcelset/detail/parcel_await.hpp b/libs/full/parcelset/include/hpx/parcelset/detail/parcel_await.hpp index daa74c10f491..4f0d90ad96e8 100644 --- a/libs/full/parcelset/include/hpx/parcelset/detail/parcel_await.hpp +++ b/libs/full/parcelset/include/hpx/parcelset/detail/parcel_await.hpp @@ -17,7 +17,7 @@ #include #include -namespace hpx { namespace parcelset { namespace detail { +namespace hpx::parcelset::detail { using put_parcel_type = hpx::move_only_function; @@ -32,6 +32,6 @@ namespace hpx { namespace parcelset { namespace detail { void HPX_EXPORT parcels_await_apply(std::vector&& p, std::vector&& f, std::uint32_t archive_flags, put_parcels_type pp); -}}} // namespace hpx::parcelset::detail +} // namespace hpx::parcelset::detail #endif diff --git a/libs/full/parcelset/include/hpx/parcelset/encode_parcels.hpp b/libs/full/parcelset/include/hpx/parcelset/encode_parcels.hpp index f97c37638048..2812ce6fba3f 100644 --- a/libs/full/parcelset/include/hpx/parcelset/encode_parcels.hpp +++ b/libs/full/parcelset/include/hpx/parcelset/encode_parcels.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2021 Hartmut Kaiser +// Copyright (c) 2007-2023 Hartmut Kaiser // Copyright (c) 2011-2015 Thomas Heller // Copyright (c) 2007 Richard D Guidry Jr // Copyright (c) 2011 Bryce Lelbach @@ -46,9 +46,9 @@ namespace hpx::parcelset { #if defined(HPX_HAVE_LOGGING) /////////////////////////////////////////////////////////////////// - inline constexpr char to_digit(int number) noexcept + constexpr char to_digit(int number) noexcept { - char number_tmp = static_cast(number); + char const number_tmp = static_cast(number); if (number >= 0 && number <= 9) { return static_cast(number_tmp + '0'); @@ -56,11 +56,11 @@ namespace hpx::parcelset { return static_cast(number_tmp - 10 + 'A'); } - inline constexpr void convert_byte( + constexpr void convert_byte( std::uint8_t b, char* buffer, char const* /* end */) noexcept { *buffer++ = to_digit((b & 0xF0) >> 4); - *buffer++ = to_digit(b & 0x0F); + *buffer = to_digit(b & 0x0F); } template @@ -70,7 +70,7 @@ namespace hpx::parcelset { if (LPT_ENABLED(debug)) { result.reserve(buffer.data_.size() * 2 + 1); - for (std::uint8_t byte : buffer.data_) + for (std::uint8_t const byte : buffer.data_) { char b[3] = {0}; convert_byte(byte, &b[0], &b[3]); @@ -122,13 +122,14 @@ namespace hpx::parcelset { buffer.chunks_.size() - chunks.size())); #if defined(HPX_HAVE_PARCELPORT_COUNTERS) data.num_zchunks_ += chunks.size(); - data.num_zchunks_per_msg_max_ = (std::max)( - data.num_zchunks_per_msg_max_, (std::int64_t) chunks.size()); + data.num_zchunks_per_msg_max_ = + (std::max)(data.num_zchunks_per_msg_max_, + static_cast(chunks.size())); for (auto& chunk : chunks) { data.size_zchunks_total_ += chunk.second; - data.size_zchunks_max_ = (std::max)( - data.size_zchunks_max_, (std::int64_t) chunk.second); + data.size_zchunks_max_ = (std::max)(data.size_zchunks_max_, + static_cast(chunk.second)); } #endif @@ -159,7 +160,7 @@ namespace hpx::parcelset { std::size_t parcels_sent = 0; std::size_t parcels_size = 1; - if (num_parcels != std::size_t(-1)) + if (num_parcels != static_cast(-1)) { arg_size = sizeof(std::int64_t); parcels_size = num_parcels; @@ -170,14 +171,15 @@ namespace hpx::parcelset { { try { - std::unique_ptr filter( + std::unique_ptr const filter( ps[0].get_serialization_filter()); int archive_flags = archive_flags_; - if (filter.get() != nullptr) + if (filter) { archive_flags = archive_flags | - int(serialization::archive_flags::enable_compression); + static_cast( + serialization::archive_flags::enable_compression); } // preallocate data @@ -195,7 +197,7 @@ namespace hpx::parcelset { // mark start of serialization #if defined(HPX_HAVE_PARCELPORT_COUNTERS) - hpx::chrono::high_resolution_timer timer; + hpx::chrono::high_resolution_timer const timer; #endif { // Serialize the data @@ -208,15 +210,15 @@ namespace hpx::parcelset { archive_flags, &buffer.chunks_, filter.get(), pp.get_zero_copy_serialization_threshold()); - if (num_parcels != std::size_t(-1)) + if (num_parcels != static_cast(-1)) archive << parcels_sent; //-V128 for (std::size_t i = 0; i != parcels_sent; ++i) { #if defined(HPX_HAVE_PARCELPORT_COUNTERS) && \ defined(HPX_HAVE_PARCELPORT_ACTION_COUNTERS) - std::size_t archive_pos = archive.current_pos(); - std::int64_t serialize_time = + std::size_t const archive_pos = archive.current_pos(); + std::int64_t const serialize_time = timer.elapsed_nanoseconds(); #endif LPT_(debug) << ps[i]; @@ -240,8 +242,6 @@ namespace hpx::parcelset { timer.elapsed_nanoseconds() - serialize_time; action_data.num_parcels_ = 1; pp.add_sent_data(ps[i].get_action_name(), action_data); -#else - HPX_UNUSED(pp); #endif } archive.flush(); @@ -279,11 +279,10 @@ namespace hpx::parcelset { catch (std::exception const& e) { // We have to repackage all exceptions thrown by the - // serialization library as otherwise we will loose the - // e.what() description of the problem, due to slicing. + // serialization library as otherwise we will loose the e.what() + // description of the problem, due to slicing. hpx::throw_with_info( hpx::exception(hpx::error::serialization_error, e.what())); - return 0; } } catch (...) diff --git a/libs/full/parcelset/include/hpx/parcelset/parcel.hpp b/libs/full/parcelset/include/hpx/parcelset/parcel.hpp index df32a5245d71..31d99d56b110 100644 --- a/libs/full/parcelset/include/hpx/parcelset/parcel.hpp +++ b/libs/full/parcelset/include/hpx/parcelset/parcel.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2021 Hartmut Kaiser +// Copyright (c) 2021-2023 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -42,7 +42,7 @@ namespace hpx::parcelset::detail { inline parcel_data& operator=(parcel_data&& rhs) noexcept; void serialize(serialization::input_archive& ar, unsigned); - void serialize(serialization::output_archive& ar, unsigned); + void serialize(serialization::output_archive& ar, unsigned) const; naming::gid_type source_id_; naming::gid_type dest_; @@ -149,7 +149,8 @@ namespace hpx::parcelset::detail { void load(serialization::input_archive& ar, unsigned) override; void save(serialization::output_archive& ar, unsigned) const override; - std::pair determine_lva(); + std::pair determine_lva() + const; detail::parcel_data data_; std::unique_ptr action_; diff --git a/libs/full/parcelset/include/hpx/parcelset/parcelhandler.hpp b/libs/full/parcelset/include/hpx/parcelset/parcelhandler.hpp index b4b0fd32bbb7..3b09f86cd636 100644 --- a/libs/full/parcelset/include/hpx/parcelset/parcelhandler.hpp +++ b/libs/full/parcelset/include/hpx/parcelset/parcelhandler.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2014 Thomas Heller -// Copyright (c) 2007-2022 Hartmut Kaiser +// Copyright (c) 2007-2023 Hartmut Kaiser // Copyright (c) 2011 Bryce Lelbach // // SPDX-License-Identifier: BSL-1.0 @@ -58,14 +58,8 @@ namespace hpx::parcelset { parcelhandler& operator=(parcelhandler&&) = delete; private: - void parcel_sink(parcel const& p); - - threads::thread_schedule_state decode_parcel(parcelport& pp, - std::shared_ptr> parcel_data, - parcelset::data_point receive_data); - // make sure the parcel has been properly initialized - void init_parcel(parcel& p); + static void init_parcel(parcel& p); using mutex_type = hpx::spinlock; @@ -78,11 +72,11 @@ namespace hpx::parcelset { using write_handler_type = parcelport::write_handler_type; /// Construct a new \a parcelhandler. - parcelhandler(util::runtime_configuration& cfg); + explicit parcelhandler(util::runtime_configuration const& cfg); ~parcelhandler(); - void set_notification_policies(util::runtime_configuration& cfg, + void set_notification_policies(util::runtime_configuration const& cfg, threads::threadmanager* tm, threads::policies::callback_notifier const& notifier); @@ -90,7 +84,7 @@ namespace hpx::parcelset { void initialize(); - void flush_parcels(); + void flush_parcels() const; /// \brief Stop all parcel ports associated with this parcelhandler void stop(bool blocking = true); @@ -105,10 +99,11 @@ namespace hpx::parcelset { /// Return the list of all remote localities supporting the given /// component type /// - /// \param prefixes [out] The reference to a vector of id_types filled - /// by the function. + /// \param locality_ids [in/out] The reference to a vector of id_types + /// filled by the function. /// \param type [in] The type of the component which needs to exist /// on the returned localities. + /// \param ec [in/out] /// /// \returns The function returns \a true if there is at least one /// remote locality known by AGAS @@ -121,10 +116,11 @@ namespace hpx::parcelset { /// Return the list of all localities supporting the given /// component type /// - /// \param prefixes [out] The reference to a vector of id_types filled - /// by the function. + /// \param locality_ids [in/out] The reference to a vector of id_types + /// filled by the function. /// \param type [in] The type of the component which needs to exist /// on the returned localities. + /// \param ec [in/out] /// /// \returns The function returns \a true if there is at least one /// locality known by AGAS @@ -188,8 +184,8 @@ namespace hpx::parcelset { /// function or function object gets invoked on completion of the send /// operation or on any error. /// - /// \param p [in] The parcels to send. - /// \param f [in] The function objects to be invoked on + /// \param parcels [in] The parcels to send. + /// \param funcs [in] The function objects to be invoked on /// successful completion or on errors. The signature /// of these function object are expected to be: /// @@ -201,14 +197,14 @@ namespace hpx::parcelset { /// \a size is the number of successfully /// transferred bytes. void put_parcels( - std::vector p, std::vector f); + std::vector parcels, std::vector funcs); /// This put_parcel() function overload is asynchronous, but no /// callback is provided by the user. /// /// \note The function \a put_parcel() is asynchronous. /// - /// \param p [in, out] A reference to the parcel to send. The + /// \param parcels [in, out] A reference to the parcel to send. The /// parcel \a p will be modified in place, as it will /// get set the resolved destination address and parcel /// id (if not already set). @@ -225,16 +221,10 @@ namespace hpx::parcelset { /// parcelport std::string get_locality_name() const; - /////////////////////////////////////////////////////////////////////// - /// The function register_counter_types() is called during startup to - /// allow the registration of all performance counter types for this - /// parcel-handler instance. - void register_counter_types(); - /// \brief Make sure the specified locality is not held by any /// connection caches anymore void remove_from_connection_cache( - naming::gid_type const& gid, endpoints_type const& endpoints); + naming::gid_type const& gid, endpoints_type const& endpoints) const; /// \brief return the endpoints associated with this parcelhandler /// \returns all connection information for the enabled parcelports @@ -254,7 +244,7 @@ namespace hpx::parcelset { } /// Return the reference to an existing io_service - util::io_service_pool* get_thread_pool(char const* name); + util::io_service_pool* get_thread_pool(char const* name) const; /////////////////////////////////////////////////////////////////////// policies::message_handler* get_message_handler(char const* action, @@ -399,8 +389,8 @@ namespace hpx::parcelset { std::string const& ppname, int priority, bool bootstrap) const; void put_parcel_impl(parcel&& p, write_handler_type&& f); - void put_parcels_impl( - std::vector&& p, std::vector&& f); + void put_parcels_impl(std::vector&& parcels, + std::vector&& handlers); // manage default exception handler void invoke_write_handler( @@ -421,7 +411,7 @@ namespace hpx::parcelset { protected: std::pair, locality> find_appropriate_destination(naming::gid_type const& dest_gid); - locality find_endpoint( + static locality find_endpoint( endpoints_type const& eps, std::string const& name); private: diff --git a/libs/full/parcelset/include/hpx/parcelset/parcelport_connection.hpp b/libs/full/parcelset/include/hpx/parcelset/parcelport_connection.hpp index 7427b40c651e..fd565d3b282f 100644 --- a/libs/full/parcelset/include/hpx/parcelset/parcelport_connection.hpp +++ b/libs/full/parcelset/include/hpx/parcelset/parcelport_connection.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2014 Thomas Heller -// Copyright (c) 2007-2021 Hartmut Kaiser +// Copyright (c) 2007-2023 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -16,7 +16,6 @@ #include #include -#include #include #include diff --git a/libs/full/parcelset/include/hpx/parcelset/parcelport_impl.hpp b/libs/full/parcelset/include/hpx/parcelset/parcelport_impl.hpp index cd2866298de5..2c7b632683e7 100644 --- a/libs/full/parcelset/include/hpx/parcelset/parcelport_impl.hpp +++ b/libs/full/parcelset/include/hpx/parcelset/parcelport_impl.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2014 Thomas Heller -// Copyright (c) 2007-2021 Hartmut Kaiser +// Copyright (c) 2007-2023 Hartmut Kaiser // Copyright (c) 2007 Richard D Guidry Jr // Copyright (c) 2011 Bryce Lelbach // Copyright (c) 2011 Katelyn Kufahl @@ -145,17 +145,19 @@ namespace hpx::parcelset { , num_thread_(0) , max_background_thread_(max_background_threads(ini)) { - std::string endian_out = get_config_entry("hpx.parcel.endian_out", - endian::native == endian::big ? "big" : "little"); + std::string const endian_out = + get_config_entry("hpx.parcel.endian_out", + endian::native == endian::big ? "big" : "little"); if (endian_out == "little") { archive_flags_ = archive_flags_ | - int(serialization::archive_flags::endian_little); + static_cast( + serialization::archive_flags::endian_little); } else if (endian_out == "big") { archive_flags_ = archive_flags_ | - int(serialization::archive_flags::endian_big); + static_cast(serialization::archive_flags::endian_big); } else { @@ -165,15 +167,17 @@ namespace hpx::parcelset { if (!this->allow_array_optimizations()) { archive_flags_ = archive_flags_ | - int(serialization::archive_flags:: + static_cast(serialization::archive_flags:: disable_array_optimization); archive_flags_ = archive_flags_ | - int(serialization::archive_flags::disable_data_chunking); + static_cast( + serialization::archive_flags::disable_data_chunking); } else if (!this->allow_zero_copy_optimizations()) { archive_flags_ = archive_flags_ | - int(serialization::archive_flags::disable_data_chunking); + static_cast( + serialization::archive_flags::disable_data_chunking); } } @@ -192,7 +196,7 @@ namespace hpx::parcelset { { io_service_pool_.run(false); // start pool - bool success = connection_handler().do_run(); + bool const success = connection_handler().do_run(); if (success && blocking) io_service_pool_.join(); @@ -271,7 +275,6 @@ namespace hpx::parcelset { HPX_THROW_EXCEPTION(hpx::error::bad_parameter, "parcelport::put_parcels", "mismatched number of parcels and handlers"); - return; } #if defined(HPX_DEBUG) @@ -378,7 +381,7 @@ namespace hpx::parcelset { static_cast(get_next_num_thread())), threads::thread_stacksize::default_, threads::thread_schedule_state::suspended, true); - threads::thread_id_ref_type id = + threads::thread_id_ref_type const id = hpx::threads::register_thread(data, ec); if (ec) return; @@ -425,7 +428,6 @@ namespace hpx::parcelset { HPX_THROW_EXCEPTION(hpx::error::bad_parameter, "parcelport_impl::get_connection_cache_statistics", "invalid connection cache statistics type"); - return 0; } private: @@ -439,29 +441,28 @@ namespace hpx::parcelset { return static_cast(*this); } - void send_early_parcel_impl(locality const& dest, parcel p) + void send_early_parcel_impl( + [[maybe_unused]] locality const& dest, [[maybe_unused]] parcel p) { if constexpr (connection_handler_traits< ConnectionHandler>::send_early_parcel::value) { put_parcel(dest, HPX_MOVE(p), - [HPX_CXX20_CAPTURE_THIS(=)]( - std::error_code const& ec, parcel const& p) -> void { - return early_pending_parcel_handler(ec, p); + [HPX_CXX20_CAPTURE_THIS(=)](std::error_code const& ec, + parcel const& parcel) -> void { + return early_pending_parcel_handler(ec, parcel); }); } else { - HPX_UNUSED(dest); - HPX_UNUSED(p); HPX_THROW_EXCEPTION(hpx::error::network_error, "send_early_parcel", "This parcelport does not support sending early parcels"); } } - bool do_background_work_impl( - std::size_t num_thread, parcelport_background_mode mode) + bool do_background_work_impl([[maybe_unused]] std::size_t num_thread, + [[maybe_unused]] parcelport_background_mode mode) { if constexpr (connection_handler_traits< ConnectionHandler>::do_background_work::value) @@ -497,7 +498,7 @@ namespace hpx::parcelset { ConnectionHandler>::send_immediate_parcels::value, "This parcelport is not suitable for the connectionless " "version of send_immediate!"); - std::size_t encoded_parcels = 0; + std::vector parcels; std::vector handlers; if (fs == nullptr) @@ -518,8 +519,9 @@ namespace hpx::parcelset { // encode the parcels typename ConnectionHandler::sender_type::parcel_buffer_type buffer; - encoded_parcels = encode_parcels(*this, ps, num_parcels, buffer, - archive_flags_, get_max_outbound_message_size()); + std::size_t const encoded_parcels = + encode_parcels(*this, ps, num_parcels, buffer, archive_flags_, + get_max_outbound_message_size()); typename ConnectionHandler::sender_type::callback_fn_type callback_fn = detail::call_for_each( @@ -535,6 +537,7 @@ namespace hpx::parcelset { { // we don't propagate errors for now } + if (num_parcels != encoded_parcels && fs != nullptr) { std::vector overflow_parcels( @@ -688,13 +691,12 @@ namespace hpx::parcelset { { using mapped_type = pending_parcels_map::mapped_type; - std::unique_lock l(mtx_); + std::unique_lock const l(mtx_); // We ignore the lock here. It might happen that while enqueuing, // we need to acquire a lock. This should not cause any problems // (famous last words) - util::ignore_while_checking il(&l); - HPX_UNUSED(il); + [[maybe_unused]] util::ignore_while_checking il(&l); mapped_type& e = pending_parcels_[locality_id]; hpx::get<0>(e).push_back(HPX_MOVE(p)); @@ -710,13 +712,12 @@ namespace hpx::parcelset { { using mapped_type = pending_parcels_map::mapped_type; - std::unique_lock l(mtx_); + std::unique_lock const l(mtx_); // We ignore the lock here. It might happen that while enqueuing, // we need to acquire a lock. This should not cause any problems // (famous last words) - util::ignore_while_checking il(&l); - HPX_UNUSED(il); + [[maybe_unused]] util::ignore_while_checking il(&l); HPX_ASSERT(parcels.size() == handlers.size()); @@ -730,7 +731,8 @@ namespace hpx::parcelset { else { HPX_ASSERT(hpx::get<0>(e).size() == hpx::get<1>(e).size()); - std::size_t new_size = hpx::get<0>(e).size() + parcels.size(); + std::size_t const new_size = + hpx::get<0>(e).size() + parcels.size(); hpx::get<0>(e).reserve(new_size); std::move(parcels.begin(), parcels.end(), @@ -748,50 +750,46 @@ namespace hpx::parcelset { std::vector& parcels, std::vector& handlers) { - using iterator = pending_parcels_map::iterator; - - { - std::unique_lock l(mtx_, std::try_to_lock); - if (!l.owns_lock()) - return false; + std::unique_lock const l(mtx_, std::try_to_lock); + if (!l.owns_lock()) + return false; - iterator it = pending_parcels_.find(locality_id); + auto const it = pending_parcels_.find(locality_id); - // do nothing if parcels have already been picked up by - // another thread - if (it != pending_parcels_.end() && - !hpx::get<0>(it->second).empty()) - { - HPX_ASSERT(it->first == locality_id); - HPX_ASSERT(handlers.size() == 0); - HPX_ASSERT(handlers.size() == parcels.size()); - std::swap(parcels, hpx::get<0>(it->second)); - HPX_ASSERT(hpx::get<0>(it->second).size() == 0); - std::swap(handlers, hpx::get<1>(it->second)); - HPX_ASSERT(handlers.size() == parcels.size()); - - HPX_ASSERT(!handlers.empty()); - } - else - { - HPX_ASSERT(hpx::get<1>(it->second).empty()); - return false; - } + // do nothing if parcels have already been picked up by another + // thread + if (it != pending_parcels_.end() && + !hpx::get<0>(it->second).empty()) + { + HPX_ASSERT(it->first == locality_id); + HPX_ASSERT(handlers.empty()); + HPX_ASSERT(handlers.size() == parcels.size()); + std::swap(parcels, hpx::get<0>(it->second)); + HPX_ASSERT(hpx::get<0>(it->second).empty()); + std::swap(handlers, hpx::get<1>(it->second)); + HPX_ASSERT(handlers.size() == parcels.size()); + + HPX_ASSERT(!handlers.empty()); + } + else + { + HPX_ASSERT(hpx::get<1>(it->second).empty()); + return false; + } - parcel_destinations_.erase(locality_id); + parcel_destinations_.erase(locality_id); - HPX_ASSERT(0 != num_parcel_destinations_.load()); - --num_parcel_destinations_; + HPX_ASSERT(0 != num_parcel_destinations_.load()); + --num_parcel_destinations_; - return true; - } + return true; } protected: bool dequeue_parcel( locality& dest, parcel& p, write_handler_type& handler) { - std::unique_lock l(mtx_, std::try_to_lock); + std::unique_lock const l(mtx_, std::try_to_lock); if (!l.owns_lock()) return false; @@ -825,7 +823,7 @@ namespace hpx::parcelset { std::vector destinations; { - std::unique_lock l(mtx_, std::try_to_lock); + std::unique_lock const l(mtx_, std::try_to_lock); if (l.owns_lock()) { if (parcel_destinations_.empty()) @@ -862,9 +860,9 @@ namespace hpx::parcelset { return; } - // If one of the sending threads are in suspended state, we - // need to force a new connection to avoid deadlocks. - bool force_connection = true; + // If one of the sending threads are in suspended state, we need to + // force a new connection to avoid deadlocks. + constexpr bool force_connection = true; error_code ec; std::shared_ptr sender_connection = @@ -872,10 +870,9 @@ namespace hpx::parcelset { if (!sender_connection) { - // We can safely return if no connection is available - // at this point. As soon as a connection becomes - // available it checks for pending parcels and sends - // those out. + // We can safely return if no connection is available at this + // point. As soon as a connection becomes available it checks + // for pending parcels and sends those out. return; } @@ -888,18 +885,13 @@ namespace hpx::parcelset { // Give this connection back to the cache as we couldn't dequeue // parcels. connection_cache_.reclaim(locality_id, sender_connection); - - return; } - - // send parcels if they didn't get sent by another connection - send_pending_parcels(locality_id, sender_connection, - HPX_MOVE(parcels), HPX_MOVE(handlers)); - - // We yield here for a short amount of time to give another - // HPX thread the chance to put a subsequent parcel which - // leads to a more effective parcel buffering - // hpx::execution_base::this_thread::yield(); + else + { + // send parcels if they didn't get sent by another connection + send_pending_parcels(locality_id, sender_connection, + HPX_MOVE(parcels), HPX_MOVE(handlers)); + } } void send_pending_parcels_trampoline(std::error_code const& ec, @@ -928,9 +920,8 @@ namespace hpx::parcelset { std::lock_guard l(mtx_); // HPX_ASSERT(locality_id == sender_connection->destination()); - pending_parcels_map::iterator it = - pending_parcels_.find(locality_id); - if (it == pending_parcels_.end() || + if (auto const it = pending_parcels_.find(locality_id); + it == pending_parcels_.end() || hpx::get<0>(it->second).empty()) { return; @@ -957,9 +948,9 @@ namespace hpx::parcelset { sender_connection->verify_(parcel_locality_id); #endif // encode the parcels - std::size_t num_parcels = encode_parcels(*this, &parcels[0], - parcels.size(), sender_connection->buffer_, archive_flags_, - this->get_max_outbound_message_size()); + std::size_t const num_parcels = encode_parcels(*this, + parcels.data(), parcels.size(), sender_connection->buffer_, + archive_flags_, this->get_max_outbound_message_size()); using hpx::parcelset::detail::call_for_each; if (num_parcels == parcels.size()) @@ -1009,6 +1000,9 @@ namespace hpx::parcelset { parcel_locality_id, HPX_MOVE(parcels), HPX_MOVE(handlers)); } + // We yield here for a short amount of time to give another HPX + // thread the chance to put a subsequent parcel which leads to a + // more effective parcel buffering hpx::execution_base::this_thread::yield(); } diff --git a/libs/full/parcelset/include/hpx/parcelset/parcelset_fwd.hpp b/libs/full/parcelset/include/hpx/parcelset/parcelset_fwd.hpp index c052dc21d8fe..f061fd005258 100644 --- a/libs/full/parcelset/include/hpx/parcelset/parcelset_fwd.hpp +++ b/libs/full/parcelset/include/hpx/parcelset/parcelset_fwd.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2021 Hartmut Kaiser +// Copyright (c) 2007-2023 Hartmut Kaiser // Copyright (c) 2011 Bryce Lelbach // // SPDX-License-Identifier: BSL-1.0 @@ -40,6 +40,7 @@ namespace hpx::parcelset { /// This returns true/false based on the background work. /// /// \param num_thread this represents the number of threads. + /// \param mode /// HPX_EXPORT bool do_background_work(std::size_t num_thread = 0, parcelport_background_mode mode = parcelport_background_mode_all); diff --git a/libs/full/parcelset/src/parcel.cpp b/libs/full/parcelset/src/parcel.cpp index de78598e29df..929ad97043bc 100644 --- a/libs/full/parcelset/src/parcel.cpp +++ b/libs/full/parcelset/src/parcel.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2021 Hartmut Kaiser +// Copyright (c) 2007-2023 Hartmut Kaiser // Copyright (c) 2011 Bryce Lelbach // // SPDX-License-Identifier: BSL-1.0 @@ -121,7 +121,8 @@ namespace hpx::parcelset::detail { ar >> has_continuation_; } - void parcel_data::serialize(serialization::output_archive& ar, unsigned) + void parcel_data::serialize( + serialization::output_archive& ar, unsigned) const { ar << source_id_; ar << dest_; @@ -159,7 +160,7 @@ namespace hpx::parcelset::detail { // verify that the action targets the correct type if (action_ && data_.addr_.type_ != components::component_invalid) { - int type = action_->get_component_type(); + int const type = action_->get_component_type(); if (!components::types_are_compatible(type, data_.addr_.type_)) { return false; @@ -218,8 +219,7 @@ namespace hpx::parcelset::detail { hpx::id_type parcel::source_id() const { - return hpx::id_type( - data_.source_id_, hpx::id_type::management_type::unmanaged); + return {data_.source_id_, hpx::id_type::management_type::unmanaged}; } void parcel::set_source_id(hpx::id_type const& source_id) @@ -329,7 +329,8 @@ namespace hpx::parcelset::detail { #if defined(HPX_HAVE_NETWORKING) serialization::binary_filter* parcel::get_serialization_filter() const { - hpx::optional p = action_->get_embedded_parcel(); + hpx::optional const p = + action_->get_embedded_parcel(); if (!p) { return action_->get_serialization_filter(); @@ -340,7 +341,8 @@ namespace hpx::parcelset::detail { policies::message_handler* parcel::get_message_handler( locality const& loc) const { - hpx::optional p = action_->get_embedded_parcel(); + hpx::optional const p = + action_->get_embedded_parcel(); if (!p) { return action_->get_message_handler(loc); @@ -388,7 +390,7 @@ namespace hpx::parcelset::detail { } std::pair - parcel::determine_lva() + parcel::determine_lva() const { int comptype = action_->get_component_type(); @@ -444,11 +446,11 @@ namespace hpx::parcelset::detail { // make sure this parcel destination matches the proper locality HPX_ASSERT(destination_locality() == data_.addr_.locality_); - std::pair p = + std::pair const p = determine_lva(); // make sure the target has not been migrated away - auto r = action_->was_object_migrated(data_.dest_, p.first); + auto const r = action_->was_object_migrated(data_.dest_, p.first); if (r.first) { // If the object was migrated, just load the action and return. @@ -481,11 +483,11 @@ namespace hpx::parcelset::detail { // make sure this parcel destination matches the proper locality HPX_ASSERT(destination_locality() == data_.addr_.locality_); - std::pair p = + std::pair const p = determine_lva(); // make sure the target has not been migrated away - auto r = action_->was_object_migrated(data_.dest_, p.first); + auto const r = action_->was_object_migrated(data_.dest_, p.first); if (r.first) { // If the object was migrated, just route. diff --git a/libs/full/parcelset/src/parcelhandler.cpp b/libs/full/parcelset/src/parcelhandler.cpp index 91926db76d98..79b0f2cab0eb 100644 --- a/libs/full/parcelset/src/parcelhandler.cpp +++ b/libs/full/parcelset/src/parcelhandler.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2022 Hartmut Kaiser +// Copyright (c) 2007-2023 Hartmut Kaiser // Copyright (c) 2013-2014 Thomas Heller // Copyright (c) 2007 Richard D Guidry Jr // Copyright (c) 2011 Bryce Lelbach & Katelyn Kufahl @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -82,7 +83,7 @@ namespace hpx::parcelset { sent_future.get(); // wait for the parcel to be sent } - parcelhandler::parcelhandler(util::runtime_configuration& cfg) + parcelhandler::parcelhandler(util::runtime_configuration const& cfg) : tm_(nullptr) , use_alternative_parcelports_(false) , enable_parcel_handling_(true) @@ -102,7 +103,7 @@ namespace hpx::parcelset { parcelhandler::~parcelhandler() = default; void parcelhandler::set_notification_policies( - util::runtime_configuration& cfg, threads::threadmanager* tm, + util::runtime_configuration const& cfg, threads::threadmanager* tm, threads::policies::callback_notifier const& notifier) { is_networking_enabled_ = hpx::is_networking_enabled(); @@ -122,10 +123,10 @@ namespace hpx::parcelset { std::shared_ptr parcelhandler::get_bootstrap_parcelport() const { - std::string cfgkey("hpx.parcel.bootstrap"); + std::string const cfgkey("hpx.parcel.bootstrap"); if (!pports_.empty()) { - auto it = + auto const it = pports_.find(get_priority(get_config_entry(cfgkey, "tcp"))); if (it != pports_.end() && it->first > 0) { @@ -169,7 +170,7 @@ namespace hpx::parcelset { std::terminate(); } - return std::shared_ptr(); + return {}; } void parcelhandler::initialize() @@ -220,7 +221,7 @@ namespace hpx::parcelset { agas::get_locality_id(), exceptions.get_message()); } - // clean up parcelports that have failed initializtion + // clean up parcelports that have failed initialization std::cerr << "the following parcelports will be disabled:\n"; for (int pp : failed_pps) { @@ -285,7 +286,7 @@ namespace hpx::parcelset { int parcelhandler::get_priority(std::string const& name) const { - std::map::const_iterator it = priority_.find(name); + auto const it = priority_.find(name); if (it == priority_.end()) return 0; return it->second; @@ -294,7 +295,7 @@ namespace hpx::parcelset { parcelport* parcelhandler::find_parcelport( std::string const& type, error_code&) const { - int priority = get_priority(type); + int const priority = get_priority(type); if (priority <= 0) return nullptr; HPX_ASSERT(pports_.find(priority) != pports_.end()); @@ -310,7 +311,8 @@ namespace hpx::parcelset { // add the new parcelport to the list of parcel-ports we care about int priority = pp->priority(); - std::string cfgkey(std::string("hpx.parcel.") + pp->type() + ".enable"); + std::string const cfgkey( + std::string("hpx.parcel.") + pp->type() + ".enable"); if (get_config_entry(cfgkey, "0") != "1") { priority = -priority; @@ -328,11 +330,11 @@ namespace hpx::parcelset { /// \brief Make sure the specified locality is not held by any /// connection caches anymore void parcelhandler::remove_from_connection_cache( - naming::gid_type const& gid, endpoints_type const& endpoints) + naming::gid_type const& gid, endpoints_type const& endpoints) const { for (endpoints_type::value_type const& loc : endpoints) { - for (pports_type::value_type& pp : pports_) + for (pports_type::value_type const& pp : pports_) { if (std::string(pp.second->type()) == loc.second.type()) { @@ -354,6 +356,10 @@ namespace hpx::parcelset { return did_some_work; } + LPT_(debug).format( + "parcelhandler::do_background_work: thread {}, mode {}", num_thread, + get_parcelport_background_mode_name(mode)); + // flush all parcel buffers if (0 == num_thread && (mode & parcelport_background_mode_flush_buffers)) @@ -363,16 +369,15 @@ namespace hpx::parcelset { if (l.owns_lock()) { using parcelset::policies::message_handler; - message_handler::flush_mode flush_mode = + constexpr message_handler::flush_mode flush_mode = message_handler::flush_mode_background_work; - message_handler_map::iterator end = handlers_.end(); - for (message_handler_map::iterator it = handlers_.begin(); - it != end; ++it) + auto const end = handlers_.end(); + for (auto it = handlers_.begin(); it != end; ++it) { if ((*it).second) { - std::shared_ptr p( + std::shared_ptr const p( (*it).second); unlock_guard> ul(l); did_some_work = p->flush(flush_mode, stop_buffering) || @@ -383,7 +388,7 @@ namespace hpx::parcelset { } // make sure all pending parcels are being handled - for (pports_type::value_type& pp : pports_) + for (pports_type::value_type const& pp : pports_) { if (pp.first > 0) { @@ -396,12 +401,12 @@ namespace hpx::parcelset { return did_some_work; } - void parcelhandler::flush_parcels() + void parcelhandler::flush_parcels() const { if (is_networking_enabled_) { // now flush all parcel ports to be shut down - for (pports_type::value_type& pp : pports_) + for (pports_type::value_type const& pp : pports_) { if (pp.first > 0) { @@ -414,7 +419,7 @@ namespace hpx::parcelset { void parcelhandler::stop(bool blocking) { // now stop all parcel ports - for (pports_type::value_type& pp : pports_) + for (pports_type::value_type const& pp : pports_) { if (pp.first > 0) { @@ -431,7 +436,7 @@ namespace hpx::parcelset { components::component_type type, error_code& ec) const { std::vector allprefixes; - bool result = get_raw_localities(allprefixes, type, ec); + bool const result = get_raw_localities(allprefixes, type, ec); if (ec || !result) return false; @@ -445,11 +450,11 @@ namespace hpx::parcelset { std::vector& locality_ids, components::component_type type, error_code&) const { - std::vector ids = agas::get_all_locality_ids(type); + std::vector const ids = agas::get_all_locality_ids(type); locality_ids.clear(); locality_ids.reserve(ids.size()); - for (auto id : ids) + for (auto const& id : ids) { locality_ids.emplace_back(naming::get_gid_from_locality_id(id)); } @@ -467,18 +472,20 @@ namespace hpx::parcelset { { if (pp.first > 0) { - locality const& dest = - find_endpoint(dest_endpoints, pp.second->type()); - if (dest && + if (locality const& dest = + find_endpoint(dest_endpoints, pp.second->type()); + dest && pp.second->can_connect(dest, use_alternative_parcelports_)) + { return std::make_pair(pp.second, dest); + } } } std::ostringstream strm; strm << "target locality: " << dest_gid << "\n"; strm << "available destination endpoints:\n" << dest_endpoints << "\n"; - strm << "available partcelports:\n"; + strm << "available parcelports:\n"; for (auto const& pp : pports_) { list_parcelport(strm, pp.second->type(), pp.second->priority(), @@ -491,23 +498,23 @@ namespace hpx::parcelset { "The locality gid cannot be resolved to a valid endpoint. " "No valid parcelport configured. Detailed information:\n{}", strm.str()); - return std::pair, locality>(); } locality parcelhandler::find_endpoint( endpoints_type const& eps, std::string const& name) { - endpoints_type::const_iterator it = eps.find(name); + auto const it = eps.find(name); if (it != eps.end()) return it->second; - return locality(); + return {}; } // Return the reference to an existing io_service - util::io_service_pool* parcelhandler::get_thread_pool(char const* name) + util::io_service_pool* parcelhandler::get_thread_pool( + char const* name) const { util::io_service_pool* result = nullptr; - for (pports_type::value_type& pp : pports_) + for (pports_type::value_type const& pp : pports_) { result = pp.second->get_thread_pool(name); if (result) @@ -517,8 +524,9 @@ namespace hpx::parcelset { } namespace detail { + void parcel_sent_handler( - parcelhandler::write_handler_type& f, //-V669 + parcelhandler::write_handler_type const& f, //-V669 std::error_code const& ec, parcelset::parcel const& p) { // inform termination detection of a sent message @@ -545,9 +553,15 @@ namespace hpx::parcelset { void parcelhandler::put_parcel(parcelset::parcel p) { + LPT_(debug).format( + "parcelhandler::put_parcel: submitted: {}", p.parcel_id()); + auto handler = [this](std::error_code const& ec, parcelset::parcel const& p) -> void { invoke_write_handler(ec, p); + + LPT_(debug).format( + "parcelhandler::put_parcel: handled: {}", p.parcel_id()); }; put_parcel_impl(HPX_MOVE(p), HPX_MOVE(handler)); @@ -555,10 +569,17 @@ namespace hpx::parcelset { void parcelhandler::put_parcel(parcelset::parcel p, write_handler_type f) { + LPT_(debug).format( + "parcelhandler::put_parcel (with handler): submitted: {}", + p.parcel_id()); + auto handler = [this, f = HPX_MOVE(f)](std::error_code const& ec, parcelset::parcel const& p) -> void { invoke_write_handler(ec, p); f(ec, p); + + LPT_(debug).format( + "parcelhandler::put_parcel: handled: {}", p.parcel_id()); }; put_parcel_impl(HPX_MOVE(p), HPX_MOVE(handler)); @@ -578,10 +599,13 @@ namespace hpx::parcelset { if (!this_thread::has_sufficient_stack_space() && hpx::threads::threadmanager_is(hpx::state::running)) { + LPT_(debug).format("parcelhandler::put_parcel_impl: reschedule: {}", + p.parcel_id()); + { // reschedule request as an HPX thread to avoid hangs - void (parcelhandler::*put_parcel_ptr)(parcel p, - write_handler_type f) = &parcelhandler::put_parcel; + void (parcelhandler::*put_parcel_ptr)( + parcel, write_handler_type) = &parcelhandler::put_parcel; threads::thread_init_data data( threads::make_thread_function_nullary(util::deferred_call( @@ -617,15 +641,13 @@ namespace hpx::parcelset { // encapsulated action using destination_pair = std::pair, locality>; - destination_pair dest = + destination_pair const dest = find_appropriate_destination(addr.locality_); if (load_message_handlers_ && !hpx::is_stopped_or_shutting_down()) { - policies::message_handler* mh = - p.get_message_handler(dest.second); - - if (mh) + if (policies::message_handler* mh = + p.get_message_handler(dest.second)) { mh->put_parcel( dest.second, HPX_MOVE(p), HPX_MOVE(wrapped_f)); @@ -647,9 +669,14 @@ namespace hpx::parcelset { void parcelhandler::put_parcels(std::vector parcels) { + LPT_(debug).format("parcelhandler::put_parcels: submitted: {} parcels", + parcels.size()); + std::vector handlers(parcels.size(), [this](std::error_code const& ec, parcel const& p) -> void { - return invoke_write_handler(ec, p); + invoke_write_handler(ec, p); + LPT_(debug).format( + "parcelhandler::put_parcels: handled: {}", p.parcel_id()); }); put_parcels_impl(HPX_MOVE(parcels), HPX_MOVE(handlers)); @@ -658,17 +685,24 @@ namespace hpx::parcelset { void parcelhandler::put_parcels( std::vector parcels, std::vector funcs) { + LPT_(debug).format( + "parcelhandler::put_parcels (with handlers): submitted: {} parcels", + parcels.size()); + std::vector handlers; handlers.reserve(parcels.size()); for (std::size_t i = 0; i != parcels.size(); ++i) { - handlers.emplace_back( - [this, f = HPX_MOVE(funcs[i])]( - std::error_code const& ec, parcel const& p) -> void { - invoke_write_handler(ec, p); - f(ec, p); - }); + handlers.emplace_back([this, f = HPX_MOVE(funcs[i])]( + std::error_code const& ec, + parcel const& p) -> void { + invoke_write_handler(ec, p); + f(ec, p); + + LPT_(debug).format( + "parcelhandler::put_parcels: handled: {}", p.parcel_id()); + }); } put_parcels_impl(HPX_MOVE(parcels), HPX_MOVE(handlers)); @@ -684,13 +718,16 @@ namespace hpx::parcelset { HPX_THROW_EXCEPTION(hpx::error::bad_parameter, "parcelhandler::put_parcels", "mismatched number of parcels and handlers"); - return; } // if this isn't an HPX thread, the stack space check will return false if (!this_thread::has_sufficient_stack_space() && hpx::threads::threadmanager_is(hpx::state::running)) { + LPT_(debug).format( + "parcelhandler::put_parcels_impl: rescheduling: {}", + parcels.size()); + // reschedule request as an HPX thread to avoid hangs void (parcelhandler::*put_parcels_ptr)(std::vector, std::vector) = &parcelhandler::put_parcels; @@ -709,7 +746,7 @@ namespace hpx::parcelset { // partition parcels depending on whether their destination can be // resolved locally - std::size_t num_parcels = parcels.size(); + std::size_t const num_parcels = parcels.size(); std::vector resolved_parcels; resolved_parcels.reserve(num_parcels); @@ -722,8 +759,9 @@ namespace hpx::parcelset { destination_pair resolved_dest; std::vector nonresolved_parcels; - nonresolved_parcels.reserve(num_parcels); std::vector nonresolved_handlers; + + nonresolved_parcels.reserve(num_parcels); nonresolved_handlers.reserve(num_parcels); for (std::size_t i = 0; i != num_parcels; ++i) @@ -751,7 +789,6 @@ namespace hpx::parcelset { "parcelhandler::put_parcels", "mismatched destinations, all parcels are expected to " "target the same locality"); - return; } // If we were able to resolve the address(es) locally we would send @@ -765,10 +802,8 @@ namespace hpx::parcelset { if (load_message_handlers_) { - policies::message_handler* mh = - p.get_message_handler(dest.second); - - if (mh) + if (policies::message_handler* mh = + p.get_message_handler(dest.second)) { mh->put_parcel(dest.second, HPX_MOVE(p), HPX_MOVE(f)); continue; @@ -793,7 +828,7 @@ namespace hpx::parcelset { } } - // handle parcel which have been locally resolved + // handle parcel that have been locally resolved if (!resolved_parcels.empty()) { HPX_ASSERT(!!resolved_dest.first && !!resolved_dest.second); @@ -814,7 +849,7 @@ namespace hpx::parcelset { void parcelhandler::invoke_write_handler( std::error_code const& ec, parcel const& p) const { - write_handler_type f = write_handler_; + write_handler_type const f = write_handler_; f(ec, p); } @@ -858,7 +893,7 @@ namespace hpx::parcelset { } // all unhandled exceptions terminate the whole application - std::exception_ptr exception = hpx::detail::get_exception( + std::exception_ptr const exception = hpx::detail::get_exception( hpx::exception(ec), "default_write_handler", __FILE__, __LINE__, parcelset::dump_parcel(p)); @@ -878,9 +913,9 @@ namespace hpx::parcelset { } std::unique_lock l(handlers_mtx_); - handler_key_type key(loc, action); - message_handler_map::iterator it = handlers_.find(key); + handler_key_type key(loc, action); + auto it = handlers_.find(key); if (it == handlers_.end()) { std::shared_ptr p; @@ -889,8 +924,7 @@ namespace hpx::parcelset { // Just ignore the handlers_mtx_ while checking. We need to hold // the lock here to avoid multiple registrations that happens // right now in the parcel coalescing plugin - hpx::util::ignore_while_checking il(&l); - HPX_UNUSED(il); + [[maybe_unused]] hpx::util::ignore_while_checking const il(&l); p.reset(hpx::create_message_handler(message_handler_type, action, find_parcelport(loc.type()), num_messages, interval, @@ -904,7 +938,7 @@ namespace hpx::parcelset { l.unlock(); if (&ec != &throws) { - if ((*it).second.get()) + if ((*it).second) ec = make_success_code(); else ec = make_error_code( @@ -913,10 +947,10 @@ namespace hpx::parcelset { return (*it).second.get(); } - if (ec || !p.get()) + if (ec || !p) { - // insert an empty entry into the map to avoid trying to - // create this handler again + // insert an empty entry into the map to avoid trying to create + // this handler again p.reset(); std::pair const r = handlers_.emplace(key, p); @@ -945,7 +979,7 @@ namespace hpx::parcelset { } it = r.first; } - else if (!(*it).second.get()) + else if (!(*it).second) { l.unlock(); if (&ec != &throws) diff --git a/libs/full/parcelset_base/CMakeLists.txt b/libs/full/parcelset_base/CMakeLists.txt index 8b31cd4608a4..78eb49583e2b 100644 --- a/libs/full/parcelset_base/CMakeLists.txt +++ b/libs/full/parcelset_base/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2019-2021 The STE||AR-Group +# Copyright (c) 2019-2023 The STE||AR-Group # # SPDX-License-Identifier: BSL-1.0 # Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -42,6 +42,7 @@ set(parcelset_base_sources locality_interface.cpp parcelport.cpp parcel_interface.cpp + parcelset_base.cpp set_parcel_write_handler.cpp ) diff --git a/libs/full/parcelset_base/include/hpx/parcelset_base/parcel_interface.hpp b/libs/full/parcelset_base/include/hpx/parcelset_base/parcel_interface.hpp index a157044e66e1..ae43e20c2b90 100644 --- a/libs/full/parcelset_base/include/hpx/parcelset_base/parcel_interface.hpp +++ b/libs/full/parcelset_base/include/hpx/parcelset_base/parcel_interface.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2021 Hartmut Kaiser +// Copyright (c) 2007-2023 Hartmut Kaiser // Copyright (c) 2015-2016 Thomas Heller // Copyright (c) 2007 Richard D Guidry Jr // Copyright (c) 2007 Alexandre (aka Alex) TABBAL @@ -113,7 +113,7 @@ namespace hpx::parcelset { class HPX_EXPORT parcel { private: - using split_gids_type = typename detail::parcel_base::split_gids_type; + using split_gids_type = detail::parcel_base::split_gids_type; bool is_valid() const; @@ -124,37 +124,37 @@ namespace hpx::parcelset { ~parcel(); public: - void reset(); + void reset() const; - char const* get_action_name() const; - int get_component_type() const; - int get_action_type() const; + [[nodiscard]] char const* get_action_name() const; + [[nodiscard]] int get_component_type() const; + [[nodiscard]] int get_action_type() const; - hpx::id_type source_id() const; - void set_source_id(hpx::id_type const& source_id); - void set_destination_id(naming::gid_type&& dest); + [[nodiscard]] hpx::id_type source_id() const; + void set_source_id(hpx::id_type const& source_id) const; + void set_destination_id(naming::gid_type&& dest) const; naming::address const& addr() const; naming::address& addr(); - std::uint32_t destination_locality_id() const; + [[nodiscard]] std::uint32_t destination_locality_id() const; naming::gid_type const& destination() const; naming::gid_type const& destination_locality() const; - double start_time() const; - void set_start_time(double time); - double creation_time() const; + [[nodiscard]] double start_time() const; + void set_start_time(double time) const; + [[nodiscard]] double creation_time() const; - threads::thread_priority get_thread_priority() const; - threads::thread_stacksize get_thread_stacksize() const; + [[nodiscard]] threads::thread_priority get_thread_priority() const; + [[nodiscard]] threads::thread_stacksize get_thread_stacksize() const; - std::uint32_t get_parent_locality_id() const; - threads::thread_id_type get_parent_thread_id() const; - std::uint64_t get_parent_thread_phase() const; + [[nodiscard]] std::uint32_t get_parent_locality_id() const; + [[nodiscard]] threads::thread_id_type get_parent_thread_id() const; + [[nodiscard]] std::uint64_t get_parent_thread_phase() const; -#if defined(HPX_HAVE_PARCEL_PROFILING) naming::gid_type const& parcel_id() const; +#if defined(HPX_HAVE_PARCEL_PROFILING) naming::gid_type& parcel_id(); #endif @@ -164,18 +164,19 @@ namespace hpx::parcelset { locality const& loc) const; #endif - bool does_termination_detection() const; + [[nodiscard]] bool does_termination_detection() const; split_gids_type move_split_gids() const; - void set_split_gids(split_gids_type&& split_gids); + void set_split_gids(split_gids_type&& split_gids) const; - std::size_t num_chunks() const; + [[nodiscard]] std::size_t num_chunks() const; std::size_t& num_chunks(); - std::size_t size() const; + [[nodiscard]] std::size_t size() const; std::size_t& size(); - bool schedule_action(std::size_t num_thread = std::size_t(-1)); + bool schedule_action( + std::size_t num_thread = static_cast(-1)) const; // returns true if parcel was migrated, false if scheduled locally bool load_schedule(serialization::input_archive& ar, @@ -191,7 +192,7 @@ namespace hpx::parcelset { friend class hpx::serialization::access; void serialize(serialization::input_archive& ar, unsigned); - void serialize(serialization::output_archive& ar, unsigned); + void serialize(serialization::output_archive& ar, unsigned) const; std::shared_ptr data_; }; diff --git a/libs/full/parcelset_base/include/hpx/parcelset_base/parcelport.hpp b/libs/full/parcelset_base/include/hpx/parcelset_base/parcelport.hpp index 7d8585ed630b..eef8cd16336e 100644 --- a/libs/full/parcelset_base/include/hpx/parcelset_base/parcelport.hpp +++ b/libs/full/parcelset_base/include/hpx/parcelset_base/parcelport.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2014-2015 Thomas Heller -// Copyright (c) 2007-2021 Hartmut Kaiser +// Copyright (c) 2007-2023 Hartmut Kaiser // Copyright (c) 2007 Richard D Guidry Jr // Copyright (c) 2011 Bryce Lelbach // Copyright (c) 2011 Katelyn Kufahl diff --git a/libs/full/parcelset_base/include/hpx/parcelset_base/parcelset_base_fwd.hpp b/libs/full/parcelset_base/include/hpx/parcelset_base/parcelset_base_fwd.hpp index 4d86b68ec6fd..0cd07d074cbe 100644 --- a/libs/full/parcelset_base/include/hpx/parcelset_base/parcelset_base_fwd.hpp +++ b/libs/full/parcelset_base/include/hpx/parcelset_base/parcelset_base_fwd.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2021 Hartmut Kaiser +// Copyright (c) 2021-2023 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -40,4 +40,7 @@ namespace hpx::parcelset { /// perform all operations parcelport_background_mode_all = 0x07 }; + + HPX_EXPORT char const* get_parcelport_background_mode_name( + parcelport_background_mode mode); } // namespace hpx::parcelset diff --git a/libs/full/parcelset_base/src/parcel_interface.cpp b/libs/full/parcelset_base/src/parcel_interface.cpp index ffd3bbae2662..b1698252abcb 100644 --- a/libs/full/parcelset_base/src/parcel_interface.cpp +++ b/libs/full/parcelset_base/src/parcel_interface.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2021 Hartmut Kaiser +// Copyright (c) 2007-2023 Hartmut Kaiser // Copyright (c) 2011 Bryce Lelbach // // SPDX-License-Identifier: BSL-1.0 @@ -43,7 +43,7 @@ namespace hpx::parcelset { parcel::~parcel() = default; - void parcel::reset() + void parcel::reset() const { data_->reset(); } @@ -68,12 +68,12 @@ namespace hpx::parcelset { return data_->source_id(); } - void parcel::set_source_id(hpx::id_type const& source_id) + void parcel::set_source_id(hpx::id_type const& source_id) const { data_->set_source_id(source_id); } - void parcel::set_destination_id(naming::gid_type&& dest) + void parcel::set_destination_id(naming::gid_type&& dest) const { data_->set_destination_id(HPX_MOVE(dest)); } @@ -108,7 +108,7 @@ namespace hpx::parcelset { return data_->start_time(); } - void parcel::set_start_time(double time) + void parcel::set_start_time(double time) const { data_->set_start_time(time); } @@ -166,7 +166,7 @@ namespace hpx::parcelset { return data_->move_split_gids(); } - void parcel::set_split_gids(split_gids_type&& split_gids) + void parcel::set_split_gids(split_gids_type&& split_gids) const { data_->set_split_gids(HPX_MOVE(split_gids)); } @@ -191,7 +191,7 @@ namespace hpx::parcelset { return data_->size(); } - bool parcel::schedule_action(std::size_t num_thread) + bool parcel::schedule_action(std::size_t num_thread) const { return data_->schedule_action(num_thread); } @@ -224,6 +224,11 @@ namespace hpx::parcelset { result.set_lsb(++id); return result; } +#else + naming::gid_type const& parcel::parcel_id() const + { + return naming::invalid_gid; + } #endif /////////////////////////////////////////////////////////////////////////// @@ -233,7 +238,7 @@ namespace hpx::parcelset { data_->load(ar, 0); } - void parcel::serialize(serialization::output_archive& ar, unsigned) + void parcel::serialize(serialization::output_archive& ar, unsigned) const { data_->save(ar, 0); } diff --git a/libs/full/parcelset_base/src/parcelset_base.cpp b/libs/full/parcelset_base/src/parcelset_base.cpp new file mode 100644 index 000000000000..137ed155196a --- /dev/null +++ b/libs/full/parcelset_base/src/parcelset_base.cpp @@ -0,0 +1,44 @@ +// Copyright (c) 2023 Hartmut Kaiser +// +// SPDX-License-Identifier: BSL-1.0 +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include + +#include + +namespace hpx::parcelset { + + /////////////////////////////////////////////////////////////////////////// + namespace strings { + + // clang-format off + inline constexpr char const* const parcelport_background_mode_names[] = { + "unknown", + "parcelport_background_mode_flush_buffers", + "unknown", + "parcelport_background_mode_send", + "parcelport_background_mode_receive", + "unknown", + "unknown", + "parcelport_background_mode_all", + }; + // clang-format on + + } // namespace strings + + char const* get_parcelport_background_mode_name( + parcelport_background_mode mode) + { + if (mode < parcelport_background_mode:: + parcelport_background_mode_flush_buffers || + mode > parcelport_background_mode::parcelport_background_mode_all) + { + return "unknown"; + } + + return strings::parcelport_background_mode_names + [static_cast(mode)]; + } +} // namespace hpx::parcelset diff --git a/libs/full/performance_counters/src/parcelhandler_counter_types.cpp b/libs/full/performance_counters/src/parcelhandler_counter_types.cpp index daa44216a77c..a550d4a10349 100644 --- a/libs/full/performance_counters/src/parcelhandler_counter_types.cpp +++ b/libs/full/performance_counters/src/parcelhandler_counter_types.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2021 Hartmut Kaiser +// Copyright (c) 2021-2023 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -479,7 +479,7 @@ namespace hpx::performance_counters { }; performance_counters::install_counter_types( - counter_types, sizeof(counter_types) / sizeof(counter_types[0])); + counter_types, std::size(counter_types)); #else HPX_UNUSED(ph); HPX_UNUSED(pp_type); @@ -586,8 +586,8 @@ namespace hpx::performance_counters { HPX_MOVE(cache_reclaims), _2), &performance_counters::locality_counter_discoverer, ""}}; - performance_counters::install_counter_types(connection_cache_types, - sizeof(connection_cache_types) / sizeof(connection_cache_types[0])); + performance_counters::install_counter_types( + connection_cache_types, std::size(connection_cache_types)); } /////////////////////////////////////////////////////////////////////////// @@ -643,7 +643,7 @@ namespace hpx::performance_counters { &performance_counters::locality_counter_discoverer, ""}}; performance_counters::install_counter_types( - counter_types, sizeof(counter_types) / sizeof(counter_types[0])); + counter_types, std::size(counter_types)); } } // namespace hpx::performance_counters diff --git a/libs/full/runtime_components/src/console_logging.cpp b/libs/full/runtime_components/src/console_logging.cpp index 689b3b751d4f..03032122d517 100644 --- a/libs/full/runtime_components/src/console_logging.cpp +++ b/libs/full/runtime_components/src/console_logging.cpp @@ -47,6 +47,7 @@ namespace hpx { namespace components { message_type const& msg = msgs[i]; switch (get<0>(msg)) { + // NOLINTNEXTLINE(bugprone-branch-clone) default: case logging_destination::hpx: LHPX_CONSOLE_(get<1>(msg)) << fail_msg << get<2>(msg); diff --git a/libs/full/runtime_components/src/server/console_logging_server.cpp b/libs/full/runtime_components/src/server/console_logging_server.cpp index 4aab2fa20caf..e26bdcb1a30e 100644 --- a/libs/full/runtime_components/src/server/console_logging_server.cpp +++ b/libs/full/runtime_components/src/server/console_logging_server.cpp @@ -61,6 +61,7 @@ namespace hpx { namespace components { namespace server { switch (dest) { + // NOLINTNEXTLINE(bugprone-branch-clone) case logging_destination::hpx: LHPX_CONSOLE_(level) << s; break;