Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-05-11 08:57:26

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_> struct Consumer;
0040 
0041     template <typename... In, typename Traits_>
0042     struct Consumer<void(const In&...), Traits_>
0043         : Gaudi::Functional::details::DataHandleMixin<std::tuple<>, std::tuple<>, Traits_> {
0044       using Gaudi::Functional::details::DataHandleMixin<std::tuple<>, std::tuple<>, Traits_>::DataHandleMixin;
0045 
0046       static_assert(((std::is_base_of_v<podio::CollectionBase, In> || isVectorLike_v<In>)&&...),
0047                     "Consumer input types must be EDM4hep collections or vectors of collection pointers");
0048 
0049       template <typename T> using InputHandle_t = Gaudi::Functional::details::InputHandle_t<Traits_, T>;
0050 
0051       std::tuple<std::vector<InputHandle_t<typename EventStoreType<In>::type>>...> m_inputs;
0052       std::array<Gaudi::Property<std::vector<DataObjID>>, sizeof...(In)>           m_inputLocations{};
0053 
0054       using base_class = Gaudi::Functional::details::DataHandleMixin<std::tuple<>, std::tuple<>, Traits_>;
0055 
0056       using KeyValues = typename base_class::KeyValues;
0057 
0058       template <typename IArgs, std::size_t... I>
0059       Consumer(std::string name, ISvcLocator* locator, const IArgs& inputs, std::index_sequence<I...>)
0060           : base_class(std::move(name), locator),
0061             // The input locations are filled by creating a property with a callback function
0062             // that creates the handles because that is when the input locations become available
0063             // (from a steering file, for example) and the handles have to be created for
0064             // Gaudi to know the data flow
0065             m_inputLocations{Gaudi::Property<std::vector<DataObjID>>{
0066                 this, std::get<I>(inputs).first, to_DataObjID(std::get<I>(inputs).second),
0067                 [this](Gaudi::Details::PropertyBase&) {
0068                   std::vector<InputHandle_t<EventStoreType_t>> handles;
0069                   for (auto& value : this->m_inputLocations[I].value()) {
0070                     auto handle = InputHandle_t<EventStoreType_t>(value, this);
0071                     handles.push_back(std::move(handle));
0072                   }
0073                   std::get<I>(m_inputs) = std::move(handles);
0074                 },
0075                 Gaudi::Details::Property::ImmediatelyInvokeHandler{true}}...} {}
0076 
0077       Consumer(std::string name, ISvcLocator* locator,
0078                Gaudi::Functional::details::RepeatValues_<KeyValues, sizeof...(In)> const& inputs)
0079           : Consumer(std::move(name), locator, inputs, std::index_sequence_for<In...>{}) {}
0080 
0081       // derived classes are NOT allowed to implement execute ...
0082       StatusCode execute(const EventContext& ctx) const final {
0083         try {
0084           filter_evtcontext_tt<In...>::apply(*this, ctx, m_inputs);
0085           return Gaudi::Functional::FilterDecision::PASSED;
0086         } catch (GaudiException& e) {
0087           (e.code() ? this->warning() : this->error()) << e.tag() << " : " << e.message() << endmsg;
0088           return e.code();
0089         }
0090       }
0091 
0092       // ... instead, they must implement the following operator
0093       virtual void operator()(const In&...) const = 0;
0094 
0095       /**
0096        * @brief    Get the input locations for a given input index
0097        * @param i  The index of the input
0098        * @return   A range of the input locations
0099        */
0100       auto inputLocations(size_t i) const {
0101         if (i >= sizeof...(In)) {
0102           throw std::out_of_range("Called inputLocations with an index out of range, index: " + std::to_string(i) +
0103                                   ", number of inputs: " + std::to_string(sizeof...(In)));
0104         }
0105         return m_inputLocations[i] | std::views::transform([](const DataObjID& id) -> const auto& { return id.key(); });
0106       }
0107       /**
0108        * @brief       Get the input locations for a given input name
0109        * @param name  The name of the input
0110        * @return      A range of the input locations
0111        */
0112       auto inputLocations(std::string_view name) const {
0113         auto it = std::ranges::find_if(m_inputLocations, [&name](const auto& prop) { return prop.name() == name; });
0114         if (it == m_inputLocations.end()) {
0115           throw std::runtime_error("Called inputLocations with an unknown name");
0116         }
0117         return it->value() | std::views::transform([](const DataObjID& id) -> const auto& { return id.key(); });
0118       }
0119       static constexpr std::size_t inputLocationsSize() { return sizeof...(In); }
0120     };
0121 
0122   }  // namespace details
0123 
0124   template <typename Signature, typename Traits_ = Gaudi::Functional::Traits::useDefaults>
0125   using Consumer = details::Consumer<Signature, Traits_>;
0126 
0127 }  // namespace k4FWCore
0128 
0129 #endif  // FWCORE_CONSUMER_H