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