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 <cassert>
15 #include <utility>
16 #include <cstring>
17 
18 // user include files
24 
25 using namespace edm;
26 
27 //
28 // constants, enums and typedefs
29 //
30 
31 //
32 // static data member definitions
33 //
34 
35 //
36 // constructors and destructor
37 //
38 //EDConsumerBase::EDConsumerBase()
39 //{
40 //}
41 
42 // EDConsumerBase::EDConsumerBase(const EDConsumerBase& rhs)
43 // {
44 // // do actual copying here;
45 // }
46 
48 {
49 }
50 
51 //
52 // assignment operators
53 //
54 // const EDConsumerBase& EDConsumerBase::operator=(const EDConsumerBase& rhs)
55 // {
56 // //An exception safe implementation is
57 // EDConsumerBase temp(rhs);
58 // swap(rhs);
59 //
60 // return *this;
61 // }
62 
63 //
64 // member functions
65 //
68  ConsumesCollector c{this};
69  return c;
70 }
71 
72 static const edm::InputTag kWasEmpty("@EmptyLabel@");
73 
74 edm::InputTag const&
76  if (iTag.label().empty()) {
77  return kWasEmpty;
78  }
79  return iTag;
80 }
81 
82 unsigned int
83 EDConsumerBase::recordConsumes(BranchType iBranch, TypeToGet const& iType, edm::InputTag const& iTag, bool iAlwaysGets) {
84 
85  if(frozen_) {
86  throwConsumesCallAfterFrozen(iType, iTag);
87  }
88 
89  unsigned int index =m_tokenInfo.size();
90 
91  bool skipCurrentProcess = iTag.willSkipCurrentProcess();
92 
93  const size_t labelSize = iTag.label().size();
94  const size_t productInstanceSize = iTag.instance().size();
95  unsigned int labelStart = m_tokenLabels.size();
96  unsigned short delta1 = labelSize+1;
97  unsigned short delta2 = labelSize+2+productInstanceSize;
98  m_tokenInfo.emplace_back(TokenLookupInfo{iType.type(), ProductHolderIndexInvalid, skipCurrentProcess, iBranch},
99  iAlwaysGets,
100  LabelPlacement{labelStart,delta1,delta2},
101  iType.kind());
102 
103  const size_t additionalSize =
104  skipCurrentProcess ?
105  labelSize+productInstanceSize+3 :
106  labelSize+productInstanceSize+iTag.process().size()+3;
107 
108  m_tokenLabels.reserve(m_tokenLabels.size()+additionalSize);
109  {
110  const std::string& m =iTag.label();
111  m_tokenLabels.insert(m_tokenLabels.end(),m.begin(),m.end());
112  m_tokenLabels.push_back('\0');
113  }
114  {
115  const std::string& m =iTag.instance();
116  m_tokenLabels.insert(m_tokenLabels.end(),m.begin(),m.end());
117  m_tokenLabels.push_back('\0');
118  }
119  {
120  if (!skipCurrentProcess) {
121  const std::string& m =iTag.process();
122  m_tokenLabels.insert(m_tokenLabels.end(),m.begin(),m.end());
123  m_tokenLabels.push_back('\0');
124  } else {
125  m_tokenLabels.push_back('\0');
126  }
127  }
128  return index;
129 }
130 
131 void
133  ProductHolderIndexHelper const& iHelper)
134 {
135  frozen_ = true;
136  {
137  auto itKind = m_tokenInfo.begin<kKind>();
138  auto itLabels = m_tokenInfo.begin<kLabels>();
139  for(auto itInfo = m_tokenInfo.begin<kLookupInfo>(),itEnd = m_tokenInfo.end<kLookupInfo>();
140  itInfo != itEnd; ++itInfo,++itKind,++itLabels) {
141  if(itInfo->m_branchType == iBranchType) {
142  const unsigned int labelStart = itLabels->m_startOfModuleLabel;
143  const char* moduleLabel = &(m_tokenLabels[labelStart]);
144  itInfo->m_index = ProductHolderIndexAndSkipBit(iHelper.index(*itKind,
145  itInfo->m_type,
146  moduleLabel,
147  moduleLabel+itLabels->m_deltaToProductInstance,
148  moduleLabel+itLabels->m_deltaToProcessName),
149  itInfo->m_index.skipCurrentProcess());
150  }
151  }
152  }
153 
154  //now add resolved requests to get many to the end of our list
155  // a get many will have an empty module label
156  for(size_t i=0, iEnd = m_tokenInfo.size(); i!=iEnd;++i) {
157  //need to copy since pointer could be invalidated by emplace_back
158  auto const info = m_tokenInfo.get<kLookupInfo>(i);
159  if(info.m_branchType == iBranchType &&
160  info.m_index.productHolderIndex() == ProductHolderIndexInvalid &&
161  m_tokenLabels[m_tokenInfo.get<kLabels>(i).m_startOfModuleLabel]=='\0') {
162  //find all matching types
163  const auto kind=m_tokenInfo.get<kKind>(i);
164  auto matches = iHelper.relatedIndexes(kind,info.m_type);
165 
166  //NOTE: This could be changed to contain the true labels for what is being
167  // requested but for now I want to remember these are part of a get many
169  bool alwaysGet = m_tokenInfo.get<kAlwaysGets>(i);
170  for(unsigned int j=0;j!=matches.numberOfMatches();++j) {
171  //only keep the ones that are for a specific data item and not a collection
172  if(matches.isFullyResolved(j)) {
173  auto index =matches.index(j);
174  m_tokenInfo.emplace_back(TokenLookupInfo{info.m_type, index, info.m_index.skipCurrentProcess(), info.m_branchType},
175  alwaysGet,
176  labels,
177  kind);
178  }
179  }
180  }
181  }
182  m_tokenInfo.shrink_to_fit();
183 
184  if(iBranchType == InEvent) {
185  itemsToGet(iBranchType, itemsToGetFromEvent_);
186  }
187 }
188 
189 //
190 // const member functions
191 //
193 EDConsumerBase::indexFrom(EDGetToken iToken, BranchType iBranch, TypeID const& iType) const
194 {
195  if(unlikely(iToken.index()>=m_tokenInfo.size())) {
196  throwBadToken(iType,iToken);
197  }
198  const auto& info = m_tokenInfo.get<kLookupInfo>(iToken.index());
199  if (likely(iBranch == info.m_branchType)) {
200  if (likely(iType == info.m_type)) {
201  return info.m_index;
202  } else {
203  throwTypeMismatch(iType, iToken);
204  }
205  } else {
206  throwBranchMismatch(iBranch,iToken);
207  }
209 }
210 
211 void
212 EDConsumerBase::itemsToGet(BranchType iBranch, std::vector<ProductHolderIndexAndSkipBit>& oIndices) const
213 {
214  //how many are we adding?
215  unsigned int count=0;
216  {
217  auto itAlwaysGet = m_tokenInfo.begin<kAlwaysGets>();
218  for(auto it = m_tokenInfo.begin<kLookupInfo>(),
219  itEnd = m_tokenInfo.end<kLookupInfo>();
220  it != itEnd; ++it,++itAlwaysGet) {
221  if(iBranch==it->m_branchType) {
222  if (it->m_index.productHolderIndex() != ProductHolderIndexInvalid) {
223  if(*itAlwaysGet) {
224  ++count;
225  }
226  }
227  }
228  }
229  }
230  oIndices.reserve(oIndices.size()+count);
231  {
232  auto itAlwaysGet = m_tokenInfo.begin<kAlwaysGets>();
233  for(auto it = m_tokenInfo.begin<kLookupInfo>(),
234  itEnd = m_tokenInfo.end<kLookupInfo>();
235  it != itEnd; ++it,++itAlwaysGet) {
236  if(iBranch==it->m_branchType) {
237  if (it->m_index.productHolderIndex() != ProductHolderIndexInvalid) {
238  if(*itAlwaysGet) {
239  oIndices.push_back(it->m_index);
240  }
241  }
242  }
243  }
244  }
245 }
246 
247 void
248 EDConsumerBase::itemsMayGet(BranchType iBranch, std::vector<ProductHolderIndexAndSkipBit>& oIndices) const
249 {
250  //how many are we adding?
251  unsigned int count=0;
252  {
253  auto itAlwaysGet = m_tokenInfo.begin<kAlwaysGets>();
254  for(auto it = m_tokenInfo.begin<kLookupInfo>(),
255  itEnd = m_tokenInfo.end<kLookupInfo>();
256  it != itEnd; ++it,++itAlwaysGet) {
257  if(iBranch==it->m_branchType) {
258  if (it->m_index.productHolderIndex() != ProductHolderIndexInvalid) {
259  if(not *itAlwaysGet) {
260  ++count;
261  }
262  }
263  }
264  }
265  }
266  oIndices.reserve(oIndices.size()+count);
267  {
268  auto itAlwaysGet = m_tokenInfo.begin<kAlwaysGets>();
269  for(auto it = m_tokenInfo.begin<kLookupInfo>(),
270  itEnd = m_tokenInfo.end<kLookupInfo>();
271  it != itEnd; ++it,++itAlwaysGet) {
272  if(iBranch==it->m_branchType) {
273  if (it->m_index.productHolderIndex() != ProductHolderIndexInvalid) {
274  if(not *itAlwaysGet) {
275  oIndices.push_back(it->m_index);
276  }
277  }
278  }
279  }
280  }
281 }
282 
283 void
285 {
286  unsigned int index = iToken.index();
287  auto labels = m_tokenInfo.get<kLabels>(index);
288  unsigned int start = labels.m_startOfModuleLabel;
289  oLabels.module = &(m_tokenLabels[start]);
290  oLabels.productInstance = oLabels.module+labels.m_deltaToProductInstance;
291  oLabels.process = oLabels.module+labels.m_deltaToProcessName;
292 }
293 
294 bool
295 EDConsumerBase::registeredToConsume(ProductHolderIndex iIndex, bool skipCurrentProcess, BranchType iBranch) const
296 {
297  for(auto it = m_tokenInfo.begin<kLookupInfo>(),
298  itEnd = m_tokenInfo.end<kLookupInfo>();
299  it != itEnd; ++it) {
300  if(it->m_index.productHolderIndex() == iIndex and
301  it->m_index.skipCurrentProcess() == skipCurrentProcess and
302  it->m_branchType == iBranch) {
303  return true;
304  }
305  }
306  //TEMPORARY: Remember so we do not have to do this again
307  //non thread-safe
308  EDConsumerBase* nonConstThis = const_cast<EDConsumerBase*>(this);
309  nonConstThis->m_tokenInfo.emplace_back(TokenLookupInfo{TypeID{}, iIndex, skipCurrentProcess, iBranch},
310  true,
311  LabelPlacement{0,0,0},
312  PRODUCT_TYPE);
313 
314  return false;
315 }
316 
317 bool
319 {
320  for(auto it = m_tokenInfo.begin<kLookupInfo>(),
321  itEnd = m_tokenInfo.end<kLookupInfo>();
322  it != itEnd; ++it) {
323  //consumesMany entries do not have their index resolved
324  if(it->m_index.productHolderIndex() == ProductHolderIndexInvalid and
325  it->m_type == iType and
326  it->m_branchType == iBranch) {
327  return true;
328  }
329  }
330  //TEMPORARY: Remember so we do not have to do this again
331  //non thread-safe
332  EDConsumerBase* nonConstThis = const_cast<EDConsumerBase*>(this);
333  nonConstThis->m_tokenInfo.emplace_back(TokenLookupInfo{iType,ProductHolderIndexInvalid, false, iBranch},
334  true,
335  LabelPlacement{0,0,0},
336  PRODUCT_TYPE);
337  return false;
338 
339 }
340 
341 
342 void
344 {
345  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.";
346 }
347 void
349  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.";
350 }
351 
352 void
354 {
355  if(iToken.isUninitialized()) {
356  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.";
357  }
358  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.";
359 }
360 
361 void
362 EDConsumerBase::throwConsumesCallAfterFrozen(TypeToGet const& typeToGet, InputTag const& inputTag) const {
363  throw cms::Exception("LogicError") << "A module declared it consumes a product after its constructor.\n"
364  << "This must be done in the contructor\n"
365  << "The product type was: " << typeToGet.type() << "\n"
366  << "and " << inputTag << "\n";
367 }
368 
369 namespace {
370  struct CharStarComp {
371  bool operator()(const char* iLHS, const char* iRHS) const {
372  return strcmp(iLHS,iRHS) < 0;
373  }
374  };
375 }
376 
377 void
379  std::vector<const char*>& oModuleLabels
380  ) const
381 {
382  std::set<const char*, CharStarComp> uniqueModules;
383  for(unsigned int index=0, iEnd=m_tokenInfo.size();index <iEnd; ++index) {
384  auto const& info = m_tokenInfo.get<kLookupInfo>(index);
385  if( not info.m_index.skipCurrentProcess() ) {
386  auto labels = m_tokenInfo.get<kLabels>(index);
387  unsigned int start = labels.m_startOfModuleLabel;
388  const char* processName = &(m_tokenLabels[start+labels.m_deltaToProcessName]);
389  if( (not processName) or processName[0]==0 or
390  iProcessName == processName) {
391  uniqueModules.insert(&(m_tokenLabels[start]));
392  }
393  }
394  }
395 
396  oModuleLabels = std::vector<const char*>(uniqueModules.begin(),uniqueModules.end());
397 }
398 
399 //
400 // static member functions
401 //
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)
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
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
BranchType
Definition: BranchType.h:11
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.
int j
Definition: DBlmapReader.cc:9
void throwBranchMismatch(BranchType, EDGetToken) const
bool isUninitialized() const
Definition: EDGetToken.h:47
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@")
bool willSkipCurrentProcess() const
Definition: InputTag.h:48
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:42
std::string const & process() const
Definition: InputTag.h:46
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
std::string const & instance() const
Definition: InputTag.h:43
unsigned int index() const
Definition: EDGetToken.h:46