Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2023-03-17 11:05:43

0001 #ifndef HeterogeneousCore_CUDACore_interface_ConvertingESProducerWithDependenciesT_h
0002 #define HeterogeneousCore_CUDACore_interface_ConvertingESProducerWithDependenciesT_h
0003 
0004 #include <tuple>
0005 #include <utility>
0006 
0007 #include "FWCore/Framework/interface/ESProducer.h"
0008 #include "FWCore/Framework/interface/ESHandle.h"
0009 #include "FWCore/Framework/interface/MakerMacros.h"
0010 #include "FWCore/Framework/interface/ModuleFactory.h"
0011 #include "FWCore/Framework/interface/eventsetuprecord_registration_macro.h"
0012 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0013 #include "FWCore/Utilities/interface/typelookup.h"
0014 
0015 /* class template: ConvertingESProducerWithDependenciesT
0016  * 
0017  * This class template can be used to simplify the implementation of any ESProducer that reads
0018  * multiple conditions data from one or more records record and pushes derived conditions data
0019  * to a combined dependent record.
0020  * The current use case is to convert and copy the calibrations from the CPU to the GPUs.
0021  */
0022 
0023 namespace detail {
0024   // simple implementation of a type zipper over 2 tuples
0025   // here, the main requirement is the default constructor for Gen template
0026   // which __does__ exist for ESGetToken
0027 
0028   template <template <typename, typename> class Gen, typename Tuple1, typename Tuple2>
0029   struct TypeZipper;
0030 
0031   template <template <typename, typename> class Gen, typename Tuple1, typename Tuple2, std::size_t... Is>
0032   auto TypeZipperImpl(Tuple1 const& t1, Tuple2 const& t2, std::index_sequence<Is...>) {
0033     return std::make_tuple(
0034         Gen<typename std::tuple_element<Is, Tuple1>::type, typename std::tuple_element<Is, Tuple2>::type>{}...);
0035   }
0036 
0037   template <template <typename, typename> class Gen, typename... Ts1, typename... Ts2>
0038   struct TypeZipper<Gen, std::tuple<Ts1...>, std::tuple<Ts2...>> {
0039     static_assert(sizeof...(Ts1) == sizeof...(Ts2));
0040     using type = typename std::decay<decltype(TypeZipperImpl<Gen>(
0041         std::tuple<Ts1...>{}, std::tuple<Ts2...>{}, std::index_sequence_for<Ts1...>{}))>::type;
0042   };
0043 
0044 }  // namespace detail
0045 
0046 template <typename CombinedRecord, typename Target, typename... Dependencies>
0047 class ConvertingESProducerWithDependenciesT;
0048 
0049 template <template <typename...> typename CombinedRecord,
0050           typename... DepsRecords,
0051           typename Target,
0052           typename... Dependencies>
0053 class ConvertingESProducerWithDependenciesT<CombinedRecord<DepsRecords...>, Target, Dependencies...>
0054     : public edm::ESProducer {
0055 public:
0056   static constexpr std::size_t nsources = sizeof...(Dependencies);
0057   static_assert(sizeof...(Dependencies) == sizeof...(DepsRecords));
0058 
0059   explicit ConvertingESProducerWithDependenciesT(edm::ParameterSet const& ps) {
0060     std::vector<edm::ESInputTag> tags(nsources);
0061     for (std::size_t i = 0; i < nsources; i++)
0062       tags[i] = edm::ESInputTag{"", ps.getParameter<std::string>("label" + std::to_string(i))};
0063 
0064     std::string const& name = ps.getParameter<std::string>("ComponentName");
0065     edm::ESConsumesCollectorT<CombinedRecord<DepsRecords...>> cc = setWhatProduced(this, name);
0066     WalkConsumes<nsources - 1>::iterate(cc, tokens_, tags);
0067   }
0068 
0069   std::unique_ptr<Target> produce(CombinedRecord<DepsRecords...> const& record) {
0070     auto handles = std::tuple<edm::ESHandle<Dependencies>...>{};
0071     WalkAndCall<nsources - 1, edm::ESHandle<Dependencies>...>::iterate(record, handles, tokens_);
0072 
0073     return std::apply([](auto const&... handles) { return std::make_unique<Target>((*handles)...); }, handles);
0074   }
0075 
0076   static void fillDescriptions(edm::ConfigurationDescriptions& confDesc) {
0077     edm::ParameterSetDescription desc;
0078 
0079     desc.add<std::string>("ComponentName", "");
0080     for (std::size_t i = 0; i < nsources; i++)
0081       desc.add<std::string>("label" + std::to_string(i), "")->setComment("Product Label");
0082     confDesc.addWithDefaultLabel(desc);
0083   }
0084 
0085 private:
0086   using TokenType =
0087       typename detail::TypeZipper<edm::ESGetToken, std::tuple<Dependencies...>, std::tuple<DepsRecords...>>::type;
0088   TokenType tokens_;
0089 
0090 private:
0091   template <std::size_t N>
0092   struct WalkConsumes {
0093     static void iterate(edm::ESConsumesCollectorT<CombinedRecord<DepsRecords...>>& cc,
0094                         TokenType& tokens,
0095                         std::vector<edm::ESInputTag> const& tags) {
0096       if constexpr (N > 0)
0097         WalkConsumes<N - 1>::iterate(cc, tokens, tags);
0098       std::get<N>(tokens) = cc.consumes(tags[N]);
0099     }
0100   };
0101 
0102   template <std::size_t N, typename... Types>
0103   struct WalkAndCall {
0104     static void iterate(CombinedRecord<DepsRecords...> const& containingRecord,
0105                         std::tuple<Types...>& ts,
0106                         TokenType const& tokens) {
0107       using Record = typename std::tuple_element<N, std::tuple<DepsRecords...>>::type;
0108       if constexpr (N > 0)
0109         WalkAndCall<N - 1, Types...>::iterate(containingRecord, ts, tokens);
0110       // get the right dependent record
0111       auto const& record = containingRecord.template getRecord<Record>();
0112       // assign the right element of the tuple
0113       std::get<N>(ts) = record.getHandle(std::get<N>(tokens));
0114     }
0115   };
0116 };
0117 
0118 #endif  // HeterogeneousCore_CUDACore_interface_ConvertingESProducerWithDependenciesT_h