Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-07-15 07:51:16

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