CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_5/src/FWCore/Framework/src/EDConsumerBase.cc

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 //
00003 // Package:     FWCore/Framework
00004 // Class  :     EDConsumerBase
00005 // 
00006 // Implementation:
00007 //     [Notes on implementation]
00008 //
00009 // Original Author:  Chris Jones
00010 //         Created:  Tue, 02 Apr 2013 21:36:06 GMT
00011 // $Id: EDConsumerBase.cc,v 1.6 2013/06/07 17:58:32 chrjones Exp $
00012 //
00013 
00014 // system include files
00015 #include <cassert>
00016 #include <utility>
00017 
00018 // user include files
00019 #include "FWCore/Framework/interface/EDConsumerBase.h"
00020 #include "FWCore/Framework/interface/ConsumesCollector.h"
00021 #include "FWCore/Utilities/interface/Likely.h"
00022 #include "FWCore/Utilities/interface/Exception.h"
00023 #include "DataFormats/Provenance/interface/ProductHolderIndexHelper.h"
00024 
00025 using namespace edm;
00026 
00027 //
00028 // constants, enums and typedefs
00029 //
00030 
00031 //
00032 // static data member definitions
00033 //
00034 
00035 //
00036 // constructors and destructor
00037 //
00038 //EDConsumerBase::EDConsumerBase()
00039 //{
00040 //}
00041 
00042 // EDConsumerBase::EDConsumerBase(const EDConsumerBase& rhs)
00043 // {
00044 //    // do actual copying here;
00045 // }
00046 
00047 EDConsumerBase::~EDConsumerBase()
00048 {
00049 }
00050 
00051 //
00052 // assignment operators
00053 //
00054 // const EDConsumerBase& EDConsumerBase::operator=(const EDConsumerBase& rhs)
00055 // {
00056 //   //An exception safe implementation is
00057 //   EDConsumerBase temp(rhs);
00058 //   swap(rhs);
00059 //
00060 //   return *this;
00061 // }
00062 
00063 //
00064 // member functions
00065 //
00066 ConsumesCollector
00067 EDConsumerBase::consumesCollector() {
00068   ConsumesCollector c{this};
00069   return std::move(c);
00070 }
00071 
00072 
00073 unsigned int
00074 EDConsumerBase::recordConsumes(BranchType iBranch, TypeToGet const& iType, edm::InputTag const& iTag, bool iAlwaysGets) {
00075   unsigned int index =m_tokenInfo.size();
00076 
00077   const size_t labelSize = iTag.label().size();
00078   const size_t productInstanceSize = iTag.instance().size();
00079   unsigned int labelStart = m_tokenLabels.size();
00080   unsigned short delta1 = labelSize+1;
00081   unsigned short delta2 = labelSize+2+productInstanceSize;
00082   m_tokenInfo.emplace_back(TokenLookupInfo{iType.type(),ProductHolderIndexInvalid,iBranch},
00083                            iAlwaysGets,
00084                            LabelPlacement{labelStart,delta1,delta2},
00085                            iType.kind());
00086 
00087   bool skipCurrentProcess = iTag.willSkipCurrentProcess();
00088 
00089   const size_t additionalSize =
00090       skipCurrentProcess ?
00091       labelSize+productInstanceSize+3 :
00092       labelSize+productInstanceSize+iTag.process().size()+3;
00093 
00094   m_tokenLabels.reserve(m_tokenLabels.size()+additionalSize);
00095   {
00096     const std::string& m =iTag.label();
00097     m_tokenLabels.insert(m_tokenLabels.end(),m.begin(),m.end());
00098     m_tokenLabels.push_back('\0');
00099   }
00100   {
00101     const std::string& m =iTag.instance();
00102     m_tokenLabels.insert(m_tokenLabels.end(),m.begin(),m.end());
00103     m_tokenLabels.push_back('\0');
00104   }
00105   {
00106     if (!skipCurrentProcess) {
00107       const std::string& m =iTag.process();
00108       m_tokenLabels.insert(m_tokenLabels.end(),m.begin(),m.end());
00109       m_tokenLabels.push_back('\0');
00110     } else {
00111       m_tokenLabels.push_back('\0');
00112     }
00113   }
00114   return index;
00115 }
00116 
00117 void
00118 EDConsumerBase::updateLookup(BranchType iBranchType,
00119                              ProductHolderIndexHelper const& iHelper)
00120 {
00121   {
00122     auto itKind = m_tokenInfo.begin<kKind>();
00123     auto itLabels = m_tokenInfo.begin<kLabels>();
00124     for(auto itInfo = m_tokenInfo.begin<kLookupInfo>(),itEnd = m_tokenInfo.end<kLookupInfo>();
00125         itInfo != itEnd; ++itInfo,++itKind,++itLabels) {
00126       const unsigned int labelStart = itLabels->m_startOfModuleLabel;
00127       const char* moduleLabel = &(m_tokenLabels[labelStart]);
00128       itInfo->m_index = iHelper.index(*itKind,
00129                                       itInfo->m_type,
00130                                       moduleLabel,
00131                                       moduleLabel+itLabels->m_deltaToProductInstance,
00132                                       moduleLabel+itLabels->m_deltaToProcessName);
00133     }
00134   }
00135   
00136   //now add resolved requests to get many to the end of our list
00137   // a get many will have an empty module label
00138   for(size_t i=0, iEnd = m_tokenInfo.size(); i!=iEnd;++i) {
00139     //need to copy since pointer could be invalidated by emplace_back
00140     auto const info = m_tokenInfo.get<kLookupInfo>(i);
00141     if(info.m_branchType == iBranchType &&
00142        info.m_index == ProductHolderIndexInvalid &&
00143        m_tokenLabels[m_tokenInfo.get<kLabels>(i).m_startOfModuleLabel]=='\0') {
00144       //find all matching types
00145       const auto kind=m_tokenInfo.get<kKind>(i);
00146       auto matches = iHelper.relatedIndexes(kind,info.m_type);
00147 
00148       //NOTE: This could be changed to contain the true labels for what is being
00149       // requested but for now I want to remember these are part of a get many
00150       const LabelPlacement labels= m_tokenInfo.get<kLabels>(i);
00151       bool alwaysGet = m_tokenInfo.get<kAlwaysGets>(i);
00152       for(unsigned int j=0;j!=matches.numberOfMatches();++j) {
00153         //only keep the ones that are for a specific data item and not a collection
00154         if(matches.isFullyResolved(j)) {
00155           auto index =matches.index(j);
00156           m_tokenInfo.emplace_back(TokenLookupInfo{info.m_type,index,info.m_branchType},
00157                                    alwaysGet,
00158                                    labels,
00159                                    kind);
00160         }
00161       }
00162     }
00163   }
00164   m_tokenInfo.shrink_to_fit();
00165 }
00166 
00167 
00168 //
00169 // const member functions
00170 //
00171 ProductHolderIndex
00172 EDConsumerBase::indexFrom(EDGetToken iToken, BranchType iBranch, TypeID const& iType) const
00173 {
00174   if(unlikely(iToken.index()>=m_tokenInfo.size())) {
00175     throwBadToken(iType,iToken);
00176   }
00177   const auto& info = m_tokenInfo.get<kLookupInfo>(iToken.index());
00178   if (likely(iBranch == info.m_branchType)) {
00179     if (likely(iType == info.m_type)) {
00180       return info.m_index;
00181     } else {
00182       throwTypeMismatch(iType, iToken);
00183     }
00184   } else {
00185     throwBranchMismatch(iBranch,iToken);
00186   }
00187   return edm::ProductHolderIndexInvalid;
00188 }
00189 
00190 void
00191 EDConsumerBase::itemsToGet(BranchType iBranch, std::vector<ProductHolderIndex>& oIndices) const
00192 {
00193   //how many are we adding?
00194   unsigned int count=0;
00195   {
00196     auto itAlwaysGet = m_tokenInfo.begin<kAlwaysGets>();
00197     for(auto it = m_tokenInfo.begin<kLookupInfo>(),
00198         itEnd = m_tokenInfo.end<kLookupInfo>();
00199         it != itEnd; ++it,++itAlwaysGet) {
00200       if(iBranch==it->m_branchType) {
00201         if (it->m_index != ProductHolderIndexInvalid) {
00202           if(*itAlwaysGet) {
00203             ++count;
00204           }
00205         }
00206       }
00207     }
00208   }
00209   oIndices.reserve(oIndices.size()+count);
00210   {
00211     auto itAlwaysGet = m_tokenInfo.begin<kAlwaysGets>();
00212     for(auto it = m_tokenInfo.begin<kLookupInfo>(),
00213         itEnd = m_tokenInfo.end<kLookupInfo>();
00214         it != itEnd; ++it,++itAlwaysGet) {
00215       if(iBranch==it->m_branchType) {
00216         if (it->m_index != ProductHolderIndexInvalid) {
00217           if(*itAlwaysGet) {
00218             oIndices.push_back(it->m_index);
00219           }
00220         }
00221       }
00222     }
00223   }
00224 }
00225 
00226 void
00227 EDConsumerBase::itemsMayGet(BranchType iBranch, std::vector<ProductHolderIndex>& oIndices) const
00228 {
00229   //how many are we adding?
00230   unsigned int count=0;
00231   {
00232     auto itAlwaysGet = m_tokenInfo.begin<kAlwaysGets>();
00233     for(auto it = m_tokenInfo.begin<kLookupInfo>(),
00234         itEnd = m_tokenInfo.end<kLookupInfo>();
00235         it != itEnd; ++it,++itAlwaysGet) {
00236       if(iBranch==it->m_branchType) {
00237         if (it->m_index != ProductHolderIndexInvalid) {
00238           if(not *itAlwaysGet) {
00239             ++count;
00240           }
00241         }
00242       }
00243     }
00244   }
00245   oIndices.reserve(oIndices.size()+count);
00246   {
00247     auto itAlwaysGet = m_tokenInfo.begin<kAlwaysGets>();
00248     for(auto it = m_tokenInfo.begin<kLookupInfo>(),
00249         itEnd = m_tokenInfo.end<kLookupInfo>();
00250         it != itEnd; ++it,++itAlwaysGet) {
00251       if(iBranch==it->m_branchType) {
00252         if (it->m_index != ProductHolderIndexInvalid) {
00253           if(not *itAlwaysGet) {
00254             oIndices.push_back(it->m_index);
00255           }
00256         }
00257       }
00258     }
00259   }
00260 }
00261 
00262 void
00263 EDConsumerBase::labelsForToken(EDGetToken iToken, Labels& oLabels) const
00264 {
00265   unsigned int index = iToken.index();
00266   auto labels = m_tokenInfo.get<kLabels>(index);
00267   unsigned int start = labels.m_startOfModuleLabel;
00268   oLabels.module = &(m_tokenLabels[start]);
00269   oLabels.productInstance = oLabels.module+labels.m_deltaToProductInstance;
00270   oLabels.process = oLabels.module+labels.m_deltaToProcessName;
00271 }
00272 
00273 
00274 void
00275 EDConsumerBase::throwTypeMismatch(edm::TypeID const& iType, EDGetToken iToken) const
00276 {
00277   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.";
00278 }
00279 void
00280 EDConsumerBase::throwBranchMismatch(BranchType iBranch, EDGetToken iToken) const {
00281   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.";
00282 }
00283 
00284 void
00285 EDConsumerBase::throwBadToken(edm::TypeID const& iType, EDGetToken iToken) const
00286 {
00287   if(iToken.isUnitialized()) {
00288     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.";
00289   }
00290   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.";
00291 }
00292 
00293 
00294 //
00295 // static member functions
00296 //