Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2022-09-11 22:29:29

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 extendUpdateLookup(BranchType iBranchType, ProductResolverIndexHelper const&);
0247     virtual void registerLateConsumes(eventsetup::ESRecordsToProxyIndices const&) {}
0248     unsigned int recordConsumes(BranchType iBranch, TypeToGet const& iType, edm::InputTag const& iTag, bool iAlwaysGets);
0249     ESTokenIndex recordESConsumes(Transition,
0250                                   eventsetup::EventSetupRecordKey const&,
0251                                   eventsetup::heterocontainer::HCTypeTag const&,
0252                                   edm::ESInputTag const& iTag);
0253 
0254     const char* labelFor(ESTokenIndex) const;
0255 
0256     void throwTypeMismatch(edm::TypeID const&, EDGetToken) const;
0257     void throwBranchMismatch(BranchType, EDGetToken) const;
0258     void throwBadToken(edm::TypeID const& iType, EDGetToken iToken) const;
0259     void throwConsumesCallAfterFrozen(TypeToGet const&, InputTag const&) const;
0260     void throwESConsumesCallAfterFrozen(eventsetup::EventSetupRecordKey const&,
0261                                         eventsetup::heterocontainer::HCTypeTag const&,
0262                                         edm::ESInputTag const&) const;
0263     void throwESConsumesInProcessBlock() const;
0264 
0265     edm::InputTag const& checkIfEmpty(edm::InputTag const& tag);
0266 
0267     virtual void doSelectInputProcessBlocks(ProductRegistry const&, ProcessBlockHelperBase const&);
0268 
0269     // ---------- member data --------------------------------
0270 
0271     struct TokenLookupInfo {
0272       TokenLookupInfo(edm::TypeID const& iID, ProductResolverIndex iIndex, bool skipCurrentProcess, BranchType iBranch)
0273           : m_type(iID), m_index(iIndex, skipCurrentProcess), m_branchType(iBranch) {}
0274       edm::TypeID m_type;
0275       ProductResolverIndexAndSkipBit m_index;
0276       BranchType m_branchType;
0277     };
0278 
0279     struct LabelPlacement {
0280       LabelPlacement(unsigned int iStartOfModuleLabel,
0281                      unsigned short iDeltaToProductInstance,
0282                      unsigned short iDeltaToProcessName)
0283           : m_startOfModuleLabel(iStartOfModuleLabel),
0284             m_deltaToProductInstance(iDeltaToProductInstance),
0285             m_deltaToProcessName(iDeltaToProcessName) {}
0286       unsigned int m_startOfModuleLabel;
0287       unsigned short m_deltaToProductInstance;
0288       unsigned short m_deltaToProcessName;
0289     };
0290 
0291     //define the purpose of each 'column' in m_tokenInfo
0292     enum { kLookupInfo, kAlwaysGets, kLabels, kKind };
0293     edm::SoATuple<TokenLookupInfo, bool, LabelPlacement, edm::KindOfType> m_tokenInfo;
0294 
0295     //m_tokenStartOfLabels holds the entries into this container
0296     // for each of the 3 labels needed to id the data
0297     std::vector<char> m_tokenLabels;
0298 
0299     std::array<std::vector<ProductResolverIndexAndSkipBit>, edm::NumBranchTypes> itemsToGetFromBranch_;
0300 
0301     struct ESTokenLookupInfo {
0302       eventsetup::EventSetupRecordKey m_record;
0303       eventsetup::DataKey m_key;
0304       unsigned int m_startOfComponentName;
0305     };
0306 
0307     // TODO We would like to be able to access m_esTokenInfo from the
0308     // index in the token, but this is currently not possible. One idea
0309     // for this is to order the entries in m_esToken so that all the ones
0310     // for transition 0 come first, then the ones for for transition 1
0311     // and so on for all the transitions. Within a transition, the
0312     // entries would be in the same order in m_esTokenInfo and
0313     // esItemsToGetFromTransition_. This is something for future
0314     // development and might require a change to SoATuple to support
0315     // inserts in the middle of the data structure.
0316     enum { kESLookupInfo, kESProxyIndex };
0317     edm::SoATuple<ESTokenLookupInfo, ESProxyIndex> m_esTokenInfo;
0318     std::array<std::vector<ESProxyIndex>, static_cast<unsigned int>(edm::Transition::NumberOfEventSetupTransitions)>
0319         esItemsToGetFromTransition_;
0320     std::array<std::vector<ESRecordIndex>, static_cast<unsigned int>(edm::Transition::NumberOfEventSetupTransitions)>
0321         esRecordsToGetFromTransition_;
0322     bool frozen_;
0323     bool containsCurrentProcessAlias_;
0324   };
0325 
0326   template <Transition TR>
0327   class EDConsumerBaseESAdaptor {
0328   public:
0329     template <typename TYPE, typename REC>
0330     ESGetToken<TYPE, REC> consumes() {
0331       return m_consumer->template esConsumes<TYPE, REC, TR>();
0332     }
0333 
0334   private:
0335     //only EDConsumerBase is allowed to make an instance of this class
0336     friend class EDConsumerBase;
0337     EDConsumerBaseESAdaptor(EDConsumerBase* iBase) : m_consumer(iBase) {}
0338 
0339     EDConsumerBase* m_consumer;
0340   };
0341 
0342   template <Transition TR>
0343   class EDConsumerBaseWithTagESAdaptor {
0344   public:
0345     template <typename TYPE, typename REC>
0346     ESGetToken<TYPE, REC> consumes() {
0347       return m_consumer->template esConsumes<TYPE, REC, TR>(m_tag);
0348     }
0349 
0350   private:
0351     //only EDConsumerBase is allowed to make an instance of this class
0352     friend class EDConsumerBase;
0353     EDConsumerBaseWithTagESAdaptor(EDConsumerBase* iBase, ESInputTag iTag) noexcept
0354         : m_consumer(iBase), m_tag(std::move(iTag)) {}
0355 
0356     EDConsumerBase* m_consumer;
0357     ESInputTag const m_tag;
0358   };
0359 
0360   template <BranchType B>
0361   class EDConsumerBaseAdaptor {
0362   public:
0363     template <typename TYPE>
0364     EDGetTokenT<TYPE> consumes() {
0365       return m_consumer->template consumes<TYPE, B>(m_tag);
0366     }
0367 
0368   private:
0369     //only EDConsumerBase is allowed to make an instance of this class
0370     friend class EDConsumerBase;
0371     EDConsumerBaseAdaptor(EDConsumerBase* iBase, edm::InputTag iTag) noexcept
0372         : m_consumer(iBase), m_tag(std::move(iTag)) {}
0373 
0374     EDConsumerBase* m_consumer;
0375     edm::InputTag const m_tag;
0376   };
0377 
0378 }  // namespace edm
0379 
0380 #endif