CMS 3D CMS Logo

ConvertingESProducerWithDependenciesT.h
Go to the documentation of this file.
1 #ifndef HeterogeneousCore_CUDACore_interface_ConvertingESProducerWithDependenciesT_h
2 #define HeterogeneousCore_CUDACore_interface_ConvertingESProducerWithDependenciesT_h
3 
4 #include <tuple>
5 #include <utility>
6 
14 
15 /* class template: ConvertingESProducerWithDependenciesT
16  *
17  * This class template can be used to simplify the implementation of any ESProducer that reads
18  * multiple conditions data from one or more records record and pushes derived conditions data
19  * to a combined dependent record.
20  * The current use case is to convert and copy the calibrations from the CPU to the GPUs.
21  */
22 
23 namespace detail {
24  // simple implementation of a type zipper over 2 tuples
25  // here, the main requirement is the default constructor for Gen template
26  // which __does__ exist for ESGetToken
27 
28  template <template <typename, typename> class Gen, typename Tuple1, typename Tuple2>
29  struct TypeZipper;
30 
31  template <template <typename, typename> class Gen, typename Tuple1, typename Tuple2, std::size_t... Is>
32  auto TypeZipperImpl(Tuple1 const& t1, Tuple2 const& t2, std::index_sequence<Is...>) {
33  return std::make_tuple(
35  }
36 
37  template <template <typename, typename> class Gen, typename... Ts1, typename... Ts2>
38  struct TypeZipper<Gen, std::tuple<Ts1...>, std::tuple<Ts2...>> {
39  static_assert(sizeof...(Ts1) == sizeof...(Ts2));
40  using type = typename std::decay<decltype(TypeZipperImpl<Gen>(
41  std::tuple<Ts1...>{}, std::tuple<Ts2...>{}, std::index_sequence_for<Ts1...>{}))>::type;
42  };
43 
44 } // namespace detail
45 
46 template <typename CombinedRecord, typename Target, typename... Dependencies>
48 
49 template <template <typename...> typename CombinedRecord,
50  typename... DepsRecords,
51  typename Target,
52  typename... Dependencies>
53 class ConvertingESProducerWithDependenciesT<CombinedRecord<DepsRecords...>, Target, Dependencies...>
54  : public edm::ESProducer {
55 public:
56  static constexpr std::size_t nsources = sizeof...(Dependencies);
57  static_assert(sizeof...(Dependencies) == sizeof...(DepsRecords));
58 
60  std::vector<edm::ESInputTag> tags(nsources);
61  for (std::size_t i = 0; i < nsources; i++)
63 
64  std::string const& name = ps.getParameter<std::string>("ComponentName");
65  edm::ESConsumesCollectorT<CombinedRecord<DepsRecords...>> cc = setWhatProduced(this, name);
66  WalkConsumes<nsources - 1>::iterate(cc, tokens_, tags);
67  }
68 
69  std::unique_ptr<Target> produce(CombinedRecord<DepsRecords...> const& record) {
70  auto handles = std::tuple<edm::ESHandle<Dependencies>...>{};
71  WalkAndCall<nsources - 1, edm::ESHandle<Dependencies>...>::iterate(record, handles, tokens_);
72 
73  return std::apply([](auto const&... handles) { return std::make_unique<Target>((*handles)...); }, handles);
74  }
75 
78 
79  desc.add<std::string>("ComponentName", "");
80  for (std::size_t i = 0; i < nsources; i++)
81  desc.add<std::string>("label" + std::to_string(i), "")->setComment("Product Label");
82  confDesc.addWithDefaultLabel(desc);
83  }
84 
85 private:
86  using TokenType =
87  typename detail::TypeZipper<edm::ESGetToken, std::tuple<Dependencies...>, std::tuple<DepsRecords...>>::type;
89 
90 private:
91  template <std::size_t N>
92  struct WalkConsumes {
93  static void iterate(edm::ESConsumesCollectorT<CombinedRecord<DepsRecords...>>& cc,
94  TokenType& tokens,
95  std::vector<edm::ESInputTag> const& tags) {
96  if constexpr (N > 0)
97  WalkConsumes<N - 1>::iterate(cc, tokens, tags);
98  std::get<N>(tokens) = cc.consumes(tags[N]);
99  }
100  };
101 
102  template <std::size_t N, typename... Types>
103  struct WalkAndCall {
104  static void iterate(CombinedRecord<DepsRecords...> const& containingRecord,
105  std::tuple<Types...>& ts,
106  TokenType const& tokens) {
107  using Record = typename std::tuple_element<N, std::tuple<DepsRecords...>>::type;
108  if constexpr (N > 0)
109  WalkAndCall<N - 1, Types...>::iterate(containingRecord, ts, tokens);
110  // get the right dependent record
111  auto const& record = containingRecord.template getRecord<Record>();
112  // assign the right element of the tuple
113  std::get<N>(ts) = record.getHandle(std::get<N>(tokens));
114  }
115  };
116 };
117 
118 #endif // HeterogeneousCore_CUDACore_interface_ConvertingESProducerWithDependenciesT_h
void addWithDefaultLabel(ParameterSetDescription const &psetDescription)
T getParameter(std::string const &) const
Definition: ParameterSet.h:303
std::string to_string(const V &value)
Definition: OMSAccess.h:71
std::vector< BaseVolumeHandle * > handles
Definition: Types.py:1
auto TypeZipperImpl(Tuple1 const &t1, Tuple2 const &t2, std::index_sequence< Is... >)
TFile * Target
typename detail::TypeZipper< edm::ESGetToken, std::tuple< Dependencies... >, std::tuple< DepsRecords... > >::type TokenType
std::vector< edm::EDGetTokenT< int > > tokens_
#define N
Definition: blowfish.cc:9
static void iterate(CombinedRecord< DepsRecords... > const &containingRecord, std::tuple< Types... > &ts, TokenType const &tokens)
static void iterate(edm::ESConsumesCollectorT< CombinedRecord< DepsRecords... >> &cc, TokenType &tokens, std::vector< edm::ESInputTag > const &tags)
typename std::decay< decltype(TypeZipperImpl< Gen >(std::tuple< Ts1... >{}, std::tuple< Ts2... >{}, std::index_sequence_for< Ts1... >{}))>::type type
Vec apply(Vec v, F f)
Definition: ExtVec.h:81