From cfa8c2a41e8a585834e4d04d56ff7eec0d57f608 Mon Sep 17 00:00:00 2001 From: Paul Cristian Sarbu Date: Tue, 30 Jan 2024 17:50:03 +0100 Subject: async maps: Create utility library to handle cycle detection --- src/buildtool/multithreading/async_map_utils.hpp | 81 ++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 src/buildtool/multithreading/async_map_utils.hpp (limited to 'src/buildtool/multithreading/async_map_utils.hpp') diff --git a/src/buildtool/multithreading/async_map_utils.hpp b/src/buildtool/multithreading/async_map_utils.hpp new file mode 100644 index 00000000..03469b02 --- /dev/null +++ b/src/buildtool/multithreading/async_map_utils.hpp @@ -0,0 +1,81 @@ +// Copyright 2024 Huawei Cloud Computing Technology Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef INCLUDED_SRC_BUILDTOOL_MULTITHREADING_ASYNC_MAP_UTILS_HPP +#define INCLUDED_SRC_BUILDTOOL_MULTITHREADING_ASYNC_MAP_UTILS_HPP + +#include +#include +#include +#include + +#include "fmt/core.h" +#include "src/buildtool/logging/log_level.hpp" +#include "src/buildtool/logging/logger.hpp" +#include "src/buildtool/multithreading/async_map_consumer.hpp" +#include "src/utils/cpp/concepts.hpp" + +/// \brief Utility to detect and report cycles for an AsyncMap instance. +/// \param name Human-readable string identifier related to the map or its use. +/// \param map The AsyncMap instance. +/// \param key_printer Callable returning key-specific identifier in string +/// format. +/// \returns The resulting cycle message as a string, or nullopt if no cycle +/// detected. +template +[[nodiscard]] auto DetectAndReportCycle( + std::string const& name, + AsyncMapConsumer const& map, + std::function key_printer) + -> std::optional { + using namespace std::string_literals; + auto cycle = map.DetectCycle(); + if (cycle) { + bool found{false}; + std::ostringstream oss{}; + oss << fmt::format("Cycle detected in {}:", name) << std::endl; + for (auto const& k : *cycle) { + auto match = (k == cycle->back()); + auto prefix{match ? found ? "`-- "s : ".-> "s + : found ? "| "s + : " "s}; + oss << prefix << key_printer(k) << std::endl; + found = found or match; + } + return oss.str(); + } + return std::nullopt; +} + +/// \brief Utility to detect and report pending tasks for an AsyncMap instance. +/// \param name Human-readable string identifier related to the map or its use. +/// \param map The AsyncMap instance. +template +void DetectAndReportPending(std::string const& name, + AsyncMapConsumer const& map) { + using namespace std::string_literals; + auto keys = map.GetPendingKeys(); + if (not keys.empty()) { + std::ostringstream oss{}; + oss << fmt::format("Internal error, failed to evaluate pending {}:", + name) + << std::endl; + for (auto const& k : keys) { + oss << " " << k.ToString() << std::endl; + } + Logger::Log(LogLevel::Error, "{}", oss.str()); + } +} + +#endif // INCLUDED_SRC_BUILDTOOL_MULTITHREADING_ASYNC_MAP_UTILS_HPP -- cgit v1.2.3