Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-16 10:19:17

0001 /*
0002  * Copyright (c) 2014-2024 Key4hep-Project.
0003  *
0004  * This file is part of Key4hep.
0005  * See https://key4hep.github.io/key4hep-doc/ for further info.
0006  *
0007  * Licensed under the Apache License, Version 2.0 (the "License");
0008  * you may not use this file except in compliance with the License.
0009  * You may obtain a copy of the License at
0010  *
0011  *     http://www.apache.org/licenses/LICENSE-2.0
0012  *
0013  * Unless required by applicable law or agreed to in writing, software
0014  * distributed under the License is distributed on an "AS IS" BASIS,
0015  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0016  * See the License for the specific language governing permissions and
0017  * limitations under the License.
0018  */
0019 #ifndef FWCORE_CONSUMER_H
0020 #define FWCORE_CONSUMER_H
0021 
0022 #include "Gaudi/Functional/details.h"
0023 #include "Gaudi/Functional/utilities.h"
0024 #include "GaudiKernel/FunctionalFilterDecision.h"
0025 
0026 // #include "GaudiKernel/CommonMessaging.h"
0027 
0028 #include "k4FWCore/FunctionalUtils.h"
0029 
0030 #include <ranges>
0031 #include <stdexcept>
0032 #include <type_traits>
0033 #include <utility>
0034 
0035 namespace k4FWCore {
0036 
0037 namespace details {
0038 
0039   template <typename Signature, typename Traits_>
0040   struct Consumer;
0041 
0042   template <typename... In, typename Traits_>
0043   struct Consumer<void(const In&...), Traits_>
0044       : Gaudi::Functional::details::DataHandleMixin<std::tuple<>, std::tuple<>, Traits_> {
0045     using Gaudi::Functional::details::DataHandleMixin<std::tuple<>, std::tuple<>, Traits_>::DataHandleMixin;
0046 
0047     static_assert(((std::is_base_of_v<podio::CollectionBase, In> || isVectorLike_v<In>)&&...),
0048                   "Consumer input types must be EDM4hep collections or vectors of collection pointers");
0049 
0050     template <typename T>
0051     using InputHandle_t = Gaudi::Functional::details::InputHandle_t<Traits_, T>;
0052 
0053     std::tuple<std::vector<InputHandle_t<typename EventStoreType<In>::type>>...> m_inputs;
0054     std::array<Gaudi::Property<std::vector<DataObjID>>, sizeof...(In)> m_inputLocations{};
0055 
0056     using base_class = Gaudi::Functional::details::DataHandleMixin<std::tuple<>, std::tuple<>, Traits_>;
0057 
0058     using KeyValues = typename base_class::KeyValues;
0059 
0060     template <typename IArgs, std::size_t... I>
0061     Consumer(std::string name, ISvcLocator* locator, const IArgs& inputs, std::index_sequence<I...>)
0062         : base_class(std::move(name), locator),
0063           // The input locations are filled by creating a property with a callback function
0064           // that creates the handles because that is when the input locations become available
0065           // (from a steering file, for example) and the handles have to be created for
0066           // Gaudi to know the data flow
0067           m_inputLocations{Gaudi::Property<std::vector<DataObjID>>{
0068               this, std::get<I>(inputs).first, to_DataObjID(std::get<I>(inputs).second),
0069               [this](Gaudi::Details::PropertyBase&) {
0070                 std::vector<InputHandle_t<EventStoreType_t>> handles;
0071                 for (auto& value : this->m_inputLocations[I].value()) {
0072                   auto handle = InputHandle_t<EventStoreType_t>(value, this);
0073                   handles.push_back(std::move(handle));
0074                 }
0075                 std::get<I>(m_inputs) = std::move(handles);
0076               },
0077               Gaudi::Details::Property::ImmediatelyInvokeHandler{true}}...} {}
0078 
0079     Consumer(std::string name, ISvcLocator* locator,
0080              Gaudi::Functional::details::RepeatValues_<KeyValues, sizeof...(In)> const& inputs)
0081         : Consumer(std::move(name), locator, inputs, std::index_sequence_for<In...>{}) {}
0082 
0083     // derived classes are NOT allowed to implement execute ...
0084     StatusCode execute(const EventContext& ctx) const final {
0085       try {
0086         filter_evtcontext_tt<In...>::apply(*this, ctx, m_inputs);
0087         return Gaudi::Functional::FilterDecision::PASSED;
0088       } catch (GaudiException& e) {
0089         (e.code() ? this->warning() : this->error()) << e.tag() << " : " << e.message() << endmsg;
0090         return e.code();
0091       }
0092     }
0093 
0094     // ... instead, they must implement the following operator
0095     virtual void operator()(const In&...) const = 0;
0096 
0097     /**
0098      * @brief    Get the input locations for a given input index
0099      * @param i  The index of the input
0100      * @return   A range of the input locations
0101      */
0102     auto inputLocations(size_t i) const {
0103       if (i >= sizeof...(In)) {
0104         throw std::out_of_range("Called inputLocations with an index out of range, index: " + std::to_string(i) +
0105                                 ", number of inputs: " + std::to_string(sizeof...(In)));
0106       }
0107       return m_inputLocations[i] | std::views::transform([](const DataObjID& id) -> const auto& { return id.key(); });
0108     }
0109     /**
0110      * @brief       Get the input locations for a given input name
0111      * @param name  The name of the input
0112      * @return      A range of the input locations
0113      */
0114     auto inputLocations(std::string_view name) const {
0115       auto it = std::ranges::find_if(m_inputLocations, [&name](const auto& prop) { return prop.name() == name; });
0116       if (it == m_inputLocations.end()) {
0117         throw std::runtime_error("Called inputLocations with an unknown name");
0118       }
0119       return it->value() | std::views::transform([](const DataObjID& id) -> const auto& { return id.key(); });
0120     }
0121     static constexpr std::size_t inputLocationsSize() { return sizeof...(In); }
0122   };
0123 
0124 } // namespace details
0125 
0126 template <typename Signature, typename Traits_ = Gaudi::Functional::Traits::useDefaults>
0127 using Consumer = details::Consumer<Signature, Traits_>;
0128 
0129 } // namespace k4FWCore
0130 
0131 #endif // FWCORE_CONSUMER_H