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