CMS 3D CMS Logo

InputProcessBlockCacheImpl.h
Go to the documentation of this file.
1 #ifndef FWCore_Framework_InputProcessBlockCacheImpl_h
2 #define FWCore_Framework_InputProcessBlockCacheImpl_h
3 
20 
21 #include <cstddef>
22 #include <functional>
23 #include <memory>
24 #include <string>
25 #include <tuple>
26 #include <type_traits>
27 #include <utility>
28 #include <vector>
29 
30 namespace edm {
31 
32  class Event;
33 
34  namespace impl {
35 
36  template <typename M>
38  return 0;
39  }
40 
41  template <typename M, typename V1, typename... Vs>
44  : countTypeInParameterPack<M, Vs...>();
45  }
46 
47  class InvalidCacheType {};
48 
49  template <typename W, typename U = InvalidCacheType, typename... Types>
52  return 0;
53  } else {
54  if constexpr (sizeof...(Types) > 0) {
55  return 1 + indexInputProcessBlockCache<W, Types...>();
56  } else {
57  static_assert(sizeof...(Types) > 0,
58  "CacheType used with registerProcessBlockCacheFiller does not match any template parameters of "
59  "InputProcessBlockCache");
60  return 0;
61  }
62  }
63  }
64 
65  struct TokenInfo {
68  };
69 
70  template <typename CacheType>
71  class CacheFiller {
72  public:
73  std::function<std::shared_ptr<CacheType>(ProcessBlock const&, std::shared_ptr<CacheType> const&)> func_;
74  };
75 
76  template <typename... CacheTypes>
78  public:
79  InputProcessBlockCacheImpl() = default;
82 
83  template <std::size_t I>
84  requires requires { requires I == sizeof...(CacheTypes); }
85  void fillTuple(std::tuple<CacheHandle<CacheTypes>...>&, Event const&) const {}
86 
87  template <std::size_t I>
88  requires requires { requires I < sizeof...(CacheTypes); }
89  void fillTuple(std::tuple<CacheHandle<CacheTypes>...>& cacheHandles, Event const& event) const {
90  unsigned int index = eventProcessBlockIndex(event, processNames_[I]);
91 
92  // If the branch associated with the token was passed to registerProcessBlockCacheFiller
93  // was not in the input file, then the index will be invalid. Note the branch (including
94  // its process name) is selected using the first input file. Also note that even if
95  // the branch is present and this index is valid, the product might not be there.
96  // The functor in the CacheFiller must deal with that case.
98  std::get<I>(cacheHandles) = CacheHandle(std::get<I>(caches_.at(index).cacheTuple_).get());
99  }
100  fillTuple<I + 1>(cacheHandles, event);
101  }
102 
103  std::tuple<CacheHandle<CacheTypes>...> processBlockCaches(Event const& event) const {
104  std::tuple<CacheHandle<CacheTypes>...> cacheHandles;
105  // processNames will be empty if and only if registerProcessBlockCacheFiller
106  // was never called by the module constructor
107  if (!processNames_.empty()) {
108  fillTuple<0>(cacheHandles, event);
109  }
110  return cacheHandles;
111  }
112 
113  void selectInputProcessBlocks(ProductRegistry const& productRegistry,
114  ProcessBlockHelperBase const& processBlockHelperBase,
115  EDConsumerBase const& edConsumerBase) {
116  unsigned int i = 0;
117  for (auto const& tokenInfo : tokenInfos_) {
118  if (!tokenInfo.token_.isUninitialized()) {
120  edConsumerBase.labelsForToken(tokenInfo.token_, productLabels);
121 
122  processNames_[i] = processBlockHelperBase.selectProcess(productRegistry, productLabels, tokenInfo.typeID_);
123  }
124  ++i;
125  }
126  tokenInfos_.clear();
127  }
128 
129  template <std::size_t N>
130  using CacheTypeT = typename std::tuple_element<N, std::tuple<CacheTypes...>>::type;
131 
132  template <std::size_t ICacheType, typename DataType, typename Func>
134  registerProcessBlockCacheFiller<ICacheType, CacheTypeT<ICacheType>, DataType, Func>(token,
135  std::forward<Func>(func));
136  }
137 
138  template <typename CacheType, typename DataType, typename Func>
140  static_assert(countTypeInParameterPack<CacheType, CacheTypes...>() == 1u,
141  "If registerProcessBlockCacheFiller is called with a type template parameter\n"
142  "then that type must appear exactly once in the template parameters of InputProcessBlockCache");
143 
144  // Find the index into the parameter pack from the CacheType
145  constexpr unsigned int I = indexInputProcessBlockCache<CacheType, CacheTypes...>();
146 
147  registerProcessBlockCacheFiller<I, CacheType, DataType, Func>(token, std::forward<Func>(func));
148  }
149 
150  // This gets used for stream type modules where the InputProcessBlockCacheImpl
151  // object is held by the adaptor. For stream modules, we use a registerProcessBlockCacheFiller
152  // function defined in edm::stream::impl::InputProcessBlockCacheHolder then
153  // move the information.
154  void moveProcessBlockCacheFiller(std::vector<edm::impl::TokenInfo>& tokenInfos,
156  tokenInfos_ = std::move(tokenInfos);
157  functors_ = std::move(functors);
158  if (!tokenInfos_.empty()) {
159  processNames_.resize(sizeof...(CacheTypes));
160  }
161  }
162 
163  // These are used to fill the CacheTuples
164  // One CacheFiller for each CacheType
165 
166  class CacheTuple {
167  public:
168  std::tuple<std::shared_ptr<CacheTypes>...> cacheTuple_;
169  };
170 
171  template <std::size_t I>
172  typename std::enable_if<I == sizeof...(CacheTypes), void>::type fillCache(ProcessBlock const&,
173  CacheTuple const&,
174  CacheTuple&) {}
175 
176  template <std::size_t I>
177  typename std::enable_if < I<sizeof...(CacheTypes), void>::type fillCache(ProcessBlock const& pb,
178  CacheTuple const& previousCacheTuple,
179  CacheTuple& cacheTuple) {
180  if (pb.processName() == processNames_[I]) {
181  auto const& previousSharedPtr = std::get<I>(previousCacheTuple.cacheTuple_);
182  std::get<I>(cacheTuple.cacheTuple_) = std::get<I>(functors_).func_(pb, previousSharedPtr);
183  }
184  fillCache<I + 1>(pb, previousCacheTuple, cacheTuple);
185  }
186 
187  void accessInputProcessBlock(ProcessBlock const& pb) {
188  if (sizeof...(CacheTypes) > 0 && !processNames_.empty()) {
189  CacheTuple cacheTuple;
190  if (caches_.empty()) {
191  CacheTuple firstCacheTuple;
192  fillCache<0>(pb, firstCacheTuple, cacheTuple);
193  } else {
194  CacheTuple const& previousCacheTuple = caches_.back();
195  fillCache<0>(pb, previousCacheTuple, cacheTuple);
196  }
197  caches_.push_back(std::move(cacheTuple));
198  }
199  }
200 
201  void clearCaches() { caches_.clear(); }
202  auto cacheSize() const { return caches_.size(); }
203 
204  private:
205  template <std::size_t ICacheType, typename CacheType, typename DataType, typename Func>
206  void registerProcessBlockCacheFiller(EDGetTokenT<DataType> const& token, Func&& func) {
207  static_assert(ICacheType < sizeof...(CacheTypes), "ICacheType out of range");
208  processNames_.resize(sizeof...(CacheTypes));
209  tokenInfos_.resize(sizeof...(CacheTypes));
210  if (!tokenInfos_[ICacheType].token_.isUninitialized()) {
212  << "registerProcessBlockCacheFiller should only be called once per cache type";
213  }
214 
215  tokenInfos_[ICacheType] = TokenInfo{EDGetToken(token), TypeID(typeid(DataType))};
216 
217  std::get<ICacheType>(functors_).func_ = std::forward<Func>(func);
218  }
219 
220  // ------------ Data members --------------------
221 
222  // This holds an entry per ProcessBlock
223  std::vector<CacheTuple> caches_;
224 
225  // The following 3 data members have one element for each CacheType
226  std::tuple<CacheFiller<CacheTypes>...> functors_;
227  std::vector<std::string> processNames_;
228  std::vector<TokenInfo> tokenInfos_;
229  };
230 
231  } // namespace impl
232 } // namespace edm
233 #endif
std::string const & processName() const
Definition: ProcessBlock.cc:23
std::function< std::shared_ptr< CacheType >ProcessBlock const &, std::shared_ptr< CacheType > const &)> func_
std::enable_if< I==sizeof...(CacheTypes), void >::type fillCache(ProcessBlock const &, CacheTuple const &, CacheTuple &)
constexpr std::size_t indexInputProcessBlockCache()
void moveProcessBlockCacheFiller(std::vector< edm::impl::TokenInfo > &tokenInfos, std::tuple< edm::impl::CacheFiller< CacheTypes >... > &functors)
static constexpr unsigned int invalidCacheIndex()
void fillTuple(std::tuple< CacheHandle< CacheTypes >... > &cacheHandles, Event const &event) const
void selectInputProcessBlocks(ProductRegistry const &productRegistry, ProcessBlockHelperBase const &processBlockHelperBase, EDConsumerBase const &edConsumerBase)
void fillTuple(std::tuple< CacheHandle< CacheTypes >... > &, Event const &) const
void registerProcessBlockCacheFiller(EDGetTokenT< DataType > const &token, Func &&func)
const std::complex< double > I
Definition: I.h:8
unsigned int eventProcessBlockIndex(Event const &event, std::string const &processName)
Definition: Types.py:1
typename std::tuple_element< N, std::tuple< CacheTypes... > >::type CacheTypeT
#define N
Definition: blowfish.cc:9
InputProcessBlockCacheImpl & operator=(InputProcessBlockCacheImpl const &)=delete
std::tuple< CacheHandle< CacheTypes >... > processBlockCaches(Event const &event) const
HLT enums.
std::string selectProcess(ProductRegistry const &, ProductLabels const &, TypeID const &) const
constexpr std::size_t countTypeInParameterPack()
std::tuple< std::shared_ptr< CacheTypes >... > cacheTuple_
def move(src, dest)
Definition: eostools.py:511
Definition: event.py:1
void labelsForToken(EDGetToken iToken, Labels &oLabels) const