Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-10-28 08:39:04

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/HashedString.hpp"
0012 #include "ActsExamples/Framework/AlgorithmContext.hpp"
0013 #include "ActsExamples/Framework/SequenceElement.hpp"
0014 #include "ActsExamples/Framework/WhiteBoard.hpp"
0015 
0016 #include <stdexcept>
0017 #include <typeinfo>
0018 #include <unordered_map>
0019 
0020 namespace Acts {
0021 class Logger;
0022 }
0023 
0024 namespace ActsExamples {
0025 
0026 /// Base class for all data handles.
0027 ///
0028 /// Provides common functionality for tracking the parent sequence element
0029 /// and key name. The key is optional until explicitly initialized.
0030 class DataHandleBase {
0031  private:
0032   struct StringHash {
0033     using is_transparent = void;  // Enables heterogeneous operations.
0034 
0035     std::size_t operator()(std::string_view sv) const {
0036       std::hash<std::string_view> hasher;
0037       return hasher(sv);
0038     }
0039   };
0040 
0041  protected:
0042   DataHandleBase(SequenceElement* parent, const std::string& name)
0043       : m_parent(parent), m_name(name) {}
0044 
0045   // We can't change addresses after construction
0046   DataHandleBase(const DataHandleBase&) = delete;
0047   DataHandleBase(DataHandleBase&&) = default;
0048 
0049  public:
0050   virtual ~DataHandleBase() = default;
0051 
0052   const std::string& key() const { return m_key.value(); }
0053 
0054   virtual const std::type_info& typeInfo() const = 0;
0055   virtual std::uint64_t typeHash() const = 0;
0056 
0057   bool isInitialized() const { return m_key.has_value(); }
0058 
0059   const std::string& name() const { return m_name; }
0060 
0061   void maybeInitialize(std::optional<std::string_view> key);
0062 
0063   virtual bool isCompatible(const DataHandleBase& other) const = 0;
0064 
0065   using StateMapType = std::unordered_map<std::string, const DataHandleBase*,
0066                                           StringHash, std::equal_to<>>;
0067 
0068   virtual void emulate(StateMapType& state, WhiteBoard::AliasMapType& aliases,
0069                        const Acts::Logger& logger) const = 0;
0070 
0071   std::string fullName() const { return m_parent->name() + "." + name(); }
0072 
0073  protected:
0074   void registerAsWriteHandle();
0075   void registerAsReadHandle();
0076 
0077   // Trampoline functions to avoid having the WhiteBoard as a friend
0078   template <typename T>
0079   const T& add(WhiteBoard& wb, T&& object) const {
0080     return wb.add(m_key.value(), std::forward<T>(object));
0081   }
0082 
0083   template <typename T>
0084   const T& get(const WhiteBoard& wb) const {
0085     return wb.get<T>(m_key.value());
0086   }
0087 
0088   template <typename T>
0089   T pop(WhiteBoard& wb) const {
0090     return wb.pop<T>(m_key.value());
0091   }
0092 
0093   std::pair<Acts::AnyMoveOnly*, std::uint64_t> getHolder(
0094       const WhiteBoard& wb) const {
0095     return wb.getHolder(m_key.value());
0096   }
0097 
0098   void addHolder(WhiteBoard& wb, std::unique_ptr<Acts::AnyMoveOnly> holder,
0099                  std::uint64_t typeHash) const {
0100     wb.addHolder(m_key.value(), std::move(holder), typeHash);
0101   }
0102 
0103   SequenceElement* m_parent{nullptr};
0104   std::string m_name;
0105   std::optional<std::string> m_key{};
0106 };
0107 
0108 /// Base class for write data handles.
0109 ///
0110 /// Write handles are used to store data in the WhiteBoard. They ensure that:
0111 /// - Each key can only be written once
0112 /// - The key must be non-empty
0113 /// - The data type is consistent for each key
0114 class WriteDataHandleBase : public DataHandleBase {
0115  protected:
0116   WriteDataHandleBase(SequenceElement* parent, const std::string& name)
0117       : DataHandleBase{parent, name} {}
0118 
0119  public:
0120   void initialize(std::string_view key);
0121 
0122   bool isCompatible(const DataHandleBase& other) const override;
0123 
0124   void emulate(StateMapType& state, WhiteBoard::AliasMapType& aliases,
0125                const Acts::Logger& logger) const final;
0126 };
0127 
0128 /// Base class for read data handles.
0129 ///
0130 /// Read handles are used to access data from the WhiteBoard. They ensure that:
0131 /// - The data exists before reading
0132 /// - The data type matches the expected type
0133 /// - The data can be read multiple times
0134 class ReadDataHandleBase : public DataHandleBase {
0135  protected:
0136   using DataHandleBase::DataHandleBase;
0137 
0138  public:
0139   void initialize(std::string_view key);
0140 
0141   bool isCompatible(const DataHandleBase& other) const final;
0142 
0143   void emulate(StateMapType& state, WhiteBoard::AliasMapType& aliases,
0144                const Acts::Logger& logger) const override;
0145 };
0146 
0147 /// Base class for consume data handles.
0148 ///
0149 /// Consume handles are used to take ownership of data from the WhiteBoard.
0150 /// They ensure that:
0151 /// - The data exists before consuming
0152 /// - The data type matches the expected type
0153 /// - The data can only be consumed once
0154 /// - The data is removed from the WhiteBoard after consumption
0155 class ConsumeDataHandleBase : public ReadDataHandleBase {
0156  protected:
0157   using ReadDataHandleBase::ReadDataHandleBase;
0158 
0159  public:
0160   void emulate(StateMapType& state, WhiteBoard::AliasMapType& aliases,
0161                const Acts::Logger& logger) const override;
0162 };
0163 
0164 /// A write handle for storing data in the WhiteBoard.
0165 ///
0166 /// @tparam T The type of data to store
0167 ///
0168 /// Example usage:
0169 /// @code
0170 /// WriteDataHandle<int> handle(parent, "my_data");
0171 /// handle.initialize("my_key");
0172 /// handle(wb, 42);  // Store value
0173 /// @endcode
0174 template <typename T>
0175 class WriteDataHandle /*final*/ : public WriteDataHandleBase {
0176  public:
0177   WriteDataHandle(SequenceElement* parent, const std::string& name)
0178       : WriteDataHandleBase{parent, name} {
0179     registerAsWriteHandle();
0180   }
0181 
0182   const T& operator()(const AlgorithmContext& ctx, T&& value) const {
0183     return (*this)(ctx.eventStore, std::move(value));
0184   }
0185 
0186   const T& operator()(WhiteBoard& wb, T&& value) const {
0187     if (!isInitialized()) {
0188       throw std::runtime_error{"WriteDataHandle '" + fullName() +
0189                                "' not initialized"};
0190     }
0191     return add(wb, std::move(value));
0192   }
0193 
0194   const std::type_info& typeInfo() const final { return typeid(T); };
0195   std::uint64_t typeHash() const final { return Acts::typeHash<T>(); };
0196 };
0197 
0198 /// A read handle for accessing data from the WhiteBoard.
0199 ///
0200 /// @tparam T The type of data to read
0201 ///
0202 /// Example usage:
0203 /// @code
0204 /// ReadDataHandle<int> handle(parent, "my_data");
0205 /// handle.initialize("my_key");
0206 /// const auto& value = handle(wb);  // Access value
0207 /// @endcode
0208 template <typename T>
0209 class ReadDataHandle /*final*/ : public ReadDataHandleBase {
0210  public:
0211   ReadDataHandle(SequenceElement* parent, const std::string& name)
0212       : ReadDataHandleBase{parent, name} {
0213     registerAsReadHandle();
0214   }
0215 
0216   const T& operator()(const AlgorithmContext& ctx) const {
0217     return (*this)(ctx.eventStore);
0218   }
0219 
0220   const T& operator()(const WhiteBoard& wb) const {
0221     if (!isInitialized()) {
0222       throw std::runtime_error{"ReadDataHandle '" + fullName() +
0223                                "' not initialized"};
0224     }
0225     return get<T>(wb);
0226   }
0227 
0228   const std::type_info& typeInfo() const final { return typeid(T); };
0229   std::uint64_t typeHash() const final { return Acts::typeHash<T>(); };
0230 };
0231 
0232 /// A consume handle for taking ownership of data from the WhiteBoard.
0233 ///
0234 /// @tparam T The type of data to consume
0235 ///
0236 /// Example usage:
0237 /// @code
0238 /// ConsumeDataHandle<int> handle(parent, "my_data");
0239 /// handle.initialize("my_key");
0240 /// auto value = handle(wb);  // Take ownership of value
0241 /// // value is no longer in WhiteBoard
0242 /// @endcode
0243 template <typename T>
0244 class ConsumeDataHandle /*final*/ : public ConsumeDataHandleBase {
0245  public:
0246   ConsumeDataHandle(SequenceElement* parent, const std::string& name)
0247       : ConsumeDataHandleBase{parent, name} {
0248     registerAsReadHandle();
0249   }
0250 
0251   T operator()(const AlgorithmContext& ctx) const {
0252     return (*this)(ctx.eventStore);
0253   }
0254 
0255   T operator()(WhiteBoard& wb) const {
0256     if (!isInitialized()) {
0257       throw std::runtime_error{"ConsumeDataHandle '" + fullName() +
0258                                "' not initialized"};
0259     }
0260     return pop<T>(wb);
0261   }
0262 
0263   const std::type_info& typeInfo() const final { return typeid(T); };
0264   std::uint64_t typeHash() const final { return Acts::typeHash<T>(); };
0265 };
0266 
0267 }  // namespace ActsExamples