Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2023-10-25 09:46:49

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 ESRecordsToProductResolverIndices;
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     // ---------- static member functions --------------------
0101 
0102     // ---------- member functions ---------------------------
0103     void updateLookup(BranchType iBranchType, ProductResolverIndexHelper const&, bool iPrefetchMayGet);
0104     void updateLookup(eventsetup::ESRecordsToProductResolverIndices const&);
0105     void selectInputProcessBlocks(ProductRegistry const& productRegistry,
0106                                   ProcessBlockHelperBase const& processBlockHelperBase) {
0107       doSelectInputProcessBlocks(productRegistry, processBlockHelperBase);
0108     }
0109 
0110     typedef ProductLabels Labels;
0111     void labelsForToken(EDGetToken iToken, Labels& oLabels) const;
0112 
0113     void modulesWhoseProductsAreConsumed(std::array<std::vector<ModuleDescription const*>*, NumBranchTypes>& modulesAll,
0114                                          std::vector<ModuleProcessName>& modulesInPreviousProcesses,
0115                                          ProductRegistry const& preg,
0116                                          std::map<std::string, ModuleDescription const*> const& labelsToDesc,
0117                                          std::string const& processName) const;
0118 
0119     /// Convert "@currentProcess" in InputTag process names to the actual current process name.
0120     void convertCurrentProcessAlias(std::string const& processName);
0121 
0122     std::vector<ConsumesInfo> consumesInfo() const;
0123 
0124     ESResolverIndex const* esGetTokenIndices(edm::Transition iTrans) const {
0125       if (iTrans < edm::Transition::NumberOfEventSetupTransitions) {
0126         auto const& v = esItemsToGetFromTransition_[static_cast<unsigned int>(iTrans)];
0127         if (v.empty()) {
0128           return nullptr;
0129         }
0130         return &(esItemsToGetFromTransition_[static_cast<unsigned int>(iTrans)].front());
0131       }
0132       return nullptr;
0133     }
0134 
0135     std::vector<ESResolverIndex> const& esGetTokenIndicesVector(edm::Transition iTrans) const {
0136       assert(iTrans < edm::Transition::NumberOfEventSetupTransitions);
0137       return esItemsToGetFromTransition_[static_cast<unsigned int>(iTrans)];
0138     }
0139 
0140     std::vector<ESRecordIndex> const& esGetTokenRecordIndicesVector(edm::Transition iTrans) const {
0141       assert(iTrans < edm::Transition::NumberOfEventSetupTransitions);
0142       return esRecordsToGetFromTransition_[static_cast<unsigned int>(iTrans)];
0143     }
0144 
0145   protected:
0146     friend class ConsumesCollector;
0147     template <Transition Tr>
0148     friend class EDConsumerBaseESAdaptor;
0149     template <Transition Tr>
0150     friend class EDConsumerBaseWithTagESAdaptor;
0151     template <BranchType B>
0152     friend class EDConsumerBaseAdaptor;
0153     template <typename T>
0154     friend class WillGetIfMatch;
0155     ///Use a ConsumesCollector to gather consumes information from helper functions
0156     ConsumesCollector consumesCollector();
0157 
0158     template <typename ProductType, BranchType B = InEvent>
0159     EDGetTokenT<ProductType> consumes(edm::InputTag const& tag) {
0160       TypeToGet tid = TypeToGet::make<ProductType>();
0161       return EDGetTokenT<ProductType>{recordConsumes(B, tid, checkIfEmpty(tag), true)};
0162     }
0163 
0164     template <BranchType B = InEvent>
0165     [[nodiscard]] EDConsumerBaseAdaptor<B> consumes(edm::InputTag tag) noexcept {
0166       return EDConsumerBaseAdaptor<B>(this, std::move(tag));
0167     }
0168 
0169     EDGetToken consumes(const TypeToGet& id, edm::InputTag const& tag) {
0170       return EDGetToken{recordConsumes(InEvent, id, checkIfEmpty(tag), true)};
0171     }
0172 
0173     template <BranchType B>
0174     EDGetToken consumes(TypeToGet const& id, edm::InputTag const& tag) {
0175       return EDGetToken{recordConsumes(B, id, checkIfEmpty(tag), true)};
0176     }
0177 
0178     template <typename ProductType, BranchType B = InEvent>
0179     EDGetTokenT<ProductType> mayConsume(edm::InputTag const& tag) {
0180       TypeToGet tid = TypeToGet::make<ProductType>();
0181       return EDGetTokenT<ProductType>{recordConsumes(B, tid, checkIfEmpty(tag), false)};
0182     }
0183 
0184     EDGetToken mayConsume(const TypeToGet& id, edm::InputTag const& tag) { return mayConsume<InEvent>(id, tag); }
0185 
0186     template <BranchType B>
0187     EDGetToken mayConsume(const TypeToGet& id, edm::InputTag const& tag) {
0188       return EDGetToken{recordConsumes(B, id, checkIfEmpty(tag), false)};
0189     }
0190 
0191     // For consuming event-setup products
0192     template <typename ESProduct, typename ESRecord, Transition Tr = Transition::Event>
0193     auto esConsumes() {
0194       return esConsumes<ESProduct, ESRecord, Tr>(ESInputTag{});
0195     }
0196 
0197     template <typename ESProduct, typename ESRecord, Transition Tr = Transition::Event>
0198     auto esConsumes(ESInputTag const& tag) {
0199       auto index = recordESConsumes(Tr,
0200                                     eventsetup::EventSetupRecordKey::makeKey<
0201                                         std::conditional_t<std::is_same_v<ESRecord, edm::DefaultRecord>,
0202                                                            eventsetup::default_record_t<ESHandleAdapter<ESProduct>>,
0203                                                            ESRecord>>(),
0204                                     eventsetup::heterocontainer::HCTypeTag::make<ESProduct>(),
0205                                     tag);
0206       return ESGetToken<ESProduct, ESRecord>{static_cast<unsigned int>(Tr), index, labelFor(index)};
0207     }
0208 
0209     template <Transition Tr = Transition::Event>
0210     [[nodiscard]] constexpr auto esConsumes() {
0211       return EDConsumerBaseESAdaptor<Tr>(this);
0212     }
0213 
0214     template <Transition Tr = Transition::Event>
0215     [[nodiscard]] auto esConsumes(ESInputTag tag) {
0216       return EDConsumerBaseWithTagESAdaptor<Tr>(this, std::move(tag));
0217     }
0218 
0219     ///Used with EventSetupRecord::doGet
0220     template <Transition Tr = Transition::Event>
0221     ESGetTokenGeneric esConsumes(eventsetup::EventSetupRecordKey const& iRecord, eventsetup::DataKey const& iKey) {
0222       return ESGetTokenGeneric(static_cast<unsigned int>(Tr),
0223                                recordESConsumes(Tr, iRecord, iKey.type(), ESInputTag("", iKey.name().value())),
0224                                iRecord.type());
0225     }
0226 
0227     //used for FinalPath
0228     void resetItemsToGetFrom(BranchType iType) { itemsToGetFromBranch_[iType].clear(); }
0229 
0230   private:
0231     virtual void extendUpdateLookup(BranchType iBranchType, ProductResolverIndexHelper const&);
0232     virtual void registerLateConsumes(eventsetup::ESRecordsToProductResolverIndices const&) {}
0233     unsigned int recordConsumes(BranchType iBranch, TypeToGet const& iType, edm::InputTag const& iTag, bool iAlwaysGets);
0234     ESTokenIndex recordESConsumes(Transition,
0235                                   eventsetup::EventSetupRecordKey const&,
0236                                   eventsetup::heterocontainer::HCTypeTag const&,
0237                                   edm::ESInputTag const& iTag);
0238 
0239     const char* labelFor(ESTokenIndex) const;
0240 
0241     void throwTypeMismatch(edm::TypeID const&, EDGetToken) const;
0242     void throwBranchMismatch(BranchType, EDGetToken) const;
0243     void throwBadToken(edm::TypeID const& iType, EDGetToken iToken) const;
0244     void throwConsumesCallAfterFrozen(TypeToGet const&, InputTag const&) const;
0245     void throwESConsumesCallAfterFrozen(eventsetup::EventSetupRecordKey const&,
0246                                         eventsetup::heterocontainer::HCTypeTag const&,
0247                                         edm::ESInputTag const&) const;
0248     void throwESConsumesInProcessBlock() const;
0249 
0250     edm::InputTag const& checkIfEmpty(edm::InputTag const& tag);
0251 
0252     virtual void doSelectInputProcessBlocks(ProductRegistry const&, ProcessBlockHelperBase const&);
0253 
0254     // ---------- member data --------------------------------
0255 
0256     struct TokenLookupInfo {
0257       TokenLookupInfo(edm::TypeID const& iID, ProductResolverIndex iIndex, bool skipCurrentProcess, BranchType iBranch)
0258           : m_type(iID), m_index(iIndex, skipCurrentProcess), m_branchType(iBranch) {}
0259       edm::TypeID m_type;
0260       ProductResolverIndexAndSkipBit m_index;
0261       BranchType m_branchType;
0262     };
0263 
0264     struct LabelPlacement {
0265       LabelPlacement(unsigned int iStartOfModuleLabel,
0266                      unsigned short iDeltaToProductInstance,
0267                      unsigned short iDeltaToProcessName)
0268           : m_startOfModuleLabel(iStartOfModuleLabel),
0269             m_deltaToProductInstance(iDeltaToProductInstance),
0270             m_deltaToProcessName(iDeltaToProcessName) {}
0271       unsigned int m_startOfModuleLabel;
0272       unsigned short m_deltaToProductInstance;
0273       unsigned short m_deltaToProcessName;
0274     };
0275 
0276     //define the purpose of each 'column' in m_tokenInfo
0277     enum { kLookupInfo, kAlwaysGets, kLabels, kKind };
0278     edm::SoATuple<TokenLookupInfo, bool, LabelPlacement, edm::KindOfType> m_tokenInfo;
0279 
0280     //m_tokenStartOfLabels holds the entries into this container
0281     // for each of the 3 labels needed to id the data
0282     std::vector<char> m_tokenLabels;
0283 
0284     std::array<std::vector<ProductResolverIndexAndSkipBit>, edm::NumBranchTypes> itemsToGetFromBranch_;
0285 
0286     struct ESTokenLookupInfo {
0287       eventsetup::EventSetupRecordKey m_record;
0288       eventsetup::DataKey m_key;
0289       unsigned int m_startOfComponentName;
0290     };
0291 
0292     // TODO We would like to be able to access m_esTokenInfo from the
0293     // index in the token, but this is currently not possible. One idea
0294     // for this is to order the entries in m_esToken so that all the ones
0295     // for transition 0 come first, then the ones for for transition 1
0296     // and so on for all the transitions. Within a transition, the
0297     // entries would be in the same order in m_esTokenInfo and
0298     // esItemsToGetFromTransition_. This is something for future
0299     // development and might require a change to SoATuple to support
0300     // inserts in the middle of the data structure.
0301     enum { kESLookupInfo, kESResolverIndex };
0302     edm::SoATuple<ESTokenLookupInfo, ESResolverIndex> m_esTokenInfo;
0303     std::array<std::vector<ESResolverIndex>, static_cast<unsigned int>(edm::Transition::NumberOfEventSetupTransitions)>
0304         esItemsToGetFromTransition_;
0305     std::array<std::vector<ESRecordIndex>, static_cast<unsigned int>(edm::Transition::NumberOfEventSetupTransitions)>
0306         esRecordsToGetFromTransition_;
0307     bool frozen_;
0308     bool containsCurrentProcessAlias_;
0309   };
0310 
0311   template <Transition TR>
0312   class EDConsumerBaseESAdaptor {
0313   public:
0314     template <typename TYPE, typename REC>
0315     ESGetToken<TYPE, REC> consumes() {
0316       return m_consumer->template esConsumes<TYPE, REC, TR>();
0317     }
0318 
0319   private:
0320     //only EDConsumerBase is allowed to make an instance of this class
0321     friend class EDConsumerBase;
0322     EDConsumerBaseESAdaptor(EDConsumerBase* iBase) : m_consumer(iBase) {}
0323 
0324     EDConsumerBase* m_consumer;
0325   };
0326 
0327   template <Transition TR>
0328   class EDConsumerBaseWithTagESAdaptor {
0329   public:
0330     template <typename TYPE, typename REC>
0331     ESGetToken<TYPE, REC> consumes() {
0332       return m_consumer->template esConsumes<TYPE, REC, TR>(m_tag);
0333     }
0334 
0335   private:
0336     //only EDConsumerBase is allowed to make an instance of this class
0337     friend class EDConsumerBase;
0338     EDConsumerBaseWithTagESAdaptor(EDConsumerBase* iBase, ESInputTag iTag) noexcept
0339         : m_consumer(iBase), m_tag(std::move(iTag)) {}
0340 
0341     EDConsumerBase* m_consumer;
0342     ESInputTag const m_tag;
0343   };
0344 
0345   template <BranchType B>
0346   class EDConsumerBaseAdaptor {
0347   public:
0348     template <typename TYPE>
0349     EDGetTokenT<TYPE> consumes() {
0350       return m_consumer->template consumes<TYPE, B>(m_tag);
0351     }
0352 
0353   private:
0354     //only EDConsumerBase is allowed to make an instance of this class
0355     friend class EDConsumerBase;
0356     EDConsumerBaseAdaptor(EDConsumerBase* iBase, edm::InputTag iTag) noexcept
0357         : m_consumer(iBase), m_tag(std::move(iTag)) {}
0358 
0359     EDConsumerBase* m_consumer;
0360     edm::InputTag const m_tag;
0361   };
0362 
0363 }  // namespace edm
0364 
0365 #endif