Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-10 08:20:19

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 CERN for the benefit of the ACTS project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
0008 
0009 #pragma once
0010 
0011 #include "Acts/Utilities/Any.hpp"
0012 #include "Acts/Utilities/HashedString.hpp"
0013 #include "Acts/Utilities/Logger.hpp"
0014 
0015 #include <algorithm>
0016 #include <cstddef>
0017 #include <memory>
0018 #include <sstream>
0019 #include <stdexcept>
0020 #include <string>
0021 #include <string_view>
0022 #include <typeinfo>
0023 #include <unordered_map>
0024 #include <utility>
0025 #include <vector>
0026 
0027 namespace ActsExamples {
0028 
0029 /// A container to store arbitrary objects with ownership transfer.
0030 ///
0031 /// This is an append-only container that takes ownership of the objects
0032 /// added to it. Once an object has been added, it can only be read but not
0033 /// be modified. Trying to replace an existing object is considered an error.
0034 /// Its lifetime is bound to the lifetime of the white board.
0035 class WhiteBoard {
0036  public:
0037   struct StringHash {
0038     using is_transparent = void;  // Enables heterogeneous operations.
0039 
0040     std::size_t operator()(std::string_view sv) const {
0041       std::hash<std::string_view> hasher;
0042       return hasher(sv);
0043     }
0044   };
0045 
0046   using StoreValue =
0047       std::pair<std::shared_ptr<Acts::AnyMoveOnly>, std::uint64_t>;
0048   using StoreMapType =
0049       std::unordered_map<std::string, StoreValue, StringHash, std::equal_to<>>;
0050   using AliasMapType = std::unordered_multimap<std::string, std::string,
0051                                                StringHash, std::equal_to<>>;
0052 
0053   explicit WhiteBoard(std::unique_ptr<const Acts::Logger> logger =
0054                           Acts::getDefaultLogger("WhiteBoard",
0055                                                  Acts::Logging::INFO),
0056                       AliasMapType objectAliases = {});
0057 
0058   WhiteBoard(const WhiteBoard& other) = delete;
0059   WhiteBoard& operator=(const WhiteBoard&) = delete;
0060 
0061   WhiteBoard(WhiteBoard&& other) = default;
0062   WhiteBoard& operator=(WhiteBoard&& other) = default;
0063 
0064   bool exists(const std::string& name) const;
0065 
0066   /// Copies key from another whiteboard to this whiteboard.
0067   /// This is a low overhead operation, since the data holders are
0068   /// shared pointers.
0069   /// Throws an exception if this whiteboard already contains one of
0070   /// the keys in the other whiteboard.
0071   void copyFrom(const WhiteBoard& other);
0072 
0073   std::vector<std::string> getKeys() const;
0074 
0075  private:
0076   /// Find similar names for suggestions with levenshtein-distance
0077   std::vector<std::string_view> similarNames(const std::string_view& name,
0078                                              int distThreshold,
0079                                              std::size_t maxNumber) const;
0080 
0081   /// Store a value on the white board.
0082   ///
0083   /// @param name Non-empty identifier to store it under
0084   /// @param holder The value to store (shared ownership for copyFrom)
0085   /// @param typeHash Hash of the stored type for runtime verification
0086   /// @throws std::invalid_argument on empty or duplicate name
0087   void addHolder(const std::string& name,
0088                  const std::shared_ptr<Acts::AnyMoveOnly>& holder,
0089                  std::uint64_t typeHash);
0090 
0091   /// Store a value on the white board (from unique ownership).
0092   void addHolder(const std::string& name,
0093                  std::unique_ptr<Acts::AnyMoveOnly> holder,
0094                  std::uint64_t typeHash);
0095 
0096   /// Store an object on the white board and transfer ownership.
0097   ///
0098   /// @param name Non-empty identifier to store it under
0099   /// @param object Movable reference to the transferable object
0100   template <typename T>
0101   const T& add(const std::string& name, T&& object) {
0102     addHolder(name,
0103               std::make_shared<Acts::AnyMoveOnly>(std::forward<T>(object)),
0104               Acts::typeHash<T>());
0105     return get<T>(name);
0106   }
0107 
0108   /// Get access to a stored object.
0109   ///
0110   /// @param[in] name Identifier for the object
0111   /// @return reference to the stored object
0112   /// @throws std::out_of_range if no object is stored under the requested name
0113   template <typename T>
0114   const T& get(const std::string& name) const;
0115 
0116   template <typename T>
0117   Acts::AnyMoveOnly* getHolder(const std::string& name) const;
0118 
0119   /// Returns (pointer to stored value, type hash). Throws if not found.
0120   std::pair<Acts::AnyMoveOnly*, std::uint64_t> getHolder(
0121       const std::string& name) const;
0122 
0123   template <typename T>
0124   T pop(const std::string& name);
0125 
0126   std::unique_ptr<const Acts::Logger> m_logger;
0127 
0128   StoreMapType m_store;
0129 
0130   AliasMapType m_objectAliases;
0131 
0132   const Acts::Logger& logger() const { return *m_logger; }
0133 
0134   static std::string typeMismatchMessage(const std::string& name,
0135                                          const char* req, const char* act);
0136 
0137   friend class DataHandleBase;
0138 };
0139 
0140 inline WhiteBoard::WhiteBoard(std::unique_ptr<const Acts::Logger> logger,
0141                               AliasMapType objectAliases)
0142     : m_logger(std::move(logger)), m_objectAliases(std::move(objectAliases)) {}
0143 
0144 template <typename T>
0145 Acts::AnyMoveOnly* WhiteBoard::getHolder(const std::string& name) const {
0146   auto it = m_store.find(name);
0147   if (it == m_store.end()) {
0148     const auto names = similarNames(name, 10, 3);
0149 
0150     std::stringstream ss;
0151     if (!names.empty()) {
0152       ss << ", similar ones are: [ ";
0153       for (std::size_t i = 0; i < std::min(3ul, names.size()); ++i) {
0154         ss << "'" << names[i] << "' ";
0155       }
0156       ss << "]";
0157     }
0158 
0159     throw std::out_of_range("Object '" + name + "' does not exists" + ss.str());
0160   }
0161 
0162   auto& [holder, storedTypeHash] = it->second;
0163   if (storedTypeHash != Acts::typeHash<T>()) {
0164     const char* holderTypeName =
0165         holder->typeInfo() ? holder->typeInfo()->name() : "unknown";
0166     std::string msg =
0167         typeMismatchMessage(name, typeid(T).name(), holderTypeName);
0168     throw std::out_of_range(msg.c_str());
0169   }
0170 
0171   return holder.get();
0172 }
0173 
0174 template <typename T>
0175 inline const T& WhiteBoard::get(const std::string& name) const {
0176   ACTS_VERBOSE("Attempt to get object '" << name << "' of type "
0177                                          << typeid(T).name());
0178   ACTS_VERBOSE("Retrieved object '" << name << "'");
0179   auto* holder = getHolder<T>(name);
0180   return holder->template as<T>();
0181 }
0182 
0183 template <typename T>
0184 T WhiteBoard::pop(const std::string& name) {
0185   ACTS_VERBOSE("Pop object '" << name << "'");
0186   (void)getHolder<T>(name);  // validates type and existence
0187   auto node = m_store.extract(name);
0188   return node.mapped().first->template take<T>();
0189 }
0190 
0191 inline bool WhiteBoard::exists(const std::string& name) const {
0192   // TODO remove this function?
0193   return m_store.contains(name);
0194 }
0195 
0196 }  // namespace ActsExamples