Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-07-30 08:36:25

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