Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:28:02

0001 // This file is part of the Acts project.
0002 //
0003 // Copyright (C) 2017-2019 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 http://mozilla.org/MPL/2.0/.
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 /// 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  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   // A WhiteBoard holds unique elements and can not be copied
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   /// Store an object on the white board and transfer ownership.
0048   ///
0049   /// @param name Non-empty identifier to store it under
0050   /// @param object Movable reference to the transferable object
0051   /// @throws std::invalid_argument on empty or duplicate name
0052   template <typename T>
0053   void add(const std::string& name, T&& object);
0054 
0055   /// Get access to a stored object.
0056   ///
0057   /// @param[in] name Identifier for the object
0058   /// @return reference to the stored object
0059   /// @throws std::out_of_range if no object is stored under the requested name
0060   template <typename T>
0061   const T& get(const std::string& name) const;
0062 
0063  private:
0064   /// Find similar names for suggestions with levenshtein-distance
0065   std::vector<std::string_view> similarNames(const std::string_view& name,
0066                                              int distThreshold,
0067                                              std::size_t maxNumber) const;
0068 
0069   // type-erased value holder for move-constructible types
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 }  // namespace ActsExamples
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 }