CMS 3D CMS Logo

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
EDConsumerBase.cc
Go to the documentation of this file.
1 // -*- C++ -*-
2 //
3 // Package: FWCore/Framework
4 // Class : EDConsumerBase
5 //
6 // Implementation:
7 // [Notes on implementation]
8 //
9 // Original Author: Chris Jones
10 // Created: Tue, 02 Apr 2013 21:36:06 GMT
11 //
12 
13 // system include files
14 #include <algorithm>
15 #include <cassert>
16 #include <cstring>
17 #include <set>
18 #include <utility>
19 
20 // user include files
29 
30 using namespace edm;
31 
32 //
33 // constants, enums and typedefs
34 //
35 
36 //
37 // static data member definitions
38 //
39 
40 //
41 // constructors and destructor
42 //
43 //EDConsumerBase::EDConsumerBase()
44 //{
45 //}
46 
47 // EDConsumerBase::EDConsumerBase(const EDConsumerBase& rhs)
48 // {
49 // // do actual copying here;
50 // }
51 
53 {
54 }
55 
56 //
57 // assignment operators
58 //
59 // const EDConsumerBase& EDConsumerBase::operator=(const EDConsumerBase& rhs)
60 // {
61 // //An exception safe implementation is
62 // EDConsumerBase temp(rhs);
63 // swap(rhs);
64 //
65 // return *this;
66 // }
67 
68 //
69 // member functions
70 //
73  ConsumesCollector c{this};
74  return c;
75 }
76 
77 static const edm::InputTag kWasEmpty("@EmptyLabel@");
78 
79 edm::InputTag const&
81  if (iTag.label().empty()) {
82  return kWasEmpty;
83  }
84  return iTag;
85 }
86 
87 unsigned int
88 EDConsumerBase::recordConsumes(BranchType iBranch, TypeToGet const& iType, edm::InputTag const& iTag, bool iAlwaysGets) {
89 
90  if(frozen_) {
91  throwConsumesCallAfterFrozen(iType, iTag);
92  }
93 
94  unsigned int index =m_tokenInfo.size();
95 
96  bool skipCurrentProcess = iTag.willSkipCurrentProcess();
97 
98  const size_t labelSize = iTag.label().size();
99  const size_t productInstanceSize = iTag.instance().size();
100  unsigned int labelStart = m_tokenLabels.size();
101  unsigned short delta1 = labelSize+1;
102  unsigned short delta2 = labelSize+2+productInstanceSize;
103  m_tokenInfo.emplace_back(TokenLookupInfo{iType.type(), ProductResolverIndexInvalid, skipCurrentProcess, iBranch},
104  iAlwaysGets,
105  LabelPlacement{labelStart,delta1,delta2},
106  iType.kind());
107 
108  const size_t additionalSize =
109  skipCurrentProcess ?
110  labelSize+productInstanceSize+3 :
111  labelSize+productInstanceSize+iTag.process().size()+3;
112 
113  m_tokenLabels.reserve(m_tokenLabels.size()+additionalSize);
114  {
115  const std::string& m =iTag.label();
116  m_tokenLabels.insert(m_tokenLabels.end(),m.begin(),m.end());
117  m_tokenLabels.push_back('\0');
118  }
119  {
120  const std::string& m =iTag.instance();
121  m_tokenLabels.insert(m_tokenLabels.end(),m.begin(),m.end());
122  m_tokenLabels.push_back('\0');
123  }
124  {
125  if (!skipCurrentProcess) {
126  const std::string& m =iTag.process();
127  m_tokenLabels.insert(m_tokenLabels.end(),m.begin(),m.end());
128  m_tokenLabels.push_back('\0');
129  } else {
130  m_tokenLabels.push_back('\0');
131  }
132  }
133  return index;
134 }
135 
136 void
138  ProductResolverIndexHelper const& iHelper,
139  bool iPrefetchMayGet)
140 {
141  frozen_ = true;
142  {
143  auto itKind = m_tokenInfo.begin<kKind>();
144  auto itLabels = m_tokenInfo.begin<kLabels>();
145  for(auto itInfo = m_tokenInfo.begin<kLookupInfo>(),itEnd = m_tokenInfo.end<kLookupInfo>();
146  itInfo != itEnd; ++itInfo,++itKind,++itLabels) {
147  if(itInfo->m_branchType == iBranchType) {
148  const unsigned int labelStart = itLabels->m_startOfModuleLabel;
149  const char* moduleLabel = &(m_tokenLabels[labelStart]);
150  itInfo->m_index = ProductResolverIndexAndSkipBit(iHelper.index(*itKind,
151  itInfo->m_type,
152  moduleLabel,
153  moduleLabel+itLabels->m_deltaToProductInstance,
154  moduleLabel+itLabels->m_deltaToProcessName),
155  itInfo->m_index.skipCurrentProcess());
156  }
157  }
158  }
159 
160  //now add resolved requests to get many to the end of our list
161  // a get many will have an empty module label
162  for(size_t i=0, iEnd = m_tokenInfo.size(); i!=iEnd;++i) {
163  //need to copy since pointer could be invalidated by emplace_back
164  auto const info = m_tokenInfo.get<kLookupInfo>(i);
165  if(info.m_branchType == iBranchType &&
166  info.m_index.productResolverIndex() == ProductResolverIndexInvalid &&
167  m_tokenLabels[m_tokenInfo.get<kLabels>(i).m_startOfModuleLabel]=='\0') {
168  //find all matching types
169  const auto kind=m_tokenInfo.get<kKind>(i);
170  auto matches = iHelper.relatedIndexes(kind,info.m_type);
171 
172  //NOTE: This could be changed to contain the true labels for what is being
173  // requested but for now I want to remember these are part of a get many
175  bool alwaysGet = m_tokenInfo.get<kAlwaysGets>(i);
176  for(unsigned int j=0;j!=matches.numberOfMatches();++j) {
177  //only keep the ones that are for a specific data item and not a collection
178  if(matches.isFullyResolved(j)) {
179  auto index =matches.index(j);
180  m_tokenInfo.emplace_back(TokenLookupInfo{info.m_type, index, info.m_index.skipCurrentProcess(), info.m_branchType},
181  alwaysGet,
182  labels,
183  kind);
184  }
185  }
186  }
187  }
188  m_tokenInfo.shrink_to_fit();
189 
190  itemsToGet(iBranchType, itemsToGetFromBranch_[iBranchType]);
191  if(iPrefetchMayGet) {
192  itemsMayGet(iBranchType, itemsToGetFromBranch_[iBranchType]);
193  }
194 }
195 
196 //
197 // const member functions
198 //
200 EDConsumerBase::indexFrom(EDGetToken iToken, BranchType iBranch, TypeID const& iType) const
201 {
202  if(unlikely(iToken.index()>=m_tokenInfo.size())) {
203  throwBadToken(iType,iToken);
204  }
205  const auto& info = m_tokenInfo.get<kLookupInfo>(iToken.index());
206  if (likely(iBranch == info.m_branchType)) {
207  if (likely(iType == info.m_type)) {
208  return info.m_index;
209  } else {
210  throwTypeMismatch(iType, iToken);
211  }
212  } else {
213  throwBranchMismatch(iBranch,iToken);
214  }
216 }
217 
218 void
219 EDConsumerBase::itemsToGet(BranchType iBranch, std::vector<ProductResolverIndexAndSkipBit>& oIndices) const
220 {
221  //how many are we adding?
222  unsigned int count=0;
223  {
224  auto itAlwaysGet = m_tokenInfo.begin<kAlwaysGets>();
225  for(auto it = m_tokenInfo.begin<kLookupInfo>(),
226  itEnd = m_tokenInfo.end<kLookupInfo>();
227  it != itEnd; ++it,++itAlwaysGet) {
228  if(iBranch==it->m_branchType) {
229  if (it->m_index.productResolverIndex() != ProductResolverIndexInvalid) {
230  if(*itAlwaysGet) {
231  ++count;
232  }
233  }
234  }
235  }
236  }
237  oIndices.reserve(oIndices.size()+count);
238  {
239  auto itAlwaysGet = m_tokenInfo.begin<kAlwaysGets>();
240  for(auto it = m_tokenInfo.begin<kLookupInfo>(),
241  itEnd = m_tokenInfo.end<kLookupInfo>();
242  it != itEnd; ++it,++itAlwaysGet) {
243  if(iBranch==it->m_branchType) {
244  if (it->m_index.productResolverIndex() != ProductResolverIndexInvalid) {
245  if(*itAlwaysGet) {
246  oIndices.push_back(it->m_index);
247  }
248  }
249  }
250  }
251  }
252 }
253 
254 void
255 EDConsumerBase::itemsMayGet(BranchType iBranch, std::vector<ProductResolverIndexAndSkipBit>& oIndices) const
256 {
257  //how many are we adding?
258  unsigned int count=0;
259  {
260  auto itAlwaysGet = m_tokenInfo.begin<kAlwaysGets>();
261  for(auto it = m_tokenInfo.begin<kLookupInfo>(),
262  itEnd = m_tokenInfo.end<kLookupInfo>();
263  it != itEnd; ++it,++itAlwaysGet) {
264  if(iBranch==it->m_branchType) {
265  if (it->m_index.productResolverIndex() != ProductResolverIndexInvalid) {
266  if(not *itAlwaysGet) {
267  ++count;
268  }
269  }
270  }
271  }
272  }
273  oIndices.reserve(oIndices.size()+count);
274  {
275  auto itAlwaysGet = m_tokenInfo.begin<kAlwaysGets>();
276  for(auto it = m_tokenInfo.begin<kLookupInfo>(),
277  itEnd = m_tokenInfo.end<kLookupInfo>();
278  it != itEnd; ++it,++itAlwaysGet) {
279  if(iBranch==it->m_branchType) {
280  if (it->m_index.productResolverIndex() != ProductResolverIndexInvalid) {
281  if(not *itAlwaysGet) {
282  oIndices.push_back(it->m_index);
283  }
284  }
285  }
286  }
287  }
288 }
289 
290 void
292 {
293  unsigned int index = iToken.index();
294  auto labels = m_tokenInfo.get<kLabels>(index);
295  unsigned int start = labels.m_startOfModuleLabel;
296  oLabels.module = &(m_tokenLabels[start]);
297  oLabels.productInstance = oLabels.module+labels.m_deltaToProductInstance;
298  oLabels.process = oLabels.module+labels.m_deltaToProcessName;
299 }
300 
301 bool
302 EDConsumerBase::registeredToConsume(ProductResolverIndex iIndex, bool skipCurrentProcess, BranchType iBranch) const
303 {
304  for(auto it = m_tokenInfo.begin<kLookupInfo>(),
305  itEnd = m_tokenInfo.end<kLookupInfo>();
306  it != itEnd; ++it) {
307  if(it->m_index.productResolverIndex() == iIndex and
308  it->m_index.skipCurrentProcess() == skipCurrentProcess and
309  it->m_branchType == iBranch) {
310  return true;
311  }
312  }
313  //TEMPORARY: Remember so we do not have to do this again
314  //non thread-safe
315  EDConsumerBase* nonConstThis = const_cast<EDConsumerBase*>(this);
316  nonConstThis->m_tokenInfo.emplace_back(TokenLookupInfo{TypeID{}, iIndex, skipCurrentProcess, iBranch},
317  true,
318  LabelPlacement{0,0,0},
319  PRODUCT_TYPE);
320 
321  return false;
322 }
323 
324 bool
326 {
327  for(auto it = m_tokenInfo.begin<kLookupInfo>(),
328  itEnd = m_tokenInfo.end<kLookupInfo>();
329  it != itEnd; ++it) {
330  //consumesMany entries do not have their index resolved
331  if(it->m_index.productResolverIndex() == ProductResolverIndexInvalid and
332  it->m_type == iType and
333  it->m_branchType == iBranch) {
334  return true;
335  }
336  }
337  //TEMPORARY: Remember so we do not have to do this again
338  //non thread-safe
339  EDConsumerBase* nonConstThis = const_cast<EDConsumerBase*>(this);
340  nonConstThis->m_tokenInfo.emplace_back(TokenLookupInfo{iType,ProductResolverIndexInvalid, false, iBranch},
341  true,
342  LabelPlacement{0,0,0},
343  PRODUCT_TYPE);
344  return false;
345 
346 }
347 
348 
349 void
351 {
352  throw cms::Exception("TypeMismatch")<<"A get using a EDGetToken used the C++ type '"<<iType.className()<<"' but the consumes call was for type '"<<m_tokenInfo.get<kLookupInfo>(iToken.index()).m_type.className()<<"'.\n Please modify either the consumes or get call so the types match.";
353 }
354 void
356  throw cms::Exception("BranchTypeMismatch")<<"A get using a EDGetToken was done in "<<BranchTypeToString(iBranch)<<" but the consumes call was for "<<BranchTypeToString(m_tokenInfo.get<kLookupInfo>(iToken.index()).m_branchType)<<".\n Please modify the consumes call to use the correct branch type.";
357 }
358 
359 void
361 {
362  if(iToken.isUninitialized()) {
363  throw cms::Exception("BadToken")<<"A get using a EDGetToken with the C++ type '"<<iType.className()<<"' was made using an uninitialized token.\n Please check that the variable is being initialized from a 'consumes' call.";
364  }
365  throw cms::Exception("BadToken")<<"A get using a EDGetToken with the C++ type '"<<iType.className()<<"' was made using a token with a value "<<iToken.index()<<" which is beyond the range used by this module.\n Please check that the variable is being initialized from a 'consumes' call from this module.\n You can not share EDGetToken values between modules.";
366 }
367 
368 void
370  throw cms::Exception("LogicError") << "A module declared it consumes a product after its constructor.\n"
371  << "This must be done in the contructor\n"
372  << "The product type was: " << typeToGet.type() << "\n"
373  << "and " << inputTag << "\n";
374 }
375 
376 namespace {
377  struct CharStarComp {
378  bool operator()(const char* iLHS, const char* iRHS) const {
379  return strcmp(iLHS,iRHS) < 0;
380  }
381  };
382 }
383 
384 namespace {
385  void
386  insertFoundModuleLabel(const char* consumedModuleLabel,
387  std::vector<ModuleDescription const*>& modules,
388  std::set<std::string>& alreadyFound,
389  std::map<std::string, ModuleDescription const*> const& labelsToDesc,
390  ProductRegistry const& preg) {
391  // Convert from label string to module description, eliminate duplicates,
392  // then insert into the vector of modules
393  auto it = labelsToDesc.find(consumedModuleLabel);
394  if(it != labelsToDesc.end()) {
395  if(alreadyFound.insert(consumedModuleLabel).second) {
396  modules.push_back(it->second);
397  }
398  return;
399  }
400  // Deal with EDAlias's by converting to the original module label first
401  std::vector<std::pair<std::string, std::string> > const& aliasToOriginal = preg.aliasToOriginal();
402  std::pair<std::string, std::string> target(consumedModuleLabel, std::string());
403  auto iter = std::lower_bound(aliasToOriginal.begin(), aliasToOriginal.end(), target);
404  if(iter != aliasToOriginal.end() && iter->first == consumedModuleLabel) {
405 
406  std::string const& originalModuleLabel = iter->second;
407  auto iter2 = labelsToDesc.find(originalModuleLabel);
408  if(iter2 != labelsToDesc.end()) {
409  if(alreadyFound.insert(originalModuleLabel).second) {
410  modules.push_back(iter2->second);
411  }
412  return;
413  }
414  }
415  // Ignore the source products, we are only interested in module products.
416  // As far as I know, it should never be anything else so throw if something
417  // unknown gets passed in.
418  if(std::string(consumedModuleLabel) != "source") {
419  throw cms::Exception("EDConsumerBase", "insertFoundModuleLabel")
420  << "Couldn't find ModuleDescription for the consumed module label: "
421  << std::string(consumedModuleLabel) << "\n";
422  }
423  }
424 }
425 
426 void
427 EDConsumerBase::modulesWhoseProductsAreConsumed(std::vector<ModuleDescription const*>& modules,
428  ProductRegistry const& preg,
429  std::map<std::string, ModuleDescription const*> const& labelsToDesc,
430  std::string const& processName) const {
431 
432  ProductResolverIndexHelper const& iHelper = *preg.productLookup(InEvent);
433 
434  std::set<std::string> alreadyFound;
435 
436  auto itKind = m_tokenInfo.begin<kKind>();
437  auto itLabels = m_tokenInfo.begin<kLabels>();
438  for(auto itInfo = m_tokenInfo.begin<kLookupInfo>(),itEnd = m_tokenInfo.end<kLookupInfo>();
439  itInfo != itEnd; ++itInfo,++itKind,++itLabels) {
440 
441  if(itInfo->m_branchType == InEvent and
442  (not itInfo->m_index.skipCurrentProcess())) {
443 
444  const unsigned int labelStart = itLabels->m_startOfModuleLabel;
445  const char* consumedModuleLabel = &(m_tokenLabels[labelStart]);
446  const char* consumedProcessName = consumedModuleLabel+itLabels->m_deltaToProcessName;
447 
448  if(*consumedModuleLabel != '\0') { // not a consumesMany
449  if(*consumedProcessName != '\0') { // process name is specified in consumes call
450  if (processName == consumedProcessName &&
451  iHelper.index(*itKind,
452  itInfo->m_type,
453  consumedModuleLabel,
454  consumedModuleLabel+itLabels->m_deltaToProductInstance,
455  consumedModuleLabel+itLabels->m_deltaToProcessName) != ProductResolverIndexInvalid) {
456  insertFoundModuleLabel(consumedModuleLabel, modules, alreadyFound, labelsToDesc, preg);
457  }
458  } else { // process name was empty
459  auto matches = iHelper.relatedIndexes(*itKind,
460  itInfo->m_type,
461  consumedModuleLabel,
462  consumedModuleLabel+itLabels->m_deltaToProductInstance);
463  for(unsigned int j = 0; j < matches.numberOfMatches(); ++j) {
464  if(processName == matches.processName(j)) {
465  insertFoundModuleLabel(consumedModuleLabel, modules, alreadyFound, labelsToDesc, preg);
466  }
467  }
468  }
469  // consumesMany case
470  } else if(itInfo->m_index.productResolverIndex() == ProductResolverIndexInvalid) {
471  auto matches = iHelper.relatedIndexes(*itKind,
472  itInfo->m_type);
473  for(unsigned int j = 0; j < matches.numberOfMatches(); ++j) {
474  if(processName == matches.processName(j)) {
475  insertFoundModuleLabel(matches.moduleLabel(j), modules, alreadyFound, labelsToDesc, preg);
476  }
477  }
478  }
479  }
480  }
481 }
482 
483 std::vector<ConsumesInfo>
485 
486  // Use this to eliminate duplicate entries related
487  // to consumesMany items where only the type was specified
488  // and the there are multiple matches. In these cases the
489  // label, instance, and process will be empty.
490  std::set<edm::TypeID> alreadySeenTypes;
491 
492  std::vector<ConsumesInfo> result;
493  auto itAlways = m_tokenInfo.begin<kAlwaysGets>();
494  auto itKind = m_tokenInfo.begin<kKind>();
495  auto itLabels = m_tokenInfo.begin<kLabels>();
496  for(auto itInfo = m_tokenInfo.begin<kLookupInfo>(),itEnd = m_tokenInfo.end<kLookupInfo>();
497  itInfo != itEnd; ++itInfo,++itKind,++itLabels, ++itAlways) {
498 
499  const unsigned int labelStart = itLabels->m_startOfModuleLabel;
500  const char* consumedModuleLabel = &(m_tokenLabels[labelStart]);
501  const char* consumedInstance = consumedModuleLabel+itLabels->m_deltaToProductInstance;
502  const char* consumedProcessName = consumedModuleLabel+itLabels->m_deltaToProcessName;
503 
504  // consumesMany case
505  if(*consumedModuleLabel == '\0') {
506  if(!alreadySeenTypes.insert(itInfo->m_type).second) {
507  continue;
508  }
509  }
510 
511  // Just copy the information into the ConsumesInfo data structure
512  result.emplace_back(itInfo->m_type,
513  consumedModuleLabel,
514  consumedInstance,
515  consumedProcessName,
516  itInfo->m_branchType,
517  *itKind,
518  *itAlways,
519  itInfo->m_index.skipCurrentProcess());
520  }
521  return result;
522 }
Definition: start.py:1
static const TGPicture * info(bool iBackgroundIsBlack)
std::vector< ConsumesInfo > consumesInfo() const
unsigned int ProductResolverIndex
KindOfType kind() const
Definition: TypeToGet.h:45
void updateLookup(BranchType iBranchType, ProductResolverIndexHelper const &, bool iPrefetchMayGet)
void throwTypeMismatch(edm::TypeID const &, EDGetToken) const
void throwBadToken(edm::TypeID const &iType, EDGetToken iToken) const
#define noexcept
void throwConsumesCallAfterFrozen(TypeToGet const &, InputTag const &) const
edm::SoATuple< TokenLookupInfo, bool, LabelPlacement, edm::KindOfType > m_tokenInfo
void modulesWhoseProductsAreConsumed(std::vector< ModuleDescription const * > &modules, ProductRegistry const &preg, std::map< std::string, ModuleDescription const * > const &labelsToDesc, std::string const &processName) const
BranchType
Definition: BranchType.h:11
char const * process
Definition: ProductLabels.h:7
unsigned int recordConsumes(BranchType iBranch, TypeToGet const &iType, edm::InputTag const &iTag, bool iAlwaysGets)
#define unlikely(x)
#define likely(x)
ProductResolverIndexAndSkipBit indexFrom(EDGetToken, BranchType, TypeID const &) const
bool registeredToConsume(ProductResolverIndex, bool, BranchType) const
ConsumesCollector consumesCollector()
Use a ConsumesCollector to gather consumes information from helper functions.
void itemsToGet(BranchType, std::vector< ProductResolverIndexAndSkipBit > &) const
Matches relatedIndexes(KindOfType kindOfType, TypeID const &typeID, char const *moduleLabel, char const *instance) const
void throwBranchMismatch(BranchType, EDGetToken) const
bool isUninitialized() const
Definition: EDGetToken.h:47
char const * module
Definition: ProductLabels.h:5
std::vector< char > m_tokenLabels
edm::InputTag const & checkIfEmpty(edm::InputTag const &tag)
static const edm::InputTag kWasEmpty("@EmptyLabel@")
std::vector< std::pair< std::string, std::string > > const & aliasToOriginal() const
bool willSkipCurrentProcess() const
Definition: InputTag.h:42
bool registeredToConsumeMany(TypeID const &, BranchType) const
void itemsMayGet(BranchType, std::vector< ProductResolverIndexAndSkipBit > &) const
std::string const & BranchTypeToString(BranchType const &branchType)
Definition: BranchType.cc:99
std::shared_ptr< ProductResolverIndexHelper const > productLookup(BranchType branchType) const
void labelsForToken(EDGetToken iToken, Labels &oLabels) const
std::string const & label() const
Definition: InputTag.h:36
std::string const & process() const
Definition: InputTag.h:40
char const * productInstance
Definition: ProductLabels.h:6
ProductResolverIndex index(KindOfType kindOfType, TypeID const &typeID, char const *moduleLabel, char const *instance, char const *process=0) const
HLT enums.
TypeID const & type() const
Definition: TypeToGet.h:44
std::string const & className() const
Definition: TypeID.cc:46
virtual ~EDConsumerBase() noexcept(false)
std::string const & instance() const
Definition: InputTag.h:37
unsigned int index() const
Definition: EDGetToken.h:46
std::array< std::vector< ProductResolverIndexAndSkipBit >, edm::NumBranchTypes > itemsToGetFromBranch_