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-format.py b/.cmake-format.py index 4ce7b1e49130..8e44cf90089a 100644 --- a/.cmake-format.py +++ b/.cmake-format.py @@ -1,4 +1,4 @@ -# Copyright (c) 2020-2022 Hartmut Kaiser +# Copyright (c) 2020-2023 Hartmut Kaiser # # SPDX-License-Identifier: BSL-1.0 # Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -238,6 +238,7 @@ 'HEADER_ROOT': 1, 'INI': 1, 'INSTALL_SUFFIX': 1, + 'INSTALL_COMPONENT': 1, 'LANGUAGE': 1, 'LINK_FLAGS': '+', 'OUTPUT_SUFFIX': 1, diff --git a/CMakeLists.txt b/CMakeLists.txt index 8372cf6cd280..9119adc9acd3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ # Copyright (c) 2020 Mikael Simberg -# Copyright (c) 2007-2022 Hartmut Kaiser +# Copyright (c) 2007-2023 Hartmut Kaiser # Copyright (c) 2011-2014 Thomas Heller # Copyright (c) 2007-2008 Chirag Dekate # Copyright (c) 2011 Bryce Lelbach @@ -2439,7 +2439,7 @@ if(PYTHONINTERP_FOUND) install( FILES "${PROJECT_BINARY_DIR}/bin/hpxrun.py" DESTINATION ${CMAKE_INSTALL_BINDIR} - COMPONENT core + COMPONENT runtime PERMISSIONS OWNER_READ OWNER_WRITE @@ -2485,18 +2485,6 @@ install( PATTERN ".git" EXCLUDE ) -if("${HPX_PLATFORM_UC}" STREQUAL "XEONPHI") - # FIXME: push changes upstream - install( - DIRECTORY external/asio/boost - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/hpx/external - COMPONENT core - FILES_MATCHING - PATTERN "*.hpp" - PATTERN ".git" EXCLUDE - ) -endif() - install( FILES "${PROJECT_SOURCE_DIR}/LICENSE_1_0.txt" DESTINATION ${CMAKE_INSTALL_DATADIR}/hpx @@ -2581,12 +2569,13 @@ include(HPX_PrintSummary) create_configuration_summary("Configuration summary:\n--" "hpx") include(HPX_ExportTargets) + # Modules can't link to this if not exported install( TARGETS hpx_base_libraries EXPORT HPXInternalTargets - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT hpx_base_libraries + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT hpx_base_libraries RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT hpx_base_libraries ) hpx_export_internal_targets(hpx_base_libraries) diff --git a/cmake/HPX_AddComponent.cmake b/cmake/HPX_AddComponent.cmake index 60cb0b9053cb..31e5fe8df4a7 100644 --- a/cmake/HPX_AddComponent.cmake +++ b/cmake/HPX_AddComponent.cmake @@ -1,4 +1,4 @@ -# Copyright (c) 2007-2012 Hartmut Kaiser +# Copyright (c) 2007-2023 Hartmut Kaiser # Copyright (c) 2011 Bryce Lelbach # # SPDX-License-Identifier: BSL-1.0 @@ -28,6 +28,7 @@ function(add_hpx_component name) HEADER_GLOB OUTPUT_SUFFIX INSTALL_SUFFIX + INSTALL_COMPONENT LANGUAGE ) set(multi_value_args @@ -191,12 +192,15 @@ function(add_hpx_component name) set(archive_install_destination ${${name}_INSTALL_SUFFIX}) set(runtime_install_destination ${${name}_INSTALL_SUFFIX}) endif() + if(${name}_INSTALL_COMPONENT) + set(install_component COMPONENT ${${name}_INSTALL_COMPONENT}) + endif() # cmake-format: off set(_target_flags INSTALL INSTALL_FLAGS - LIBRARY DESTINATION ${library_install_destination} - ARCHIVE DESTINATION ${archive_install_destination} - RUNTIME DESTINATION ${runtime_install_destination} + LIBRARY DESTINATION ${library_install_destination} ${install_component} + ARCHIVE DESTINATION ${archive_install_destination} ${install_component} + RUNTIME DESTINATION ${runtime_install_destination} ${install_component} ) # cmake-format: on @@ -210,6 +214,7 @@ function(add_hpx_component name) ${_target_flags} INSTALL_PDB $ DESTINATION ${runtime_install_destination} + ${install_component} CONFIGURATIONS Debug RelWithDebInfo OPTIONAL ) diff --git a/cmake/HPX_AddConfigTest.cmake b/cmake/HPX_AddConfigTest.cmake index 1220e4f0bbc1..8fa35e969aad 100644 --- a/cmake/HPX_AddConfigTest.cmake +++ b/cmake/HPX_AddConfigTest.cmake @@ -587,6 +587,15 @@ function(hpx_check_for_cxx20_std_default_sentinel) ) endfunction() +# ############################################################################## +function(hpx_check_for_cxx20_std_bit_cast) + add_hpx_config_test( + HPX_WITH_CXX20_STD_BIT_CAST + SOURCE cmake/tests/cxx20_std_bit_cast.cpp + FILE ${ARGN} + ) +endfunction() + # ############################################################################## function(hpx_check_for_cxx23_std_generator) add_hpx_config_test( 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/cmake/HPX_AddExecutable.cmake b/cmake/HPX_AddExecutable.cmake index 6db831c58cce..87c3117dadc0 100644 --- a/cmake/HPX_AddExecutable.cmake +++ b/cmake/HPX_AddExecutable.cmake @@ -1,4 +1,4 @@ -# Copyright (c) 2007-2012 Hartmut Kaiser +# Copyright (c) 2007-2023 Hartmut Kaiser # Copyright (c) 2011 Bryce Lelbach # # SPDX-License-Identifier: BSL-1.0 @@ -165,7 +165,9 @@ function(add_hpx_executable name) if(${name}_INSTALL_SUFFIX) set(install_destination ${${name}_INSTALL_SUFFIX}) endif() - set(_target_flags INSTALL INSTALL_FLAGS DESTINATION ${install_destination}) + set(_target_flags INSTALL INSTALL_FLAGS DESTINATION ${install_destination} + COMPONENT executables + ) # install PDB if needed if(MSVC AND NOT ${name}_STATIC @@ -176,6 +178,7 @@ function(add_hpx_executable name) ${_target_flags} INSTALL_PDB $ DESTINATION ${install_destination} + COMPONENT executables CONFIGURATIONS Debug RelWithDebInfo OPTIONAL ) diff --git a/cmake/HPX_AddLibrary.cmake b/cmake/HPX_AddLibrary.cmake index 3ebd99d04747..ca0f25f403ec 100644 --- a/cmake/HPX_AddLibrary.cmake +++ b/cmake/HPX_AddLibrary.cmake @@ -1,4 +1,4 @@ -# Copyright (c) 2007-2012 Hartmut Kaiser +# Copyright (c) 2007-2023 Hartmut Kaiser # Copyright (c) 2011 Bryce Lelbach # # SPDX-License-Identifier: BSL-1.0 @@ -180,9 +180,9 @@ function(add_hpx_library name) # cmake-format: off set(_target_flags INSTALL INSTALL_FLAGS - LIBRARY DESTINATION ${library_install_destination} - ARCHIVE DESTINATION ${archive_install_destination} - RUNTIME DESTINATION ${runtime_install_destination} + LIBRARY DESTINATION ${library_install_destination} COMPONENT runtime + ARCHIVE DESTINATION ${archive_install_destination} COMPONENT runtime + RUNTIME DESTINATION ${runtime_install_destination} COMPONENT runtime ) # cmake-format: on @@ -196,6 +196,7 @@ function(add_hpx_library name) ${_target_flags} INSTALL_PDB $ DESTINATION ${runtime_install_destination} + COMPONENT runtime CONFIGURATIONS Debug RelWithDebInfo OPTIONAL ) diff --git a/cmake/HPX_AddModule.cmake b/cmake/HPX_AddModule.cmake index 4fb192e968ce..f63f6ec29029 100644 --- a/cmake/HPX_AddModule.cmake +++ b/cmake/HPX_AddModule.cmake @@ -1,4 +1,4 @@ -# Copyright (c) 2019 ETH Zurich +# Copyright (c) 2019-2023 ETH Zurich # # SPDX-License-Identifier: BSL-1.0 # Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -380,8 +380,8 @@ function(add_hpx_module libname modulename) install( TARGETS hpx_${modulename} EXPORT HPXInternalTargets - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT ${modulename} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT ${modulename} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT ${modulename} ) hpx_export_internal_targets(hpx_${modulename}) @@ -420,6 +420,7 @@ function(add_hpx_module libname modulename) FILES ${_pdb_dir}/${_pdb_file}.pdb DESTINATION ${CMAKE_INSTALL_LIBDIR} CONFIGURATIONS ${cfg} + COMPONENT ${modulename} OPTIONAL ) endforeach() diff --git a/cmake/HPX_CompilerFlagsTargets.cmake b/cmake/HPX_CompilerFlagsTargets.cmake index 5bf4649f42a0..66410dd6369d 100644 --- a/cmake/HPX_CompilerFlagsTargets.cmake +++ b/cmake/HPX_CompilerFlagsTargets.cmake @@ -34,20 +34,22 @@ target_compile_definitions( # Remaining flags are set through the macros in cmake/HPX_AddCompileFlag.cmake include(HPX_ExportTargets) + # Modules can't link to this if not exported install( TARGETS hpx_private_flags EXPORT HPXInternalTargets - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT hpx_private_flags + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT hpx_private_flags RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT hpx_private_flags ) install( TARGETS hpx_public_flags EXPORT HPXInternalTargets - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT hpx_public_flags + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT hpx_public_flags RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT hpx_public_flags ) + hpx_export_internal_targets(hpx_private_flags) hpx_export_internal_targets(hpx_public_flags) diff --git a/cmake/HPX_ForwardCacheVariables.cmake b/cmake/HPX_ForwardCacheVariables.cmake index 34cc47c7750b..f97a3abf98d3 100644 --- a/cmake/HPX_ForwardCacheVariables.cmake +++ b/cmake/HPX_ForwardCacheVariables.cmake @@ -1,4 +1,4 @@ -# Copyright (c) 2019 Ste||ar Group +# Copyright (c) 2019-2023 Ste||ar Group # # SPDX-License-Identifier: BSL-1.0 # Distributed under the Boost Software License, Version 1.0. (See accompanying diff --git a/cmake/HPX_GeneratePackage.cmake b/cmake/HPX_GeneratePackage.cmake index 45a60d29476e..d0f473945c74 100644 --- a/cmake/HPX_GeneratePackage.cmake +++ b/cmake/HPX_GeneratePackage.cmake @@ -32,6 +32,7 @@ install( NAMESPACE HPXInternal:: FILE HPXInternalTargets.cmake DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${HPX_PACKAGE_NAME} + COMPONENT cmake ) # Export HPXTargets in the build directory @@ -56,6 +57,7 @@ install( NAMESPACE HPX:: FILE HPXTargets.cmake DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${HPX_PACKAGE_NAME} + COMPONENT cmake ) # Install dir @@ -117,7 +119,7 @@ if(HPX_WITH_PKGCONFIG) install( FILES "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/hpxcxx" DESTINATION ${CMAKE_INSTALL_BINDIR} - COMPONENT compiler_wrapper + COMPONENT runtime PERMISSIONS OWNER_READ OWNER_WRITE diff --git a/cmake/HPX_PerformCxxFeatureTests.cmake b/cmake/HPX_PerformCxxFeatureTests.cmake index f2f6071b9e8c..851c44f6cdd2 100644 --- a/cmake/HPX_PerformCxxFeatureTests.cmake +++ b/cmake/HPX_PerformCxxFeatureTests.cmake @@ -144,6 +144,8 @@ function(hpx_perform_cxx_feature_tests) hpx_check_for_cxx20_std_default_sentinel( DEFINITIONS HPX_HAVE_CXX20_STD_DEFAULT_SENTINEL ) + + hpx_check_for_cxx20_std_bit_cast(DEFINITIONS HPX_HAVE_CXX20_STD_BIT_CAST) endif() if(HPX_WITH_CXX_STANDARD GREATER_EQUAL 23) diff --git a/cmake/HPX_SetupAsio.cmake b/cmake/HPX_SetupAsio.cmake index 71c8a8fc320d..1dfbdd9416d6 100644 --- a/cmake/HPX_SetupAsio.cmake +++ b/cmake/HPX_SetupAsio.cmake @@ -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 @@ -61,6 +61,7 @@ elseif(NOT TARGET Asio::asio AND NOT HPX_FIND_PACKAGE) NAMESPACE Asio:: FILE HPXAsioTarget.cmake DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${HPX_PACKAGE_NAME} + COMPONENT cmake ) add_library(Asio::asio ALIAS asio) diff --git a/cmake/HPX_SetupEve.cmake b/cmake/HPX_SetupEve.cmake index 04d08db9fe85..9dff0f454a4d 100644 --- a/cmake/HPX_SetupEve.cmake +++ b/cmake/HPX_SetupEve.cmake @@ -60,6 +60,7 @@ if(("${HPX_WITH_DATAPAR_BACKEND}" STREQUAL "EVE") AND NOT TARGET eve::eve) NAMESPACE eve:: FILE HPXEveTarget.cmake DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${HPX_PACKAGE_NAME} + COMPONENT cmake ) add_library(eve::eve ALIAS eve) diff --git a/cmake/HPX_SetupLCI.cmake b/cmake/HPX_SetupLCI.cmake index 638e8aba3b0b..98a01ea68205 100644 --- a/cmake/HPX_SetupLCI.cmake +++ b/cmake/HPX_SetupLCI.cmake @@ -1,4 +1,4 @@ -# Copyright (c) 2021 Ste||ar Group +# Copyright (c) 2021-2023 Ste||ar Group # # SPDX-License-Identifier: BSL-1.0 # Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -103,13 +103,18 @@ macro(hpx_setup_lci) NAMESPACE LCI:: FILE HPXLCITarget.cmake DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${HPX_PACKAGE_NAME} + COMPONENT cmake ) - install(FILES "${lci_SOURCE_DIR}/cmake_modules/FindIBV.cmake" - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${HPX_PACKAGE_NAME} + install( + FILES "${lci_SOURCE_DIR}/cmake_modules/FindIBV.cmake" + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${HPX_PACKAGE_NAME} + COMPONENT cmake ) - install(FILES "${lci_SOURCE_DIR}/cmake_modules/FindOFI.cmake" - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${HPX_PACKAGE_NAME} + install( + FILES "${lci_SOURCE_DIR}/cmake_modules/FindOFI.cmake" + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${HPX_PACKAGE_NAME} + COMPONENT cmake ) endif() endif() diff --git a/cmake/HPX_SetupSVE.cmake b/cmake/HPX_SetupSVE.cmake index e528b6085832..c85b69c51104 100644 --- a/cmake/HPX_SetupSVE.cmake +++ b/cmake/HPX_SetupSVE.cmake @@ -61,6 +61,7 @@ if(("${HPX_WITH_DATAPAR_BACKEND}" STREQUAL "SVE") AND NOT TARGET SVE::sve) NAMESPACE SVE:: FILE HPXSVETarget.cmake DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${HPX_PACKAGE_NAME} + COMPONENT cmake ) else() diff --git a/cmake/HPX_SetupTarget.cmake b/cmake/HPX_SetupTarget.cmake index 7f8256465a54..0a15727ca69a 100644 --- a/cmake/HPX_SetupTarget.cmake +++ b/cmake/HPX_SetupTarget.cmake @@ -1,5 +1,5 @@ # Copyright (c) 2014 Thomas Heller -# Copyright (c) 2007-2018 Hartmut Kaiser +# Copyright (c) 2007-2023 Hartmut Kaiser # Copyright (c) 2011 Bryce Lelbach # # SPDX-License-Identifier: BSL-1.0 diff --git a/cmake/tests/cxx20_std_bit_cast.cpp b/cmake/tests/cxx20_std_bit_cast.cpp new file mode 100644 index 000000000000..5a79e6d1568f --- /dev/null +++ b/cmake/tests/cxx20_std_bit_cast.cpp @@ -0,0 +1,18 @@ +// 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) + +// Test if std::bit_cast is available + +#include +#include + +int main() +{ + float a = 42.0; + std::uint32_t i = std::bit_cast(a); + (void) i; + return 0; +} diff --git a/components/component_storage/CMakeLists.txt b/components/component_storage/CMakeLists.txt index 328bf511721d..69dfa7eb293f 100644 --- a/components/component_storage/CMakeLists.txt +++ b/components/component_storage/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2015 Hartmut Kaiser +# Copyright (c) 2015-2023 Hartmut Kaiser # # SPDX-License-Identifier: BSL-1.0 # Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -32,6 +32,7 @@ add_hpx_component( component_storage INTERNAL_FLAGS FOLDER "Core/Components/IO" INSTALL_HEADERS PREPEND_HEADER_ROOT + INSTALL_COMPONENT runtime HEADER_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/include HEADERS ${component_storage_headers} PREPEND_SOURCE_ROOT diff --git a/components/containers/partitioned_vector/CMakeLists.txt b/components/containers/partitioned_vector/CMakeLists.txt index a17a3b40cba6..c0aa1f2433fc 100644 --- a/components/containers/partitioned_vector/CMakeLists.txt +++ b/components/containers/partitioned_vector/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2017 Hartmut Kaiser +# Copyright (c) 2015-2023 Hartmut Kaiser # # SPDX-License-Identifier: BSL-1.0 # Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -45,7 +45,8 @@ set(partitioned_vector_sources add_hpx_component( partitioned_vector INTERNAL_FLAGS FOLDER "Core/Components/Containers" - INSTALL_HEADERS PREPEND_HEADER_ROOT + PREPEND_HEADER_ROOT INSTALL_HEADERS + INSTALL_COMPONENT runtime HEADER_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/include" HEADERS ${partitioned_vector_headers} PREPEND_SOURCE_ROOT diff --git a/components/containers/unordered/CMakeLists.txt b/components/containers/unordered/CMakeLists.txt index 39d15eec094a..333b5702d41b 100644 --- a/components/containers/unordered/CMakeLists.txt +++ b/components/containers/unordered/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2015 Hartmut Kaiser +# Copyright (c) 2015-2023 Hartmut Kaiser # # SPDX-License-Identifier: BSL-1.0 # Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -25,7 +25,8 @@ set(unordered_sources partition_unordered_map_component.cpp) add_hpx_component( unordered INTERNAL_FLAGS FOLDER "Core/Components/Containers" - INSTALL_HEADERS PREPEND_HEADER_ROOT + PREPEND_HEADER_ROOT INSTALL_HEADERS + INSTALL_COMPONENT runtime HEADER_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/include" HEADERS ${unordered_headers} PREPEND_SOURCE_ROOT diff --git a/components/iostreams/CMakeLists.txt b/components/iostreams/CMakeLists.txt index 790cecfa8cfd..cf366aa13dc3 100644 --- a/components/iostreams/CMakeLists.txt +++ b/components/iostreams/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2007-2012 Hartmut Kaiser +# Copyright (c) 2007-2023 Hartmut Kaiser # Copyright (c) 2011 Bryce Lelbach # # SPDX-License-Identifier: BSL-1.0 @@ -35,6 +35,7 @@ add_hpx_component( iostreams INTERNAL_FLAGS FOLDER "Core/Components/IO" INSTALL_HEADERS PREPEND_HEADER_ROOT + INSTALL_COMPONENT runtime HEADER_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/include" HEADERS ${iostreams_headers} PREPEND_SOURCE_ROOT diff --git a/components/performance_counters/io/CMakeLists.txt b/components/performance_counters/io/CMakeLists.txt index 4f674df41ac1..623a0ff03b9c 100644 --- a/components/performance_counters/io/CMakeLists.txt +++ b/components/performance_counters/io/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2007-2016 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 @@ -20,6 +20,7 @@ if(HPX_WITH_IO_COUNTERS) io_counters INTERNAL_FLAGS FOLDER "Core/Components/Counters" INSTALL_HEADERS PLUGIN PREPEND_HEADER_ROOT + INSTALL_COMPONENT runtime HEADER_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/include" HEADERS ${io_counters_headers} PREPEND_SOURCE_ROOT diff --git a/components/performance_counters/memory_counters/CMakeLists.txt b/components/performance_counters/memory_counters/CMakeLists.txt index 7f2262e23861..ffd466045ec7 100644 --- a/components/performance_counters/memory_counters/CMakeLists.txt +++ b/components/performance_counters/memory_counters/CMakeLists.txt @@ -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 @@ -30,6 +30,7 @@ add_hpx_component( memory_counters INTERNAL_FLAGS FOLDER "Core/Components/Counters" INSTALL_HEADERS PLUGIN PREPEND_HEADER_ROOT + INSTALL_COMPONENT runtime HEADER_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/include" HEADERS ${memory_headers} PREPEND_SOURCE_ROOT diff --git a/components/performance_counters/papi/CMakeLists.txt b/components/performance_counters/papi/CMakeLists.txt index 851a8c166cbb..72641541976a 100644 --- a/components/performance_counters/papi/CMakeLists.txt +++ b/components/performance_counters/papi/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2007-2012 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 @@ -21,6 +21,7 @@ if(HPX_WITH_PAPI) papi_counters INTERNAL_FLAGS FOLDER "Core/Components/Counters" INSTALL_HEADERS PLUGIN PREPEND_HEADER_ROOT + INSTALL_COMPONENT runtime HEADER_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/include" HEADERS ${papi_counters_headers} PREPEND_SOURCE_ROOT diff --git a/components/performance_counters/power/CMakeLists.txt b/components/performance_counters/power/CMakeLists.txt index 73778baeaa58..fe96fd48ea76 100644 --- a/components/performance_counters/power/CMakeLists.txt +++ b/components/performance_counters/power/CMakeLists.txt @@ -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 @@ -47,6 +47,7 @@ add_hpx_component( power INTERNAL_FLAGS FOLDER "Core/Components/Counters" INSTALL_HEADERS PLUGIN PREPEND_HEADER_ROOT + INSTALL_COMPONENT runtime HEADER_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/include" HEADERS ${power_headers} PREPEND_SOURCE_ROOT diff --git a/components/process/CMakeLists.txt b/components/process/CMakeLists.txt index 56d69125567f..cfb793fcc83f 100644 --- a/components/process/CMakeLists.txt +++ b/components/process/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2007-2016 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 @@ -113,6 +113,7 @@ add_hpx_component( process INTERNAL_FLAGS FOLDER "Core/Components/Process" INSTALL_HEADERS PREPEND_HEADER_ROOT + INSTALL_COMPONENT runtime HEADER_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/include" HEADERS ${process_headers} PREPEND_SOURCE_ROOT diff --git a/docs/sphinx/manual/writing_single_node_hpx_applications.rst b/docs/sphinx/manual/writing_single_node_hpx_applications.rst index 8f859689ef74..b48b66a38a06 100644 --- a/docs/sphinx/manual/writing_single_node_hpx_applications.rst +++ b/docs/sphinx/manual/writing_single_node_hpx_applications.rst @@ -137,9 +137,21 @@ is released. The code below shows the basic use of mutexes: :start-after: //[mutex_docs :end-before: //] -In this example, two |hpx| threads created using ``hpx::async`` are acquiring a ``hpx::mutex m``. The ``m.lock()`` -function is called before accessing the shared resource, and ``m.unlock()`` is called after the access is complete. -This ensures that only one thread can access the shared resource at a time. +In this example, two |hpx| threads created using ``hpx::async`` are acquiring a ``hpx::mutex m``. +``std::scoped_lock sl(m)`` is used to take ownership of the given mutex ``m``. When control leaves +the scope in which the ``scoped_lock`` object was created, the ``scoped_lock`` is destructed and +the mutex is released. + +.. attention:: + + A common way to acquire and release mutexes is by using the function ``m.lock()`` before accessing + the shared resource, and ``m.unlock()`` called after the access is complete. However, these functions + may lead to deadlocks in case of exception(s). That is, if an exception happens when the mutex is locked + then the code that unlocks the mutex will never be executed, the lock will remain held by the thread + that acquired it, and other threads will be unable to access the shared resource. This can cause a + deadlock if the other threads are also waiting to acquire the same lock. For this reason, we suggest + you use ``std::scoped_lock``, which prevents this issue by releasing the lock when control leaves the + scope in which the ``scoped_lock`` object was created. .. _shared_mutex: @@ -175,9 +187,9 @@ Both the writer and reader threads use the ``hpx::shared_mutex`` object ``stm`` resource. * For the writer threads, a ``unique_lock`` on the shared mutex is acquired before each write operation and is released - after the operation is complete. + after control leaves the scope in which the ``unique_lock`` object was created. * For the reader threads, a ``shared_lock`` on the shared mutex is acquired before each read operation and is released - after the operation is complete. + after control leaves the scope in which the ``shared_lock`` object was created. Before each operation, both the reader and writer threads sleep for a random time period, which is generated using a random number generator. The random time period simulates the processing time of the operation. @@ -196,7 +208,7 @@ access to a shared resource. The two types of semaphores are: the counter by releasing the semaphore. Unlike ``hpx::mutex``, an ``hpx::counting_semaphore`` is not bound to a thread, which means that the acquire and release call of a semaphore can happen on different threads. * binary semaphore: it is an alias for a ``hpx::counting_semaphore<1>``. In this case, the least maximal value - is 1. ``hpx::binary_semaphores`` can be used to implement locks. + is 1. ``hpx::binary_semaphore`` can be used to implement locks. .. literalinclude:: ../../examples/quickstart/counting_semaphore_docs.cpp :language: c++ @@ -232,8 +244,8 @@ To call an application with a single guard, simply declare the guard and call If a single method needs to run with multiple guards, use a guard set:: - boost::shared gu1(new hpx::lcos::local::guard()); - boost::shared gu2(new hpx::lcos::local::guard()); + std::shared_ptr gu1(new hpx::lcos::local::guard()); + std::shared_ptr gu2(new hpx::lcos::local::guard()); gs.add(*gu1); gs.add(*gu2); run_guarded(gs,task); @@ -641,8 +653,8 @@ the ``wait()`` method to synchronize the tasks and wait for them to complete. .. note:: - `task groups` and `task blocks`` are both ways to group and synchronize parallel tasks, but - `task groups`` are used to group multiple tasks together as a single unit, while `task blocks`` + `task groups` and `task blocks` are both ways to group and synchronize parallel tasks, but + `task groups` are used to group multiple tasks together as a single unit, while `task blocks` are used to execute a loop in parallel, with each iteration of the loop executing in a separate task. If the difference is not clear yet, continue reading. @@ -667,7 +679,7 @@ such as futures or shared data structures. The example below demonstrates how to launch multiple threads and synchronize them using a ``hpx::latch`` object. It also shows how to query the state of threads and wait for futures to complete. -.. literalinclude:: ../../examples/quickstart/task_group_docs.cpp +.. literalinclude:: ../../examples/quickstart/enumerate_threads.cpp :language: c++ :start-after: //[threads_docs :end-before: //] @@ -717,25 +729,8 @@ C++ Extensions for Parallelism), |cpp17_n4755|_ (Task Blocks), and Using parallel algorithms ------------------------- -.. |sequenced_execution_policy| replace:: :cpp:class:`hpx::execution::sequenced_policy` -.. |sequenced_task_execution_policy| replace:: :cpp:class:`hpx::execution::sequenced_task_policy` -.. |parallel_execution_policy| replace:: :cpp:class:`hpx::execution::parallel_policy` -.. |parallel_unsequenced_execution_policy| replace:: :cpp:class:`hpx::execution::parallel_unsequenced_policy` -.. |parallel_task_execution_policy| replace:: :cpp:class:`hpx::execution::parallel_task_policy` -.. |execution_policy| replace:: :cpp:class:`hpx::parallel::execution_policy` -.. |exception_list| replace:: :cpp:class:`hpx::exception_list` -.. |for_each| replace:: :cpp:class:`hpx::for_each` - -A parallel algorithm is a function template described by this document -which is declared in the (inline) namespace ``hpx::parallel``. - -.. note:: - - For compilers that do not support inline namespaces, all of the ``namespace - v1`` is imported into the namespace ``hpx::parallel``. The effect is similar - to what inline namespaces would do, namely all names defined in - ``hpx::parallel`` are accessible from the namespace ``hpx::parallel`` as - well. +A parallel algorithm is a function template declared in the namespace +``hpx::parallel``. All parallel algorithms are very similar in semantics to their sequential counterparts (as defined in the ``namespace std``) with an additional formal @@ -745,13 +740,13 @@ manner in which the execution of these algorithms may be parallelized and the manner in which they apply user-provided function objects. The applications of function objects in parallel algorithms invoked with an -execution policy object of type |sequenced_execution_policy| or -|sequenced_task_execution_policy| execute in sequential order. For -|sequenced_execution_policy| the execution happens in the calling thread. +execution policy object of type :cpp:class:`hpx::execution::sequenced_policy` or +:cpp:class:`hpx::execution::sequenced_task_policy` execute in sequential order. For +:cpp:class:`hpx::execution::sequenced_policy` the execution happens in the calling thread. The applications of function objects in parallel algorithms invoked with an -execution policy object of type |parallel_execution_policy| or -|parallel_task_execution_policy| are permitted to execute in an unordered +execution policy object of type :cpp:class:`hpx::execution::parallel_policy` or +:cpp:class:`hpx::execution::parallel_task_policy` are permitted to execute in an unordered fashion in unspecified threads, and are indeterminately sequenced within each thread. @@ -760,18 +755,22 @@ thread. It is the caller's responsibility to ensure correctness, such as making sure that the invocation does not introduce data races or deadlocks. -The applications of function objects in parallel algorithms invoked with an -execution policy of type |parallel_unsequenced_execution_policy| is, in |hpx|, -equivalent to the use of the execution policy |parallel_execution_policy|. - -Algorithms invoked with an execution policy object of type |execution_policy| -execute internally as if invoked with the contained execution policy object. No -exception is thrown when an |execution_policy| contains an execution policy of -type |sequenced_task_execution_policy| or |parallel_task_execution_policy| -(which normally turn the algorithm into its asynchronous version). In this case -the execution is semantically equivalent to the case of passing a -|sequenced_execution_policy| or |parallel_execution_policy| contained in the -|execution_policy| object respectively. +The example below demonstrates how to perform a sequential and parallel :cpp:func:`hpx::for_each` \ +loop on a vector of integers. + +.. literalinclude:: ../../examples/quickstart/for_each_docs.cpp + :language: c++ + :start-after: //[for_each_docs + :end-before: //] + +The above code uses ``hpx::for_each`` to print the elements of the vector ``v{1, 2, 3, 4, 5}``. +At first, ``hpx::for_each()`` is called without an execution policy, which means that it applies +the lambda function ``print`` to each element in the vector sequentially. Hence, the elements are +printed in order. + +Next, ``hpx::for_each()`` is called with the ``hpx::execution::par`` execution policy, +which applies the lambda function ``print`` to each element in the vector in parallel. Therefore, +the output order of the elements in the vector is not deterministic and may vary from run to run. Parallel exceptions ------------------- @@ -786,18 +785,18 @@ program is determined by the type of execution policy used to invoke the algorithm: * If the execution policy object is of type - |parallel_unsequenced_execution_policy|, :cpp:func:`hpx::terminate` shall + :cpp:class:`hpx::execution::parallel_unsequenced_policy`, :cpp:func:`hpx::terminate` shall be called. -* If the execution policy object is of type |sequenced_execution_policy|, - |sequenced_task_execution_policy|, |parallel_execution_policy|, or - |parallel_task_execution_policy|, the execution of the algorithm terminates - with an |exception_list| exception. All uncaught exceptions thrown during the +* If the execution policy object is of type :cpp:class:`hpx::execution::sequenced_policy`, + :cpp:class:`hpx::execution::sequenced_task_policy`, :cpp:class:`hpx::execution::parallel_policy`, or + :cpp:class:`hpx::execution::parallel_task_policy`, the execution of the algorithm terminates + with an :cpp:class:`hpx::exception_list` exception. All uncaught exceptions thrown during the application of user-provided function objects shall be contained in the - |exception_list|. + :cpp:class:`hpx::exception_list`. For example, the number of invocations of the user-provided function object in -for_each is unspecified. When |for_each| is executed sequentially, only one -exception will be contained in the |exception_list| object. +for_each is unspecified. When :cpp:class:`hpx::for_each` is executed sequentially, only one +exception will be contained in the :cpp:class:`hpx::exception_list` object. These guarantees imply that, unless the algorithm has failed to allocate memory and terminated with ``std::bad_alloc``, all exceptions thrown during the @@ -808,7 +807,7 @@ capturing a user exception. The algorithm may terminate with the ``std::bad_alloc`` exception even if one or more user-provided function objects have terminated with an exception. For example, this can happen when an algorithm fails to allocate memory while -creating or adding elements to the |exception_list| object. +creating or adding elements to the :cpp:class:`hpx::exception_list` object. Parallel algorithms ------------------- @@ -876,6 +875,8 @@ Parallel algorithms * Searches for a number consecutive copies of an element in a range. * :cppreference-algorithm:`search_n` +| + .. list-table:: Modifying parallel algorithms of header :ref:`public_api_header_hpx_algorithm` :widths: 25 55 20 @@ -968,6 +969,8 @@ Parallel algorithms * Copies the elements from one range to another in such a way that there are no consecutive equal elements. * :cppreference-algorithm:`unique_copy` +| + .. list-table:: Set operations on sorted sequences of header :ref:`public_api_header_hpx_algorithm` :widths: 25 55 20 @@ -996,6 +999,8 @@ Parallel algorithms * Computes the union of two sets. * :cppreference-algorithm:`set_union` +| + .. list-table:: Heap operations of header :ref:`public_api_header_hpx_algorithm` :widths: 25 55 20 @@ -1012,6 +1017,8 @@ Parallel algorithms * Constructs a max heap in the range [first, last). * :cppreference-algorithm:`make_heap` +| + .. list-table:: Minimum/maximum operations of header :ref:`public_api_header_hpx_algorithm` :widths: 25 55 20 @@ -1028,6 +1035,8 @@ Parallel algorithms * Returns the smallest and the largest element in a range. * :cppreference-algorithm:`minmax_element` +| + .. list-table:: Partitioning Operations of header :ref:`public_api_header_hpx_algorithm` :widths: 25 55 20 @@ -1050,6 +1059,8 @@ Parallel algorithms * Divides elements into two groups while preserving their relative order. * :cppreference-algorithm:`stable_partition` +| + .. list-table:: Sorting Operations of header :ref:`public_api_header_hpx_algorithm` :widths: 25 55 20 @@ -1078,6 +1089,8 @@ Parallel algorithms * Sorts one range of data using keys supplied in another range. * +| + .. list-table:: Numeric Parallel Algorithms of header :ref:`public_api_header_hpx_numeric` :widths: 25 55 20 @@ -1106,6 +1119,7 @@ Parallel algorithms * Sums up a range of elements after applying a function. Also, accumulates the inner products of two input ranges. * :cppreference-algorithm:`transform_reduce` +| .. list-table:: Dynamic Memory Management of header :ref:`public_api_header_hpx_memory` :widths: 25 55 20 @@ -1150,6 +1164,8 @@ Parallel algorithms * Constructs objects in an uninitialized area of memory. * :cppreference-memory:`uninitialized_value_construct_n` +| + .. list-table:: Index-based for-loops of header :ref:`public_api_header_hpx_algorithm` * * Name @@ -1195,8 +1211,9 @@ number of cores ``num_cores`` and tasks to schedule is given by ``num_tasks``. The lambda function exposes a means of test-probing the execution of a single iteration for performance measurement purposes. The execution parameter type might dynamically determine the execution time of one or more tasks in order -to calculate the chunk size; see :cpp:class:`hpx::execution::auto_chunk_size` -for an example of this executor parameter type. +to calculate the chunk size; see +:cpp:class:`hpx::execution::experimental::auto_chunk_size` for an example of +this executor parameter type. Other functions in the interface exist to discover whether an executor parameter type should be invoked once (i.e., it returns a static chunk size; see diff --git a/examples/accumulators/CMakeLists.txt b/examples/accumulators/CMakeLists.txt index b9018e4f2f23..6123c0217a20 100644 --- a/examples/accumulators/CMakeLists.txt +++ b/examples/accumulators/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2007-2016 Hartmut Kaiser +# Copyright (c) 2007-2023 Hartmut Kaiser # Copyright (c) 2011 Bryce Lelbach # # SPDX-License-Identifier: BSL-1.0 @@ -26,6 +26,7 @@ foreach(example_program ${example_programs}) # add example components add_hpx_component( ${example_program} INTERNAL_FLAGS NOEXPORT + INSTALL_COMPONENT examples SOURCES ${component_sources} HEADERS ${component_headers} FOLDER "Examples/Quickstart/Accumulators/${example_program}" diff --git a/examples/cancelable_action/cancelable_action/CMakeLists.txt b/examples/cancelable_action/cancelable_action/CMakeLists.txt index 4218c74206f0..bec12e4e6859 100644 --- a/examples/cancelable_action/cancelable_action/CMakeLists.txt +++ b/examples/cancelable_action/cancelable_action/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2007-2012 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 @@ -6,6 +6,7 @@ add_hpx_component( cancelable_action INTERNAL_FLAGS NOEXPORT AUTOGLOB + INSTALL_COMPONENT examples HEADER_GLOB "cancelable_action.h*" SOURCE_GLOB "cancelable_action.c*" FOLDER "Examples/CancelableAction" diff --git a/examples/interpolate1d/interpolate1d/CMakeLists.txt b/examples/interpolate1d/interpolate1d/CMakeLists.txt index cb1daf22a5a5..81a1076b5ed5 100644 --- a/examples/interpolate1d/interpolate1d/CMakeLists.txt +++ b/examples/interpolate1d/interpolate1d/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2007-2017 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 @@ -6,6 +6,7 @@ add_hpx_component( interpolate1d INTERNAL_FLAGS + INSTALL_COMPONENT examples FOLDER "Examples/Interpolate1D" AUTOGLOB ) diff --git a/examples/jacobi/jacobi_component/CMakeLists.txt b/examples/jacobi/jacobi_component/CMakeLists.txt index 8640b298b553..9ded29027a6f 100644 --- a/examples/jacobi/jacobi_component/CMakeLists.txt +++ b/examples/jacobi/jacobi_component/CMakeLists.txt @@ -6,6 +6,7 @@ add_hpx_component( jacobi INTERNAL_FLAGS NOEXPORT AUTOGLOB + INSTALL_COMPONENT examples SOURCE_GLOB "*.c*" HEADER_GLOB "*.h*" ${jacobi_component_FLAGS} FOLDER "Examples/Jacobi" diff --git a/examples/nqueen/CMakeLists.txt b/examples/nqueen/CMakeLists.txt index 8cb0d3a6c606..16b39ac4bcba 100644 --- a/examples/nqueen/CMakeLists.txt +++ b/examples/nqueen/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2007-2009 Hartmut Kaiser +# Copyright (c) 2007-2023 Hartmut Kaiser # Copyright (c) 2011 Bryce Lelbach # Copyright (c) 2011 Vinay C Amatya # @@ -12,6 +12,7 @@ endif() add_hpx_component( nqueen INTERNAL_FLAGS NOEXPORT + INSTALL_COMPONENT examples SOURCE_GLOB "nqueen.cp*" HEADER_GLOB "nqueen.hp*" FOLDER "Examples/Applications/NQueen" diff --git a/examples/performance_counters/sine/CMakeLists.txt b/examples/performance_counters/sine/CMakeLists.txt index bc5098179377..04b1c22203a4 100644 --- a/examples/performance_counters/sine/CMakeLists.txt +++ b/examples/performance_counters/sine/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2007-2012 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 @@ -10,6 +10,7 @@ set(root "${PROJECT_SOURCE_DIR}/examples/performance_counters/sine") # add component add_hpx_component( sine INTERNAL_FLAGS NOEXPORT + INSTALL_COMPONENT examples FOLDER "Examples/PerformanceCounters/Sine" HEADER_GLOB "${root}/*.h*" SOURCE_GLOB "${root}/sine.c*" diff --git a/examples/quickstart/CMakeLists.txt b/examples/quickstart/CMakeLists.txt index 67a4e0b7d91d..b86d8b748a98 100644 --- a/examples/quickstart/CMakeLists.txt +++ b/examples/quickstart/CMakeLists.txt @@ -18,6 +18,7 @@ set(example_programs fibonacci_futures fibonacci_local file_serialization + for_each_docs hello_world_3 latch_local local_channel_docs diff --git a/examples/quickstart/for_each_docs.cpp b/examples/quickstart/for_each_docs.cpp new file mode 100644 index 000000000000..9e1c76512704 --- /dev/null +++ b/examples/quickstart/for_each_docs.cpp @@ -0,0 +1,38 @@ +// Copyright (c) 2023 Dimitra Karatza +// +// 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) + +// This example is meant for inclusion in the documentation. + +//[for_each_docs +#include +#include +#include + +#include +#include + +int hpx_main() +{ + std::vector v{1, 2, 3, 4, 5}; + + auto print = [](const int& n) { std::cout << n << ' '; }; + + std::cout << "Print sequential: "; + hpx::for_each(v.begin(), v.end(), print); + std::cout << '\n'; + + std::cout << "Print parallel: "; + hpx::for_each(hpx::execution::par, v.begin(), v.end(), print); + std::cout << '\n'; + + return hpx::local::finalize(); +} + +int main(int argc, char* argv[]) +{ + return hpx::local::init(hpx_main, argc, argv); +} +//] diff --git a/examples/quickstart/mutex_docs.cpp b/examples/quickstart/mutex_docs.cpp index a9dfc268a327..34e6d315b71f 100644 --- a/examples/quickstart/mutex_docs.cpp +++ b/examples/quickstart/mutex_docs.cpp @@ -18,15 +18,13 @@ int hpx_main() hpx::mutex m; hpx::future f1 = hpx::async([&m]() { - m.lock(); + std::scoped_lock sl(m); std::cout << "Thread 1 acquired the mutex" << std::endl; - m.unlock(); }); hpx::future f2 = hpx::async([&m]() { - m.lock(); + std::scoped_lock sl(m); std::cout << "Thread 2 acquired the mutex" << std::endl; - m.unlock(); }); hpx::wait_all(f1, f2); diff --git a/examples/quickstart/shared_mutex.cpp b/examples/quickstart/shared_mutex.cpp index caefd8ed85af..55cb9f4d51dd 100644 --- a/examples/quickstart/shared_mutex.cpp +++ b/examples/quickstart/shared_mutex.cpp @@ -49,13 +49,16 @@ int hpx_main() for (int j = 0; j < cycles; ++j) { - std::unique_lock ul(stm); + // scope of unique_lock + { + std::unique_lock ul(stm); - std::cout << "^^^ Writer " << i << " starting..." << std::endl; - hpx::this_thread::sleep_for(milliseconds(dist(urng))); - std::cout << "vvv Writer " << i << " finished." << std::endl; - - ul.unlock(); + std::cout << "^^^ Writer " << i << " starting..." + << std::endl; + hpx::this_thread::sleep_for(milliseconds(dist(urng))); + std::cout << "vvv Writer " << i << " finished." + << std::endl; + } hpx::this_thread::sleep_for(milliseconds(dist(urng))); } @@ -76,14 +79,14 @@ int hpx_main() for (int j = 0; j < cycles; ++j) { - std::shared_lock sl(stm); - - std::cout << "Reader " << i << " starting..." << std::endl; - hpx::this_thread::sleep_for(milliseconds(dist(urng))); - std::cout << "Reader " << i << " finished." << std::endl; - - sl.unlock(); - + // scope of shared_lock + { + std::shared_lock sl(stm); + + std::cout << "Reader " << i << " starting..." << std::endl; + hpx::this_thread::sleep_for(milliseconds(dist(urng))); + std::cout << "Reader " << i << " finished." << std::endl; + } hpx::this_thread::sleep_for(milliseconds(dist(urng))); } }); diff --git a/examples/random_mem_access/random_mem_access/CMakeLists.txt b/examples/random_mem_access/random_mem_access/CMakeLists.txt index 8fe52d32f858..2101b000e06d 100644 --- a/examples/random_mem_access/random_mem_access/CMakeLists.txt +++ b/examples/random_mem_access/random_mem_access/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2007-2009 Hartmut Kaiser +# Copyright (c) 2007-2023 Hartmut Kaiser # Copyright (c) 2011 Matt Anderson # # SPDX-License-Identifier: BSL-1.0 @@ -24,6 +24,7 @@ source_group("Header Files\\Server" FILES ${server_headers}) # ############################################################################## add_hpx_component( random_mem_access INTERNAL_FLAGS NOEXPORT MODULE random_mem_access + INSTALL_COMPONENT examples SOURCES ${client_sources} HEADERS ${headers} FOLDER "Examples/RandomMemoryAccess/random_mem_access" diff --git a/examples/sheneos/sheneos/CMakeLists.txt b/examples/sheneos/sheneos/CMakeLists.txt index 4f12f93b4c44..1ec2e47d0295 100644 --- a/examples/sheneos/sheneos/CMakeLists.txt +++ b/examples/sheneos/sheneos/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2007-2017 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 @@ -6,6 +6,7 @@ add_hpx_component( sheneos + INSTALL_COMPONENT examples DEPENDENCIES ${HDF5_LIBRARIES} FOLDER "Examples/ShenEOS" AUTOGLOB diff --git a/examples/startup_shutdown/CMakeLists.txt b/examples/startup_shutdown/CMakeLists.txt index 0217893860ae..65e0ad11ebe1 100644 --- a/examples/startup_shutdown/CMakeLists.txt +++ b/examples/startup_shutdown/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2007-2012 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 @@ -10,6 +10,7 @@ endif() add_hpx_component( startup_shutdown INTERNAL_FLAGS NOEXPORT + INSTALL_COMPONENT examples FOLDER "Examples/StartupShutdown" AUTOGLOB ) diff --git a/examples/throttle/throttle/CMakeLists.txt b/examples/throttle/throttle/CMakeLists.txt index d27bfcd509a2..bef4aa0f72d9 100644 --- a/examples/throttle/throttle/CMakeLists.txt +++ b/examples/throttle/throttle/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2007-2012 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 @@ -28,6 +28,7 @@ source_group("Header Files\\Server" FILES ${server_headers}) # ############################################################################## add_hpx_component( throttle INTERNAL_FLAGS NOEXPORT + INSTALL_COMPONENT examples SOURCES ${client_sources} ${server_sources} HEADERS ${headers} FOLDER "Examples/Throttle" diff --git a/examples/tuplespace/central_tuplespace/CMakeLists.txt b/examples/tuplespace/central_tuplespace/CMakeLists.txt index eaa46755f642..d3a295fc4aef 100644 --- a/examples/tuplespace/central_tuplespace/CMakeLists.txt +++ b/examples/tuplespace/central_tuplespace/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2007-2009 Hartmut Kaiser +# Copyright (c) 2007-2023 Hartmut Kaiser # Copyright (c) 2011 Bryce Adelstein-Lelbach # # SPDX-License-Identifier: BSL-1.0 @@ -15,6 +15,7 @@ foreach(component ${components}) add_hpx_component( ${component} INTERNAL_FLAGS NOEXPORT AUTOGLOB + INSTALL_COMPONENT examples HEADER_GLOB "${component}.h*" SOURCE_GLOB "${component}.c*" FOLDER "Examples/TupleSpace/${component}" diff --git a/init/CMakeLists.txt b/init/CMakeLists.txt index 356df22f712f..159b6c356c1b 100644 --- a/init/CMakeLists.txt +++ b/init/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2007-2017 Hartmut Kaiser +# Copyright (c) 2007-2023 Hartmut Kaiser # Copyright (c) 2011 Bryce Lelbach # Copyright (c) 2018 Nikunj Gupta # @@ -83,15 +83,15 @@ endif() install( TARGETS hpx_init EXPORT HPXInternalTargets - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT runtime + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT hpx_init + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT hpx_init + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT hpx_init ) install( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} - COMPONENT runtime + COMPONENT core ) # install PDB if needed @@ -103,6 +103,7 @@ if(MSVC) FILES ${_pdb_dir}/${_pdb_file}.pdb DESTINATION ${CMAKE_INSTALL_LIBDIR} CONFIGURATIONS ${cfg} + COMPONENT runtime OPTIONAL ) endforeach() diff --git a/libs/CMakeLists.txt b/libs/CMakeLists.txt index d6b4cba26fcf..1791882be2e0 100644 --- a/libs/CMakeLists.txt +++ b/libs/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2007-2021 Hartmut Kaiser +# Copyright (c) 2007-2023 Hartmut Kaiser # Copyright (c) 2011 Bryce Lelbach # Copyright (c) 2018 Nikunj Gupta # Copyright (c) 2020 The STE||AR-Group @@ -218,25 +218,25 @@ target_compile_definitions( set(hpx_targets hpx wrap_main plugin component) set(hpx_internal_targets hpx_full hpx_interface hpx_interface_wrap_main) +# cmake-format: off install( TARGETS ${hpx_targets} EXPORT HPXTargets - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} - COMPONENT runtime + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT runtime + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT runtime + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT runtime ${_optional} ) install( TARGETS ${hpx_internal_targets} EXPORT HPXInternalTargets - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} - COMPONENT runtime + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT runtime + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT runtime + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT runtime ${_optional} ) +# cmake-format: on # install PDB if needed if(MSVC AND NOT HPX_WITH_STATIC_LINKING) @@ -244,6 +244,7 @@ if(MSVC AND NOT HPX_WITH_STATIC_LINKING) FILES $ DESTINATION ${CMAKE_INSTALL_BINDIR} CONFIGURATIONS Debug RelWithDebInfo + COMPONENT runtime OPTIONAL ) endif() @@ -319,11 +320,22 @@ foreach(lib ${HPX_LIBS}) install( TARGETS hpx_${lib} EXPORT HPXInternalTargets - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT ${lib} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT runtime + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT runtime + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT runtime ) + # install PDB if needed + if(MSVC AND NOT HPX_WITH_STATIC_LINKING) + install( + FILES $ + DESTINATION ${CMAKE_INSTALL_BINDIR} + CONFIGURATIONS Debug RelWithDebInfo + COMPONENT runtime + OPTIONAL + ) + endif() + hpx_export_internal_targets(hpx_${lib}) endif() diff --git a/libs/core/algorithms/include/hpx/parallel/algorithms/detail/set_operation.hpp b/libs/core/algorithms/include/hpx/parallel/algorithms/detail/set_operation.hpp index 17ce7810fcab..6ad845a27d70 100644 --- a/libs/core/algorithms/include/hpx/parallel/algorithms/detail/set_operation.hpp +++ b/libs/core/algorithms/include/hpx/parallel/algorithms/detail/set_operation.hpp @@ -74,11 +74,21 @@ namespace hpx::parallel::detail { struct set_chunk_data { - std::size_t start = static_cast(-1); - std::size_t len = static_cast(-1); - std::size_t start_index = static_cast(-1); - std::size_t first1 = static_cast(-1); - std::size_t first2 = static_cast(-1); + static constexpr std::size_t uninit_start = + static_cast(-1); + static constexpr std::size_t uninit_len = static_cast(0); + static constexpr std::size_t uninit_start_index = + static_cast(-1); + static constexpr std::size_t uninit_first1 = + static_cast(-1); + static constexpr std::size_t uninit_first2 = + static_cast(-1); + + std::size_t start = uninit_start; + std::size_t len = uninit_len; + std::size_t start_index = uninit_start_index; + std::size_t first1 = uninit_first1; + std::size_t first2 = uninit_first2; }; /////////////////////////////////////////////////////////////////////////// @@ -246,9 +256,10 @@ namespace hpx::parallel::detail { hpx::execution::par, chunks.get(), cores, [buffer, dest]( set_chunk_data* ch, std::size_t, std::size_t) { - if (ch->start == static_cast(-1) || - ch->start_index == static_cast(-1) || - ch->len == static_cast(-1)) + if (ch->start == set_chunk_data::uninit_start || + ch->start_index == + set_chunk_data::uninit_start_index || + ch->len == set_chunk_data::uninit_len) { return; } diff --git a/libs/core/algorithms/include/hpx/parallel/algorithms/make_heap.hpp b/libs/core/algorithms/include/hpx/parallel/algorithms/make_heap.hpp index 8f0c6bcc3afb..96c7771778b8 100644 --- a/libs/core/algorithms/include/hpx/parallel/algorithms/make_heap.hpp +++ b/libs/core/algorithms/include/hpx/parallel/algorithms/make_heap.hpp @@ -389,15 +389,37 @@ namespace hpx::parallel { try { - // Get workitems that are to be run in parallel + // parent of last node + // last node has index (n-1) + // parent of x is floor of (x-1)/2 std::size_t start = (n - 2) / 2; while (start > 0) { - // Index of start of level, and amount of items in level - std::size_t const end_exclusive = - static_cast( - std::pow(2, std::floor(std::log2(start)))) - - 2; + /* + helps find number of elements + in parent level of start + The following are indexes of + elements in the heap, not the + value of the elements + 0 + 1 2 + 3 4 5 6 + (size of heap) n = 7 + (parent of last element) start = 2 + end_exclusive => + last element index in + parent level of start + */ + std::size_t end_exclusive = static_cast( + std::pow(2, std::floor(std::log2(start)))); + if (end_exclusive >= 2) + { + end_exclusive -= static_cast(2); + } + else + { + end_exclusive = static_cast(0); + } std::size_t level_items = start - end_exclusive; // If we can't at least run two chunks in parallel, diff --git a/libs/core/algorithms/include/hpx/parallel/util/detail/chunk_size.hpp b/libs/core/algorithms/include/hpx/parallel/util/detail/chunk_size.hpp index 2247ad70001d..22836ce2de03 100644 --- a/libs/core/algorithms/include/hpx/parallel/util/detail/chunk_size.hpp +++ b/libs/core/algorithms/include/hpx/parallel/util/detail/chunk_size.hpp @@ -135,6 +135,12 @@ namespace hpx::parallel::util::detail { get_bulk_iteration_shape(ExPolicy&& policy, IterOrR& it_or_r, std::size_t& count, Stride s = Stride(1)) { + if (count == 0) + { + auto it = chunk_size_iterator(it_or_r, 1); + return hpx::util::iterator_range(it, it); + } + std::size_t const cores = execution::processing_units_count(policy.parameters(), policy.executor(), hpx::chrono::null_duration, count); @@ -172,6 +178,12 @@ namespace hpx::parallel::util::detail { get_bulk_iteration_shape(ExPolicy&& policy, std::vector& workitems, F1&& f1, IterOrR& it_or_r, std::size_t& count, Stride s = Stride(1)) { + if (count == 0) + { + auto it = chunk_size_iterator(it_or_r, 1); + return hpx::util::iterator_range(it, it); + } + Stride stride = parallel::detail::abs(s); auto test_function = [&](std::size_t test_chunk_size) -> std::size_t { @@ -242,6 +254,12 @@ namespace hpx::parallel::util::detail { std::size_t& count, Stride s = Stride(1)) { using tuple_type = hpx::tuple; + std::vector shape; + + if (count == 0) + { + return shape; + } std::size_t const cores = execution::processing_units_count(policy.parameters(), @@ -251,7 +269,6 @@ namespace hpx::parallel::util::detail { policy.parameters(), policy.executor(), cores, count); HPX_ASSERT(0 != max_chunks); - std::vector shape; Stride stride = parallel::detail::abs(s); // different versions of clang-format do different things @@ -346,6 +363,15 @@ namespace hpx::parallel::util::detail { get_bulk_iteration_shape_idx(ExPolicy&& policy, FwdIter begin, std::size_t count, Stride s = Stride(1)) { + using iterator = + parallel::util::detail::chunk_size_idx_iterator; + + if (count == 0) + { + auto it = iterator(begin, 1); + return hpx::util::iterator_range(it, it); + } + std::size_t const cores = execution::processing_units_count(policy.parameters(), policy.executor(), hpx::chrono::null_duration, count); @@ -371,9 +397,6 @@ namespace hpx::parallel::util::detail { // clang-format on } - using iterator = - parallel::util::detail::chunk_size_idx_iterator; - iterator shape_begin(begin, chunk_size, count, 0, 0); iterator shape_end(last, chunk_size, count, count, 0); @@ -388,6 +411,15 @@ namespace hpx::parallel::util::detail { std::vector& workitems, F1&& f1, FwdIter begin, std::size_t count, Stride s = Stride(1)) { + using iterator = + parallel::util::detail::chunk_size_idx_iterator; + + if (count == 0) + { + auto it = iterator(begin, 1); + return hpx::util::iterator_range(it, it); + } + Stride stride = parallel::detail::abs(s); std::size_t base_idx = 0; @@ -443,9 +475,6 @@ namespace hpx::parallel::util::detail { // clang-format on } - using iterator = - parallel::util::detail::chunk_size_idx_iterator; - iterator shape_begin(begin, chunk_size, count, 0, base_idx); iterator shape_end(last, chunk_size, count, count, base_idx); @@ -459,6 +488,12 @@ namespace hpx::parallel::util::detail { std::size_t count, Stride s = Stride(1)) { using tuple_type = hpx::tuple; + std::vector shape; + + if (count == 0) + { + return shape; + } std::size_t const cores = execution::processing_units_count(policy.parameters(), @@ -467,7 +502,6 @@ namespace hpx::parallel::util::detail { std::size_t max_chunks = execution::maximal_number_of_chunks( policy.parameters(), policy.executor(), cores, count); - std::vector shape; Stride stride = parallel::detail::abs(s); // different versions of clang-format do different things diff --git a/libs/core/algorithms/include/hpx/parallel/util/detail/chunk_size_iterator.hpp b/libs/core/algorithms/include/hpx/parallel/util/detail/chunk_size_iterator.hpp index 4b8c30bb9208..546cf5508536 100644 --- a/libs/core/algorithms/include/hpx/parallel/util/detail/chunk_size_iterator.hpp +++ b/libs/core/algorithms/include/hpx/parallel/util/detail/chunk_size_iterator.hpp @@ -130,7 +130,8 @@ namespace hpx::parallel::util::detail { HPX_HOST_DEVICE chunk_size_iterator(IterOrR it, std::size_t chunk_size, std::size_t count = 0, std::size_t current = 0) noexcept : data_(it, 0) - , chunk_size_((hpx::detail::min)(chunk_size, count)) + , chunk_size_( + (std::max)((std::min)(chunk_size, count), std::size_t(1))) , last_chunk_size_(get_last_chunk_size(count, chunk_size)) , count_(count) , current_(get_current(current, chunk_size)) @@ -352,7 +353,8 @@ namespace hpx::parallel::util::detail { std::size_t chunk_size, std::size_t count = 0, std::size_t current = 0, std::size_t base_idx = 0) : data_(it, 0, base_idx) - , chunk_size_((hpx::detail::min)(chunk_size, count)) + , chunk_size_( + (std::max)((std::min)(chunk_size, count), std::size_t(1))) , last_chunk_size_(get_last_chunk_size(count, chunk_size)) , count_(count) , current_(get_current(current, chunk_size)) diff --git a/libs/core/algorithms/tests/regressions/set_operations_3442.cpp b/libs/core/algorithms/tests/regressions/set_operations_3442.cpp index 565d64b57c18..a579d55679d9 100644 --- a/libs/core/algorithms/tests/regressions/set_operations_3442.cpp +++ b/libs/core/algorithms/tests/regressions/set_operations_3442.cpp @@ -9,70 +9,89 @@ #include #include +#include +#include +#include #include #include -void set_difference_small_test(int rounds) -{ - std::vector set_a{1, 2, 3, 4, 5}; - std::vector set_b{1, 2, 4}; - std::vector a_minus_b(2); +#ifdef HPX_WITH_CXX17_STD_EXECUTION_POLICES +#include +#endif - std::vector perfect(2); - std::set_difference(set_a.begin(), set_a.end(), set_b.begin(), set_b.end(), - perfect.begin()); +int seed = std::random_device{}(); +std::mt19937 gen(seed); - while (--rounds) +// returns random integer in range (rangeMin, rangeMax] +struct RandomIntInRange +{ + int rangeMin, rangeMax; + RandomIntInRange(int rangeMin, int rangeMax) + : rangeMin(rangeMin) + , rangeMax(rangeMax){}; + int operator()() { - hpx::set_difference(hpx::execution::par, set_a.begin(), set_a.end(), - set_b.begin(), set_b.end(), a_minus_b.begin()); - HPX_TEST(perfect == a_minus_b); + return (static_cast(gen()) % (rangeMax - rangeMin + 1)) + rangeMin; } -} +}; -void set_difference_medium_test(int rounds) +void set_difference_randomized(int rounds, int maxLen) { - std::vector set_a(50); - std::vector set_b(20); - - std::iota(set_a.begin(), set_a.end(), 1); - std::iota(set_b.begin(), set_b.end(), 2); - - std::vector a_minus_b(50); - - std::vector perfect(50); - std::set_difference(set_a.begin(), set_a.end(), set_b.begin(), set_b.end(), - perfect.begin()); - - while (--rounds) + while (rounds--) { + std::size_t len_a = gen() % maxLen, len_b = gen() % maxLen; + std::vector set_a(len_a), set_b(len_b); + + std::size_t rangeMin = 0; + // rangeMax is set to increase probability of common elements + std::size_t rangeMax = (std::min)(len_a, len_b) * 2; + +#ifdef HPX_WITH_CXX17_STD_EXECUTION_POLICES + std::generate(std::execution::par_unseq, set_a.begin(), set_a.end(), + RandomIntInRange(rangeMin, rangeMax)); + std::generate(std::execution::par_unseq, set_b.begin(), set_b.end(), + RandomIntInRange(rangeMin, rangeMax)); +#else + std::generate( + set_a.begin(), set_a.end(), RandomIntInRange(rangeMin, rangeMax)); + std::generate( + set_b.begin(), set_b.end(), RandomIntInRange(rangeMin, rangeMax)); +#endif + std::sort(set_a.begin(), set_a.end()); + std::sort(set_b.begin(), set_b.end()); + + len_a = std::unique(set_a.begin(), set_a.end()) - set_a.begin(); + len_b = std::unique(set_b.begin(), set_b.end()) - set_b.begin(); + + set_a.resize(len_a); + set_b.resize(len_b); + + // rand always gives non negative values, rangeMin >= 0 + std::vector perfect((std::max)(len_a, len_b), -1); + std::vector a_minus_b((std::max)(len_a, len_b), -1); + + std::set_difference(set_a.begin(), set_a.end(), set_b.begin(), + set_b.end(), perfect.begin()); + hpx::set_difference(hpx::execution::par, set_a.begin(), set_a.end(), set_b.begin(), set_b.end(), a_minus_b.begin()); HPX_TEST(perfect == a_minus_b); } } -void set_difference_large_test(int rounds) +void set_difference_small_test(int rounds) { - std::vector set_a(5000000); - std::vector set_b(3000000); - - std::iota(set_a.begin(), set_a.end(), 1); - std::fill(set_b.begin(), set_b.begin() + 1000000, 1); - std::iota(set_b.begin() + 1000000, set_b.end(), 2); - - std::vector a_minus_b(5000000); + set_difference_randomized(rounds, 1 << 3); +} - std::vector perfect(5000000); - std::set_difference(set_a.begin(), set_a.end(), set_b.begin(), set_b.end(), - perfect.begin()); +void set_difference_medium_test(int rounds) +{ + set_difference_randomized(rounds, 1 << 10); +} - while (--rounds) - { - hpx::set_difference(hpx::execution::par, set_a.begin(), set_a.end(), - set_b.begin(), set_b.end(), a_minus_b.begin()); - HPX_TEST(perfect == a_minus_b); - } +void set_difference_large_test(int rounds) +{ + set_difference_randomized(rounds, 1 << 20); } void set_difference_test(int rounds) @@ -82,7 +101,7 @@ void set_difference_test(int rounds) set_difference_large_test(rounds); } -void set_intersection_small_test(int rounds) +void set_intersection_small_test1(int rounds) { std::vector set_a{1, 2, 3, 4, 5}; std::vector set_b{1, 2, 7}; @@ -100,6 +119,24 @@ void set_intersection_small_test(int rounds) } } +void set_intersection_small_test2(int rounds) +{ + std::vector set_a{-1, 1, 2, 3, 4, 5}; + std::vector set_b{0, 1, 2, 3, 8, 10}; + std::vector a_and_b(3); + + std::vector perfect(3); + std::set_intersection(set_a.begin(), set_a.end(), set_b.begin(), + set_b.end(), perfect.begin()); + + while (--rounds) + { + hpx::set_intersection(hpx::execution::par, set_a.begin(), set_a.end(), + set_b.begin(), set_b.end(), a_and_b.begin()); + HPX_TEST(perfect == a_and_b); + } +} + void set_intersection_medium_test(int rounds) { std::vector set_a(50); @@ -147,7 +184,8 @@ void set_intersection_large_test(int rounds) void set_intersection_test(int rounds) { - set_intersection_small_test(rounds); + set_intersection_small_test1(rounds); + set_intersection_small_test2(rounds); set_intersection_medium_test(rounds); set_intersection_large_test(rounds); } diff --git a/libs/core/algorithms/tests/unit/algorithms/foreach_sender.cpp b/libs/core/algorithms/tests/unit/algorithms/foreach_sender.cpp index ad40d9a0fa48..8685e651edaa 100644 --- a/libs/core/algorithms/tests/unit/algorithms/foreach_sender.cpp +++ b/libs/core/algorithms/tests/unit/algorithms/foreach_sender.cpp @@ -32,7 +32,6 @@ void test_for_each_explicit_sender_direct( std::iota(std::begin(c), std::end(c), std::rand()); namespace ex = hpx::execution::experimental; - namespace tt = hpx::this_thread::experimental; auto f = [](std::size_t& v) { v = 42; }; diff --git a/libs/core/algorithms/tests/unit/algorithms/make_heap.cpp b/libs/core/algorithms/tests/unit/algorithms/make_heap.cpp index 85215c58f573..6feeff74165c 100644 --- a/libs/core/algorithms/tests/unit/algorithms/make_heap.cpp +++ b/libs/core/algorithms/tests/unit/algorithms/make_heap.cpp @@ -24,6 +24,26 @@ int seed = std::random_device{}(); std::mt19937 gen(seed); /////////////////////////////////////////////////////////////////////////// +template +void test_make_heap_small1(IteratorTag) +{ + typedef std::vector::iterator base_iterator; + typedef test::test_iterator iterator; + + std::size_t len = 0; + while (len < 15) + { + std::vector c(len); + std::iota(hpx::util::begin(c), hpx::util::end(c), gen()); + + hpx::make_heap( + iterator(hpx::util::begin(c)), iterator(hpx::util::end(c))); + + HPX_TEST_EQ(std::is_heap(hpx::util::begin(c), hpx::util::end(c)), true); + len++; + } +} + template void test_make_heap1(IteratorTag) { @@ -31,13 +51,36 @@ void test_make_heap1(IteratorTag) typedef test::test_iterator iterator; std::vector c(10007); - std::iota(hpx::util::begin(c), hpx::util::end(c), 0); + std::iota(hpx::util::begin(c), hpx::util::end(c), gen()); hpx::make_heap(iterator(hpx::util::begin(c)), iterator(hpx::util::end(c))); HPX_TEST_EQ(std::is_heap(hpx::util::begin(c), hpx::util::end(c)), true); } +template +void test_make_heap_small1(ExPolicy&& policy, IteratorTag) +{ + static_assert(hpx::is_execution_policy::value, + "hpx::is_execution_policy::value"); + + typedef std::vector::iterator base_iterator; + typedef test::test_iterator iterator; + + std::size_t len = 0; + while (len < 15) + { + std::vector c(len); + std::iota(hpx::util::begin(c), hpx::util::end(c), gen()); + + hpx::make_heap( + policy, iterator(hpx::util::begin(c)), iterator(hpx::util::end(c))); + + HPX_TEST_EQ(std::is_heap(hpx::util::begin(c), hpx::util::end(c)), true); + len++; + } +} + template void test_make_heap1(ExPolicy&& policy, IteratorTag) { @@ -78,11 +121,16 @@ void test_make_heap1() using namespace hpx::execution; test_make_heap1(IteratorTag()); + test_make_heap_small1(IteratorTag()); test_make_heap1(seq, IteratorTag()); test_make_heap1(par, IteratorTag()); test_make_heap1(par_unseq, IteratorTag()); + test_make_heap_small1(seq, IteratorTag()); + test_make_heap_small1(par, IteratorTag()); + test_make_heap_small1(par_unseq, IteratorTag()); + test_make_heap_async1(seq(task), IteratorTag()); test_make_heap_async1(par(task), IteratorTag()); } 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/async_base/include/hpx/async_base/post.hpp b/libs/core/async_base/include/hpx/async_base/post.hpp index 6cbb5956ed32..a824c2482cab 100644 --- a/libs/core/async_base/include/hpx/async_base/post.hpp +++ b/libs/core/async_base/include/hpx/async_base/post.hpp @@ -4,8 +4,38 @@ // 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) +/// \file async_base/post.hpp + #pragma once +#if defined(DOXYGEN) + +namespace hpx { + // clang-format off + + /// \brief Runs the function \c f asynchronously (potentially in a separate + /// thread which might be a part of a thread pool). This is done in + /// a fire-and-forget manner, meaning there is no return value or way + /// to synchronize with the function execution (it does not return an + /// \c hpx::future that would hold the result of that function call). + /// + /// \details \c hpx::post is particularly useful when synchronization mechanisms + /// as heavyweight as futures are not desired, and instead, more + /// lightweight mechanisms like latches or atomic variables are preferred. + /// Essentially, the post function enables the launch of a new thread + /// without the overhead of creating a future. + /// + /// \note \c hpx::post is similar to \c hpx::async but does not return a future. + /// This is why there is no way of finding out the result/failure of the + /// execution of this function. + /// + template + HPX_FORCEINLINE bool post(F&& f, Ts&&... ts); + // clang-format on +} // namespace hpx + +#else + #include #include @@ -20,7 +50,6 @@ namespace hpx::detail { } // namespace hpx::detail namespace hpx { - template HPX_FORCEINLINE bool post(F&& f, Ts&&... ts) { @@ -36,3 +65,5 @@ namespace hpx { HPX_FORWARD(F, f), HPX_FORWARD(Ts, ts)...); } } // namespace hpx + +#endif diff --git a/libs/core/batch_environments/include/hpx/batch_environments/batch_environment.hpp b/libs/core/batch_environments/include/hpx/batch_environments/batch_environment.hpp index 6786cb5a2fba..81a45b7c2633 100644 --- a/libs/core/batch_environments/include/hpx/batch_environments/batch_environment.hpp +++ b/libs/core/batch_environments/include/hpx/batch_environments/batch_environment.hpp @@ -12,7 +12,6 @@ #include #include -#include #include #include #include diff --git a/libs/core/batch_environments/include/hpx/batch_environments/pbs_environment.hpp b/libs/core/batch_environments/include/hpx/batch_environments/pbs_environment.hpp index 69f75f6e1ee3..2d37f0a503ed 100644 --- a/libs/core/batch_environments/include/hpx/batch_environments/pbs_environment.hpp +++ b/libs/core/batch_environments/include/hpx/batch_environments/pbs_environment.hpp @@ -49,6 +49,6 @@ namespace hpx::util::batch_environments { HPX_CORE_EXPORT void read_nodefile( std::vector& nodelist, bool have_mpi, bool debug); HPX_CORE_EXPORT void read_nodelist( - std::vector& nodelist, bool debug); + std::vector const& nodelist, bool debug); }; } // namespace hpx::util::batch_environments diff --git a/libs/core/batch_environments/src/alps_environment.cpp b/libs/core/batch_environments/src/alps_environment.cpp index 03bdd555f167..c70222e56d1b 100644 --- a/libs/core/batch_environments/src/alps_environment.cpp +++ b/libs/core/batch_environments/src/alps_environment.cpp @@ -21,7 +21,7 @@ namespace hpx::util::batch_environments { , num_localities_(0) , valid_(false) { - char* node_num = std::getenv("ALPS_APP_PE"); + char const* node_num = std::getenv("ALPS_APP_PE"); valid_ = node_num != nullptr; if (valid_) { @@ -29,7 +29,7 @@ namespace hpx::util::batch_environments { node_num_ = from_string(node_num); // Get the number of threads - char* num_threads = std::getenv("ALPS_APP_DEPTH"); + char const* num_threads = std::getenv("ALPS_APP_DEPTH"); if (!num_threads) { valid_ = false; @@ -38,7 +38,7 @@ namespace hpx::util::batch_environments { num_threads_ = from_string(num_threads); // Get the number of localities - char* total_num_threads = std::getenv("PBS_NP"); + char const* total_num_threads = std::getenv("PBS_NP"); if (!total_num_threads) { valid_ = false; diff --git a/libs/core/batch_environments/src/batch_environment.cpp b/libs/core/batch_environments/src/batch_environment.cpp index fceac2995180..f51c696858ca 100644 --- a/libs/core/batch_environments/src/batch_environment.cpp +++ b/libs/core/batch_environments/src/batch_environment.cpp @@ -30,9 +30,9 @@ namespace hpx::util { batch_environment::batch_environment(std::vector& nodelist, bool have_mpi, bool debug, bool enable) : agas_node_num_(0) - , node_num_(std::size_t(-1)) - , num_threads_(std::size_t(-1)) - , num_localities_(std::size_t(-1)) + , node_num_(static_cast(-1)) + , num_threads_(static_cast(-1)) + , num_localities_(static_cast(-1)) , debug_(debug) { if (!enable) @@ -45,6 +45,12 @@ namespace hpx::util { { } + onexit(onexit const&) = delete; + onexit(onexit&&) = delete; + + onexit& operator=(onexit const&) = delete; + onexit& operator=(onexit&&) = delete; + ~onexit() { if (env_.debug_) @@ -64,7 +70,7 @@ namespace hpx::util { onexit _(*this); - batch_environments::alps_environment alps_env(nodelist, debug); + batch_environments::alps_environment const alps_env(nodelist, debug); if (alps_env.valid()) { batch_name_ = "ALPS"; @@ -74,7 +80,8 @@ namespace hpx::util { return; } - batch_environments::pjm_environment pjm_env(nodelist, have_mpi, debug); + batch_environments::pjm_environment const pjm_env( + nodelist, have_mpi, debug); if (pjm_env.valid()) { batch_name_ = "PJM"; @@ -84,7 +91,7 @@ namespace hpx::util { return; } - batch_environments::slurm_environment slurm_env(nodelist, debug); + batch_environments::slurm_environment const slurm_env(nodelist, debug); if (slurm_env.valid()) { batch_name_ = "SLURM"; @@ -94,7 +101,8 @@ namespace hpx::util { return; } - batch_environments::pbs_environment pbs_env(nodelist, have_mpi, debug); + batch_environments::pbs_environment const pbs_env( + nodelist, have_mpi, debug); if (pbs_env.valid()) { batch_name_ = "PBS"; @@ -178,7 +186,7 @@ namespace hpx::util { } std::cerr << "Nodes from nodelist:" << std::endl; - node_map_type::const_iterator end = nodes_.end(); + node_map_type::const_iterator const end = nodes_.end(); for (node_map_type::const_iterator it = nodes_.begin(); it != end; ++it) { diff --git a/libs/core/batch_environments/src/pbs_environment.cpp b/libs/core/batch_environments/src/pbs_environment.cpp index 44f6e403f0ed..986383905cfe 100644 --- a/libs/core/batch_environments/src/pbs_environment.cpp +++ b/libs/core/batch_environments/src/pbs_environment.cpp @@ -21,17 +21,18 @@ namespace hpx::util::batch_environments { pbs_environment::pbs_environment( std::vector& nodelist, bool have_mpi, bool debug) - : node_num_(std::size_t(-1)) - , num_localities_(std::size_t(-1)) - , num_threads_(std::size_t(-1)) + : node_num_(static_cast(-1)) + , num_localities_(static_cast(-1)) + , num_threads_(static_cast(-1)) , valid_(false) { - char* node_num = std::getenv("PBS_NODENUM"); + char const* node_num = std::getenv("PBS_NODENUM"); valid_ = node_num != nullptr; if (valid_) { // Initialize our node number - node_num_ = from_string(node_num, std::size_t(1)); + node_num_ = + from_string(node_num, static_cast(1)); if (nodelist.empty()) { @@ -46,12 +47,12 @@ namespace hpx::util::batch_environments { read_nodelist(nodelist, debug); } - char* thread_num = std::getenv("PBS_NUM_PPN"); + char const* thread_num = std::getenv("PBS_NUM_PPN"); if (thread_num != nullptr) { // Initialize number of cores to run on - num_threads_ = - from_string(thread_num, std::size_t(-1)); + num_threads_ = from_string( + thread_num, static_cast(-1)); } } } @@ -70,12 +71,14 @@ namespace hpx::util::batch_environments { if (ifs.is_open()) { std::set nodes; - typedef std::set::iterator nodes_iterator; + using nodes_iterator = std::set::iterator; - bool fill_nodelist = nodelist.empty(); + bool const fill_nodelist = nodelist.empty(); if (debug) + { std::cerr << "opened: " << node_file << std::endl; + } std::string line; while (std::getline(ifs, line)) @@ -98,7 +101,9 @@ namespace hpx::util::batch_environments { else { if (debug) + { std::cerr << "failed opening: " << node_file << std::endl; + } // if MPI is active we can ignore the missing node-file if (have_mpi) @@ -113,7 +118,7 @@ namespace hpx::util::batch_environments { } void pbs_environment::read_nodelist( - std::vector& nodelist, bool debug) + std::vector const& nodelist, bool debug) { if (nodelist.empty()) { @@ -122,17 +127,18 @@ namespace hpx::util::batch_environments { } std::set nodes; - typedef std::set::iterator nodes_iterator; + using nodes_iterator = std::set::iterator; if (debug) + { std::cerr << "parsing nodelist" << std::endl; + } for (std::string const& s : nodelist) { if (!s.empty()) { - nodes_iterator it = nodes.find(s); - if (it == nodes.end()) + if (nodes_iterator it = nodes.find(s); it == nodes.end()) { nodes.insert(s); } diff --git a/libs/core/batch_environments/src/pjm_environment.cpp b/libs/core/batch_environments/src/pjm_environment.cpp index 6c6f87592041..80468aa1a142 100644 --- a/libs/core/batch_environments/src/pjm_environment.cpp +++ b/libs/core/batch_environments/src/pjm_environment.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 @@ -8,7 +8,6 @@ #include #include -#include #include #include #include @@ -35,7 +34,7 @@ namespace hpx::util::batch_environments { , num_localities_(0) , valid_(false) { - char* num_nodes = std::getenv("PJM_NODE"); + char const* num_nodes = std::getenv("PJM_NODE"); valid_ = num_nodes != nullptr; if (valid_) { @@ -45,7 +44,7 @@ namespace hpx::util::batch_environments { if (have_mpi) { // Initialize our node number, if available - char* var = std::getenv("PMIX_RANK"); + char const* var = std::getenv("PMIX_RANK"); if (var != nullptr) { node_num_ = from_string(var); diff --git a/libs/core/batch_environments/src/slurm_environment.cpp b/libs/core/batch_environments/src/slurm_environment.cpp index 3d3cfcf6e4ff..a6edd18a723f 100644 --- a/libs/core/batch_environments/src/slurm_environment.cpp +++ b/libs/core/batch_environments/src/slurm_environment.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2022 Hartmut Kaiser +// Copyright (c) 2007-2023 Hartmut Kaiser // Copyright (c) 2013-2015 Thomas Heller // // SPDX-License-Identifier: BSL-1.0 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/concurrency/CMakeLists.txt b/libs/core/concurrency/CMakeLists.txt index 332fb0a6cadd..b5169a94d099 100644 --- a/libs/core/concurrency/CMakeLists.txt +++ b/libs/core/concurrency/CMakeLists.txt @@ -62,6 +62,7 @@ add_hpx_module( hpx_itt_notify hpx_lock_registration hpx_thread_support + hpx_type_support hpx_version CMAKE_SUBDIRS examples tests ) diff --git a/libs/core/concurrency/include/hpx/concurrency/barrier.hpp b/libs/core/concurrency/include/hpx/concurrency/barrier.hpp index de27219d6d6a..dd120889e203 100644 --- a/libs/core/concurrency/include/hpx/concurrency/barrier.hpp +++ b/libs/core/concurrency/include/hpx/concurrency/barrier.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017 Hartmut Kaiser +// Copyright (c) 2017-2023 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -28,7 +28,13 @@ namespace hpx::util { << (CHAR_BIT * sizeof(std::size_t) - 1); public: - barrier(std::size_t number_of_threads); + explicit barrier(std::size_t number_of_threads); + + barrier(barrier const&) = delete; + barrier(barrier&&) = delete; + barrier& operator=(barrier const&) = delete; + barrier& operator=(barrier&&) = delete; + ~barrier(); void wait(); diff --git a/libs/core/concurrency/include/hpx/concurrency/cache_line_data.hpp b/libs/core/concurrency/include/hpx/concurrency/cache_line_data.hpp index eee99479a7d8..8df03a0ffec8 100644 --- a/libs/core/concurrency/include/hpx/concurrency/cache_line_data.hpp +++ b/libs/core/concurrency/include/hpx/concurrency/cache_line_data.hpp @@ -8,6 +8,7 @@ #pragma once #include +#include #include #include @@ -191,9 +192,10 @@ namespace hpx { /////////////////////////////////////////////////////////////////////////// template - constexpr inline auto align_up(T value, std::size_t alignment) noexcept + constexpr auto align_up(T value, std::size_t alignment) noexcept { - return T(std::size_t(value + (alignment - 1)) & ~(alignment - 1)); + return T(hpx::bit_cast(value + (alignment - 1)) & + ~(alignment - 1)); } } // namespace util diff --git a/libs/core/concurrency/include/hpx/concurrency/deque.hpp b/libs/core/concurrency/include/hpx/concurrency/deque.hpp index 60c88932dee1..f3e28f9ac29c 100644 --- a/libs/core/concurrency/include/hpx/concurrency/deque.hpp +++ b/libs/core/concurrency/include/hpx/concurrency/deque.hpp @@ -4,6 +4,7 @@ // Link: http://www.research.ibm.com/people/m/michael/europar-2003.pdf // // C++ implementation - Copyright (C) 2011 Bryce Lelbach +// Copyright (c) 2022-2023 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -166,26 +167,26 @@ namespace hpx::lockfree { return pair_.load(mo).get_right_tag(); } - bool cas(deque_anchor& expected, deque_anchor const& desired, + bool cas(deque_anchor const& expected, deque_anchor const& desired, std::memory_order mo = std::memory_order_acq_rel) noexcept { return pair_.compare_exchange_strong( - expected.load(std::memory_order_acquire), - desired.load(std::memory_order_acquire), mo); + expected.lrs(std::memory_order_acquire), + desired.lrs(std::memory_order_acquire), mo); } bool cas(pair& expected, deque_anchor const& desired, std::memory_order mo = std::memory_order_acq_rel) noexcept { return pair_.compare_exchange_strong( - expected, desired.load(std::memory_order_acquire), mo); + expected, desired.lrs(std::memory_order_acquire), mo); } - bool cas(deque_anchor& expected, pair const& desired, + bool cas(deque_anchor const& expected, pair const& desired, std::memory_order mo = std::memory_order_acq_rel) noexcept { return pair_.compare_exchange_strong( - expected.load(std::memory_order_acquire), desired, mo); + expected.lrs(std::memory_order_acquire), desired, mo); } bool cas(pair& expected, pair const& desired, @@ -229,7 +230,7 @@ namespace hpx::lockfree { return !(lhs == rhs); } - bool is_lock_free() const noexcept + [[nodiscard]] bool is_lock_free() const noexcept { return pair_.is_lock_free(); } @@ -417,7 +418,7 @@ namespace hpx::lockfree { // Not thread-safe. // Complexity: O(Processes) // FIXME: Should we check both pointers here? - bool empty() const noexcept + [[nodiscard]] bool empty() const noexcept { return anchor_.lrs(std::memory_order_relaxed).get_left_ptr() == nullptr; @@ -425,7 +426,7 @@ namespace hpx::lockfree { // Thread-safe and non-blocking. // Complexity: O(1) - bool is_lock_free() const noexcept + [[nodiscard]] bool is_lock_free() const noexcept { return anchor_.is_lock_free(); } diff --git a/libs/core/concurrency/include/hpx/concurrency/detail/freelist.hpp b/libs/core/concurrency/include/hpx/concurrency/detail/freelist.hpp index 28d662dcd511..901e7fd093b1 100644 --- a/libs/core/concurrency/include/hpx/concurrency/detail/freelist.hpp +++ b/libs/core/concurrency/include/hpx/concurrency/detail/freelist.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2012 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 @@ -20,7 +20,7 @@ namespace hpx::lockfree { using base_type = lockfree::detail::freelist_stack; public: - caching_freelist(std::size_t n = 0) + explicit caching_freelist(std::size_t n = 0) : lockfree::detail::freelist_stack(Alloc(), n) { } @@ -42,7 +42,7 @@ namespace hpx::lockfree { using base_type = lockfree::detail::freelist_stack; public: - static_freelist(std::size_t n = 0) + explicit static_freelist(std::size_t n = 0) : lockfree::detail::freelist_stack(Alloc(), n) { } diff --git a/libs/core/concurrency/include/hpx/concurrency/detail/freelist_stack.hpp b/libs/core/concurrency/include/hpx/concurrency/detail/freelist_stack.hpp index 5cb685c0c396..75bae5077d6c 100644 --- a/libs/core/concurrency/include/hpx/concurrency/detail/freelist_stack.hpp +++ b/libs/core/concurrency/include/hpx/concurrency/detail/freelist_stack.hpp @@ -1,5 +1,5 @@ // Copyright (C) 2008-2016 Tim Blechmann -// Copyright (c) 2022 Hartmut Kaiser +// Copyright (c) 2023 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -56,7 +57,7 @@ namespace hpx::lockfree::detail { for (std::size_t i = 0; i != count; ++i) { T* node = Alloc::allocate(1); - std::memset((void*) node, 0, sizeof(T)); + std::memset(static_cast(node), 0, sizeof(T)); deallocate(node); } } @@ -94,7 +95,7 @@ namespace hpx::lockfree::detail { freelist_node* current_ptr = current.get_ptr(); if (current_ptr) current = current_ptr->next; - Alloc::deallocate((T*) current_ptr, 1); + Alloc::deallocate(hpx::bit_cast(current_ptr), 1); } } @@ -155,7 +156,7 @@ namespace hpx::lockfree::detail { if constexpr (!Bounded) { T* ptr = Alloc::allocate(1); - std::memset((void*) ptr, 0, sizeof(T)); + std::memset(static_cast(ptr), 0, sizeof(T)); return ptr; } else @@ -170,7 +171,7 @@ namespace hpx::lockfree::detail { if (pool_.compare_exchange_weak(old_pool, new_pool)) { void* ptr = old_pool.get_ptr(); - return reinterpret_cast(ptr); + return static_cast(ptr); } } } @@ -185,7 +186,7 @@ namespace hpx::lockfree::detail { if constexpr (!Bounded) { T* ptr = Alloc::allocate(1); - std::memset((void*) ptr, 0, sizeof(T)); + std::memset(static_cast(ptr), 0, sizeof(T)); return ptr; } else @@ -199,7 +200,7 @@ namespace hpx::lockfree::detail { pool_.store(new_pool, std::memory_order_relaxed); void* ptr = old_pool.get_ptr(); - return reinterpret_cast(ptr); + return static_cast(ptr); } protected: @@ -221,8 +222,7 @@ namespace hpx::lockfree::detail { { void* node = n; tagged_node_ptr old_pool = pool_.load(std::memory_order_consume); - freelist_node* new_pool_ptr = - reinterpret_cast(node); + auto* new_pool_ptr = static_cast(node); for (;;) { @@ -238,8 +238,7 @@ namespace hpx::lockfree::detail { { void* node = n; tagged_node_ptr old_pool = pool_.load(std::memory_order_relaxed); - freelist_node* new_pool_ptr = - reinterpret_cast(node); + auto* new_pool_ptr = static_cast(node); tagged_node_ptr new_pool(new_pool_ptr, old_pool.get_tag()); new_pool->next.set_ptr(old_pool.get_ptr()); @@ -303,7 +302,8 @@ namespace hpx::lockfree::detail { constexpr tag_t get_next_tag() const noexcept { - tag_t next = (get_tag() + 1u) & (std::numeric_limits::max)(); + tag_t const next = + (get_tag() + 1u) & (std::numeric_limits::max)(); return next; } @@ -358,7 +358,7 @@ namespace hpx::lockfree::detail { data_pointer, hpx::threads::get_cache_line_size())); } - constexpr std::size_t node_count() const noexcept + static constexpr std::size_t node_count() noexcept { return Size; } @@ -393,7 +393,7 @@ namespace hpx::lockfree::detail { "of 65535 objects"); } nodes_ = allocator_type::allocate(count); - std::memset((void*) nodes_, 0, sizeof(T) * count); + std::memset(static_cast(nodes_), 0, sizeof(T) * count); } ~runtime_sized_freelist_storage() @@ -548,10 +548,10 @@ namespace hpx::lockfree::detail { return index; T* old_node = NodeStorage::nodes() + index; - tagged_index* next_index = + tagged_index const* next_index = reinterpret_cast(old_node); - tagged_index new_pool( + tagged_index const new_pool( next_index->get_index(), old_pool.get_next_tag()); if (pool_.compare_exchange_weak(old_pool, new_pool)) @@ -561,17 +561,17 @@ namespace hpx::lockfree::detail { index_t allocate_impl_unsafe() { - tagged_index old_pool = pool_.load(std::memory_order_consume); + tagged_index const old_pool = pool_.load(std::memory_order_consume); index_t index = old_pool.get_index(); if (index == null_handle()) return index; T* old_node = NodeStorage::nodes() + index; - tagged_index* next_index = + tagged_index const* next_index = reinterpret_cast(old_node); - tagged_index new_pool( + tagged_index const new_pool( next_index->get_index(), old_pool.get_next_tag()); pool_.store(new_pool, std::memory_order_relaxed); @@ -599,7 +599,7 @@ namespace hpx::lockfree::detail { for (;;) { - tagged_index new_pool(index, old_pool.get_tag()); + tagged_index const new_pool(index, old_pool.get_tag()); new_pool_node->next.set_index(old_pool.get_index()); if (pool_.compare_exchange_weak(old_pool, new_pool)) @@ -611,9 +611,9 @@ namespace hpx::lockfree::detail { { freelist_node* new_pool_node = reinterpret_cast(NodeStorage::nodes() + index); - tagged_index old_pool = pool_.load(std::memory_order_consume); + tagged_index const old_pool = pool_.load(std::memory_order_consume); - tagged_index new_pool(index, old_pool.get_tag()); + tagged_index const new_pool(index, old_pool.get_tag()); new_pool_node->next.set_index(old_pool.get_index()); pool_.store(new_pool); @@ -643,6 +643,6 @@ namespace hpx::lockfree::detail { std::conditional_t, tagged_index>; using handle_type = - std::conditional_t; + std::conditional_t; }; } // namespace hpx::lockfree::detail diff --git a/libs/core/concurrency/include/hpx/concurrency/detail/tagged_ptr_dcas.hpp b/libs/core/concurrency/include/hpx/concurrency/detail/tagged_ptr_dcas.hpp index 726ec43e8591..86ebd05122a9 100644 --- a/libs/core/concurrency/include/hpx/concurrency/detail/tagged_ptr_dcas.hpp +++ b/libs/core/concurrency/include/hpx/concurrency/detail/tagged_ptr_dcas.hpp @@ -1,5 +1,5 @@ // Copyright (C) 2008, 2016 Tim Blechmann -// Copyright (c) 2022 Hartmut Kaiser +// Copyright (c) 2022-2023 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -24,11 +24,12 @@ namespace hpx::lockfree::detail { using index_t = T*; /** uninitialized constructor */ - tagged_ptr() noexcept //: ptr(0), tag(0) + constexpr tagged_ptr() noexcept //: ptr(0), tag(0) { } tagged_ptr(tagged_ptr const& p) = default; + tagged_ptr(tagged_ptr&& p) = default; explicit constexpr tagged_ptr(T* p, tag_t t = 0) noexcept : ptr(p) @@ -39,8 +40,11 @@ namespace hpx::lockfree::detail { /** unsafe set operation */ /* @{ */ tagged_ptr& operator=(tagged_ptr const& p) = default; + tagged_ptr& operator=(tagged_ptr&& p) = default; - void set(T* p, tag_t t) noexcept + ~tagged_ptr() = default; + + constexpr void set(T* p, tag_t t) noexcept { ptr = p; tag = t; @@ -67,7 +71,7 @@ namespace hpx::lockfree::detail { return ptr; } - void set_ptr(T* p) noexcept + constexpr void set_ptr(T* p) noexcept { ptr = p; } @@ -82,11 +86,12 @@ namespace hpx::lockfree::detail { constexpr tag_t get_next_tag() const noexcept { - tag_t next = (get_tag() + 1) & (std::numeric_limits::max)(); + tag_t const next = + (get_tag() + 1) & (std::numeric_limits::max)(); return next; } - void set_tag(tag_t t) noexcept + constexpr void set_tag(tag_t t) noexcept { tag = t; } @@ -106,7 +111,7 @@ namespace hpx::lockfree::detail { explicit constexpr operator bool() const noexcept { - return ptr != 0; + return ptr != nullptr; } /* @} */ diff --git a/libs/core/concurrency/include/hpx/concurrency/detail/tagged_ptr_pair.hpp b/libs/core/concurrency/include/hpx/concurrency/detail/tagged_ptr_pair.hpp index 588b1a87436b..cc2afb9f940f 100644 --- a/libs/core/concurrency/include/hpx/concurrency/detail/tagged_ptr_pair.hpp +++ b/libs/core/concurrency/include/hpx/concurrency/detail/tagged_ptr_pair.hpp @@ -1,6 +1,6 @@ // Copyright (C) 2008-2011 Tim Blechmann // Copyright (C) 2011 Bryce Lelbach -// Copyright (c) 2022 Hartmut Kaiser +// Copyright (c) 2022-2023 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -12,6 +12,7 @@ #pragma once #include +#include #include // for std::size_t #include @@ -20,13 +21,28 @@ namespace hpx::lockfree { struct HPX_LOCKFREE_DCAS_ALIGNMENT uint128_type { - std::uint64_t left; - std::uint64_t right; + std::uint64_t left = 0; + std::uint64_t right = 0; + + uint128_type() = default; + + constexpr uint128_type(std::uint64_t l, std::uint64_t r) noexcept + : left(l) + , right(r) + { + } + + uint128_type(uint128_type const&) = default; + uint128_type(uint128_type&&) = default; + uint128_type& operator=(uint128_type const&) = default; + uint128_type& operator=(uint128_type&&) = default; + + ~uint128_type() = default; friend constexpr bool operator==(uint128_type const& lhs, //-V835 uint128_type const& rhs) noexcept //-V835 { - return (lhs.left == rhs.left) && (lhs.right == rhs.right); + return lhs.left == rhs.left && lhs.right == rhs.right; } friend constexpr bool operator!=(uint128_type const& lhs, //-V835 @@ -43,65 +59,79 @@ namespace hpx::lockfree { using compressed_ptr_t = std::uint64_t; using tag_t = std::uint16_t; - union HPX_LOCKFREE_DCAS_ALIGNMENT cast_unit + struct HPX_LOCKFREE_DCAS_ALIGNMENT cast_unit { - compressed_ptr_pair_t value; - tag_t tags[8]; + union + { + compressed_ptr_pair_t value; + tag_t tags[8]; + }; + + explicit constexpr cast_unit(compressed_ptr_pair_t i) noexcept + : value(i) + { + } + constexpr cast_unit(compressed_ptr_t l, compressed_ptr_t r, + tag_t ltag, tag_t rtag) noexcept + : value(l, r) + { + tags[left_tag_index] = ltag; + tags[right_tag_index] = rtag; + } }; static constexpr std::size_t left_tag_index = 3; static constexpr std::size_t right_tag_index = 7; static constexpr compressed_ptr_t ptr_mask = 0xffffffffffff; - static Left* extract_left_ptr(compressed_ptr_pair_t i) noexcept + static constexpr Left* extract_left_ptr( + compressed_ptr_pair_t i) noexcept { - return reinterpret_cast(i.left & ptr_mask); + return hpx::bit_cast(i.left & ptr_mask); } - static Right* extract_right_ptr(compressed_ptr_pair_t i) noexcept + static constexpr Right* extract_right_ptr( + compressed_ptr_pair_t i) noexcept { - return reinterpret_cast(i.right & ptr_mask); + return hpx::bit_cast(i.right & ptr_mask); } - static tag_t extract_left_tag(compressed_ptr_pair_t i) noexcept + static constexpr tag_t extract_left_tag( + compressed_ptr_pair_t i) noexcept { - cast_unit cu; - cu.value.left = i.left; - cu.value.right = i.right; + cast_unit cu(i); return cu.tags[left_tag_index]; } - static tag_t extract_right_tag(compressed_ptr_pair_t i) noexcept + static constexpr tag_t extract_right_tag( + compressed_ptr_pair_t i) noexcept { - cast_unit cu; - cu.value.left = i.left; - cu.value.right = i.right; + cast_unit cu(i); return cu.tags[right_tag_index]; } template - static void pack_ptr_pair(compressed_ptr_pair_t& pair, Left* lptr, - Right* rptr, IntegralL ltag, IntegralR rtag) noexcept - { - cast_unit ret; - ret.value.left = reinterpret_cast(lptr); - ret.value.right = reinterpret_cast(rptr); - ret.tags[left_tag_index] = static_cast(ltag); - ret.tags[right_tag_index] = static_cast(rtag); + static constexpr void pack_ptr_pair(compressed_ptr_pair_t& pair, + Left* lptr, Right* rptr, IntegralL ltag, IntegralR rtag) noexcept + { + cast_unit ret(hpx::bit_cast(lptr), + hpx::bit_cast(rptr), static_cast(ltag), + static_cast(rtag)); pair = ret.value; } /** uninitialized constructor */ - tagged_ptr_pair() {} //-V730 //-V832 + constexpr tagged_ptr_pair() {} //-V730 //-V832 template - tagged_ptr_pair(Left* lptr, Right* rptr, IntegralL ltag) noexcept + constexpr tagged_ptr_pair( + Left* lptr, Right* rptr, IntegralL ltag) noexcept { pack_ptr_pair(pair_, lptr, rptr, ltag, 0); } template - tagged_ptr_pair( + constexpr tagged_ptr_pair( Left* lptr, Right* rptr, IntegralL ltag, IntegralR rtag) noexcept { pack_ptr_pair(pair_, lptr, rptr, ltag, rtag); @@ -109,8 +139,9 @@ namespace hpx::lockfree { /** copy constructors */ tagged_ptr_pair(tagged_ptr_pair const& p) = default; + tagged_ptr_pair(tagged_ptr_pair&& p) = default; - tagged_ptr_pair(Left* lptr, Right* rptr) noexcept + constexpr tagged_ptr_pair(Left* lptr, Right* rptr) noexcept { pack_ptr_pair(pair_, lptr, rptr, 0, 0); } @@ -118,38 +149,41 @@ namespace hpx::lockfree { /** unsafe set operations */ /* @{ */ tagged_ptr_pair& operator=(tagged_ptr_pair const& p) = default; + tagged_ptr_pair& operator=(tagged_ptr_pair&& p) = default; + + ~tagged_ptr_pair() = default; - void set(Left* lptr, Right* rptr) noexcept + constexpr void set(Left* lptr, Right* rptr) noexcept { pack_ptr_pair(pair_, lptr, rptr, 0, 0); } - void reset(Left* lptr, Right* rptr) noexcept + constexpr void reset(Left* lptr, Right* rptr) noexcept { set(lptr, rptr, 0, 0); } template - void set(Left* lptr, Right* rptr, IntegralL ltag) noexcept + constexpr void set(Left* lptr, Right* rptr, IntegralL ltag) noexcept { pack_ptr_pair(pair_, lptr, rptr, ltag, 0); } template - void set( + constexpr void set( Left* lptr, Right* rptr, IntegralL ltag, IntegralR rtag) noexcept { pack_ptr_pair(pair_, lptr, rptr, ltag, rtag); } template - void reset(Left* lptr, Right* rptr, IntegralL ltag) noexcept + constexpr void reset(Left* lptr, Right* rptr, IntegralL ltag) noexcept { set(lptr, rptr, ltag, 0); } template - void reset( + constexpr void reset( Left* lptr, Right* rptr, IntegralL ltag, IntegralR rtag) noexcept { set(lptr, rptr, ltag, rtag); @@ -173,47 +207,47 @@ namespace hpx::lockfree { /** pointer access */ /* @{ */ - Left* get_left_ptr() const noexcept + constexpr Left* get_left_ptr() const noexcept { return extract_left_ptr(pair_); } - Right* get_right_ptr() const noexcept + constexpr Right* get_right_ptr() const noexcept { return extract_right_ptr(pair_); } - void set_left_ptr(Left* lptr) noexcept + constexpr void set_left_ptr(Left* lptr) noexcept { Right* rptr = get_right_ptr(); - tag_t ltag = get_left_tag(); - tag_t rtag = get_right_tag(); + tag_t const ltag = get_left_tag(); + tag_t const rtag = get_right_tag(); pack_ptr_pair(pair_, lptr, rptr, ltag, rtag); } - void set_right_ptr(Right* rptr) noexcept + constexpr void set_right_ptr(Right* rptr) noexcept { Left* lptr = get_left_ptr(); - tag_t ltag = get_left_tag(); - tag_t rtag = get_right_tag(); + tag_t const ltag = get_left_tag(); + tag_t const rtag = get_right_tag(); pack_ptr_pair(pair_, lptr, rptr, ltag, rtag); } /* @} */ /** tag access */ /* @{ */ - tag_t get_left_tag() const noexcept + constexpr tag_t get_left_tag() const noexcept { return extract_left_tag(pair_); } - tag_t get_right_tag() const noexcept + constexpr tag_t get_right_tag() const noexcept { return extract_right_tag(pair_); } template - void set_left_tag(Integral ltag) noexcept + constexpr void set_left_tag(Integral ltag) noexcept { Left* lptr = get_left_ptr(); Right* rptr = get_right_ptr(); @@ -222,7 +256,7 @@ namespace hpx::lockfree { } template - void set_right_tag(Integral rtag) noexcept + constexpr void set_right_tag(Integral rtag) noexcept { Left* lptr = get_left_ptr(); Right* rptr = get_right_ptr(); @@ -233,9 +267,9 @@ namespace hpx::lockfree { /** smart pointer support */ /* @{ */ - explicit operator bool() const noexcept + explicit constexpr operator bool() const noexcept { - return (get_left_ptr() != 0) && (get_right_ptr() != 0); + return get_left_ptr() != nullptr && get_right_ptr() != nullptr; } /* @} */ diff --git a/libs/core/concurrency/include/hpx/concurrency/detail/tagged_ptr_ptrcompression.hpp b/libs/core/concurrency/include/hpx/concurrency/detail/tagged_ptr_ptrcompression.hpp index ae1bd0af9418..e40e0164b78f 100644 --- a/libs/core/concurrency/include/hpx/concurrency/detail/tagged_ptr_ptrcompression.hpp +++ b/libs/core/concurrency/include/hpx/concurrency/detail/tagged_ptr_ptrcompression.hpp @@ -1,5 +1,5 @@ // Copyright (C) 2008, 2009, 2016 Tim Blechmann, based on code by Cory Nelson -// Copyright (c) 2022 Hartmut Kaiser +// Copyright (c) 2022-2023 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -10,6 +10,7 @@ #pragma once #include +#include #include #include @@ -28,33 +29,44 @@ namespace hpx::lockfree::detail { using index_t = T*; private: - union cast_unit - { - compressed_ptr_t value; - tag_t tag[4]; + struct cast_unit + { + union + { + compressed_ptr_t value; + tag_t tag[4]; + }; + + explicit constexpr cast_unit(compressed_ptr_t i) noexcept + : value(i) + { + } + + constexpr cast_unit(compressed_ptr_t i, tag_t t) noexcept + : value(i) + { + tag[tag_index] = t; + } }; static constexpr int tag_index = 3; static constexpr compressed_ptr_t ptr_mask = 0xffffffffffffUL; // (1L<<48L)-1; - static T* extract_ptr(compressed_ptr_t i) noexcept + static constexpr T* extract_ptr(compressed_ptr_t i) noexcept { - return reinterpret_cast(i & ptr_mask); + return hpx::bit_cast(i & ptr_mask); } - static tag_t extract_tag(compressed_ptr_t i) noexcept + static constexpr tag_t extract_tag(compressed_ptr_t i) noexcept { - cast_unit cu; - cu.value = i; + cast_unit cu(i); return cu.tag[tag_index]; } - static compressed_ptr_t pack_ptr(T* ptr, tag_t tag) noexcept + static constexpr compressed_ptr_t pack_ptr(T* ptr, tag_t tag) noexcept { - cast_unit ret; - ret.value = compressed_ptr_t(ptr); - ret.tag[tag_index] = tag; + cast_unit ret(hpx::bit_cast(ptr), tag); return ret.value; } @@ -66,8 +78,9 @@ namespace hpx::lockfree::detail { /** copy constructor */ tagged_ptr(tagged_ptr const& p) = default; + tagged_ptr(tagged_ptr&& p) = default; - explicit tagged_ptr(T* p, tag_t t = 0) noexcept + explicit constexpr tagged_ptr(T* p, tag_t t = 0) noexcept : ptr(pack_ptr(p, t)) { } @@ -75,6 +88,9 @@ namespace hpx::lockfree::detail { /** unsafe set operation */ /* @{ */ tagged_ptr& operator=(tagged_ptr const& p) = default; + tagged_ptr& operator=(tagged_ptr&& p) = default; + + ~tagged_ptr() = default; void set(T* p, tag_t t) noexcept { @@ -99,28 +115,29 @@ namespace hpx::lockfree::detail { /** pointer access */ /* @{ */ - T* get_ptr() const noexcept + constexpr T* get_ptr() const noexcept { return extract_ptr(ptr); } void set_ptr(T* p) noexcept { - tag_t tag = get_tag(); + tag_t const tag = get_tag(); ptr = pack_ptr(p, tag); } /* @} */ /** tag access */ /* @{ */ - tag_t get_tag() const noexcept + constexpr tag_t get_tag() const noexcept { return extract_tag(ptr); } - tag_t get_next_tag() const noexcept + constexpr tag_t get_next_tag() const noexcept { - tag_t next = (get_tag() + 1u) & (std::numeric_limits::max)(); + tag_t const next = + (get_tag() + 1u) & (std::numeric_limits::max)(); return next; } @@ -133,17 +150,17 @@ namespace hpx::lockfree::detail { /** smart pointer support */ /* @{ */ - T& operator*() const noexcept + constexpr T& operator*() const noexcept { return *get_ptr(); } - T* operator->() const noexcept + constexpr T* operator->() const noexcept { return get_ptr(); } - explicit operator bool() const noexcept + constexpr explicit operator bool() const noexcept { return get_ptr() != nullptr; } diff --git a/libs/core/concurrency/include/hpx/concurrency/queue.hpp b/libs/core/concurrency/include/hpx/concurrency/queue.hpp index d8abd5a6a9b2..8315ce66ff2d 100644 --- a/libs/core/concurrency/include/hpx/concurrency/queue.hpp +++ b/libs/core/concurrency/include/hpx/concurrency/queue.hpp @@ -1,5 +1,5 @@ // Copyright (C) 2008-2013 Tim Blechmann -// Copyright (c) 2022 Hartmut Kaiser +// Copyright (c) 2022-2023 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -149,10 +149,12 @@ namespace hpx::lockfree { using size_type = std::size_t; }; + public: queue(queue const&) = delete; + queue(queue&&) = delete; queue& operator=(queue const&) = delete; + queue& operator=(queue&&) = delete; - public: using value_type = T; using allocator = typename implementation_defined::allocator; using size_type = typename implementation_defined::size_type; @@ -168,7 +170,7 @@ namespace hpx::lockfree { * need to test every internal node, which is impossible if further * nodes will be allocated from the operating system. */ - constexpr bool is_lock_free() const noexcept + [[nodiscard]] constexpr bool is_lock_free() const noexcept { return head_.is_lock_free() && tail_.is_lock_free() && pool.is_lock_free(); @@ -295,7 +297,7 @@ namespace hpx::lockfree { * queue. Therefore it is rarely practical to use this value in * program logic. */ - bool empty() const noexcept + [[nodiscard]] bool empty() const noexcept { return pool.get_handle(head_.load()) == pool.get_handle(tail_.load()); @@ -595,7 +597,7 @@ namespace hpx::lockfree { bool consume_one(F&& f) { T element; - bool success = pop(element); + bool const success = pop(element); if (success) f(element); diff --git a/libs/core/concurrency/include/hpx/concurrency/spinlock_pool.hpp b/libs/core/concurrency/include/hpx/concurrency/spinlock_pool.hpp index 95475828ad7a..b1751a1e7120 100644 --- a/libs/core/concurrency/include/hpx/concurrency/spinlock_pool.hpp +++ b/libs/core/concurrency/include/hpx/concurrency/spinlock_pool.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2012 Hartmut Kaiser +// Copyright (c) 2012-2023 Hartmut Kaiser // // taken from: // boost/detail/spinlock_pool.hpp @@ -21,7 +21,7 @@ #include -namespace hpx { namespace util { +namespace hpx::util { namespace detail { #if HPX_HAVE_ITTNOTIFY != 0 @@ -56,6 +56,7 @@ namespace hpx { namespace util { #if HPX_HAVE_ITTNOTIFY != 0 namespace detail { + template itt_spinlock_init::itt_spinlock_init() noexcept { @@ -79,5 +80,4 @@ namespace hpx { namespace util { template util::detail::itt_spinlock_init spinlock_pool::init_; #endif - -}} // namespace hpx::util +} // namespace hpx::util diff --git a/libs/core/concurrency/include/hpx/concurrency/stack.hpp b/libs/core/concurrency/include/hpx/concurrency/stack.hpp index da9aa47f561d..ffeb832a40dc 100644 --- a/libs/core/concurrency/include/hpx/concurrency/stack.hpp +++ b/libs/core/concurrency/include/hpx/concurrency/stack.hpp @@ -1,5 +1,5 @@ // Copyright (C) 2008-2013 Tim Blechmann -// Copyright (c) 2022 Hartmut Kaiser +// Copyright (c) 2022-2023 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -113,10 +113,12 @@ namespace hpx::lockfree { using size_type = std::size_t; }; + public: stack(stack const&) = delete; + stack(stack&&) = delete; stack& operator=(stack const&) = delete; + stack& operator=(stack&&) = delete; - public: using value_type = T; using allocator = typename implementation_defined::allocator; using size_type = typename implementation_defined::size_type; @@ -132,7 +134,7 @@ namespace hpx::lockfree { * to test every internal node, which is impossible if further * nodes will be allocated from the operating system. */ - constexpr bool is_lock_free() const noexcept + [[nodiscard]] constexpr bool is_lock_free() const noexcept { return tos.is_lock_free() && pool.is_lock_free(); } diff --git a/libs/core/concurrency/src/barrier.cpp b/libs/core/concurrency/src/barrier.cpp index 00b895de64d4..510aeb59498a 100644 --- a/libs/core/concurrency/src/barrier.cpp +++ b/libs/core/concurrency/src/barrier.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017 Hartmut Kaiser +// Copyright (c) 2017-2023 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -9,7 +9,8 @@ #include -namespace hpx { namespace util { +namespace hpx::util { + barrier::barrier(std::size_t number_of_threads) : number_of_threads_(number_of_threads) , total_(barrier_flag) @@ -66,4 +67,4 @@ namespace hpx { namespace util { } } } -}} // namespace hpx::util +} // namespace hpx::util diff --git a/libs/core/coroutines/CMakeLists.txt b/libs/core/coroutines/CMakeLists.txt index 348ebbc43070..ca8560283b9b 100644 --- a/libs/core/coroutines/CMakeLists.txt +++ b/libs/core/coroutines/CMakeLists.txt @@ -58,6 +58,7 @@ set(coroutines_sources detail/tss.cpp swapcontext.cpp thread_enums.cpp + thread_id_type.cpp signal_handler_debugging.cpp ) diff --git a/libs/core/coroutines/include/hpx/coroutines/coroutine.hpp b/libs/core/coroutines/include/hpx/coroutines/coroutine.hpp index 9d2df4973ecd..0bc356698ba7 100644 --- a/libs/core/coroutines/include/hpx/coroutines/coroutine.hpp +++ b/libs/core/coroutines/include/hpx/coroutines/coroutine.hpp @@ -37,7 +37,6 @@ #include #include #include -#include #include #include @@ -64,7 +63,7 @@ namespace hpx::threads::coroutines { coroutine(functor_type&& f, thread_id_type id, std::ptrdiff_t stack_size = detail::default_stack_size) - : impl_(HPX_MOVE(f), id, stack_size) + : impl_(HPX_MOVE(f), HPX_MOVE(id), stack_size) { HPX_ASSERT(impl_.is_ready()); } @@ -74,6 +73,8 @@ namespace hpx::threads::coroutines { coroutine(coroutine&& src) = delete; coroutine& operator=(coroutine&& src) = delete; + ~coroutine() = default; + constexpr thread_id_type get_thread_id() const noexcept { return impl_.get_thread_id(); @@ -91,7 +92,7 @@ namespace hpx::threads::coroutines { return impl_.get_thread_data(); } - std::size_t set_thread_data(std::size_t data) noexcept + std::size_t set_thread_data(std::size_t data) const noexcept { return impl_.set_thread_data(data); } @@ -102,7 +103,7 @@ namespace hpx::threads::coroutines { return impl_.get_libcds_data(); } - std::size_t set_libcds_data(std::size_t data) + std::size_t set_libcds_data(std::size_t data) const { return impl_.set_libcds_data(data); } @@ -112,7 +113,7 @@ namespace hpx::threads::coroutines { return impl_.get_libcds_hazard_pointer_data(); } - std::size_t set_libcds_hazard_pointer_data(std::size_t data) + std::size_t set_libcds_hazard_pointer_data(std::size_t data) const { return impl_.set_libcds_hazard_pointer_data(data); } @@ -122,7 +123,8 @@ namespace hpx::threads::coroutines { return impl_.get_libcds_dynamic_hazard_pointer_data(); } - std::size_t set_libcds_dynamic_hazard_pointer_data(std::size_t data) + std::size_t set_libcds_dynamic_hazard_pointer_data( + std::size_t data) const { return impl_.set_libcds_dynamic_hazard_pointer_data(data); } @@ -135,7 +137,7 @@ namespace hpx::threads::coroutines { void rebind(functor_type&& f, thread_id_type id) { - impl_.rebind(HPX_MOVE(f), id); + impl_.rebind(HPX_MOVE(f), HPX_MOVE(id)); } HPX_FORCEINLINE result_type operator()(arg_type arg = arg_type()) @@ -160,7 +162,7 @@ namespace hpx::threads::coroutines { return impl_.get_available_stack_space(); } #else - std::ptrdiff_t get_available_stack_space() const noexcept + static std::ptrdiff_t get_available_stack_space() noexcept { return (std::numeric_limits::max)(); } diff --git a/libs/core/coroutines/include/hpx/coroutines/coroutine_fwd.hpp b/libs/core/coroutines/include/hpx/coroutines/coroutine_fwd.hpp index 276117834df9..dcf8f49837eb 100644 --- a/libs/core/coroutines/include/hpx/coroutines/coroutine_fwd.hpp +++ b/libs/core/coroutines/include/hpx/coroutines/coroutine_fwd.hpp @@ -30,8 +30,6 @@ #pragma once -#include - namespace hpx::threads::coroutines { namespace detail { diff --git a/libs/core/coroutines/include/hpx/coroutines/detail/combined_tagged_state.hpp b/libs/core/coroutines/include/hpx/coroutines/detail/combined_tagged_state.hpp index 8e495e090f2b..22d56cfde006 100644 --- a/libs/core/coroutines/include/hpx/coroutines/detail/combined_tagged_state.hpp +++ b/libs/core/coroutines/include/hpx/coroutines/detail/combined_tagged_state.hpp @@ -26,15 +26,14 @@ namespace hpx::threads::detail { using thread_state_ex_type = std::int8_t; using tag_type = std::int64_t; - static constexpr std::size_t const state_shift = 56; // 8th byte - static constexpr std::size_t const state_ex_shift = 48; // 7th byte + static constexpr std::size_t state_shift = 56; // 8th byte + static constexpr std::size_t state_ex_shift = 48; // 7th byte - static constexpr tagged_state_type const state_mask = 0xffull; - static constexpr tagged_state_type const state_ex_mask = 0xffull; + static constexpr tagged_state_type state_mask = 0xffull; + static constexpr tagged_state_type state_ex_mask = 0xffull; // (1L << 48L) - 1; - static constexpr tagged_state_type const tag_mask = - 0x0000ffffffffffffull; + static constexpr tagged_state_type tag_mask = 0x0000ffffffffffffull; static constexpr tag_type extract_tag(tagged_state_type i) noexcept { @@ -44,21 +43,22 @@ namespace hpx::threads::detail { static constexpr thread_state_type extract_state( tagged_state_type i) noexcept { - return (i >> state_shift) & state_mask; + return static_cast( + (i >> state_shift) & state_mask); } static constexpr thread_state_ex_type extract_state_ex( tagged_state_type i) noexcept { - return (i >> state_ex_shift) & state_ex_mask; + return static_cast( + (i >> state_ex_shift) & state_ex_mask); } static tagged_state_type pack_state( T1 state_, T2 state_ex_, tag_type tag) noexcept { - tagged_state_type state = static_cast(state_); - tagged_state_type state_ex = - static_cast(state_ex_); + auto const state = static_cast(state_); + auto const state_ex = static_cast(state_ex_); HPX_ASSERT(!(state & ~state_mask)); HPX_ASSERT(!(state_ex & ~state_ex_mask)); @@ -91,12 +91,12 @@ namespace hpx::threads::detail { } /////////////////////////////////////////////////////////////////////// - bool operator==(combined_tagged_state const& p) const + constexpr bool operator==(combined_tagged_state const& p) const noexcept { return state_ == p.state_; } - bool operator!=(combined_tagged_state const& p) const + constexpr bool operator!=(combined_tagged_state const& p) const noexcept { return !operator==(p); } diff --git a/libs/core/coroutines/include/hpx/coroutines/detail/context_base.hpp b/libs/core/coroutines/include/hpx/coroutines/detail/context_base.hpp index c22c854ae232..01262b449087 100644 --- a/libs/core/coroutines/include/hpx/coroutines/detail/context_base.hpp +++ b/libs/core/coroutines/include/hpx/coroutines/detail/context_base.hpp @@ -30,14 +30,6 @@ #pragma once -/* - * Currently asio can, in some cases. call copy constructors and - * operator= from different threads, even if in the - * one-thread-per-service model. (i.e. from the resolver thread) - * This will be corrected in future versions, but for now - * we will play it safe and use an atomic count. The overhead shouldn't - * be big. - */ #include // This needs to be first for building on Macs @@ -48,11 +40,9 @@ #include #include -#include #include #include #include -#include #include namespace hpx::threads::coroutines::detail { @@ -89,12 +79,18 @@ namespace hpx::threads::coroutines::detail { , libcds_dynamic_hazard_pointer_data_(0) #endif , m_type_info() - , m_thread_id(id) + , m_thread_id(HPX_MOVE(id)) , continuation_recursion_count_(0) { } - void reset_tss() + context_base(context_base const&) = delete; + context_base(context_base&&) = delete; + + context_base& operator=(context_base const&) = delete; + context_base& operator=(context_base&&) = delete; + + void reset_tss() const { #if defined(HPX_HAVE_THREAD_LOCAL_STORAGE) delete_tss_storage(m_thread_data); @@ -243,14 +239,14 @@ namespace hpx::threads::coroutines::detail { #endif #if defined(HPX_HAVE_THREAD_LOCAL_STORAGE) - std::size_t set_thread_data(std::size_t data) + std::size_t set_thread_data(std::size_t data) const { return set_tss_thread_data(m_thread_data, data); } #else - std::size_t set_thread_data(std::size_t data) noexcept + std::size_t set_thread_data(std::size_t data) const noexcept { - std::size_t olddata = m_thread_data; + std::size_t const olddata = m_thread_data; m_thread_data = data; return olddata; } @@ -335,7 +331,7 @@ namespace hpx::threads::coroutines::detail { { HPX_ASSERT(!running()); - m_thread_id = id; + m_thread_id = HPX_MOVE(id); m_state = context_state::ready; m_exit_state = context_exit_state::not_requested; m_exit_status = context_exit_status::not_exited; diff --git a/libs/core/coroutines/include/hpx/coroutines/detail/context_generic_context.hpp b/libs/core/coroutines/include/hpx/coroutines/detail/context_generic_context.hpp index 54f98d405b47..9a1856327b73 100644 --- a/libs/core/coroutines/include/hpx/coroutines/detail/context_generic_context.hpp +++ b/libs/core/coroutines/include/hpx/coroutines/detail/context_generic_context.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2014 Thomas Heller -// Copyright (c) 2012-2022 Hartmut Kaiser +// Copyright (c) 2012-2023 Hartmut Kaiser // Copyright (c) 2009 Oliver Kowalke // // SPDX-License-Identifier: BSL-1.0 @@ -13,10 +13,12 @@ #include #include #include +#if defined(HPX_HAVE_COROUTINE_COUNTERS) #include +#endif -// include unist.d conditionally to check for POSIX version. Not all OSs have the -// unistd header... +// include unistd.h conditionally to check for POSIX version. Not all OSs have +// the unistd header... #if defined(HPX_HAVE_UNISTD_H) #include #endif @@ -29,16 +31,18 @@ #endif #include -#include #include #include #include #include -#include #include #include +#if !defined(HPX_HAVE_THREADS_GET_STACK_POINTER) +#include +#endif + /////////////////////////////////////////////////////////////////////////////// #if defined(HPX_GENERIC_CONTEXT_USE_SEGMENTED_STACKS) @@ -93,7 +97,7 @@ namespace hpx::threads::coroutines { return HPX_SMALL_STACK_SIZE; } - void* allocate(std::size_t size) const + static void* allocate(std::size_t size) { // Condition excludes MacOS/M1 from using posix mmap #if defined(HPX_USE_POSIX_STACK_UTILITIES) @@ -107,7 +111,7 @@ namespace hpx::threads::coroutines { return static_cast(limit) + size; } - void deallocate(void* vp, std::size_t size) const noexcept + static void deallocate(void* vp, std::size_t size) noexcept { HPX_ASSERT(vp); void* limit = static_cast(vp) - size; @@ -169,7 +173,7 @@ namespace hpx::threads::coroutines { template [[noreturn]] void trampoline(boost::context::detail::transfer_t tr) { - auto arg = static_cast< + auto const arg = static_cast< std::pair*>( tr.data); @@ -197,10 +201,11 @@ namespace hpx::threads::coroutines { explicit fcontext_context_impl(std::ptrdiff_t stack_size = -1) : cb_(std::make_pair(static_cast(this), nullptr)) , funp_(&trampoline) - , ctx_(0) + , ctx_(nullptr) , alloc_() - , stack_size_((stack_size == -1) ? alloc_.minimum_stacksize() : - std::size_t(stack_size)) + , stack_size_((stack_size == -1) ? + alloc_.minimum_stacksize() : + static_cast(stack_size)) , stack_pointer_(nullptr) { } @@ -247,7 +252,7 @@ namespace hpx::threads::coroutines { return (std::numeric_limits::max)(); } #endif - void reset_stack() + void reset_stack() const { if (ctx_) { diff --git a/libs/core/coroutines/include/hpx/coroutines/detail/context_posix.hpp b/libs/core/coroutines/include/hpx/coroutines/detail/context_posix.hpp index 734e138f1bbe..4a38b5325bad 100644 --- a/libs/core/coroutines/include/hpx/coroutines/detail/context_posix.hpp +++ b/libs/core/coroutines/include/hpx/coroutines/detail/context_posix.hpp @@ -47,8 +47,8 @@ #include #include -// include unist.d conditionally to check for POSIX version. Not all OSs have the -// unistd header... +// include unistd.h conditionally to check for POSIX version. Not all OSs have +// the unistd header... #if defined(HPX_HAVE_UNISTD_H) #include #endif diff --git a/libs/core/coroutines/include/hpx/coroutines/detail/coroutine_impl.hpp b/libs/core/coroutines/include/hpx/coroutines/detail/coroutine_impl.hpp index 6f758b20a446..c72859ef5b38 100644 --- a/libs/core/coroutines/include/hpx/coroutines/detail/coroutine_impl.hpp +++ b/libs/core/coroutines/include/hpx/coroutines/detail/coroutine_impl.hpp @@ -34,7 +34,6 @@ #include #include #include -#include #include #include #include @@ -65,7 +64,7 @@ namespace hpx::threads::coroutines::detail { coroutine_impl(functor_type&& f, thread_id_type id, std::ptrdiff_t stack_size) noexcept - : context_base(stack_size, id) + : context_base(stack_size, HPX_MOVE(id)) , m_result(thread_schedule_state::unknown, invalid_thread_id) , m_arg(nullptr) , m_fun(HPX_MOVE(f)) @@ -80,7 +79,7 @@ namespace hpx::threads::coroutines::detail { HPX_CORE_EXPORT void operator()() noexcept; public: - void bind_result(result_type res) noexcept + void bind_result(result_type const& res) noexcept { HPX_ASSERT(m_result.first != thread_schedule_state::terminated); m_result = res; @@ -90,11 +89,11 @@ namespace hpx::threads::coroutines::detail { { return m_result; } - arg_type* args() noexcept + arg_type* args() const noexcept { HPX_ASSERT(m_arg); return m_arg; - }; + } void bind_args(arg_type* arg) noexcept { @@ -134,7 +133,7 @@ namespace hpx::threads::coroutines::detail { result_type(thread_schedule_state::unknown, invalid_thread_id); m_arg = nullptr; m_fun = HPX_MOVE(f); - this->super_type::rebind_base(id); + this->super_type::rebind_base(HPX_MOVE(id)); } private: diff --git a/libs/core/coroutines/include/hpx/coroutines/detail/coroutine_self.hpp b/libs/core/coroutines/include/hpx/coroutines/detail/coroutine_self.hpp index a251ee349578..ebfed04f8e7a 100644 --- a/libs/core/coroutines/include/hpx/coroutines/detail/coroutine_self.hpp +++ b/libs/core/coroutines/include/hpx/coroutines/detail/coroutine_self.hpp @@ -30,7 +30,6 @@ #pragma once #include -#include #include #include #include @@ -38,8 +37,6 @@ #include #include -#include -#include #include namespace hpx::threads::coroutines::detail { @@ -59,6 +56,12 @@ namespace hpx::threads::coroutines::detail { set_self(self->next_self_); } + reset_self_on_exit(reset_self_on_exit const&) = delete; + reset_self_on_exit(reset_self_on_exit&&) = delete; + + reset_self_on_exit& operator=(reset_self_on_exit const&) = delete; + reset_self_on_exit& operator=(reset_self_on_exit&&) = delete; + ~reset_self_on_exit() { set_self(self_); @@ -183,6 +186,12 @@ namespace hpx::threads::coroutines::detail { coroutine_self::set_self(val); } + reset_self_on_exit(reset_self_on_exit const&) = delete; + reset_self_on_exit(reset_self_on_exit&&) = delete; + + reset_self_on_exit& operator=(reset_self_on_exit const&) = delete; + reset_self_on_exit& operator=(reset_self_on_exit&&) = delete; + ~reset_self_on_exit() { coroutine_self::set_self(old_self); diff --git a/libs/core/coroutines/include/hpx/coroutines/detail/coroutine_stackful_self.hpp b/libs/core/coroutines/include/hpx/coroutines/detail/coroutine_stackful_self.hpp index 1ea891f357ba..8819b21ab375 100644 --- a/libs/core/coroutines/include/hpx/coroutines/detail/coroutine_stackful_self.hpp +++ b/libs/core/coroutines/include/hpx/coroutines/detail/coroutine_stackful_self.hpp @@ -10,11 +10,9 @@ #include #include #include -#include #include #include -#include #include #include diff --git a/libs/core/coroutines/include/hpx/coroutines/detail/coroutine_stackless_self.hpp b/libs/core/coroutines/include/hpx/coroutines/detail/coroutine_stackless_self.hpp index e44c8950cc3e..903e911817ff 100644 --- a/libs/core/coroutines/include/hpx/coroutines/detail/coroutine_stackless_self.hpp +++ b/libs/core/coroutines/include/hpx/coroutines/detail/coroutine_stackless_self.hpp @@ -11,10 +11,8 @@ #include #include #include -#include #include -#include #include #include diff --git a/libs/core/coroutines/include/hpx/coroutines/detail/posix_utility.hpp b/libs/core/coroutines/include/hpx/coroutines/detail/posix_utility.hpp index 88255e18080a..4af47013f87b 100644 --- a/libs/core/coroutines/include/hpx/coroutines/detail/posix_utility.hpp +++ b/libs/core/coroutines/include/hpx/coroutines/detail/posix_utility.hpp @@ -189,7 +189,7 @@ namespace hpx::threads::coroutines::detail::posix { * mmap (might be required on some systems) and/or * using a pooling allocator. * NOTE: the SuSv3 documentation explicitly allows - * the use of malloc to allocate stacks for makectx. + * the use of malloc to allocate stacks for makecontext. * We use new/delete for guaranteed alignment. */ inline void* alloc_stack(std::size_t size) diff --git a/libs/core/coroutines/include/hpx/coroutines/stackless_coroutine.hpp b/libs/core/coroutines/include/hpx/coroutines/stackless_coroutine.hpp index ff558d7168eb..b1783a6b8ba7 100644 --- a/libs/core/coroutines/include/hpx/coroutines/stackless_coroutine.hpp +++ b/libs/core/coroutines/include/hpx/coroutines/stackless_coroutine.hpp @@ -11,14 +11,16 @@ #include #include #include -#include #include #include #include #include -#include +#if defined(HPX_HAVE_THREAD_LOCAL_STORAGE) +#include +#endif #include +#include #include namespace hpx::threads::coroutines { @@ -60,7 +62,7 @@ namespace hpx::threads::coroutines { std::ptrdiff_t /*stack_size*/ = default_stack_size) noexcept : f_(HPX_MOVE(f)) , state_(context_state::ready) - , id_(id) + , id_(HPX_MOVE(id)) #if defined(HPX_HAVE_THREAD_PHASE_INFORMATION) , phase_(0) #endif @@ -118,9 +120,9 @@ namespace hpx::threads::coroutines { return detail::set_tss_thread_data(thread_data_, data); } #else - std::size_t set_thread_data(std::size_t data) noexcept + std::size_t set_thread_data(std::size_t data) const noexcept { - std::size_t olddata = thread_data_; + std::size_t const olddata = thread_data_; thread_data_ = data; return olddata; } @@ -175,7 +177,7 @@ namespace hpx::threads::coroutines { HPX_ASSERT(exited()); f_ = HPX_MOVE(f); - id_ = id; + id_ = HPX_MOVE(id); #if defined(HPX_HAVE_THREAD_PHASE_INFORMATION) phase_ = 0; @@ -194,7 +196,7 @@ namespace hpx::threads::coroutines { detail::delete_tss_storage(thread_data_); } #else - void reset_tss() noexcept + void reset_tss() const noexcept { thread_data_ = 0; } @@ -215,13 +217,18 @@ namespace hpx::threads::coroutines { private: struct reset_on_exit { - explicit constexpr reset_on_exit( - stackless_coroutine& this__) noexcept - : this_(this__) + explicit constexpr reset_on_exit(stackless_coroutine& that) noexcept + : this_(that) { this_.state_ = context_state::running; } + reset_on_exit(reset_on_exit const&) = delete; + reset_on_exit(reset_on_exit&&) = delete; + + reset_on_exit& operator=(reset_on_exit const&) = delete; + reset_on_exit& operator=(reset_on_exit&&) = delete; + ~reset_on_exit() { this_.state_ = context_state::exited; @@ -244,7 +251,7 @@ namespace hpx::threads::coroutines { return state_ == context_state::ready; } - constexpr std::ptrdiff_t get_available_stack_space() const noexcept + static constexpr std::ptrdiff_t get_available_stack_space() noexcept { return (std::numeric_limits::max)(); } @@ -294,9 +301,7 @@ namespace hpx::threads::coroutines { detail::reset_self_on_exit on_self_exit(&self, nullptr); { - reset_on_exit on_exit{*this}; - - HPX_UNUSED(on_exit); + [[maybe_unused]] reset_on_exit const on_exit{*this}; result = f_(arg); // invoke wrapped function diff --git a/libs/core/coroutines/include/hpx/coroutines/thread_id_type.hpp b/libs/core/coroutines/include/hpx/coroutines/thread_id_type.hpp index 2e71a241ffaa..4e5803ae70dc 100644 --- a/libs/core/coroutines/include/hpx/coroutines/thread_id_type.hpp +++ b/libs/core/coroutines/include/hpx/coroutines/thread_id_type.hpp @@ -10,8 +10,6 @@ #pragma once #include -#include -#include #include #include @@ -36,6 +34,8 @@ namespace hpx::threads { thread_id(thread_id const&) = default; thread_id& operator=(thread_id const&) = default; + ~thread_id() = default; + constexpr thread_id(thread_id&& rhs) noexcept : thrd_(rhs.thrd_) { @@ -136,23 +136,10 @@ namespace hpx::threads { return !(rhs < lhs); } - template - friend std::basic_ostream& operator<<( - std::basic_ostream& os, thread_id const& id) - { - os << id.get(); - return os; - } - - friend void format_value( - std::ostream& os, std::string_view spec, thread_id const& id) - { - // propagate spec - char format[16]; - std::snprintf( - format, 16, "{:%.*s}", (int) spec.size(), spec.data()); - hpx::util::format_to(os, format, id.get()); - } + HPX_CORE_EXPORT friend std::ostream& operator<<( + std::ostream& os, thread_id const& id); + HPX_CORE_EXPORT friend void format_value( + std::ostream& os, std::string_view spec, thread_id const& id); private: thread_id_repr thrd_ = nullptr; @@ -169,8 +156,10 @@ namespace hpx::threads { struct thread_data_reference_counting; - void intrusive_ptr_add_ref(thread_data_reference_counting* p) noexcept; - void intrusive_ptr_release(thread_data_reference_counting* p) noexcept; + HPX_CORE_EXPORT void intrusive_ptr_add_ref( + thread_data_reference_counting* p) noexcept; + HPX_CORE_EXPORT void intrusive_ptr_release( + thread_data_reference_counting* p) noexcept; struct thread_data_reference_counting { @@ -183,26 +172,23 @@ namespace hpx::threads { { } + thread_data_reference_counting( + thread_data_reference_counting const&) = delete; + thread_data_reference_counting( + thread_data_reference_counting&&) = delete; + thread_data_reference_counting& operator=( + thread_data_reference_counting const&) = delete; + thread_data_reference_counting& operator=( + thread_data_reference_counting&&) = delete; + virtual ~thread_data_reference_counting() = default; virtual void destroy_thread() = 0; // reference counting - friend void intrusive_ptr_add_ref( - thread_data_reference_counting* p) noexcept - { - ++p->count_; - } - - friend void intrusive_ptr_release( - thread_data_reference_counting* p) noexcept - { - HPX_ASSERT(p->count_ != 0); - if (--p->count_ == 0) - { - // give this object back to the system - p->destroy_thread(); - } - } + HPX_CORE_EXPORT friend void intrusive_ptr_add_ref( + thread_data_reference_counting* p) noexcept; + HPX_CORE_EXPORT friend void intrusive_ptr_release( + thread_data_reference_counting* p) noexcept; util::atomic_count count_; }; @@ -224,6 +210,8 @@ namespace hpx::threads { thread_id_ref(thread_id_ref&& rhs) noexcept = default; thread_id_ref& operator=(thread_id_ref&& rhs) noexcept = default; + ~thread_id_ref() = default; + explicit thread_id_ref(thread_id_repr const& thrd) noexcept : thrd_(thrd) { @@ -248,7 +236,7 @@ namespace hpx::threads { explicit thread_id_ref(thread_repr* thrd, thread_id_addref addref = thread_id_addref::yes) noexcept - : thrd_(thrd, addref == thread_id_addref::yes ? 1 : 0) + : thrd_(thrd, addref == thread_id_addref::yes) { } @@ -287,21 +275,21 @@ namespace hpx::threads { return nullptr != thrd_; } - constexpr thread_id noref() const noexcept + [[nodiscard]] constexpr thread_id noref() const noexcept { return thread_id(thrd_.get()); } - constexpr thread_id_repr& get() & noexcept + [[nodiscard]] constexpr thread_id_repr& get() & noexcept { return thrd_; } - thread_id_repr&& get() && noexcept + [[nodiscard]] thread_id_repr&& get() && noexcept { return HPX_MOVE(thrd_); } - constexpr thread_id_repr const& get() const& noexcept + [[nodiscard]] constexpr thread_id_repr const& get() const& noexcept { return thrd_; } @@ -383,23 +371,10 @@ namespace hpx::threads { return !(rhs < lhs); } - template - friend std::basic_ostream& operator<<( - std::basic_ostream& os, thread_id_ref const& id) - { - os << id.get(); - return os; - } - - friend void format_value( - std::ostream& os, std::string_view spec, thread_id_ref const& id) - { - // propagate spec - char format[16]; - std::snprintf( - format, 16, "{:%.*s}", (int) spec.size(), spec.data()); - hpx::util::format_to(os, format, id.get()); - } + HPX_CORE_EXPORT friend std::ostream& operator<<( + std::ostream& os, thread_id_ref const& id); + HPX_CORE_EXPORT friend void format_value( + std::ostream& os, std::string_view spec, thread_id_ref const& id); private: thread_id_repr thrd_; @@ -422,7 +397,7 @@ namespace std { std::size_t operator()( ::hpx::threads::thread_id const& v) const noexcept { - std::hash hasher_; + constexpr std::hash hasher_; return hasher_(reinterpret_cast(v.get())); } }; @@ -433,7 +408,7 @@ namespace std { std::size_t operator()( ::hpx::threads::thread_id_ref const& v) const noexcept { - std::hash hasher_; + constexpr std::hash hasher_; return hasher_(reinterpret_cast(v.get().get())); } }; diff --git a/libs/core/coroutines/src/detail/coroutine_self.cpp b/libs/core/coroutines/src/detail/coroutine_self.cpp index bf6a917ba61f..9ef24b0663ae 100644 --- a/libs/core/coroutines/src/detail/coroutine_self.cpp +++ b/libs/core/coroutines/src/detail/coroutine_self.cpp @@ -1,16 +1,12 @@ -// Copyright (c) 2008-2022 Hartmut Kaiser +// Copyright (c) 2008-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 - namespace hpx::threads::coroutines::detail { coroutine_self*& coroutine_self::local_self() noexcept diff --git a/libs/core/coroutines/src/detail/posix_utility.cpp b/libs/core/coroutines/src/detail/posix_utility.cpp index 8b50e4171d40..cfb53d9763d7 100644 --- a/libs/core/coroutines/src/detail/posix_utility.cpp +++ b/libs/core/coroutines/src/detail/posix_utility.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2005-2022 Hartmut Kaiser +// Copyright (c) 2005-2023 Hartmut Kaiser // Copyright (c) 2011 Bryce Adelstein-Lelbach // // SPDX-License-Identifier: BSL-1.0 @@ -14,9 +14,9 @@ namespace hpx::threads::coroutines::detail::posix { - /////////////////////////////////////////////////////////////////////// - // this global (urghhh) variable is used to control whether guard pages - // will be used or not + /////////////////////////////////////////////////////////////////////////// + // this global variable is used to control whether guard pages will be used + // or not bool use_guard_pages = true; } // namespace hpx::threads::coroutines::detail::posix diff --git a/libs/core/coroutines/src/thread_id_type.cpp b/libs/core/coroutines/src/thread_id_type.cpp new file mode 100644 index 000000000000..ddbfd0f95a58 --- /dev/null +++ b/libs/core/coroutines/src/thread_id_type.cpp @@ -0,0 +1,70 @@ +// Copyright (c) 2018 Thomas Heller +// Copyright (c) 2019-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 +#include +#include + +namespace hpx::threads { + + std::ostream& operator<<(std::ostream& os, thread_id const& id) + { + os << id.get(); + return os; + } + + void format_value( + std::ostream& os, std::string_view spec, thread_id const& id) + { + // propagate spec + char format[16]; + std::snprintf(format, sizeof(format), "{:%.*s}", + static_cast(spec.size()), spec.data()); + hpx::util::format_to(os, format, id.get()); + } + + namespace detail { + + // reference counting + void intrusive_ptr_add_ref(thread_data_reference_counting* p) noexcept + { + ++p->count_; + } + + void intrusive_ptr_release(thread_data_reference_counting* p) noexcept + { + HPX_ASSERT(p->count_ != 0); + if (--p->count_ == 0) + { + // give this object back to the system + p->destroy_thread(); + } + } + } // namespace detail + + /////////////////////////////////////////////////////////////////////////// + std::ostream& operator<<(std::ostream& os, thread_id_ref const& id) + { + os << id.get(); + return os; + } + + void format_value( + std::ostream& os, std::string_view spec, thread_id_ref const& id) + { + // propagate spec + char format[16]; + std::snprintf( + format, sizeof(format), "{:%.*s}", (int) spec.size(), spec.data()); + hpx::util::format_to(os, format, id.get()); + } +} // namespace hpx::threads diff --git a/libs/core/execution_base/include/hpx/execution_base/agent_base.hpp b/libs/core/execution_base/include/hpx/execution_base/agent_base.hpp index ffcc7e750a39..f45aca42ec7d 100644 --- a/libs/core/execution_base/include/hpx/execution_base/agent_base.hpp +++ b/libs/core/execution_base/include/hpx/execution_base/agent_base.hpp @@ -18,9 +18,9 @@ namespace hpx::execution_base { { virtual ~agent_base() = default; - virtual std::string description() const = 0; + [[nodiscard]] virtual std::string description() const = 0; - virtual context_base const& context() const noexcept = 0; + [[nodiscard]] virtual context_base const& context() const noexcept = 0; virtual void yield(char const* desc) = 0; virtual void yield_k(std::size_t k, char const* desc) = 0; diff --git a/libs/core/execution_base/include/hpx/execution_base/agent_ref.hpp b/libs/core/execution_base/include/hpx/execution_base/agent_ref.hpp index 84956fea1517..6c7b4d0ae37b 100644 --- a/libs/core/execution_base/include/hpx/execution_base/agent_ref.hpp +++ b/libs/core/execution_base/include/hpx/execution_base/agent_ref.hpp @@ -1,4 +1,5 @@ // Copyright (c) 2019 Thomas Heller +// Copyright (c) 2023 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -21,17 +22,17 @@ namespace hpx::execution_base { { public: agent_ref() = default; + ~agent_ref() = default; - constexpr agent_ref(agent_base* impl) noexcept + explicit constexpr agent_ref(agent_base* impl) noexcept : impl_(impl) { } - constexpr agent_ref(agent_ref const&) noexcept = default; - constexpr agent_ref& operator=(agent_ref const&) noexcept = default; - - constexpr agent_ref(agent_ref&&) noexcept = default; - constexpr agent_ref& operator=(agent_ref&&) noexcept = default; + agent_ref(agent_ref const&) = default; + agent_ref& operator=(agent_ref const&) = default; + agent_ref(agent_ref&&) = default; + agent_ref& operator=(agent_ref&&) = default; explicit constexpr operator bool() const noexcept { @@ -43,14 +44,16 @@ namespace hpx::execution_base { impl_ = impl; } - void yield(char const* desc = "hpx::execution_base::agent_ref::yield"); + void yield( + char const* desc = "hpx::execution_base::agent_ref::yield") const; void yield_k(std::size_t k, - char const* desc = "hpx::execution_base::agent_ref::yield_k"); + char const* desc = "hpx::execution_base::agent_ref::yield_k") const; void suspend( - char const* desc = "hpx::execution_base::agent_ref::suspend"); + char const* desc = "hpx::execution_base::agent_ref::suspend") const; void resume( - char const* desc = "hpx::execution_base::agent_ref::resume"); - void abort(char const* desc = "hpx::execution_base::agent_ref::abort"); + char const* desc = "hpx::execution_base::agent_ref::resume") const; + void abort( + char const* desc = "hpx::execution_base::agent_ref::abort") const; template void sleep_for(std::chrono::duration const& sleep_duration, @@ -67,7 +70,7 @@ namespace hpx::execution_base { sleep_until(hpx::chrono::steady_time_point{sleep_time}, desc); } - agent_base& ref() noexcept + [[nodiscard]] agent_base& ref() const noexcept { return *impl_; } @@ -81,9 +84,9 @@ namespace hpx::execution_base { agent_base* impl_ = nullptr; void sleep_for(hpx::chrono::steady_duration const& sleep_duration, - char const* desc); - void sleep_until( - hpx::chrono::steady_time_point const& sleep_time, char const* desc); + char const* desc) const; + void sleep_until(hpx::chrono::steady_time_point const& sleep_time, + char const* desc) const; friend constexpr bool operator==( agent_ref const& lhs, agent_ref const& rhs) noexcept diff --git a/libs/core/execution_base/include/hpx/execution_base/any_sender.hpp b/libs/core/execution_base/include/hpx/execution_base/any_sender.hpp index c6ec37671671..86f08ec8154a 100644 --- a/libs/core/execution_base/include/hpx/execution_base/any_sender.hpp +++ b/libs/core/execution_base/include/hpx/execution_base/any_sender.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2021 ETH Zurich -// Copyright (c) 2022 Hartmut Kaiser +// Copyright (c) 2022-2023 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -101,13 +101,13 @@ namespace hpx::detail { return fits_storage && sufficiently_aligned; } - bool using_embedded_storage() const noexcept + [[nodiscard]] bool using_embedded_storage() const noexcept { return object == reinterpret_cast(&data.embedded_storage); } - bool empty() const noexcept + [[nodiscard]] bool empty() const noexcept { return get().empty(); } @@ -193,12 +193,12 @@ namespace hpx::detail { movable_sbo_storage(movable_sbo_storage const&) = delete; movable_sbo_storage& operator=(movable_sbo_storage const&) = delete; - base_type const& get() const noexcept + [[nodiscard]] base_type const& get() const noexcept { return *object; } - base_type& get() noexcept + [[nodiscard]] base_type& get() noexcept { return *object; } @@ -268,6 +268,7 @@ namespace hpx::detail { using storage_base_type::store; copyable_sbo_storage() = default; + ~copyable_sbo_storage() = default; copyable_sbo_storage(copyable_sbo_storage&&) = default; copyable_sbo_storage& operator=(copyable_sbo_storage&&) = default; @@ -299,7 +300,7 @@ namespace hpx::execution::experimental::detail { { virtual ~any_operation_state_base() = default; - virtual bool empty() const noexcept + [[nodiscard]] virtual bool empty() const noexcept { return false; } @@ -309,21 +310,18 @@ namespace hpx::execution::experimental::detail { struct HPX_CORE_EXPORT empty_any_operation_state final : any_operation_state_base { - bool empty() const noexcept override; + [[nodiscard]] bool empty() const noexcept override; void start() & noexcept override; }; } // namespace hpx::execution::experimental::detail -namespace hpx::detail { - - template <> - struct empty_vtable_type< - hpx::execution::experimental::detail::any_operation_state_base> - { - using type = - hpx::execution::experimental::detail::empty_any_operation_state; - }; -} // namespace hpx::detail +template <> +struct hpx::detail::empty_vtable_type< + hpx::execution::experimental::detail::any_operation_state_base> +{ + using type = + hpx::execution::experimental::detail::empty_any_operation_state; +}; // namespace hpx::detail namespace hpx::execution::experimental::detail { @@ -383,7 +381,7 @@ namespace hpx::execution::experimental::detail { virtual void set_value(Ts... ts) && = 0; virtual void set_error(std::exception_ptr ep) && noexcept = 0; virtual void set_stopped() && noexcept = 0; - virtual bool empty() const noexcept + [[nodiscard]] virtual bool empty() const noexcept { return false; } @@ -400,7 +398,7 @@ namespace hpx::execution::experimental::detail { HPX_UNREACHABLE; } - bool empty() const noexcept override + [[nodiscard]] bool empty() const noexcept override { return true; } @@ -422,16 +420,13 @@ namespace hpx::execution::experimental::detail { }; } // namespace hpx::execution::experimental::detail -namespace hpx::detail { - - template - struct empty_vtable_type< - hpx::execution::experimental::detail::any_receiver_base> - { - using type = - hpx::execution::experimental::detail::empty_any_receiver; - }; -} // namespace hpx::detail +template +struct hpx::detail::empty_vtable_type< + hpx::execution::experimental::detail::any_receiver_base> +{ + using type = + hpx::execution::experimental::detail::empty_any_receiver; +}; // namespace hpx::detail namespace hpx::execution::experimental::detail { @@ -551,7 +546,7 @@ namespace hpx::execution::experimental::detail { virtual void move_into(void* p) = 0; virtual any_operation_state connect( any_receiver&& receiver) && = 0; - virtual bool empty() const noexcept + [[nodiscard]] virtual bool empty() const noexcept { return false; } @@ -576,7 +571,7 @@ namespace hpx::execution::experimental::detail { HPX_UNREACHABLE; } - bool empty() const noexcept override + [[nodiscard]] bool empty() const noexcept override { return true; } @@ -606,7 +601,7 @@ namespace hpx::execution::experimental::detail { HPX_UNREACHABLE; } - bool empty() const noexcept override + [[nodiscard]] bool empty() const noexcept override { return true; } diff --git a/libs/core/execution_base/include/hpx/execution_base/completion_signatures.hpp b/libs/core/execution_base/include/hpx/execution_base/completion_signatures.hpp index 36cafc74fdfa..7e26205bed5a 100644 --- a/libs/core/execution_base/include/hpx/execution_base/completion_signatures.hpp +++ b/libs/core/execution_base/include/hpx/execution_base/completion_signatures.hpp @@ -290,9 +290,10 @@ namespace hpx::execution::experimental { static constexpr bool sends_stopped = false; #if defined(HPX_HAVE_CXX20_COROUTINES) - bool await_ready(); - void await_suspend(hpx::coroutine_handle>); - dependent_completion_signatures await_resume(); + bool await_ready() = delete; + void await_suspend( + hpx::coroutine_handle>) = delete; + dependent_completion_signatures await_resume() = delete; #endif }; @@ -334,17 +335,16 @@ namespace hpx::execution::experimental { { }; - // sender only checks if T is an awaitable if enable_sender - // is false. Then it checks for awaitability with a promise type - // that doesn't have any environment queries, but that does have an - // await_transform that pipes the T through stdexec::as_awaitable. - // So you have two options for opting into the sender concept if you type - // is not generally awaitable: (1) specialize enable_sender, or (2) - // customize as_awaitable for T. + // sender only checks if T is an awaitable if enable_sender is + // false. Then it checks for awaitability with a promise type that + // doesn't have any environment queries, but that does have an + // await_transform that pipes the T through + // std::execution::as_awaitable. So you have two options for opting into + // the sender concept if you type is not generally awaitable: (1) + // specialize enable_sender, or (2) customize as_awaitable for T. HPX_HAS_MEMBER_XXX_TRAIT_DEF(is_sender) #ifdef HPX_HAVE_CXX20_COROUTINES - template inline constexpr bool is_enable_sender_v = has_is_sender_v; @@ -970,7 +970,7 @@ namespace hpx::execution::experimental { stopped_continuation.resume(); } friend coroutine_env_t tag_invoke( - get_env_t, const type& self) + get_env_t, type const& self) { if constexpr (hpx::functional::is_tag_invocable_v) @@ -996,7 +996,7 @@ namespace hpx::execution::experimental { template struct sender_awaitable_base { - constexpr bool await_ready() const noexcept + static constexpr bool await_ready() noexcept { return false; } @@ -1005,6 +1005,8 @@ namespace hpx::execution::experimental { { switch (result.index()) { + default: + [[fallthrough]]; case 0: // receiver contract not satisfied HPX_ASSERT_MSG(0, "_Should never get here"); break; @@ -1061,28 +1063,34 @@ namespace hpx::execution::experimental { if constexpr (hpx::functional::is_tag_invocable_v) { - using Result = + using result_type = hpx::functional::tag_invoke_result_t; constexpr bool Nothrow = hpx::functional::is_nothrow_tag_invocable_v; - return static_cast(nullptr); + return static_cast( + nullptr); } else if constexpr (is_awaitable_v) - { // NOT awaitable !! - return static_cast < T && (*) () noexcept > (nullptr); + { + // NOT awaitable !! + using func_type = T && (*) () noexcept; + return static_cast(nullptr); } else if constexpr (detail::is_awaitable_sender_v) { - using Result = detail::sender_awaitable_t; - constexpr bool Nothrow = std::is_nothrow_constructible_v>; - return static_cast(nullptr); + using result_type = detail::sender_awaitable_t; + constexpr bool Nothrow = + std::is_nothrow_constructible_v>; + return static_cast( + nullptr); } else { - return static_cast < T && (*) () noexcept > (nullptr); + using func_type = T && (*) () noexcept; + return static_cast(nullptr); } } @@ -1136,8 +1144,8 @@ namespace hpx::execution::experimental { } template - friend auto tag_invoke(get_env_t, const env_promise&) noexcept - -> const T&; + friend auto tag_invoke(get_env_t, env_promise const&) noexcept + -> T const&; }; struct with_awaitable_senders_base @@ -1176,7 +1184,7 @@ namespace hpx::execution::experimental { return continuation_handle; } - hpx::coroutine_handle<> unhandled_stopped() noexcept + hpx::coroutine_handle<> unhandled_stopped() const noexcept { return (*stopped_callback)(continuation_handle.address()); } @@ -1193,7 +1201,7 @@ namespace hpx::execution::experimental { // clang-format off template inline constexpr bool is_derived_from_v = std::is_base_of_v && - std::is_convertible_v; + std::is_convertible_v; // clang-format on template @@ -1211,22 +1219,22 @@ namespace hpx::execution::experimental { struct promise_base { - constexpr hpx::suspend_always initial_suspend() noexcept + static constexpr hpx::suspend_always initial_suspend() noexcept { return {}; } - [[noreturn]] hpx::suspend_always final_suspend() noexcept + [[noreturn]] static hpx::suspend_always final_suspend() noexcept { std::terminate(); } - [[noreturn]] void unhandled_exception() noexcept + [[noreturn]] static void unhandled_exception() noexcept { std::terminate(); } - [[noreturn]] void return_void() noexcept + [[noreturn]] static void return_void() noexcept { std::terminate(); } @@ -1238,7 +1246,7 @@ namespace hpx::execution::experimental { { Fun&& fun; - constexpr bool await_ready() noexcept + static constexpr bool await_ready() noexcept { return false; } @@ -1253,7 +1261,7 @@ namespace hpx::execution::experimental { HPX_FORWARD(Fun, fun)(); } - [[noreturn]] void await_resume() noexcept + [[noreturn]] static void await_resume() noexcept { std::terminate(); } @@ -1272,11 +1280,19 @@ namespace hpx::execution::experimental { { } + operation_base(operation_base const& other) = delete; operation_base(operation_base&& other) noexcept : coro_handle(std::exchange(other.coro_handle, {})) { } + operation_base& operator=(operation_base const&) = delete; + operation_base& operator=(operation_base&& rhs) noexcept + { + coro_handle = std::exchange(rhs.coro_handle, {}); + return *this; + } + ~operation_base() { if (coro_handle) @@ -1390,7 +1406,7 @@ namespace hpx::execution::experimental { fn_(); } - [[noreturn]] void await_resume() noexcept + [[noreturn]] static void await_resume() noexcept { std::terminate(); } @@ -1424,8 +1440,11 @@ namespace hpx::execution::experimental { eptr = std::current_exception(); } - co_await co_call(set_error, HPX_FORWARD(Receiver, rcvr), - HPX_FORWARD(std::exception_ptr, eptr)); + if (eptr) + { + co_await co_call(set_error, HPX_FORWARD(Receiver, rcvr), + HPX_FORWARD(std::exception_ptr, eptr)); + } } template struct sender_awaitable { - using Promise = hpx::meta::type; - using Sender = hpx::meta::type; - using Env = env_of_t; - using Value = single_sender_value_t; + using promise_type = hpx::meta::type; + using sender_type = hpx::meta::type; + using env_type = env_of_t; + using value_type = single_sender_value_t; - struct type : sender_awaitable_base + struct type : sender_awaitable_base { // clang-format off - type(Sender&& sender, hpx::coroutine_handle hcoro) - noexcept(has_nothrow_connect::value) - : op_state_(connect(HPX_FORWARD(Sender, sender), + type(sender_type&& sender, hpx::coroutine_handle hcoro) + noexcept(has_nothrow_connect::value) + : op_state_(connect(HPX_FORWARD(sender_type, sender), receiver{{&this->result, hcoro}})) { } // clang-format on - void await_suspend(hpx::coroutine_handle) noexcept + void await_suspend(hpx::coroutine_handle) noexcept { start(op_state_); } private: - using receiver = receiver_t; - connect_result_t op_state_; + using receiver = receiver_t; + connect_result_t op_state_; }; }; } // namespace detail diff --git a/libs/core/execution_base/include/hpx/execution_base/context_base.hpp b/libs/core/execution_base/include/hpx/execution_base/context_base.hpp index 64af64a2d448..8e88c7d65244 100644 --- a/libs/core/execution_base/include/hpx/execution_base/context_base.hpp +++ b/libs/core/execution_base/include/hpx/execution_base/context_base.hpp @@ -7,9 +7,6 @@ #pragma once #include -#include - -#include namespace hpx::execution_base { diff --git a/libs/core/execution_base/include/hpx/execution_base/coroutine_utils.hpp b/libs/core/execution_base/include/hpx/execution_base/coroutine_utils.hpp index ba79fd05fae8..2125f8e82331 100644 --- a/libs/core/execution_base/include/hpx/execution_base/coroutine_utils.hpp +++ b/libs/core/execution_base/include/hpx/execution_base/coroutine_utils.hpp @@ -1,4 +1,5 @@ // Copyright (c) 2022 Shreyas Atre +// Copyright (c) 2023 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -9,18 +10,7 @@ #include #if defined(HPX_HAVE_CXX20_COROUTINES) - -#include -#include -#include -#include #include -#include -#include - -#include -#include -#include namespace hpx::execution::experimental { @@ -33,14 +23,14 @@ namespace hpx::execution::experimental { // E names the type decltype((e)) and P names the type decltype((p)), // as_awaitable(e, p) is expression-equivalent to the following: // - // 1. tag_invoke(as_awaitable, e, p) - // if that expression is well-formed. - // -- Mandates: is-awaitable is true, - // where A is the type of the tag_invoke expression above. - // 2. Otherwise, e if is-awaitable is true. - // 3. Otherwise, sender-awaitable{e, p} if awaitable-sender + // 1. tag_invoke(as_awaitable, e, p) + // if that expression is well-formed. + // -- Mandates: is-awaitable is true, + // where A is the type of the tag_invoke expression above. + // 2. Otherwise, e if is-awaitable is true. + // 3. Otherwise, sender-awaitable{e, p} if awaitable-sender // is true. - // 4. Otherwise, e. + // 4. Otherwise, e. struct as_awaitable_t; struct connect_awaitable_t; diff --git a/libs/core/execution_base/include/hpx/execution_base/receiver.hpp b/libs/core/execution_base/include/hpx/execution_base/receiver.hpp index 84dfb965d1a1..61965b969ebb 100644 --- a/libs/core/execution_base/include/hpx/execution_base/receiver.hpp +++ b/libs/core/execution_base/include/hpx/execution_base/receiver.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2020 Thomas Heller -// Copyright (c) 2020 Hartmut Kaiser +// Copyright (c) 2020-2023 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -22,68 +22,73 @@ namespace hpx::execution::experimental { #if defined(DOXYGEN) /// set_value is a customization point object. The expression /// `hpx::execution::set_value(r, as...)` is equivalent to: - /// * `r.set_value(as...)`, if that expression is valid. If the function selected - /// does not send the value(s) `as...` to the Receiver `r`'s value channel, - /// the program is ill-formed (no diagnostic required). + /// * `r.set_value(as...)`, if that expression is valid. If the function + /// selected does not send the value(s) `as...` to the Receiver `r`'s + /// value channel, the program is ill-formed (no diagnostic required). /// * Otherwise, `set_value(r, as...), if that expression is valid, with - /// overload resolution performed in a context that include the declaration - /// `void set_value();` + /// overload resolution performed in a context that include the + /// declaration `void set_value();` /// * Otherwise, the expression is ill-formed. /// - /// The customization is implemented in terms of `hpx::functional::tag_invoke`. + /// The customization is implemented in terms of + /// `hpx::functional::tag_invoke`. template void set_value(R&& r, As&&... as); /// set_stopped is a customization point object. The expression /// `hpx::execution::set_stopped(r)` is equivalent to: - /// * `r.set_stopped()`, if that expression is valid. If the function selected - /// does not signal the Receiver `r`'s done channel, - /// the program is ill-formed (no diagnostic required). + /// * `r.set_stopped()`, if that expression is valid. If the function + /// selected does not signal the Receiver `r`'s done channel, the + /// program is ill-formed (no diagnostic required). /// * Otherwise, `set_stopped(r), if that expression is valid, with - /// overload resolution performed in a context that include the declaration - /// `void set_stopped();` + /// overload resolution performed in a context that include the + /// declaration `void set_stopped();` /// * Otherwise, the expression is ill-formed. /// - /// The customization is implemented in terms of `hpx::functional::tag_invoke`. + /// The customization is implemented in terms of + /// `hpx::functional::tag_invoke`. template void set_stopped(R&& r); /// set_error is a customization point object. The expression /// `hpx::execution::set_error(r, e)` is equivalent to: - /// * `r.set_stopped(e)`, if that expression is valid. If the function selected - /// does not send the error `e` the Receiver `r`'s error channel, - /// the program is ill-formed (no diagnostic required). + /// * `r.set_stopped(e)`, if that expression is valid. If the function + /// selected does not send the error `e` the Receiver `r`'s error + /// channel, the program is ill-formed (no diagnostic required). /// * Otherwise, `set_error(r, e), if that expression is valid, with - /// overload resolution performed in a context that include the declaration - /// `void set_error();` + /// overload resolution performed in a context that include the + /// declaration `void set_error();` /// * Otherwise, the expression is ill-formed. /// - /// The customization is implemented in terms of `hpx::functional::tag_invoke`. + /// The customization is implemented in terms of + /// `hpx::functional::tag_invoke`. template void set_error(R&& r, E&& e); #endif - /// Receiving values from asynchronous computations is handled by the `Receiver` - /// concept. A `Receiver` needs to be able to receive an error or be marked as - /// being canceled. As such, the Receiver concept is defined by having the - /// following two customization points defined, which form the completion-signal - /// operations: - /// * `hpx::execution::experimental::set_stopped` - /// * `hpx::execution::experimental::set_error` + /// Receiving values from asynchronous computations is handled by the + /// `Receiver` concept. A `Receiver` needs to be able to receive an error or + /// be marked as being canceled. As such, the Receiver concept is defined by + /// having the following two customization points defined, which form the + /// completion-signal operations: + /// * `hpx::execution::experimental::set_stopped` * + /// `hpx::execution::experimental::set_error` /// - /// Those two functions denote the completion-signal operations. The Receiver - /// contract is as follows: + /// Those two functions denote the completion-signal operations. The + /// Receiver contract is as follows: /// * None of a Receiver's completion-signal operation shall be invoked - /// before `hpx::execution::experimental::start` has been called on the operation - /// state object that was returned by connecting a Receiver to a sender - /// `hpx::execution::experimental::connect`. + /// before `hpx::execution::experimental::start` has been called on + /// the operation state object that was returned by connecting a + /// Receiver to a sender `hpx::execution::experimental::connect`. /// * Once `hpx::execution::start` has been called on the operation - /// state object, exactly one of the Receiver's completion-signal operation - /// shall complete without an exception before the Receiver is destroyed + /// state object, exactly one of the Receiver's completion-signal + /// operation shall complete without an exception before the Receiver + /// is destroyed /// - /// Once one of the Receiver's completion-signal operation has been completed - /// without throwing an exception, the Receiver contract has been satisfied. - /// In other words: The asynchronous operation has been completed. + /// Once one of the Receiver's completion-signal operation has been + /// completed without throwing an exception, the Receiver contract has been + /// satisfied. In other words: The asynchronous operation has been + /// completed. /// /// \see hpx::execution::experimental::is_receiver_of template @@ -94,13 +99,12 @@ namespace hpx::execution::experimental { /// * `hpx::execution::set_value` /// /// The `receiver_of` concept takes a receiver and an instance of the - /// `completion_signatures<>` class template. - /// The `receiver_of` concept, rather than accepting a receiver and some - /// value types, is changed to take a receiver and an instance of the - /// `completion_signatures<>` class template. - /// A sender uses `completion_signatures<>` to describe the signals - /// with which it completes. The `receiver_of` concept ensures that a - /// particular receiver is capable of receiving those signals. + /// `completion_signatures<>` class template. The `receiver_of` concept, + /// rather than accepting a receiver and some value types, is changed to + /// take a receiver and an instance of the `completion_signatures<>` class + /// template. A sender uses `completion_signatures<>` to describe the + /// signals with which it completes. The `receiver_of` concept ensures that + /// a particular receiver is capable of receiving those signals. /// /// This completion-signal operation adds the following to the Receiver's /// contract: @@ -150,8 +154,8 @@ namespace hpx::execution::experimental { template struct is_receiver : detail::is_receiver_impl< - std::is_move_constructible>::value && - std::is_constructible, T>::value, + std::is_move_constructible_v> && + std::is_constructible_v, T>, T, E> { }; diff --git a/libs/core/execution_base/include/hpx/execution_base/sender.hpp b/libs/core/execution_base/include/hpx/execution_base/sender.hpp index f0de58c030a8..e9da414662f5 100644 --- a/libs/core/execution_base/include/hpx/execution_base/sender.hpp +++ b/libs/core/execution_base/include/hpx/execution_base/sender.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2020 Thomas Heller -// Copyright (c) 2022 Hartmut Kaiser +// Copyright (c) 2022-2023 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -20,9 +20,7 @@ #include #include -#include #include -#include namespace hpx::execution::experimental { @@ -126,12 +124,12 @@ namespace hpx::execution::experimental { } template - [[noreturn]] void set_error(E_&&) noexcept + [[noreturn]] static void set_error(E_&&) noexcept { std::terminate(); } - constexpr void set_stopped() noexcept {} + static constexpr void set_stopped() noexcept {} }; } // namespace detail diff --git a/libs/core/execution_base/include/hpx/execution_base/this_thread.hpp b/libs/core/execution_base/include/hpx/execution_base/this_thread.hpp index d7f86cf5e336..6bfa339d87e5 100644 --- a/libs/core/execution_base/include/hpx/execution_base/this_thread.hpp +++ b/libs/core/execution_base/include/hpx/execution_base/this_thread.hpp @@ -10,16 +10,15 @@ #include #include #include -#include #include #include #include #include #include -#include #ifdef HPX_HAVE_SPINLOCK_DEADLOCK_DETECTION #include +#include #endif #include @@ -47,6 +46,11 @@ namespace hpx::execution_base { explicit reset_agent(agent_base& impl); reset_agent(detail::agent_storage*, agent_base& impl); + reset_agent(reset_agent const&) = delete; + reset_agent(reset_agent&&) = delete; + reset_agent& operator=(reset_agent const&) = delete; + reset_agent& operator=(reset_agent&&) = delete; + ~reset_agent(); detail::agent_storage* storage_; @@ -225,7 +229,7 @@ namespace hpx::util { using duration_type = std::chrono::duration; // Initialize timer only if needed - bool use_timeout = timeout >= duration_type(0.0); + bool const use_timeout = timeout >= duration_type(0.0); hpx::chrono::high_resolution_timer t( hpx::chrono::high_resolution_timer::init::no_init); diff --git a/libs/core/execution_base/include/hpx/execution_base/traits/coroutine_traits.hpp b/libs/core/execution_base/include/hpx/execution_base/traits/coroutine_traits.hpp index e02cef46ed81..665fd4f077a6 100644 --- a/libs/core/execution_base/include/hpx/execution_base/traits/coroutine_traits.hpp +++ b/libs/core/execution_base/include/hpx/execution_base/traits/coroutine_traits.hpp @@ -184,7 +184,7 @@ namespace hpx::execution::experimental { // member then the awaitable is the awaited value itself. // // The awaitable concept simply checks whether the type supports applying - // the co_await operator to avalue of that type. If the object has either a + // the co_await operator to a value of that type. If the object has either a // member or non-member operator co_await() then its return value must // satisfy the Awaiter concept. Otherwise, the Awaitable object must satisfy // the Awaiter concept itself. diff --git a/libs/core/execution_base/src/agent_ref.cpp b/libs/core/execution_base/src/agent_ref.cpp index bfa511108788..4aaad279ad71 100644 --- a/libs/core/execution_base/src/agent_ref.cpp +++ b/libs/core/execution_base/src/agent_ref.cpp @@ -15,7 +15,7 @@ namespace hpx::execution_base { - void agent_ref::yield(const char* desc) + void agent_ref::yield(const char* desc) const { HPX_ASSERT(*this == hpx::execution_base::this_thread::agent()); @@ -24,7 +24,7 @@ namespace hpx::execution_base { impl_->yield(desc); } - void agent_ref::yield_k(std::size_t k, const char* desc) + void agent_ref::yield_k(std::size_t k, const char* desc) const { HPX_ASSERT(*this == hpx::execution_base::this_thread::agent()); @@ -33,7 +33,7 @@ namespace hpx::execution_base { impl_->yield_k(k, desc); } - void agent_ref::suspend(const char* desc) + void agent_ref::suspend(const char* desc) const { HPX_ASSERT(*this == hpx::execution_base::this_thread::agent()); @@ -42,27 +42,29 @@ namespace hpx::execution_base { impl_->suspend(desc); } - void agent_ref::resume(const char* desc) + void agent_ref::resume(const char* desc) const { HPX_ASSERT(*this != hpx::execution_base::this_thread::agent()); impl_->resume(desc); } - void agent_ref::abort(const char* desc) + void agent_ref::abort(const char* desc) const { HPX_ASSERT(*this != hpx::execution_base::this_thread::agent()); impl_->abort(desc); } void agent_ref::sleep_for( - hpx::chrono::steady_duration const& sleep_duration, const char* desc) + hpx::chrono::steady_duration const& sleep_duration, + const char* desc) const { HPX_ASSERT(*this == hpx::execution_base::this_thread::agent()); impl_->sleep_for(sleep_duration, desc); } void agent_ref::sleep_until( - hpx::chrono::steady_time_point const& sleep_time, const char* desc) + hpx::chrono::steady_time_point const& sleep_time, + const char* desc) const { HPX_ASSERT(*this == hpx::execution_base::this_thread::agent()); impl_->sleep_until(sleep_time, desc); diff --git a/libs/core/execution_base/src/spinlock_deadlock_detection.cpp b/libs/core/execution_base/src/spinlock_deadlock_detection.cpp index 6cbdf82b2caf..01b03855050b 100644 --- a/libs/core/execution_base/src/spinlock_deadlock_detection.cpp +++ b/libs/core/execution_base/src/spinlock_deadlock_detection.cpp @@ -9,12 +9,12 @@ //////////////////////////////////////////////////////////////////////////////// #include + +#ifdef HPX_HAVE_SPINLOCK_DEADLOCK_DETECTION #include #include -#ifdef HPX_HAVE_SPINLOCK_DEADLOCK_DETECTION - namespace hpx::util::detail { static bool spinlock_break_on_deadlock_enabled = false; @@ -41,4 +41,5 @@ namespace hpx::util::detail { return spinlock_deadlock_detection_limit; } } // namespace hpx::util::detail + #endif diff --git a/libs/core/execution_base/src/this_thread.cpp b/libs/core/execution_base/src/this_thread.cpp index b2727d338329..93aece98c9cb 100644 --- a/libs/core/execution_base/src/this_thread.cpp +++ b/libs/core/execution_base/src/this_thread.cpp @@ -52,12 +52,13 @@ namespace hpx::execution_base { { default_agent(); - std::string description() const override + [[nodiscard]] std::string description() const override { return hpx::util::format("{}", id_); } - default_context const& context() const noexcept override + [[nodiscard]] default_context const& context() + const noexcept override { return context_; } @@ -199,7 +200,7 @@ namespace hpx::execution_base { namespace detail { - agent_base& get_default_agent() + [[nodiscard]] agent_base& get_default_agent() { static thread_local default_agent agent; return agent; @@ -226,7 +227,7 @@ namespace hpx::execution_base { agent_base* impl_; }; - agent_storage* get_agent_storage() + [[nodiscard]] agent_storage* get_agent_storage() { static thread_local agent_storage storage; return &storage; @@ -250,10 +251,9 @@ namespace hpx::execution_base { storage_->set(old_); } - hpx::execution_base::agent_ref agent() + [[nodiscard]] agent_ref agent() { - return hpx::execution_base::agent_ref( - detail::get_agent_storage()->impl_); + return agent_ref(detail::get_agent_storage()->impl_); } void yield(char const* desc) diff --git a/libs/core/futures/include/hpx/futures/future.hpp b/libs/core/futures/include/hpx/futures/future.hpp index 0a0a1c8d9592..8cdec07b98cd 100644 --- a/libs/core/futures/include/hpx/futures/future.hpp +++ b/libs/core/futures/include/hpx/futures/future.hpp @@ -920,6 +920,47 @@ namespace hpx { using base_type::is_ready; using base_type::valid; + /// \brief Attaches a continuation to \a *this. The behavior is undefined + /// if \a *this has no associated shared state (i.e., + /// \a valid()==false ). + /// \details In cases where \a decltype(func(*this)) is \a future, + /// the resulting type is \a future instead of + /// \a future>. + /// Effects: + /// - The continuation is called when the object's shared + /// state is ready (has a value or exception stored). + /// - The continuation launches according to the specified + /// launch policy or executor. + /// - When the executor or launch policy is not provided the + /// continuation inherits the parent's launch policy or + /// executor. + /// - If the parent was created with \a std::promise or with a + /// packaged_task (has no associated launch policy), the + /// continuation behaves the same as the third overload + /// with a policy argument of \a launch::async | + /// \a launch::deferred and the same argument for \a func. + /// - If the parent has a policy of \a launch::deferred and the + /// continuation does not have a specified launch policy or + /// scheduler, then the parent is filled by immediately + /// calling \a .wait(), and the policy of the antecedent is + /// \a launch::deferred + /// + /// \tparam F The type of the function/function object to use + /// (deduced). F must meet requirements of + /// \a MoveConstructible. + /// \tparam error_code The type of error code. + /// + /// \param f A continuation to be attached. + /// \param ec Used to hold error code value originated during the + /// operation. Defaults to \a throws -- A special + /// 'throw on error' \a error_code. + /// \returns An object of type \a future that + /// refers to the shared state created by the continuation. + /// \note Postcondition: + /// - The future object is moved to the parameter of the + /// continuation function. + /// - valid() == false on original future object immediately + /// after it returns. template decltype(auto) then(F&& f, error_code& ec = throws) { @@ -941,6 +982,27 @@ namespace hpx { #endif } + /// \copybrief hpx::future::then(F&& f, error_code& ec = throws) + /// \copydetail hpx::future::then(F&& f, error_code& ec = throws) + /// + /// \tparam T0 The type of executor or launch policy. + /// \tparam F The type of the function/function object to use + /// (deduced). F must meet requirements of + /// \a MoveConstructible. + /// \tparam error_code The type of error code. + /// + /// \param t0 The executor or launch policy to be used. + /// \param f A continuation to be attached. + /// \param ec Used to hold error code value originated during the + /// operation. Defaults to \a throws -- A special + /// 'throw on error' \a error_code. + /// \returns An object of type \a future that + /// refers to the shared state created by the continuation. + /// \note Postcondition: + /// - The future object is moved to the parameter of the + /// continuation function. + /// - valid() == false on original future object immediately + /// after it returns. template decltype(auto) then(T0&& t0, F&& f, error_code& ec = throws) { @@ -1203,6 +1265,7 @@ namespace hpx { using base_type::is_ready; using base_type::valid; + /// \copydoc hpx::future::then(F&& f, error_code& ec = throws) template decltype(auto) then(F&& f, error_code& ec = throws) const { @@ -1218,6 +1281,7 @@ namespace hpx { #endif } + /// \copydoc hpx::future::then(T0&& t0, F&& f, error_code& ec = throws) template decltype(auto) then(T0&& t0, F&& f, error_code& ec = throws) const { diff --git a/libs/core/ini/include/hpx/ini/ini.hpp b/libs/core/ini/include/hpx/ini/ini.hpp index 48dbafb588a9..08405e296eb5 100644 --- a/libs/core/ini/include/hpx/ini/ini.hpp +++ b/libs/core/ini/include/hpx/ini/ini.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2005-2007 Andre Merzky -// Copyright (c) 2005-2022 Hartmut Kaiser +// Copyright (c) 2005-2023 Hartmut Kaiser // Copyright (c) 2011 Bryce Lelbach // // SPDX-License-Identifier: BSL-1.0 @@ -73,7 +73,7 @@ namespace hpx::util { protected: void line_msg(std::string msg, std::string const& file, int lnum = 0, - std::string const& line = ""); + std::string const& line = "") const; section& clone_from(section const& rhs, section* root = nullptr); @@ -104,7 +104,7 @@ namespace hpx::util { std::string get_entry( std::unique_lock& l, std::string const& key) const; std::string get_entry(std::unique_lock& l, - std::string const& key, std::string const& dflt) const; + std::string const& key, std::string const& default_val) const; void add_notification_callback(std::unique_lock& l, std::string const& key, entry_changed_func const& callback); @@ -132,7 +132,7 @@ namespace hpx::util { } void read(std::string const& filename); - void merge(std::string const& second); + void merge(std::string const& filename); void merge(section& second); void dump(int ind = 0) const; void dump(int ind, std::ostream& strm) const; @@ -229,7 +229,7 @@ namespace hpx::util { private: std::string expand( - std::unique_lock& l, std::string in) const; + std::unique_lock& l, std::string value) const; void expand(std::unique_lock& l, std::string&, std::string::size_type) const; @@ -238,8 +238,8 @@ namespace hpx::util { void expand_brace(std::unique_lock& l, std::string&, std::string::size_type) const; - std::string expand_only(std::unique_lock& l, std::string in, - std::string const& expand_this) const; + std::string expand_only(std::unique_lock& l, + std::string value, std::string const& expand_this) const; void expand_only(std::unique_lock& l, std::string&, std::string::size_type, std::string const& expand_this) const; @@ -266,9 +266,8 @@ namespace hpx::util { root_ = r; if (recursive) { - section_map::iterator send = sections_.end(); - for (section_map::iterator si = sections_.begin(); si != send; - ++si) + auto const send = sections_.end(); + for (auto si = sections_.begin(); si != send; ++si) si->second.set_root(r, true); } } diff --git a/libs/core/ini/src/ini.cpp b/libs/core/ini/src/ini.cpp index 3c38c1338637..45b47440e304 100644 --- a/libs/core/ini/src/ini.cpp +++ b/libs/core/ini/src/ini.cpp @@ -56,11 +56,11 @@ namespace hpx::util { { typedef std::string::size_type size_type; - size_type first = s.find_first_not_of(" \t\r\n"); + size_type const first = s.find_first_not_of(" \t\r\n"); if (std::string::npos == first) return (std::string()); - size_type last = s.find_last_not_of(" \t\r\n"); + size_type const last = s.find_last_not_of(" \t\r\n"); return s.substr(first, last - first + 1); } @@ -101,13 +101,13 @@ namespace hpx::util { , parent_name_(in.get_parent_name()) { entry_map const& e = in.get_entries(); - entry_map::const_iterator end = e.end(); - for (entry_map::const_iterator i = e.begin(); i != end; ++i) + auto const end = e.end(); + for (auto i = e.begin(); i != end; ++i) add_entry(i->first, i->second); section_map s = in.get_sections(); - section_map::iterator send = s.end(); - for (section_map::iterator si = s.begin(); si != send; ++si) + auto const send = s.end(); + for (auto si = s.begin(); si != send; ++si) add_section(si->first, si->second, get_root()); } @@ -122,13 +122,13 @@ namespace hpx::util { name_ = rhs.get_name(); entry_map const& e = rhs.get_entries(); - entry_map::const_iterator end = e.end(); - for (entry_map::const_iterator i = e.begin(); i != end; ++i) + auto const end = e.end(); + for (auto i = e.begin(); i != end; ++i) add_entry(l, i->first, i->first, i->second); section_map s = rhs.get_sections(); - section_map::iterator send = s.end(); - for (section_map::iterator si = s.begin(); si != send; ++si) + auto const send = s.end(); + for (auto si = s.begin(); si != send; ++si) add_section(l, si->first, si->second, get_root()); } return *this; @@ -145,13 +145,13 @@ namespace hpx::util { name_ = rhs.get_name(); entry_map const& e = rhs.get_entries(); - entry_map::const_iterator end = e.end(); - for (entry_map::const_iterator i = e.begin(); i != end; ++i) + auto const end = e.end(); + for (auto i = e.begin(); i != end; ++i) add_entry(l, i->first, i->first, i->second); section_map s = rhs.get_sections(); - section_map::iterator send = s.end(); - for (section_map::iterator si = s.begin(); si != send; ++si) + auto const send = s.end(); + for (auto si = s.begin(); si != send; ++si) add_section(l, si->first, si->second, get_root()); } return *this; @@ -187,7 +187,7 @@ namespace hpx::util { bool force_entry(std::string& str) { - std::string::size_type p = str.find_last_of('!'); + std::string::size_type const p = str.find_last_of('!'); if (p != std::string::npos && str.find_first_not_of(" \t", p + 1) == std::string::npos) { @@ -207,9 +207,8 @@ namespace hpx::util { std::regex regex_comment(pattern_comment, std::regex_constants::icase); - std::vector::const_iterator end = lines.end(); - for (std::vector::const_iterator it = lines.begin(); - it != end; ++it) + auto const end = lines.end(); + for (auto it = lines.begin(); it != end; ++it) { ++linenum; @@ -233,17 +232,17 @@ namespace hpx::util { continue; } } - // no comments anymore: line is either section, key=val, - // or garbage/empty + // no comments anymore: line is either section, key=val, or + // garbage/empty - // Check if we have a section. - // Example: [sec.ssec] + // Check if we have a section. Example: [sec.ssec] if (line.front() == '[' && line.back() == ']') { current = this; // start adding sections at the root - // got the section name. It might be hierarchical, so split it up, and - // for each elem, check if we have it. If not, create it, and add + // got the section name. It might be hierarchical, so split it + // up, and for each elem, check if we have it. If not, create + // it, and add std::string sec_name(line.substr(1, line.size() - 2)); std::string::size_type pos = 0; for (std::string::size_type pos1 = sec_name.find_first_of('.'); @@ -348,15 +347,15 @@ namespace hpx::util { bool section::has_section( std::unique_lock& l, std::string const& sec_name) const { - std::string::size_type i = sec_name.find('.'); + std::string::size_type const i = sec_name.find('.'); if (i != std::string::npos) { - std::string cor_sec_name = sec_name.substr(0, i); + std::string const cor_sec_name = sec_name.substr(0, i); - section_map::const_iterator it = sections_.find(cor_sec_name); + auto const it = sections_.find(cor_sec_name); if (it != sections_.end()) { - std::string sub_sec_name = sec_name.substr(i + 1); + std::string const sub_sec_name = sec_name.substr(i + 1); hpx::unlock_guard> ul(l); return (*it).second.has_section(sub_sec_name); } @@ -368,14 +367,14 @@ namespace hpx::util { section* section::get_section( std::unique_lock& l, std::string const& sec_name) { - std::string::size_type i = sec_name.find('.'); + std::string::size_type const i = sec_name.find('.'); if (i != std::string::npos) { - std::string cor_sec_name = sec_name.substr(0, i); - section_map::iterator it = sections_.find(cor_sec_name); + std::string const cor_sec_name = sec_name.substr(0, i); + auto const it = sections_.find(cor_sec_name); if (it != sections_.end()) { - std::string sub_sec_name = sec_name.substr(i + 1); + std::string const sub_sec_name = sec_name.substr(i + 1); hpx::unlock_guard> ul(l); return (*it).second.get_section(sub_sec_name); } @@ -387,29 +386,27 @@ namespace hpx::util { HPX_THROW_EXCEPTION(hpx::error::bad_parameter, "section::get_section", "No such section ({}) in section: {}", sec_name, name); - return nullptr; } - section_map::iterator it = sections_.find(sec_name); + auto const it = sections_.find(sec_name); if (it != sections_.end()) return &((*it).second); HPX_THROW_EXCEPTION(hpx::error::bad_parameter, "section::get_section", "No such section ({}) in section: {}", sec_name, get_name()); - return nullptr; } section const* section::get_section( std::unique_lock& l, std::string const& sec_name) const { - std::string::size_type i = sec_name.find('.'); + std::string::size_type const i = sec_name.find('.'); if (i != std::string::npos) { - std::string cor_sec_name = sec_name.substr(0, i); - section_map::const_iterator it = sections_.find(cor_sec_name); + std::string const cor_sec_name = sec_name.substr(0, i); + auto const it = sections_.find(cor_sec_name); if (it != sections_.end()) { - std::string sub_sec_name = sec_name.substr(i + 1); + std::string const sub_sec_name = sec_name.substr(i + 1); hpx::unlock_guard> ul(l); return (*it).second.get_section(sub_sec_name); } @@ -421,32 +418,30 @@ namespace hpx::util { HPX_THROW_EXCEPTION(hpx::error::bad_parameter, "section::get_section", "No such section ({}) in section: {}", sec_name, name); - return nullptr; } - section_map::const_iterator it = sections_.find(sec_name); + auto const it = sections_.find(sec_name); if (it != sections_.end()) return &((*it).second); HPX_THROW_EXCEPTION(hpx::error::bad_parameter, "section::get_section", "No such section ({}) in section: {}", sec_name, get_name()); - return nullptr; } void section::add_entry(std::unique_lock& l, std::string const& fullkey, std::string const& key, std::string val) { // first expand the full property name in the value (avoids infinite recursion) - expand_only( - l, val, std::string::size_type(-1), get_full_name() + "." + key); + expand_only(l, val, static_cast(-1), + get_full_name() + "." + key); - std::string::size_type i = key.find_last_of('.'); + std::string::size_type const i = key.find_last_of('.'); if (i != std::string::npos) { section* current = root_; // make sure all sections in key exist - std::string sec_name = key.substr(0, i); + std::string const sec_name = key.substr(0, i); std::string::size_type pos = 0; for (std::string::size_type pos1 = sec_name.find_first_of('.'); @@ -464,15 +459,15 @@ namespace hpx::util { } else { - entry_map::iterator it = entries_.find(key); + auto const it = entries_.find(key); if (it != entries_.end()) { auto& e = it->second; e.first = HPX_MOVE(val); if (!e.second.empty()) { - std::string value = e.first; - entry_changed_func f = e.second; + std::string const value = e.first; + entry_changed_func const f = e.second; hpx::unlock_guard> ul(l); f(fullkey, value); @@ -490,13 +485,13 @@ namespace hpx::util { std::string const& fullkey, std::string const& key, entry_type const& val) { - std::string::size_type i = key.find_last_of('.'); + std::string::size_type const i = key.find_last_of('.'); if (i != std::string::npos) { section* current = root_; // make sure all sections in key exist - std::string sec_name = key.substr(0, i); + std::string const sec_name = key.substr(0, i); std::string::size_type pos = 0; for (std::string::size_type pos1 = sec_name.find_first_of('.'); @@ -514,15 +509,15 @@ namespace hpx::util { } else { - entry_map::iterator it = entries_.find(key); + auto const it = entries_.find(key); if (it != entries_.end()) { auto& second = it->second; second = val; if (!second.second.empty()) { - std::string value = second.first; - entry_changed_func f = second.second; + std::string const value = second.first; + entry_changed_func const f = second.second; hpx::unlock_guard> ul(l); f(fullkey, value); @@ -531,19 +526,19 @@ namespace hpx::util { else { // just add this entry to the section - std::pair p = + std::pair const p = entries_.emplace(key, val); HPX_ASSERT(p.second); - auto& second = p.first->second; + auto const& second = p.first->second; if (!second.second.empty()) { - std::string key = p.first->first; - std::string value = second.first; - entry_changed_func f = second.second; + std::string const k = p.first->first; + std::string const value = second.first; + entry_changed_func const f = second.second; hpx::unlock_guard> ul(l); - f(key, value); + f(k, value); } } } @@ -591,13 +586,13 @@ namespace hpx::util { void section::add_notification_callback(std::unique_lock& l, std::string const& key, entry_changed_func const& callback) { - std::string::size_type i = key.find_last_of('.'); + std::string::size_type const i = key.find_last_of('.'); if (i != std::string::npos) { section* current = root_; // make sure all sections in key exist - std::string sec_name = key.substr(0, i); + std::string const sec_name = key.substr(0, i); std::string::size_type pos = 0; for (std::string::size_type pos1 = sec_name.find_first_of('.'); @@ -616,7 +611,7 @@ namespace hpx::util { else { // just add this entry to the section - entry_map::iterator it = entries_.find(key); + auto const it = entries_.find(key); if (it != entries_.end()) { it->second.second = @@ -632,14 +627,14 @@ namespace hpx::util { bool section::has_entry( std::unique_lock& l, std::string const& key) const { - std::string::size_type i = key.find('.'); + std::string::size_type const i = key.find('.'); if (i != std::string::npos) { - std::string sub_sec = key.substr(0, i); + std::string const sub_sec = key.substr(0, i); if (has_section(l, sub_sec)) { - std::string sub_key = key.substr(i + 1, key.size() - i); - section_map::const_iterator cit = sections_.find(sub_sec); + std::string const sub_key = key.substr(i + 1, key.size() - i); + auto const cit = sections_.find(sub_sec); HPX_ASSERT(cit != sections_.end()); hpx::unlock_guard> ul(l); return (*cit).second.has_entry(sub_key); //-V783 @@ -652,14 +647,14 @@ namespace hpx::util { std::string section::get_entry( std::unique_lock& l, std::string const& key) const { - std::string::size_type i = key.find('.'); - if (i != std::string::npos) + if (std::string::size_type const i = key.find('.'); + i != std::string::npos) { - std::string sub_sec = key.substr(0, i); + std::string const sub_sec = key.substr(0, i); if (has_section(l, sub_sec)) { - std::string sub_key = key.substr(i + 1, key.size() - i); - section_map::const_iterator cit = sections_.find(sub_sec); + std::string const sub_key = key.substr(i + 1, key.size() - i); + auto const cit = sections_.find(sub_sec); HPX_ASSERT(cit != sections_.end()); hpx::unlock_guard> ul(l); return (*cit).second.get_entry(sub_key); //-V783 @@ -667,19 +662,17 @@ namespace hpx::util { HPX_THROW_EXCEPTION(hpx::error::bad_parameter, "section::get_entry", "No such key ({}) in section: {}", key, get_name()); - return ""; } if (entries_.find(key) != entries_.end()) { - entry_map::const_iterator cit = entries_.find(key); + auto const cit = entries_.find(key); HPX_ASSERT(cit != entries_.end()); return expand(l, (*cit).second.first); //-V783 } HPX_THROW_EXCEPTION(hpx::error::bad_parameter, "section::get_entry", "No such section ({}) in section: {}", key, get_name()); - return ""; } std::string section::get_entry(std::unique_lock& l, @@ -691,22 +684,19 @@ namespace hpx::util { hpx::string_util::split( split_key, key, hpx::string_util::is_any_of(".")); - std::string sk = split_key.back(); + std::string const sk = split_key.back(); split_key.pop_back(); section const* cur_section = this; - for (string_vector::const_iterator iter = split_key.begin(), - end = split_key.end(); - iter != end; ++iter) + for (const auto& iter : split_key) { - section_map::const_iterator next = - cur_section->sections_.find(*iter); + auto next = cur_section->sections_.find(iter); if (cur_section->sections_.end() == next) return expand(l, default_val); cur_section = &next->second; } - entry_map::const_iterator entry = cur_section->entries_.find(sk); + auto const entry = cur_section->entries_.find(sk); if (cur_section->entries_.end() == entry) return expand(l, default_val); @@ -747,8 +737,8 @@ namespace hpx::util { } } - entry_map::const_iterator eend = entries_.end(); - for (entry_map::const_iterator i = entries_.begin(); i != eend; ++i) + auto const eend = entries_.end(); + for (auto i = entries_.begin(); i != eend; ++i) { indent(ind, strm); @@ -769,8 +759,8 @@ namespace hpx::util { } } - section_map::const_iterator send = sections_.end(); - for (section_map::const_iterator i = sections_.begin(); i != send; ++i) + auto const send = sections_.end(); + for (auto i = sections_.begin(); i != send; ++i) { indent(ind, strm); strm << "[" << i->first << "]\n"; @@ -795,13 +785,13 @@ namespace hpx::util { // merge entries: keep own entries, and add other entries entry_map const& s_entries = second.get_entries(); - entry_map::const_iterator end = s_entries.end(); - for (entry_map::const_iterator i = s_entries.begin(); i != end; ++i) + auto const end = s_entries.end(); + for (auto i = s_entries.begin(); i != end; ++i) entries_[i->first] = i->second; // merge subsection known in first section - section_map::iterator send = sections_.end(); - for (section_map::iterator i = sections_.begin(); i != send; ++i) + auto const send = sections_.end(); + for (auto i = sections_.begin(); i != send; ++i) { // is there something to merge with? if (second.has_section(l, i->first)) @@ -810,8 +800,8 @@ namespace hpx::util { // merge subsection known in second section section_map s = second.get_sections(); - section_map::iterator secend = s.end(); - for (section_map::iterator i = s.begin(); i != secend; ++i) + auto const secend = s.end(); + for (auto i = s.begin(); i != secend; ++i) { // if THIS knows the section, we already merged it above if (!has_section(l, i->first)) @@ -824,7 +814,7 @@ namespace hpx::util { ///////////////////////////////////////////////////////////////////////////////// void section::line_msg(std::string msg, std::string const& file, int lnum, - std::string const& line) + std::string const& line) const { msg += " " + file; if (lnum > 0) @@ -874,11 +864,11 @@ namespace hpx::util { expand(l, value, begin); // now expand the key itself - std::string::size_type end = find_next("]", value, begin + 1); + std::string::size_type const end = find_next("]", value, begin + 1); if (end != std::string::npos) { std::string to_expand = value.substr(begin + 2, end - begin - 2); - std::string::size_type colon = find_next(":", to_expand); + std::string::size_type const colon = find_next(":", to_expand); if (colon == std::string::npos) { value = detail::replace_substr(value, begin, end - begin + 1, @@ -900,20 +890,20 @@ namespace hpx::util { expand(l, value, begin); // now expand the key itself - std::string::size_type end = find_next("}", value, begin + 1); + std::string::size_type const end = find_next("}", value, begin + 1); if (end != std::string::npos) { std::string to_expand = value.substr(begin + 2, end - begin - 2); - std::string::size_type colon = find_next(":", to_expand); + std::string::size_type const colon = find_next(":", to_expand); if (colon == std::string::npos) { - char* env = getenv(to_expand.c_str()); + char const* env = std::getenv(to_expand.c_str()); value = detail::replace_substr( value, begin, end - begin + 1, nullptr != env ? env : ""); } else { - char* env = getenv(to_expand.substr(0, colon).c_str()); + char* env = std::getenv(to_expand.substr(0, colon).c_str()); value = detail::replace_substr(value, begin, end - begin + 1, nullptr != env ? std::string(env) : to_expand.substr(colon + 1)); @@ -924,7 +914,7 @@ namespace hpx::util { std::string section::expand( std::unique_lock& l, std::string value) const { - expand(l, value, std::string::size_type(-1)); + expand(l, value, static_cast(-1)); return value; } @@ -952,11 +942,11 @@ namespace hpx::util { expand_only(l, value, begin, expand_this); // now expand the key itself - std::string::size_type end = find_next("]", value, begin + 1); + std::string::size_type const end = find_next("]", value, begin + 1); if (end != std::string::npos) { std::string to_expand = value.substr(begin + 2, end - begin - 2); - std::string::size_type colon = find_next(":", to_expand); + std::string::size_type const colon = find_next(":", to_expand); if (colon == std::string::npos) { if (to_expand == expand_this) @@ -983,20 +973,20 @@ namespace hpx::util { expand_only(l, value, begin, expand_this); // now expand the key itself - std::string::size_type end = find_next("}", value, begin + 1); + std::string::size_type const end = find_next("}", value, begin + 1); if (end != std::string::npos) { std::string to_expand = value.substr(begin + 2, end - begin - 2); - std::string::size_type colon = find_next(":", to_expand); + std::string::size_type const colon = find_next(":", to_expand); if (colon == std::string::npos) { - char* env = getenv(to_expand.c_str()); + char const* env = std::getenv(to_expand.c_str()); value = detail::replace_substr( value, begin, end - begin + 1, nullptr != env ? env : ""); } else { - char* env = getenv(to_expand.substr(0, colon).c_str()); + char* env = std::getenv(to_expand.substr(0, colon).c_str()); value = detail::replace_substr(value, begin, end - begin + 1, nullptr != env ? std::string(env) : to_expand.substr(colon + 1)); @@ -1007,7 +997,8 @@ namespace hpx::util { std::string section::expand_only(std::unique_lock& l, std::string value, std::string const& expand_this) const { - expand_only(l, value, std::string::size_type(-1), expand_this); + expand_only( + l, value, static_cast(-1), expand_this); return value; } @@ -1040,7 +1031,7 @@ namespace hpx::util { entries_.clear(); for (std::size_t i = 0; i < size; ++i) { - using value_type = typename entry_map::value_type; + using value_type = entry_map::value_type; value_type v; ar >> const_cast(v.first); 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/prefix/include/hpx/prefix/find_prefix.hpp b/libs/core/prefix/include/hpx/prefix/find_prefix.hpp index 25b0d76acf4b..839f88ea881a 100644 --- a/libs/core/prefix/include/hpx/prefix/find_prefix.hpp +++ b/libs/core/prefix/include/hpx/prefix/find_prefix.hpp @@ -17,25 +17,26 @@ namespace hpx::util { // set and query the prefix as configured at compile time HPX_CORE_EXPORT void set_hpx_prefix(const char* prefix) noexcept; - HPX_CORE_EXPORT char const* hpx_prefix() noexcept; + [[nodiscard]] HPX_CORE_EXPORT char const* hpx_prefix() noexcept; // return the installation path of the specified module - HPX_CORE_EXPORT std::string find_prefix(std::string const& library = "hpx"); + [[nodiscard]] HPX_CORE_EXPORT std::string find_prefix( + std::string const& library = "hpx"); // return a list of paths delimited by HPX_INI_PATH_DELIMITER - HPX_CORE_EXPORT std::string find_prefixes( + [[nodiscard]] HPX_CORE_EXPORT std::string find_prefixes( std::string const& suffix, std::string const& library = "hpx"); // return the full path of the current executable - HPX_CORE_EXPORT std::string get_executable_filename( + [[nodiscard]] HPX_CORE_EXPORT std::string get_executable_filename( char const* argv0 = nullptr); - HPX_CORE_EXPORT std::string get_executable_prefix( + [[nodiscard]] HPX_CORE_EXPORT std::string get_executable_prefix( char const* argv0 = nullptr); } // namespace hpx::util // The HPX runtime needs to know where to look for the HPX ini files if no ini // path is specified by the user (default in $HPX_LOCATION/share/hpx-1.0.0/ini). -// Also, the default component path is set within the same prefix +// Also, the default component path is set within the same prefix. // clang-format off #define HPX_BASE_DIR_NAME \ diff --git a/libs/core/prefix/src/find_prefix.cpp b/libs/core/prefix/src/find_prefix.cpp index 3425ea3009a9..6cca5fd6fd23 100644 --- a/libs/core/prefix/src/find_prefix.cpp +++ b/libs/core/prefix/src/find_prefix.cpp @@ -8,7 +8,6 @@ //////////////////////////////////////////////////////////////////////////////// #include -#include #include #include #include @@ -69,7 +68,7 @@ namespace hpx::util { using hpx::filesystem::path; - std::string const prefix = + std::string prefix = path(dll.get_directory(ec)).parent_path().string(); if (ec || prefix.empty()) @@ -79,7 +78,7 @@ namespace hpx::util { } catch (std::logic_error const&) { - ; // just ignore loader problems + // just ignore loader problems } #endif return hpx_prefix(); @@ -124,7 +123,7 @@ namespace hpx::util { std::string get_executable_prefix(char const* argv0) { using hpx::filesystem::path; - path p(get_executable_filename(argv0)); + path const p(get_executable_filename(argv0)); return p.parent_path().parent_path().string(); } diff --git a/libs/core/program_options/include/hpx/modules/program_options.hpp b/libs/core/program_options/include/hpx/modules/program_options.hpp index 472902d96c45..a95526ea6c21 100644 --- a/libs/core/program_options/include/hpx/modules/program_options.hpp +++ b/libs/core/program_options/include/hpx/modules/program_options.hpp @@ -1,8 +1,8 @@ -// Copyright Vladimir Prus 2002. +// Copyright Vladimir Prus 2002. +// // 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) +// 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) // See www.boost.org/libs/program_options for documentation. diff --git a/libs/core/program_options/include/hpx/program_options/cmdline.hpp b/libs/core/program_options/include/hpx/program_options/cmdline.hpp index 26bb8a6481cf..25f7185c9687 100644 --- a/libs/core/program_options/include/hpx/program_options/cmdline.hpp +++ b/libs/core/program_options/include/hpx/program_options/cmdline.hpp @@ -1,8 +1,8 @@ -// Copyright Vladimir Prus 2004. +// Copyright Vladimir Prus 2004. +// // 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) +// 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) #pragma once diff --git a/libs/core/program_options/include/hpx/program_options/config.hpp b/libs/core/program_options/include/hpx/program_options/config.hpp index e0f9218002be..825cd910d802 100644 --- a/libs/core/program_options/include/hpx/program_options/config.hpp +++ b/libs/core/program_options/include/hpx/program_options/config.hpp @@ -1,9 +1,8 @@ // Copyright (c) 2004 Hartmut Kaiser // -// SPDX-License-Identifier: BSL-1.0 -// Use, modification and distribution is subject to 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) +// 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) #pragma once diff --git a/libs/core/program_options/include/hpx/program_options/detail/cmdline.hpp b/libs/core/program_options/include/hpx/program_options/detail/cmdline.hpp index 1a41b3b57fdb..f34242013833 100644 --- a/libs/core/program_options/include/hpx/program_options/detail/cmdline.hpp +++ b/libs/core/program_options/include/hpx/program_options/detail/cmdline.hpp @@ -1,8 +1,8 @@ -// Copyright Vladimir Prus 2002-2004. +// Copyright Vladimir Prus 2002-2004. +// // 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) +// 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) #pragma once @@ -86,7 +86,7 @@ namespace hpx::program_options::detail { * * This is mainly used for the diagnostic messages in exceptions */ - int get_canonical_option_prefix() noexcept; + [[nodiscard]] int get_canonical_option_prefix() const noexcept; void allow_unregistered() noexcept; @@ -96,14 +96,18 @@ namespace hpx::program_options::detail { std::vector