File indexing completed on 2025-01-18 09:28:02
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011 #include <Acts/Utilities/Logger.hpp>
0012
0013 #include <algorithm>
0014 #include <cstddef>
0015 #include <memory>
0016 #include <ostream>
0017 #include <stdexcept>
0018 #include <string>
0019 #include <string_view>
0020 #include <type_traits>
0021 #include <typeinfo>
0022 #include <unordered_map>
0023 #include <utility>
0024 #include <vector>
0025
0026 namespace ActsExamples {
0027
0028
0029
0030
0031
0032
0033
0034 class WhiteBoard {
0035 public:
0036 WhiteBoard(std::unique_ptr<const Acts::Logger> logger =
0037 Acts::getDefaultLogger("WhiteBoard", Acts::Logging::INFO),
0038 std::unordered_map<std::string, std::string> objectAliases = {});
0039
0040
0041 WhiteBoard(const WhiteBoard& other) = delete;
0042 WhiteBoard& operator=(const WhiteBoard&) = delete;
0043
0044 bool exists(const std::string& name) const;
0045
0046 private:
0047
0048
0049
0050
0051
0052 template <typename T>
0053 void add(const std::string& name, T&& object);
0054
0055
0056
0057
0058
0059
0060 template <typename T>
0061 const T& get(const std::string& name) const;
0062
0063 private:
0064
0065 std::vector<std::string_view> similarNames(const std::string_view& name,
0066 int distThreshold,
0067 std::size_t maxNumber) const;
0068
0069
0070 struct IHolder {
0071 virtual ~IHolder() = default;
0072 virtual const std::type_info& type() const = 0;
0073 };
0074 template <typename T,
0075 typename =
0076 std::enable_if_t<std::is_nothrow_move_constructible<T>::value>>
0077 struct HolderT : public IHolder {
0078 T value;
0079
0080 HolderT(T&& v) : value(std::move(v)) {}
0081 const std::type_info& type() const override { return typeid(T); }
0082 };
0083
0084 std::unique_ptr<const Acts::Logger> m_logger;
0085 std::unordered_map<std::string, std::shared_ptr<IHolder>> m_store;
0086 std::unordered_map<std::string, std::string> m_objectAliases;
0087
0088 const Acts::Logger& logger() const { return *m_logger; }
0089
0090 static std::string typeMismatchMessage(const std::string& name,
0091 const char* req, const char* act);
0092
0093 template <typename T>
0094 friend class WriteDataHandle;
0095
0096 template <typename T>
0097 friend class ReadDataHandle;
0098 };
0099
0100 }
0101
0102 inline ActsExamples::WhiteBoard::WhiteBoard(
0103 std::unique_ptr<const Acts::Logger> logger,
0104 std::unordered_map<std::string, std::string> objectAliases)
0105 : m_logger(std::move(logger)), m_objectAliases(std::move(objectAliases)) {}
0106
0107 template <typename T>
0108 inline void ActsExamples::WhiteBoard::add(const std::string& name, T&& object) {
0109 if (name.empty()) {
0110 throw std::invalid_argument("Object can not have an empty name");
0111 }
0112 if (0 < m_store.count(name)) {
0113 throw std::invalid_argument("Object '" + name + "' already exists");
0114 }
0115 auto holder = std::make_shared<HolderT<T>>(std::forward<T>(object));
0116 m_store.emplace(name, holder);
0117 ACTS_VERBOSE("Added object '" << name << "' of type " << typeid(T).name());
0118 if (auto it = m_objectAliases.find(name); it != m_objectAliases.end()) {
0119 m_store[it->second] = holder;
0120 ACTS_VERBOSE("Added alias object '" << it->second << "'");
0121 }
0122 }
0123
0124 template <typename T>
0125 inline const T& ActsExamples::WhiteBoard::get(const std::string& name) const {
0126 ACTS_VERBOSE("Attempt to get object '" << name << "' of type "
0127 << typeid(T).name());
0128 auto it = m_store.find(name);
0129 if (it == m_store.end()) {
0130 const auto names = similarNames(name, 10, 3);
0131
0132 std::stringstream ss;
0133 if (!names.empty()) {
0134 ss << ", similar ones are: [ ";
0135 for (std::size_t i = 0; i < std::min(3ul, names.size()); ++i) {
0136 ss << "'" << names[i] << "' ";
0137 }
0138 ss << "]";
0139 }
0140
0141 throw std::out_of_range("Object '" + name + "' does not exists" + ss.str());
0142 }
0143
0144 const IHolder* holder = it->second.get();
0145
0146 const auto* castedHolder = dynamic_cast<const HolderT<T>*>(holder);
0147 if (castedHolder == nullptr) {
0148 std::string msg =
0149 typeMismatchMessage(name, typeid(T).name(), holder->type().name());
0150 throw std::out_of_range(msg.c_str());
0151 }
0152
0153 ACTS_VERBOSE("Retrieved object '" << name << "'");
0154 return castedHolder->value;
0155 }
0156
0157 inline bool ActsExamples::WhiteBoard::exists(const std::string& name) const {
0158 return m_store.find(name) != m_store.end();
0159 }