Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-08-22 04:57:36

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