Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2022-06-03 00:58:59

0001 #ifndef FWCore_Framework_EDConsumerBase_h
0002 #define FWCore_Framework_EDConsumerBase_h
0003 // -*- C++ -*-
0004 //
0005 // Package:     FWCore/Framework
0006 // Class  :     EDConsumerBase
0007 //
0008 /**\class edm::EDConsumerBase
0009 
0010  Description: Allows declaration of what data is being consumed
0011 
0012  Usage:
0013     The EDM modules all inherit from this base class
0014 
0015 */
0016 //
0017 // Original Author:  Chris Jones
0018 //         Created:  Tue, 02 Apr 2013 21:35:53 GMT
0019 //
0020 
0021 // system include files
0022 #include <array>
0023 #include <map>
0024 #include <string>
0025 #include <vector>
0026 #include <array>
0027 #include <cassert>
0028 
0029 // user include files
0030 #include "DataFormats/Provenance/interface/BranchType.h"
0031 #include "DataFormats/Provenance/interface/ProvenanceFwd.h"
0032 #include "FWCore/Common/interface/FWCoreCommonFwd.h"
0033 #include "FWCore/Framework/interface/ProductResolverIndexAndSkipBit.h"
0034 #include "FWCore/Framework/interface/EventSetupRecordKey.h"
0035 #include "FWCore/Framework/interface/HCTypeTag.h"
0036 #include "FWCore/Framework/interface/DataKey.h"
0037 #include "FWCore/Framework/interface/data_default_record_trait.h"
0038 #include "FWCore/ServiceRegistry/interface/ConsumesInfo.h"
0039 #include "FWCore/Utilities/interface/ESIndices.h"
0040 #include "FWCore/Utilities/interface/TypeID.h"
0041 #include "FWCore/Utilities/interface/TypeToGet.h"
0042 #include "FWCore/Utilities/interface/InputTag.h"
0043 #include "FWCore/Utilities/interface/EDGetToken.h"
0044 #include "FWCore/Utilities/interface/ESGetToken.h"
0045 #include "FWCore/Utilities/interface/ESGetTokenGeneric.h"
0046 #include "FWCore/Utilities/interface/ESInputTag.h"
0047 #include "FWCore/Utilities/interface/SoATuple.h"
0048 #include "FWCore/Utilities/interface/Transition.h"
0049 #include "FWCore/Utilities/interface/ProductResolverIndex.h"
0050 #include "FWCore/Utilities/interface/ProductKindOfType.h"
0051 #include "FWCore/Utilities/interface/ProductLabels.h"
0052 
0053 // forward declarations
0054 
0055 namespace edm {
0056   class ModuleProcessName;
0057   class ProductResolverIndexHelper;
0058   class ConsumesCollector;
0059   template <Transition Tr>
0060   class EDConsumerBaseESAdaptor;
0061   template <Transition Tr>
0062   class EDConsumerBaseWithTagESAdaptor;
0063   template <BranchType B>
0064   class EDConsumerBaseAdaptor;
0065   template <typename T>
0066   class WillGetIfMatch;
0067 
0068   namespace eventsetup {
0069     class ESRecordsToProxyIndices;
0070   }
0071 
0072   class EDConsumerBase {
0073   public:
0074     EDConsumerBase();
0075     virtual ~EDConsumerBase() noexcept(false);
0076 
0077     // disallow copying
0078     EDConsumerBase(EDConsumerBase const&) = delete;
0079     EDConsumerBase const& operator=(EDConsumerBase const&) = delete;
0080 
0081     // allow moving
0082     EDConsumerBase(EDConsumerBase&&) = default;
0083     EDConsumerBase& operator=(EDConsumerBase&&) = default;
0084 
0085     // ---------- const member functions ---------------------
0086     ProductResolverIndexAndSkipBit indexFrom(EDGetToken, BranchType, TypeID const&) const;
0087     ProductResolverIndexAndSkipBit uncheckedIndexFrom(EDGetToken) const;
0088 
0089     void itemsToGet(BranchType, std::vector<ProductResolverIndexAndSkipBit>&) const;
0090     void itemsMayGet(BranchType, std::vector<ProductResolverIndexAndSkipBit>&) const;
0091 
0092     //used for prefetching
0093     std::vector<ProductResolverIndexAndSkipBit> const& itemsToGetFrom(BranchType iType) const {
0094       return itemsToGetFromBranch_[iType];
0095     }
0096 
0097     ///\return true if the product corresponding to the index was registered via consumes or mayConsume call
0098     bool registeredToConsume(ProductResolverIndex, bool, BranchType) const;
0099 
0100     ///\return true of TypeID corresponds to a type specified in a consumesMany call
0101     bool registeredToConsumeMany(TypeID const&, BranchType) const;
0102     // ---------- static member functions --------------------
0103 
0104     // ---------- member functions ---------------------------
0105     void updateLookup(BranchType iBranchType, ProductResolverIndexHelper const&, bool iPrefetchMayGet);
0106     void updateLookup(eventsetup::ESRecordsToProxyIndices const&);
0107     void selectInputProcessBlocks(ProductRegistry const& productRegistry,
0108                                   ProcessBlockHelperBase const& processBlockHelperBase) {
0109       doSelectInputProcessBlocks(productRegistry, processBlockHelperBase);
0110     }
0111 
0112     typedef ProductLabels Labels;
0113     void labelsForToken(EDGetToken iToken, Labels& oLabels) const;
0114 
0115     void modulesWhoseProductsAreConsumed(std::array<std::vector<ModuleDescription const*>*, NumBranchTypes>& modulesAll,
0116                                          std::vector<ModuleProcessName>& modulesInPreviousProcesses,
0117                                          ProductRegistry const& preg,
0118                                          std::map<std::string, ModuleDescription const*> const& labelsToDesc,
0119                                          std::string const& processName) const;
0120 
0121     /// Convert "@currentProcess" in InputTag process names to the actual current process name.
0122     void convertCurrentProcessAlias(std::string const& processName);
0123 
0124     std::vector<ConsumesInfo> consumesInfo() const;
0125 
0126     ESProxyIndex const* esGetTokenIndices(edm::Transition iTrans) const {
0127       if (iTrans < edm::Transition::NumberOfEventSetupTransitions) {
0128         auto const& v = esItemsToGetFromTransition_[static_cast<unsigned int>(iTrans)];
0129         if (v.empty()) {
0130           return nullptr;
0131         }
0132         return &(esItemsToGetFromTransition_[static_cast<unsigned int>(iTrans)].front());
0133       }
0134       return nullptr;
0135     }
0136 
0137     std::vector<ESProxyIndex> const& esGetTokenIndicesVector(edm::Transition iTrans) const {
0138       assert(iTrans < edm::Transition::NumberOfEventSetupTransitions);
0139       return esItemsToGetFromTransition_[static_cast<unsigned int>(iTrans)];
0140     }
0141 
0142     std::vector<ESRecordIndex> const& esGetTokenRecordIndicesVector(edm::Transition iTrans) const {
0143       assert(iTrans < edm::Transition::NumberOfEventSetupTransitions);
0144       return esRecordsToGetFromTransition_[static_cast<unsigned int>(iTrans)];
0145     }
0146 
0147   protected:
0148     friend class ConsumesCollector;
0149     template <Transition Tr>
0150     friend class EDConsumerBaseESAdaptor;
0151     template <Transition Tr>
0152     friend class EDConsumerBaseWithTagESAdaptor;
0153     template <BranchType B>
0154     friend class EDConsumerBaseAdaptor;
0155     template <typename T>
0156     friend class WillGetIfMatch;
0157     ///Use a ConsumesCollector to gather consumes information from helper functions
0158     ConsumesCollector consumesCollector();
0159 
0160     template <typename ProductType, BranchType B = InEvent>
0161     EDGetTokenT<ProductType> consumes(edm::InputTag const& tag) {
0162       TypeToGet tid = TypeToGet::make<ProductType>();
0163       return EDGetTokenT<ProductType>{recordConsumes(B, tid, checkIfEmpty(tag), true)};
0164     }
0165 
0166     template <BranchType B = InEvent>
0167     [[nodiscard]] EDConsumerBaseAdaptor<B> consumes(edm::InputTag tag) noexcept {
0168       return EDConsumerBaseAdaptor<B>(this, std::move(tag));
0169     }
0170 
0171     EDGetToken consumes(const TypeToGet& id, edm::InputTag const& tag) {
0172       return EDGetToken{recordConsumes(InEvent, id, checkIfEmpty(tag), true)};
0173     }
0174 
0175     template <BranchType B>
0176     EDGetToken consumes(TypeToGet const& id, edm::InputTag const& tag) {
0177       return EDGetToken{recordConsumes(B, id, checkIfEmpty(tag), true)};
0178     }
0179 
0180     template <typename ProductType, BranchType B = InEvent>
0181     EDGetTokenT<ProductType> mayConsume(edm::InputTag const& tag) {
0182       TypeToGet tid = TypeToGet::make<ProductType>();
0183       return EDGetTokenT<ProductType>{recordConsumes(B, tid, checkIfEmpty(tag), false)};
0184     }
0185 
0186     EDGetToken mayConsume(const TypeToGet& id, edm::InputTag const& tag) { return mayConsume<InEvent>(id, tag); }
0187 
0188     template <BranchType B>
0189     EDGetToken mayConsume(const TypeToGet& id, edm::InputTag const& tag) {
0190       return EDGetToken{recordConsumes(B, id, checkIfEmpty(tag), false)};
0191     }
0192 
0193     template <typename ProductType, BranchType B = InEvent>
0194     void consumesMany() {
0195       TypeToGet tid = TypeToGet::make<ProductType>();
0196       consumesMany<B>(tid);
0197     }
0198 
0199     void consumesMany(const TypeToGet& id) { consumesMany<InEvent>(id); }
0200 
0201     template <BranchType B>
0202     void consumesMany(const TypeToGet& id) {
0203       recordConsumes(B, id, edm::InputTag{}, true);
0204     }
0205 
0206     // For consuming event-setup products
0207     template <typename ESProduct, typename ESRecord, Transition Tr = Transition::Event>
0208     auto esConsumes() {
0209       return esConsumes<ESProduct, ESRecord, Tr>(ESInputTag{});
0210     }
0211 
0212     template <typename ESProduct, typename ESRecord, Transition Tr = Transition::Event>
0213     auto esConsumes(ESInputTag const& tag) {
0214       auto index = recordESConsumes(Tr,
0215                                     eventsetup::EventSetupRecordKey::makeKey<
0216                                         std::conditional_t<std::is_same_v<ESRecord, edm::DefaultRecord>,
0217                                                            eventsetup::default_record_t<ESHandleAdapter<ESProduct>>,
0218                                                            ESRecord>>(),
0219                                     eventsetup::heterocontainer::HCTypeTag::make<ESProduct>(),
0220                                     tag);
0221       return ESGetToken<ESProduct, ESRecord>{static_cast<unsigned int>(Tr), index, labelFor(index)};
0222     }
0223 
0224     template <Transition Tr = Transition::Event>
0225     [[nodiscard]] constexpr auto esConsumes() {
0226       return EDConsumerBaseESAdaptor<Tr>(this);
0227     }
0228 
0229     template <Transition Tr = Transition::Event>
0230     [[nodiscard]] auto esConsumes(ESInputTag tag) {
0231       return EDConsumerBaseWithTagESAdaptor<Tr>(this, std::move(tag));
0232     }
0233 
0234     ///Used with EventSetupRecord::doGet
0235     template <Transition Tr = Transition::Event>
0236     ESGetTokenGeneric esConsumes(eventsetup::EventSetupRecordKey const& iRecord, eventsetup::DataKey const& iKey) {
0237       return ESGetTokenGeneric(static_cast<unsigned int>(Tr),
0238                                recordESConsumes(Tr, iRecord, iKey.type(), ESInputTag("", iKey.name().value())),
0239                                iRecord.type());
0240     }
0241 
0242     //used for FinalPath
0243     void resetItemsToGetFrom(BranchType iType) { itemsToGetFromBranch_[iType].clear(); }
0244 
0245   private:
0246     virtual void registerLateConsumes(eventsetup::ESRecordsToProxyIndices const&) {}
0247     unsigned int recordConsumes(BranchType iBranch, TypeToGet const& iType, edm::InputTag const& iTag, bool iAlwaysGets);
0248     ESTokenIndex recordESConsumes(Transition,
0249                                   eventsetup::EventSetupRecordKey const&,
0250                                   eventsetup::heterocontainer::HCTypeTag const&,
0251                                   edm::ESInputTag const& iTag);
0252 
0253     const char* labelFor(ESTokenIndex) const;
0254 
0255     void throwTypeMismatch(edm::TypeID const&, EDGetToken) const;
0256     void throwBranchMismatch(BranchType, EDGetToken) const;
0257     void throwBadToken(edm::TypeID const& iType, EDGetToken iToken) const;
0258     void throwConsumesCallAfterFrozen(TypeToGet const&, InputTag const&) const;
0259     void throwESConsumesCallAfterFrozen(eventsetup::EventSetupRecordKey const&,
0260                                         eventsetup::heterocontainer::HCTypeTag const&,
0261                                         edm::ESInputTag const&) const;
0262     void throwESConsumesInProcessBlock() const;
0263 
0264     edm::InputTag const& checkIfEmpty(edm::InputTag const& tag);
0265 
0266     virtual void doSelectInputProcessBlocks(ProductRegistry const&, ProcessBlockHelperBase const&);
0267 
0268     // ---------- member data --------------------------------
0269 
0270     struct TokenLookupInfo {
0271       TokenLookupInfo(edm::TypeID const& iID, ProductResolverIndex iIndex, bool skipCurrentProcess, BranchType iBranch)
0272           : m_type(iID), m_index(iIndex, skipCurrentProcess), m_branchType(iBranch) {}
0273       edm::TypeID m_type;
0274       ProductResolverIndexAndSkipBit m_index;
0275       BranchType m_branchType;
0276     };
0277 
0278     struct LabelPlacement {
0279       LabelPlacement(unsigned int iStartOfModuleLabel,
0280                      unsigned short iDeltaToProductInstance,
0281                      unsigned short iDeltaToProcessName)
0282           : m_startOfModuleLabel(iStartOfModuleLabel),
0283             m_deltaToProductInstance(iDeltaToProductInstance),
0284             m_deltaToProcessName(iDeltaToProcessName) {}
0285       unsigned int m_startOfModuleLabel;
0286       unsigned short m_deltaToProductInstance;
0287       unsigned short m_deltaToProcessName;
0288     };
0289 
0290     //define the purpose of each 'column' in m_tokenInfo
0291     enum { kLookupInfo, kAlwaysGets, kLabels, kKind };
0292     edm::SoATuple<TokenLookupInfo, bool, LabelPlacement, edm::KindOfType> m_tokenInfo;
0293 
0294     //m_tokenStartOfLabels holds the entries into this container
0295     // for each of the 3 labels needed to id the data
0296     std::vector<char> m_tokenLabels;
0297 
0298     std::array<std::vector<ProductResolverIndexAndSkipBit>, edm::NumBranchTypes> itemsToGetFromBranch_;
0299 
0300     struct ESTokenLookupInfo {
0301       eventsetup::EventSetupRecordKey m_record;
0302       eventsetup::DataKey m_key;
0303       unsigned int m_startOfComponentName;
0304     };
0305 
0306     // TODO We would like to be able to access m_esTokenInfo from the
0307     // index in the token, but this is currently not possible. One idea
0308     // for this is to order the entries in m_esToken so that all the ones
0309     // for transition 0 come first, then the ones for for transition 1
0310     // and so on for all the transitions. Within a transition, the
0311     // entries would be in the same order in m_esTokenInfo and
0312     // esItemsToGetFromTransition_. This is something for future
0313     // development and might require a change to SoATuple to support
0314     // inserts in the middle of the data structure.
0315     enum { kESLookupInfo, kESProxyIndex };
0316     edm::SoATuple<ESTokenLookupInfo, ESProxyIndex> m_esTokenInfo;
0317     std::array<std::vector<ESProxyIndex>, static_cast<unsigned int>(edm::Transition::NumberOfEventSetupTransitions)>
0318         esItemsToGetFromTransition_;
0319     std::array<std::vector<ESRecordIndex>, static_cast<unsigned int>(edm::Transition::NumberOfEventSetupTransitions)>
0320         esRecordsToGetFromTransition_;
0321     bool frozen_;
0322     bool containsCurrentProcessAlias_;
0323   };
0324 
0325   template <Transition TR>
0326   class EDConsumerBaseESAdaptor {
0327   public:
0328     template <typename TYPE, typename REC>
0329     ESGetToken<TYPE, REC> consumes() {
0330       return m_consumer->template esConsumes<TYPE, REC, TR>();
0331     }
0332 
0333   private:
0334     //only EDConsumerBase is allowed to make an instance of this class
0335     friend class EDConsumerBase;
0336     EDConsumerBaseESAdaptor(EDConsumerBase* iBase) : m_consumer(iBase) {}
0337 
0338     EDConsumerBase* m_consumer;
0339   };
0340 
0341   template <Transition TR>
0342   class EDConsumerBaseWithTagESAdaptor {
0343   public:
0344     template <typename TYPE, typename REC>
0345     ESGetToken<TYPE, REC> consumes() {
0346       return m_consumer->template esConsumes<TYPE, REC, TR>(m_tag);
0347     }
0348 
0349   private:
0350     //only EDConsumerBase is allowed to make an instance of this class
0351     friend class EDConsumerBase;
0352     EDConsumerBaseWithTagESAdaptor(EDConsumerBase* iBase, ESInputTag iTag) noexcept
0353         : m_consumer(iBase), m_tag(std::move(iTag)) {}
0354 
0355     EDConsumerBase* m_consumer;
0356     ESInputTag const m_tag;
0357   };
0358 
0359   template <BranchType B>
0360   class EDConsumerBaseAdaptor {
0361   public:
0362     template <typename TYPE>
0363     EDGetTokenT<TYPE> consumes() {
0364       return m_consumer->template consumes<TYPE, B>(m_tag);
0365     }
0366 
0367   private:
0368     //only EDConsumerBase is allowed to make an instance of this class
0369     friend class EDConsumerBase;
0370     EDConsumerBaseAdaptor(EDConsumerBase* iBase, edm::InputTag iTag) noexcept
0371         : m_consumer(iBase), m_tag(std::move(iTag)) {}
0372 
0373     EDConsumerBase* m_consumer;
0374     edm::InputTag const m_tag;
0375   };
0376 
0377 }  // namespace edm
0378 
0379 #endif