Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-02 07:51:28

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/Concepts.hpp>
0012 #include <Acts/Utilities/Logger.hpp>
0013 
0014 #include <algorithm>
0015 #include <cstddef>
0016 #include <memory>
0017 #include <ostream>
0018 #include <stdexcept>
0019 #include <string>
0020 #include <string_view>
0021 #include <typeinfo>
0022 #include <unordered_map>
0023 #include <utility>
0024 #include <vector>
0025 
0026 namespace ActsExamples {
0027 
0028 /// A container to store arbitrary objects with ownership transfer.
0029 ///
0030 /// This is an append-only container that takes ownership of the objects
0031 /// added to it. Once an object has been added, it can only be read but not
0032 /// be modified. Trying to replace an existing object is considered an error.
0033 /// Its lifetime is bound to the lifetime of the white board.
0034 class WhiteBoard {
0035  private:
0036   // type-erased value holder for move-constructible types
0037   struct IHolder {
0038     virtual ~IHolder() = default;
0039     virtual const std::type_info& type() const = 0;
0040   };
0041   template <Acts::Concepts::nothrow_move_constructible T>
0042   struct HolderT : public IHolder {
0043     T value;
0044 
0045     explicit HolderT(T&& v) : value(std::move(v)) {}
0046     const std::type_info& type() const override { return typeid(T); }
0047   };
0048 
0049   struct StringHash {
0050     using is_transparent = void;  // Enables heterogeneous operations.
0051 
0052     std::size_t operator()(std::string_view sv) const {
0053       std::hash<std::string_view> hasher;
0054       return hasher(sv);
0055     }
0056   };
0057 
0058  public:
0059   using StoreMapType = std::unordered_map<std::string, std::shared_ptr<IHolder>,
0060                                           StringHash, std::equal_to<>>;
0061   using AliasMapType = std::unordered_multimap<std::string, std::string,
0062                                                StringHash, std::equal_to<>>;
0063 
0064   explicit WhiteBoard(std::unique_ptr<const Acts::Logger> logger =
0065                           Acts::getDefaultLogger("WhiteBoard",
0066                                                  Acts::Logging::INFO),
0067                       AliasMapType objectAliases = {});
0068 
0069   WhiteBoard(const WhiteBoard& other) = delete;
0070   WhiteBoard& operator=(const WhiteBoard&) = delete;
0071 
0072   WhiteBoard(WhiteBoard&& other) = default;
0073   WhiteBoard& operator=(WhiteBoard&& other) = default;
0074 
0075   bool exists(const std::string& name) const;
0076 
0077   /// Copies key from another whiteboard to this whiteboard.
0078   /// This is a low overhead operation, since the data holders are
0079   /// shared pointers.
0080   /// Throws an exception if this whiteboard already contains one of
0081   /// the keys in the other whiteboard.
0082   void copyFrom(const WhiteBoard& other);
0083 
0084   std::vector<std::string> getKeys() const;
0085 
0086  private:
0087   /// Find similar names for suggestions with levenshtein-distance
0088   std::vector<std::string_view> similarNames(const std::string_view& name,
0089                                              int distThreshold,
0090                                              std::size_t maxNumber) const;
0091 
0092   /// Store a holder on the white board.
0093   ///
0094   /// @param name Non-empty identifier to store it under
0095   /// @param holder The holder to store
0096   /// @throws std::invalid_argument on empty or duplicate name
0097   void addHolder(const std::string& name,
0098                  const std::shared_ptr<IHolder>& holder);
0099 
0100   /// Store an object on the white board and transfer ownership.
0101   ///
0102   /// @param name Non-empty identifier to store it under
0103   /// @param object Movable reference to the transferable object
0104   template <typename T>
0105   void add(const std::string& name, T&& object) {
0106     addHolder(name, std::make_shared<HolderT<T>>(std::forward<T>(object)));
0107   }
0108 
0109   /// Get access to a stored object.
0110   ///
0111   /// @param[in] name Identifier for the object
0112   /// @return reference to the stored object
0113   /// @throws std::out_of_range if no object is stored under the requested name
0114   template <typename T>
0115   const T& get(const std::string& name) const;
0116 
0117   template <typename T>
0118   HolderT<T>* getHolder(const std::string& name) const;
0119 
0120   template <typename T>
0121   T pop(const std::string& name);
0122 
0123   std::unique_ptr<const Acts::Logger> m_logger;
0124 
0125   StoreMapType m_store;
0126 
0127   AliasMapType m_objectAliases;
0128 
0129   const Acts::Logger& logger() const { return *m_logger; }
0130 
0131   static std::string typeMismatchMessage(const std::string& name,
0132                                          const char* req, const char* act);
0133 
0134   friend class DataHandleBase;
0135 };
0136 
0137 }  // namespace ActsExamples
0138 
0139 inline ActsExamples::WhiteBoard::WhiteBoard(
0140     std::unique_ptr<const Acts::Logger> logger, AliasMapType objectAliases)
0141     : m_logger(std::move(logger)), m_objectAliases(std::move(objectAliases)) {}
0142 
0143 template <typename T>
0144 ActsExamples::WhiteBoard::HolderT<T>* ActsExamples::WhiteBoard::getHolder(
0145     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   IHolder* holder = it->second.get();
0163 
0164   auto* castedHolder = dynamic_cast<HolderT<T>*>(holder);
0165   if (castedHolder == nullptr) {
0166     std::string msg =
0167         typeMismatchMessage(name, typeid(T).name(), holder->type().name());
0168     throw std::out_of_range(msg.c_str());
0169   }
0170 
0171   return castedHolder;
0172 }
0173 
0174 template <typename T>
0175 inline const T& ActsExamples::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->value;
0181 }
0182 
0183 template <typename T>
0184 T ActsExamples::WhiteBoard::pop(const std::string& name) {
0185   ACTS_VERBOSE("Pop object '" << name << "'");
0186   // This will throw if the object is not of the requested type or does not
0187   // exist
0188   auto* holder = getHolder<T>(name);
0189   // Remove the holder from the store, will go out of scope after return
0190   auto owned = m_store.extract(name);
0191   // Return the value by moving it out of the holder
0192   return std::move(holder->value);
0193 }
0194 
0195 inline bool ActsExamples::WhiteBoard::exists(const std::string& name) const {
0196   // TODO remove this function?
0197   return m_store.contains(name);
0198 }