CMS 3D CMS Logo

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  const std::string& m = iTag.process();
126  if (m == InputTag::kCurrentProcess) {
128  }
129  if (!skipCurrentProcess) {
130  m_tokenLabels.insert(m_tokenLabels.end(),m.begin(),m.end());
131  m_tokenLabels.push_back('\0');
132  } else {
133  m_tokenLabels.push_back('\0');
134  }
135  }
136  return index;
137 }
138 
139 void
141  ProductResolverIndexHelper const& iHelper,
142  bool iPrefetchMayGet)
143 {
144  frozen_ = true;
146  {
147  auto itKind = m_tokenInfo.begin<kKind>();
148  auto itLabels = m_tokenInfo.begin<kLabels>();
149  for(auto itInfo = m_tokenInfo.begin<kLookupInfo>(),itEnd = m_tokenInfo.end<kLookupInfo>();
150  itInfo != itEnd; ++itInfo,++itKind,++itLabels) {
151  if(itInfo->m_branchType == iBranchType) {
152  const unsigned int labelStart = itLabels->m_startOfModuleLabel;
153  const char* moduleLabel = &(m_tokenLabels[labelStart]);
154  itInfo->m_index = ProductResolverIndexAndSkipBit(iHelper.index(*itKind,
155  itInfo->m_type,
156  moduleLabel,
157  moduleLabel+itLabels->m_deltaToProductInstance,
158  moduleLabel+itLabels->m_deltaToProcessName),
159  itInfo->m_index.skipCurrentProcess());
160  }
161  }
162  }
163 
164  //now add resolved requests to get many to the end of our list
165  // a get many will have an empty module label
166  for(size_t i=0, iEnd = m_tokenInfo.size(); i!=iEnd;++i) {
167  //need to copy since pointer could be invalidated by emplace_back
168  auto const info = m_tokenInfo.get<kLookupInfo>(i);
169  if(info.m_branchType == iBranchType &&
170  info.m_index.productResolverIndex() == ProductResolverIndexInvalid &&
171  m_tokenLabels[m_tokenInfo.get<kLabels>(i).m_startOfModuleLabel]=='\0') {
172  //find all matching types
173  const auto kind=m_tokenInfo.get<kKind>(i);
174  auto matches = iHelper.relatedIndexes(kind,info.m_type);
175 
176  //NOTE: This could be changed to contain the true labels for what is being
177  // requested but for now I want to remember these are part of a get many
179  bool alwaysGet = m_tokenInfo.get<kAlwaysGets>(i);
180  for(unsigned int j=0;j!=matches.numberOfMatches();++j) {
181  //only keep the ones that are for a specific data item and not a collection
182  if(matches.isFullyResolved(j)) {
183  auto index =matches.index(j);
184  m_tokenInfo.emplace_back(TokenLookupInfo{info.m_type, index, info.m_index.skipCurrentProcess(), info.m_branchType},
185  alwaysGet,
186  labels,
187  kind);
188  }
189  }
190  }
191  }
192  m_tokenInfo.shrink_to_fit();
193 
194  itemsToGet(iBranchType, itemsToGetFromBranch_[iBranchType]);
195  if(iPrefetchMayGet) {
196  itemsMayGet(iBranchType, itemsToGetFromBranch_[iBranchType]);
197  }
198 }
199 
200 //
201 // const member functions
202 //
204 EDConsumerBase::indexFrom(EDGetToken iToken, BranchType iBranch, TypeID const& iType) const
205 {
206  if(UNLIKELY(iToken.index()>=m_tokenInfo.size())) {
207  throwBadToken(iType,iToken);
208  }
209  const auto& info = m_tokenInfo.get<kLookupInfo>(iToken.index());
210  if (LIKELY(iBranch == info.m_branchType)) {
211  if (LIKELY(iType == info.m_type)) {
212  return info.m_index;
213  } else {
214  throwTypeMismatch(iType, iToken);
215  }
216  } else {
217  throwBranchMismatch(iBranch,iToken);
218  }
220 }
221 
224  return m_tokenInfo.get<kLookupInfo>(iToken.index()).m_index;
225 }
226 
227 
228 void
229 EDConsumerBase::itemsToGet(BranchType iBranch, std::vector<ProductResolverIndexAndSkipBit>& oIndices) const
230 {
231  //how many are we adding?
232  unsigned int count=0;
233  {
234  auto itAlwaysGet = m_tokenInfo.begin<kAlwaysGets>();
235  for(auto it = m_tokenInfo.begin<kLookupInfo>(),
236  itEnd = m_tokenInfo.end<kLookupInfo>();
237  it != itEnd; ++it,++itAlwaysGet) {
238  if(iBranch==it->m_branchType) {
239  if (it->m_index.productResolverIndex() != ProductResolverIndexInvalid) {
240  if(*itAlwaysGet) {
241  ++count;
242  }
243  }
244  }
245  }
246  }
247  oIndices.reserve(oIndices.size()+count);
248  {
249  auto itAlwaysGet = m_tokenInfo.begin<kAlwaysGets>();
250  for(auto it = m_tokenInfo.begin<kLookupInfo>(),
251  itEnd = m_tokenInfo.end<kLookupInfo>();
252  it != itEnd; ++it,++itAlwaysGet) {
253  if(iBranch==it->m_branchType) {
254  if (it->m_index.productResolverIndex() != ProductResolverIndexInvalid) {
255  if(*itAlwaysGet) {
256  oIndices.push_back(it->m_index);
257  }
258  }
259  }
260  }
261  }
262 }
263 
264 void
265 EDConsumerBase::itemsMayGet(BranchType iBranch, std::vector<ProductResolverIndexAndSkipBit>& oIndices) const
266 {
267  //how many are we adding?
268  unsigned int count=0;
269  {
270  auto itAlwaysGet = m_tokenInfo.begin<kAlwaysGets>();
271  for(auto it = m_tokenInfo.begin<kLookupInfo>(),
272  itEnd = m_tokenInfo.end<kLookupInfo>();
273  it != itEnd; ++it,++itAlwaysGet) {
274  if(iBranch==it->m_branchType) {
275  if (it->m_index.productResolverIndex() != ProductResolverIndexInvalid) {
276  if(not *itAlwaysGet) {
277  ++count;
278  }
279  }
280  }
281  }
282  }
283  oIndices.reserve(oIndices.size()+count);
284  {
285  auto itAlwaysGet = m_tokenInfo.begin<kAlwaysGets>();
286  for(auto it = m_tokenInfo.begin<kLookupInfo>(),
287  itEnd = m_tokenInfo.end<kLookupInfo>();
288  it != itEnd; ++it,++itAlwaysGet) {
289  if(iBranch==it->m_branchType) {
290  if (it->m_index.productResolverIndex() != ProductResolverIndexInvalid) {
291  if(not *itAlwaysGet) {
292  oIndices.push_back(it->m_index);
293  }
294  }
295  }
296  }
297  }
298 }
299 
300 void
302 {
303  unsigned int index = iToken.index();
304  auto labels = m_tokenInfo.get<kLabels>(index);
305  unsigned int start = labels.m_startOfModuleLabel;
306  oLabels.module = &(m_tokenLabels[start]);
307  oLabels.productInstance = oLabels.module+labels.m_deltaToProductInstance;
308  oLabels.process = oLabels.module+labels.m_deltaToProcessName;
309 }
310 
311 bool
312 EDConsumerBase::registeredToConsume(ProductResolverIndex iIndex, bool skipCurrentProcess, BranchType iBranch) const
313 {
314  for(auto it = m_tokenInfo.begin<kLookupInfo>(),
315  itEnd = m_tokenInfo.end<kLookupInfo>();
316  it != itEnd; ++it) {
317  if(it->m_index.productResolverIndex() == iIndex and
318  it->m_index.skipCurrentProcess() == skipCurrentProcess and
319  it->m_branchType == iBranch) {
320  return true;
321  }
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  return false;
340 
341 }
342 
343 
344 void
346 {
347  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.";
348 }
349 void
351  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.";
352 }
353 
354 void
356 {
357  if(iToken.isUninitialized()) {
358  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.";
359  }
360  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.";
361 }
362 
363 void
365  throw cms::Exception("LogicError") << "A module declared it consumes a product after its constructor.\n"
366  << "This must be done in the contructor\n"
367  << "The product type was: " << typeToGet.type() << "\n"
368  << "and " << inputTag << "\n";
369 }
370 
371 namespace {
372  struct CharStarComp {
373  bool operator()(const char* iLHS, const char* iRHS) const {
374  return strcmp(iLHS,iRHS) < 0;
375  }
376  };
377 }
378 
379 namespace {
380  void
381  insertFoundModuleLabel(const char* consumedModuleLabel,
382  std::vector<ModuleDescription const*>& modules,
383  std::set<std::string>& alreadyFound,
384  std::map<std::string, ModuleDescription const*> const& labelsToDesc,
385  ProductRegistry const& preg) {
386  // Convert from label string to module description, eliminate duplicates,
387  // then insert into the vector of modules
388  auto it = labelsToDesc.find(consumedModuleLabel);
389  if(it != labelsToDesc.end()) {
390  if(alreadyFound.insert(consumedModuleLabel).second) {
391  modules.push_back(it->second);
392  }
393  return;
394  }
395  // Deal with EDAlias's by converting to the original module label first
396  std::vector<std::pair<std::string, std::string> > const& aliasToOriginal = preg.aliasToOriginal();
397  std::pair<std::string, std::string> target(consumedModuleLabel, std::string());
398  auto iter = std::lower_bound(aliasToOriginal.begin(), aliasToOriginal.end(), target);
399  if(iter != aliasToOriginal.end() && iter->first == consumedModuleLabel) {
400 
401  std::string const& originalModuleLabel = iter->second;
402  auto iter2 = labelsToDesc.find(originalModuleLabel);
403  if(iter2 != labelsToDesc.end()) {
404  if(alreadyFound.insert(originalModuleLabel).second) {
405  modules.push_back(iter2->second);
406  }
407  return;
408  }
409  }
410  // Ignore the source products, we are only interested in module products.
411  // As far as I know, it should never be anything else so throw if something
412  // unknown gets passed in.
413  if(std::string(consumedModuleLabel) != "source") {
414  throw cms::Exception("EDConsumerBase", "insertFoundModuleLabel")
415  << "Couldn't find ModuleDescription for the consumed module label: "
416  << std::string(consumedModuleLabel) << "\n";
417  }
418  }
419 }
420 
421 void
422 EDConsumerBase::modulesWhoseProductsAreConsumed(std::vector<ModuleDescription const*>& modules,
423  ProductRegistry const& preg,
424  std::map<std::string, ModuleDescription const*> const& labelsToDesc,
425  std::string const& processName) const {
426 
427  ProductResolverIndexHelper const& iHelper = *preg.productLookup(InEvent);
428 
429  std::set<std::string> alreadyFound;
430 
431  auto itKind = m_tokenInfo.begin<kKind>();
432  auto itLabels = m_tokenInfo.begin<kLabels>();
433  for(auto itInfo = m_tokenInfo.begin<kLookupInfo>(),itEnd = m_tokenInfo.end<kLookupInfo>();
434  itInfo != itEnd; ++itInfo,++itKind,++itLabels) {
435 
436  if(itInfo->m_branchType == InEvent and
437  (not itInfo->m_index.skipCurrentProcess())) {
438 
439  const unsigned int labelStart = itLabels->m_startOfModuleLabel;
440  const char* consumedModuleLabel = &(m_tokenLabels[labelStart]);
441  const char* consumedProcessName = consumedModuleLabel+itLabels->m_deltaToProcessName;
442 
443  if(*consumedModuleLabel != '\0') { // not a consumesMany
444  if(*consumedProcessName != '\0') { // process name is specified in consumes call
445  if (processName == consumedProcessName &&
446  iHelper.index(*itKind,
447  itInfo->m_type,
448  consumedModuleLabel,
449  consumedModuleLabel+itLabels->m_deltaToProductInstance,
450  consumedModuleLabel+itLabels->m_deltaToProcessName) != ProductResolverIndexInvalid) {
451  insertFoundModuleLabel(consumedModuleLabel, modules, alreadyFound, labelsToDesc, preg);
452  }
453  } else { // process name was empty
454  auto matches = iHelper.relatedIndexes(*itKind,
455  itInfo->m_type,
456  consumedModuleLabel,
457  consumedModuleLabel+itLabels->m_deltaToProductInstance);
458  for(unsigned int j = 0; j < matches.numberOfMatches(); ++j) {
459  if(processName == matches.processName(j)) {
460  insertFoundModuleLabel(consumedModuleLabel, modules, alreadyFound, labelsToDesc, preg);
461  }
462  }
463  }
464  // consumesMany case
465  } else if(itInfo->m_index.productResolverIndex() == ProductResolverIndexInvalid) {
466  auto matches = iHelper.relatedIndexes(*itKind,
467  itInfo->m_type);
468  for(unsigned int j = 0; j < matches.numberOfMatches(); ++j) {
469  if(processName == matches.processName(j)) {
470  insertFoundModuleLabel(matches.moduleLabel(j), modules, alreadyFound, labelsToDesc, preg);
471  }
472  }
473  }
474  }
475  }
476 }
477 
478 void
480 
481  frozen_ = true;
482 
485 
486  std::vector<char> newTokenLabels;
487 
488  // first calculate the size of the new vector and reserve memory for it
489  std::vector<char>::size_type newSize = 0;
490  std::string newProcessName;
491  for(auto iter = m_tokenInfo.begin<kLabels>(), itEnd = m_tokenInfo.end<kLabels>();
492  iter != itEnd; ++iter) {
493  newProcessName = &m_tokenLabels[iter->m_startOfModuleLabel + iter->m_deltaToProcessName];
494  if (newProcessName == InputTag::kCurrentProcess) {
495  newProcessName = processName;
496  }
497  newSize += (iter->m_deltaToProcessName + newProcessName.size() + 1);
498  }
499  newTokenLabels.reserve(newSize);
500 
501  unsigned int newStartOfModuleLabel = 0;
502  for(auto iter = m_tokenInfo.begin<kLabels>(), itEnd = m_tokenInfo.end<kLabels>();
503  iter != itEnd; ++iter) {
504 
505  unsigned int startOfModuleLabel = iter->m_startOfModuleLabel;
506  unsigned short deltaToProcessName = iter->m_deltaToProcessName;
507 
508  iter->m_startOfModuleLabel = newStartOfModuleLabel;
509 
510  newProcessName = &m_tokenLabels[startOfModuleLabel + deltaToProcessName];
511  if (newProcessName == InputTag::kCurrentProcess) {
512  newProcessName = processName;
513  }
514 
515  newStartOfModuleLabel += (deltaToProcessName + newProcessName.size() + 1);
516 
517  // Copy in both the module label and instance, they are the same
518  newTokenLabels.insert(newTokenLabels.end(),
519  m_tokenLabels.begin() + startOfModuleLabel,
520  m_tokenLabels.begin() + (startOfModuleLabel + deltaToProcessName));
521 
522  newTokenLabels.insert(newTokenLabels.end(), newProcessName.begin(), newProcessName.end());
523  newTokenLabels.push_back('\0');
524  }
525  m_tokenLabels = std::move(newTokenLabels);
526  }
527 }
528 
529 std::vector<ConsumesInfo>
531 
532  // Use this to eliminate duplicate entries related
533  // to consumesMany items where only the type was specified
534  // and the there are multiple matches. In these cases the
535  // label, instance, and process will be empty.
536  std::set<edm::TypeID> alreadySeenTypes;
537 
538  std::vector<ConsumesInfo> result;
539  auto itAlways = m_tokenInfo.begin<kAlwaysGets>();
540  auto itKind = m_tokenInfo.begin<kKind>();
541  auto itLabels = m_tokenInfo.begin<kLabels>();
542  for(auto itInfo = m_tokenInfo.begin<kLookupInfo>(),itEnd = m_tokenInfo.end<kLookupInfo>();
543  itInfo != itEnd; ++itInfo,++itKind,++itLabels, ++itAlways) {
544 
545  const unsigned int labelStart = itLabels->m_startOfModuleLabel;
546  const char* consumedModuleLabel = &(m_tokenLabels[labelStart]);
547  const char* consumedInstance = consumedModuleLabel+itLabels->m_deltaToProductInstance;
548  const char* consumedProcessName = consumedModuleLabel+itLabels->m_deltaToProcessName;
549 
550  // consumesMany case
551  if(*consumedModuleLabel == '\0') {
552  if(!alreadySeenTypes.insert(itInfo->m_type).second) {
553  continue;
554  }
555  }
556 
557  // Just copy the information into the ConsumesInfo data structure
558  result.emplace_back(itInfo->m_type,
559  consumedModuleLabel,
560  consumedInstance,
561  consumedProcessName,
562  itInfo->m_branchType,
563  *itKind,
564  *itAlways,
565  itInfo->m_index.skipCurrentProcess());
566  }
567  return result;
568 }
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
uint16_t size_type
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)
ProductResolverIndexAndSkipBit uncheckedIndexFrom(EDGetToken) const
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
static const std::string kCurrentProcess
Definition: InputTag.h:51
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
HLT enums.
TypeID const & type() const
Definition: TypeToGet.h:44
std::string const & className() const
Definition: TypeID.cc:46
#define LIKELY(x)
virtual ~EDConsumerBase() noexcept(false)
void convertCurrentProcessAlias(std::string const &processName)
Convert "@currentProcess" in InputTag process names to the actual current process name...
std::string const & instance() const
Definition: InputTag.h:37
unsigned int index() const
Definition: EDGetToken.h:46
def move(src, dest)
Definition: eostools.py:510
ProductResolverIndex index(KindOfType kindOfType, TypeID const &typeID, char const *moduleLabel, char const *instance, char const *process=nullptr) const
std::array< std::vector< ProductResolverIndexAndSkipBit >, edm::NumBranchTypes > itemsToGetFromBranch_
#define UNLIKELY(x)