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  if(iBranchType == InEvent) {
191  itemsToGet(iBranchType, itemsToGetFromEvent_);
192  if(iPrefetchMayGet) {
193  itemsMayGet(iBranchType, itemsToGetFromEvent_);
194  }
195  }
196 }
197 
198 //
199 // const member functions
200 //
202 EDConsumerBase::indexFrom(EDGetToken iToken, BranchType iBranch, TypeID const& iType) const
203 {
204  if(unlikely(iToken.index()>=m_tokenInfo.size())) {
205  throwBadToken(iType,iToken);
206  }
207  const auto& info = m_tokenInfo.get<kLookupInfo>(iToken.index());
208  if (likely(iBranch == info.m_branchType)) {
209  if (likely(iType == info.m_type)) {
210  return info.m_index;
211  } else {
212  throwTypeMismatch(iType, iToken);
213  }
214  } else {
215  throwBranchMismatch(iBranch,iToken);
216  }
218 }
219 
220 void
221 EDConsumerBase::itemsToGet(BranchType iBranch, std::vector<ProductResolverIndexAndSkipBit>& oIndices) const
222 {
223  //how many are we adding?
224  unsigned int count=0;
225  {
226  auto itAlwaysGet = m_tokenInfo.begin<kAlwaysGets>();
227  for(auto it = m_tokenInfo.begin<kLookupInfo>(),
228  itEnd = m_tokenInfo.end<kLookupInfo>();
229  it != itEnd; ++it,++itAlwaysGet) {
230  if(iBranch==it->m_branchType) {
231  if (it->m_index.productResolverIndex() != ProductResolverIndexInvalid) {
232  if(*itAlwaysGet) {
233  ++count;
234  }
235  }
236  }
237  }
238  }
239  oIndices.reserve(oIndices.size()+count);
240  {
241  auto itAlwaysGet = m_tokenInfo.begin<kAlwaysGets>();
242  for(auto it = m_tokenInfo.begin<kLookupInfo>(),
243  itEnd = m_tokenInfo.end<kLookupInfo>();
244  it != itEnd; ++it,++itAlwaysGet) {
245  if(iBranch==it->m_branchType) {
246  if (it->m_index.productResolverIndex() != ProductResolverIndexInvalid) {
247  if(*itAlwaysGet) {
248  oIndices.push_back(it->m_index);
249  }
250  }
251  }
252  }
253  }
254 }
255 
256 void
257 EDConsumerBase::itemsMayGet(BranchType iBranch, std::vector<ProductResolverIndexAndSkipBit>& oIndices) const
258 {
259  //how many are we adding?
260  unsigned int count=0;
261  {
262  auto itAlwaysGet = m_tokenInfo.begin<kAlwaysGets>();
263  for(auto it = m_tokenInfo.begin<kLookupInfo>(),
264  itEnd = m_tokenInfo.end<kLookupInfo>();
265  it != itEnd; ++it,++itAlwaysGet) {
266  if(iBranch==it->m_branchType) {
267  if (it->m_index.productResolverIndex() != ProductResolverIndexInvalid) {
268  if(not *itAlwaysGet) {
269  ++count;
270  }
271  }
272  }
273  }
274  }
275  oIndices.reserve(oIndices.size()+count);
276  {
277  auto itAlwaysGet = m_tokenInfo.begin<kAlwaysGets>();
278  for(auto it = m_tokenInfo.begin<kLookupInfo>(),
279  itEnd = m_tokenInfo.end<kLookupInfo>();
280  it != itEnd; ++it,++itAlwaysGet) {
281  if(iBranch==it->m_branchType) {
282  if (it->m_index.productResolverIndex() != ProductResolverIndexInvalid) {
283  if(not *itAlwaysGet) {
284  oIndices.push_back(it->m_index);
285  }
286  }
287  }
288  }
289  }
290 }
291 
292 void
294 {
295  unsigned int index = iToken.index();
296  auto labels = m_tokenInfo.get<kLabels>(index);
297  unsigned int start = labels.m_startOfModuleLabel;
298  oLabels.module = &(m_tokenLabels[start]);
299  oLabels.productInstance = oLabels.module+labels.m_deltaToProductInstance;
300  oLabels.process = oLabels.module+labels.m_deltaToProcessName;
301 }
302 
303 bool
304 EDConsumerBase::registeredToConsume(ProductResolverIndex iIndex, bool skipCurrentProcess, BranchType iBranch) const
305 {
306  for(auto it = m_tokenInfo.begin<kLookupInfo>(),
307  itEnd = m_tokenInfo.end<kLookupInfo>();
308  it != itEnd; ++it) {
309  if(it->m_index.productResolverIndex() == iIndex and
310  it->m_index.skipCurrentProcess() == skipCurrentProcess and
311  it->m_branchType == iBranch) {
312  return true;
313  }
314  }
315  //TEMPORARY: Remember so we do not have to do this again
316  //non thread-safe
317  EDConsumerBase* nonConstThis = const_cast<EDConsumerBase*>(this);
318  nonConstThis->m_tokenInfo.emplace_back(TokenLookupInfo{TypeID{}, iIndex, skipCurrentProcess, iBranch},
319  true,
320  LabelPlacement{0,0,0},
321  PRODUCT_TYPE);
322 
323  return false;
324 }
325 
326 bool
328 {
329  for(auto it = m_tokenInfo.begin<kLookupInfo>(),
330  itEnd = m_tokenInfo.end<kLookupInfo>();
331  it != itEnd; ++it) {
332  //consumesMany entries do not have their index resolved
333  if(it->m_index.productResolverIndex() == ProductResolverIndexInvalid and
334  it->m_type == iType and
335  it->m_branchType == iBranch) {
336  return true;
337  }
338  }
339  //TEMPORARY: Remember so we do not have to do this again
340  //non thread-safe
341  EDConsumerBase* nonConstThis = const_cast<EDConsumerBase*>(this);
342  nonConstThis->m_tokenInfo.emplace_back(TokenLookupInfo{iType,ProductResolverIndexInvalid, false, iBranch},
343  true,
344  LabelPlacement{0,0,0},
345  PRODUCT_TYPE);
346  return false;
347 
348 }
349 
350 
351 void
353 {
354  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.";
355 }
356 void
358  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.";
359 }
360 
361 void
363 {
364  if(iToken.isUninitialized()) {
365  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.";
366  }
367  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.";
368 }
369 
370 void
372  throw cms::Exception("LogicError") << "A module declared it consumes a product after its constructor.\n"
373  << "This must be done in the contructor\n"
374  << "The product type was: " << typeToGet.type() << "\n"
375  << "and " << inputTag << "\n";
376 }
377 
378 namespace {
379  struct CharStarComp {
380  bool operator()(const char* iLHS, const char* iRHS) const {
381  return strcmp(iLHS,iRHS) < 0;
382  }
383  };
384 }
385 
386 namespace {
387  void
388  insertFoundModuleLabel(const char* consumedModuleLabel,
389  std::vector<ModuleDescription const*>& modules,
390  std::set<std::string>& alreadyFound,
391  std::map<std::string, ModuleDescription const*> const& labelsToDesc,
392  ProductRegistry const& preg) {
393  // Convert from label string to module description, eliminate duplicates,
394  // then insert into the vector of modules
395  auto it = labelsToDesc.find(consumedModuleLabel);
396  if(it != labelsToDesc.end()) {
397  if(alreadyFound.insert(consumedModuleLabel).second) {
398  modules.push_back(it->second);
399  }
400  return;
401  }
402  // Deal with EDAlias's by converting to the original module label first
403  std::vector<std::pair<std::string, std::string> > const& aliasToOriginal = preg.aliasToOriginal();
404  std::pair<std::string, std::string> target(consumedModuleLabel, std::string());
405  auto iter = std::lower_bound(aliasToOriginal.begin(), aliasToOriginal.end(), target);
406  if(iter != aliasToOriginal.end() && iter->first == consumedModuleLabel) {
407 
408  std::string const& originalModuleLabel = iter->second;
409  auto iter2 = labelsToDesc.find(originalModuleLabel);
410  if(iter2 != labelsToDesc.end()) {
411  if(alreadyFound.insert(originalModuleLabel).second) {
412  modules.push_back(iter2->second);
413  }
414  return;
415  }
416  }
417  // Ignore the source products, we are only interested in module products.
418  // As far as I know, it should never be anything else so throw if something
419  // unknown gets passed in.
420  if(std::string(consumedModuleLabel) != "source") {
421  throw cms::Exception("EDConsumerBase", "insertFoundModuleLabel")
422  << "Couldn't find ModuleDescription for the consumed module label: "
423  << std::string(consumedModuleLabel) << "\n";
424  }
425  }
426 }
427 
428 void
429 EDConsumerBase::modulesWhoseProductsAreConsumed(std::vector<ModuleDescription const*>& modules,
430  ProductRegistry const& preg,
431  std::map<std::string, ModuleDescription const*> const& labelsToDesc,
432  std::string const& processName) const {
433 
434  ProductResolverIndexHelper const& iHelper = *preg.productLookup(InEvent);
435 
436  std::set<std::string> alreadyFound;
437 
438  auto itKind = m_tokenInfo.begin<kKind>();
439  auto itLabels = m_tokenInfo.begin<kLabels>();
440  for(auto itInfo = m_tokenInfo.begin<kLookupInfo>(),itEnd = m_tokenInfo.end<kLookupInfo>();
441  itInfo != itEnd; ++itInfo,++itKind,++itLabels) {
442 
443  if(itInfo->m_branchType == InEvent and
444  (not itInfo->m_index.skipCurrentProcess())) {
445 
446  const unsigned int labelStart = itLabels->m_startOfModuleLabel;
447  const char* consumedModuleLabel = &(m_tokenLabels[labelStart]);
448  const char* consumedProcessName = consumedModuleLabel+itLabels->m_deltaToProcessName;
449 
450  if(*consumedModuleLabel != '\0') { // not a consumesMany
451  if(*consumedProcessName != '\0') { // process name is specified in consumes call
452  if (processName == consumedProcessName &&
453  iHelper.index(*itKind,
454  itInfo->m_type,
455  consumedModuleLabel,
456  consumedModuleLabel+itLabels->m_deltaToProductInstance,
457  consumedModuleLabel+itLabels->m_deltaToProcessName) != ProductResolverIndexInvalid) {
458  insertFoundModuleLabel(consumedModuleLabel, modules, alreadyFound, labelsToDesc, preg);
459  }
460  } else { // process name was empty
461  auto matches = iHelper.relatedIndexes(*itKind,
462  itInfo->m_type,
463  consumedModuleLabel,
464  consumedModuleLabel+itLabels->m_deltaToProductInstance);
465  for(unsigned int j = 0; j < matches.numberOfMatches(); ++j) {
466  if(processName == matches.processName(j)) {
467  insertFoundModuleLabel(consumedModuleLabel, modules, alreadyFound, labelsToDesc, preg);
468  }
469  }
470  }
471  // consumesMany case
472  } else if(itInfo->m_index.productResolverIndex() == ProductResolverIndexInvalid) {
473  auto matches = iHelper.relatedIndexes(*itKind,
474  itInfo->m_type);
475  for(unsigned int j = 0; j < matches.numberOfMatches(); ++j) {
476  if(processName == matches.processName(j)) {
477  insertFoundModuleLabel(matches.moduleLabel(j), modules, alreadyFound, labelsToDesc, preg);
478  }
479  }
480  }
481  }
482  }
483 }
484 
485 std::vector<ConsumesInfo>
487 
488  // Use this to eliminate duplicate entries related
489  // to consumesMany items where only the type was specified
490  // and the there are multiple matches. In these cases the
491  // label, instance, and process will be empty.
492  std::set<edm::TypeID> alreadySeenTypes;
493 
494  std::vector<ConsumesInfo> result;
495  auto itAlways = m_tokenInfo.begin<kAlwaysGets>();
496  auto itKind = m_tokenInfo.begin<kKind>();
497  auto itLabels = m_tokenInfo.begin<kLabels>();
498  for(auto itInfo = m_tokenInfo.begin<kLookupInfo>(),itEnd = m_tokenInfo.end<kLookupInfo>();
499  itInfo != itEnd; ++itInfo,++itKind,++itLabels, ++itAlways) {
500 
501  const unsigned int labelStart = itLabels->m_startOfModuleLabel;
502  const char* consumedModuleLabel = &(m_tokenLabels[labelStart]);
503  const char* consumedInstance = consumedModuleLabel+itLabels->m_deltaToProductInstance;
504  const char* consumedProcessName = consumedModuleLabel+itLabels->m_deltaToProcessName;
505 
506  // consumesMany case
507  if(*consumedModuleLabel == '\0') {
508  if(!alreadySeenTypes.insert(itInfo->m_type).second) {
509  continue;
510  }
511  }
512 
513  // Just copy the information into the ConsumesInfo data structure
514  result.emplace_back(itInfo->m_type,
515  consumedModuleLabel,
516  consumedInstance,
517  consumedProcessName,
518  itInfo->m_branchType,
519  *itKind,
520  *itAlways,
521  itInfo->m_index.skipCurrentProcess());
522  }
523  return result;
524 }
int i
Definition: DBlmapReader.cc:9
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
tuple result
Definition: mps_fire.py:84
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
std::vector< ProductResolverIndexAndSkipBit > itemsToGetFromEvent_
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
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
TypeID const & type() const
Definition: TypeToGet.h:44
std::string const & className() const
Definition: TypeID.cc:46
virtual ~EDConsumerBase() noexcept(false)
volatile std::atomic< bool > shutdown_flag false
preg
Definition: Schedule.cc:384
std::string const & instance() const
Definition: InputTag.h:37
unsigned int index() const
Definition: EDGetToken.h:46