Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2025-04-30 22:24:06

0001 // -*- C++ -*-
0002 #ifndef FWCore_Framework_EDConsumerBase_h
0003 #define FWCore_Framework_EDConsumerBase_h
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 <memory>
0025 #include <string>
0026 #include <vector>
0027 #include <array>
0028 #include <cassert>
0029 #include <tuple>
0030 #include <utility>
0031 
0032 // user include files
0033 #include "DataFormats/Provenance/interface/ProvenanceFwd.h"
0034 #include "FWCore/Common/interface/FWCoreCommonFwd.h"
0035 #include "FWCore/Framework/interface/ProductResolverIndexAndSkipBit.h"
0036 #include "FWCore/Framework/interface/EventSetupRecordKey.h"
0037 #include "FWCore/Framework/interface/HCTypeTag.h"
0038 #include "FWCore/Framework/interface/DataKey.h"
0039 #include "FWCore/Framework/interface/data_default_record_trait.h"
0040 #include "FWCore/Framework/interface/ModuleConsumesMinimalESInfo.h"
0041 #include "FWCore/ServiceRegistry/interface/ServiceRegistryfwd.h"
0042 #include "FWCore/ServiceRegistry/interface/ModuleConsumesInfo.h"
0043 #include "FWCore/Utilities/interface/BranchType.h"
0044 #include "FWCore/Utilities/interface/ESIndices.h"
0045 #include "FWCore/Utilities/interface/TypeID.h"
0046 #include "FWCore/Utilities/interface/TypeToGet.h"
0047 #include "FWCore/Utilities/interface/InputTag.h"
0048 #include "FWCore/Utilities/interface/EDGetToken.h"
0049 #include "FWCore/Utilities/interface/ESGetToken.h"
0050 #include "FWCore/Utilities/interface/ESGetTokenGeneric.h"
0051 #include "FWCore/Utilities/interface/ESInputTag.h"
0052 #include "FWCore/Utilities/interface/SoATuple.h"
0053 #include "FWCore/Utilities/interface/Transition.h"
0054 #include "FWCore/Utilities/interface/ProductResolverIndex.h"
0055 #include "FWCore/Utilities/interface/ProductKindOfType.h"
0056 #include "FWCore/Utilities/interface/ProductLabels.h"
0057 
0058 // forward declarations
0059 
0060 namespace edm {
0061   class ProductResolverIndexHelper;
0062   class ConsumesCollector;
0063   template <Transition Tr>
0064   class EDConsumerBaseESAdaptor;
0065   template <Transition Tr>
0066   class EDConsumerBaseWithTagESAdaptor;
0067   template <BranchType B>
0068   class EDConsumerBaseAdaptor;
0069   template <typename T>
0070   class WillGetIfMatch;
0071 
0072   namespace eventsetup {
0073     struct ComponentDescription;
0074     class ESRecordsToProductResolverIndices;
0075   }  // namespace eventsetup
0076 
0077   class EDConsumerBase {
0078   public:
0079     EDConsumerBase();
0080     virtual ~EDConsumerBase() noexcept(false);
0081 
0082     // disallow copying
0083     EDConsumerBase(EDConsumerBase const&) = delete;
0084     EDConsumerBase const& operator=(EDConsumerBase const&) = delete;
0085 
0086     // allow moving
0087     EDConsumerBase(EDConsumerBase&&) = default;
0088     EDConsumerBase& operator=(EDConsumerBase&&) = default;
0089 
0090     // ---------- const member functions ---------------------
0091     ProductResolverIndexAndSkipBit indexFrom(EDGetToken, BranchType, TypeID const&) const;
0092     ProductResolverIndexAndSkipBit uncheckedIndexFrom(EDGetToken) const;
0093 
0094     void itemsToGet(BranchType, std::vector<ProductResolverIndexAndSkipBit>&) const;
0095     void itemsMayGet(BranchType, std::vector<ProductResolverIndexAndSkipBit>&) const;
0096 
0097     //used for prefetching
0098     std::vector<ProductResolverIndexAndSkipBit> const& itemsToGetFrom(BranchType iType) const {
0099       return itemsToGetFromBranch_[iType];
0100     }
0101 
0102     ///\return true if the product corresponding to the index was registered via consumes or mayConsume call
0103     bool registeredToConsume(ProductResolverIndex, bool, BranchType) const;
0104 
0105     // ---------- static member functions --------------------
0106 
0107     // ---------- member functions ---------------------------
0108     void updateLookup(BranchType iBranchType, ProductResolverIndexHelper const&, bool iPrefetchMayGet);
0109     void updateLookup(eventsetup::ESRecordsToProductResolverIndices const&);
0110     void releaseMemoryPostLookupSignal();
0111     void selectInputProcessBlocks(ProductRegistry const& productRegistry,
0112                                   ProcessBlockHelperBase const& processBlockHelperBase) {
0113       doSelectInputProcessBlocks(productRegistry, processBlockHelperBase);
0114     }
0115 
0116     typedef ProductLabels Labels;
0117     void labelsForToken(EDGetToken iToken, Labels& oLabels) 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<ModuleConsumesInfo> moduleConsumesInfos() const;
0123     ///This can only be called before the end of beginJob (after that the underlying data has been deleted)
0124     /// The pointers held by ModuleConsumesMinimalESInfo will also be invalid at that time so copies of
0125     /// that class should not be held beyond the end of beginJob.
0126     std::vector<ModuleConsumesMinimalESInfo> moduleConsumesMinimalESInfos() const;
0127 
0128     ESResolverIndex const* esGetTokenIndices(edm::Transition iTrans) const {
0129       if (iTrans < edm::Transition::NumberOfEventSetupTransitions) {
0130         auto const& v = esItemsToGetFromTransition_[static_cast<unsigned int>(iTrans)];
0131         if (v.empty()) {
0132           return nullptr;
0133         }
0134         return &(esItemsToGetFromTransition_[static_cast<unsigned int>(iTrans)].front());
0135       }
0136       return nullptr;
0137     }
0138 
0139     std::vector<ESResolverIndex> const& esGetTokenIndicesVector(edm::Transition iTrans) const {
0140       assert(iTrans < edm::Transition::NumberOfEventSetupTransitions);
0141       return esItemsToGetFromTransition_[static_cast<unsigned int>(iTrans)];
0142     }
0143 
0144     std::vector<ESRecordIndex> const& esGetTokenRecordIndicesVector(edm::Transition iTrans) const {
0145       assert(iTrans < edm::Transition::NumberOfEventSetupTransitions);
0146       return esRecordsToGetFromTransition_[static_cast<unsigned int>(iTrans)];
0147     }
0148 
0149   protected:
0150     friend class ConsumesCollector;
0151     template <Transition Tr>
0152     friend class EDConsumerBaseESAdaptor;
0153     template <Transition Tr>
0154     friend class EDConsumerBaseWithTagESAdaptor;
0155     template <BranchType B>
0156     friend class EDConsumerBaseAdaptor;
0157     template <typename T>
0158     friend class WillGetIfMatch;
0159     ///Use a ConsumesCollector to gather consumes information from helper functions
0160     ConsumesCollector consumesCollector();
0161 
0162     template <typename ProductType, BranchType B = InEvent>
0163     EDGetTokenT<ProductType> consumes(edm::InputTag const& tag) {
0164       TypeToGet tid = TypeToGet::make<ProductType>();
0165       return EDGetTokenT<ProductType>{recordConsumes(B, tid, checkIfEmpty(tag), true)};
0166     }
0167 
0168     template <BranchType B = InEvent>
0169     [[nodiscard]] EDConsumerBaseAdaptor<B> consumes(edm::InputTag tag) noexcept {
0170       return EDConsumerBaseAdaptor<B>(this, std::move(tag));
0171     }
0172 
0173     EDGetToken consumes(const TypeToGet& id, edm::InputTag const& tag) {
0174       return EDGetToken{recordConsumes(InEvent, id, checkIfEmpty(tag), true)};
0175     }
0176 
0177     template <BranchType B>
0178     EDGetToken consumes(TypeToGet const& id, edm::InputTag const& tag) {
0179       return EDGetToken{recordConsumes(B, id, checkIfEmpty(tag), true)};
0180     }
0181 
0182     template <typename ProductType, BranchType B = InEvent>
0183     EDGetTokenT<ProductType> mayConsume(edm::InputTag const& tag) {
0184       TypeToGet tid = TypeToGet::make<ProductType>();
0185       return EDGetTokenT<ProductType>{recordConsumes(B, tid, checkIfEmpty(tag), false)};
0186     }
0187 
0188     EDGetToken mayConsume(const TypeToGet& id, edm::InputTag const& tag) { return mayConsume<InEvent>(id, tag); }
0189 
0190     template <BranchType B>
0191     EDGetToken mayConsume(const TypeToGet& id, edm::InputTag const& tag) {
0192       return EDGetToken{recordConsumes(B, id, checkIfEmpty(tag), false)};
0193     }
0194 
0195     // For consuming event-setup products
0196     template <typename ESProduct, typename ESRecord, Transition Tr = Transition::Event>
0197     auto esConsumes() {
0198       return esConsumes<ESProduct, ESRecord, Tr>(ESInputTag{});
0199     }
0200 
0201     template <typename ESProduct, typename ESRecord, Transition Tr = Transition::Event>
0202     auto esConsumes(ESInputTag const& tag) {
0203       auto [index, productLabel] =
0204           recordESConsumes(Tr,
0205                            eventsetup::EventSetupRecordKey::makeKey<
0206                                std::conditional_t<std::is_same_v<ESRecord, edm::DefaultRecord>,
0207                                                   eventsetup::default_record_t<ESHandleAdapter<ESProduct>>,
0208                                                   ESRecord>>(),
0209                            eventsetup::heterocontainer::HCTypeTag::make<ESProduct>(),
0210                            tag);
0211       return ESGetToken<ESProduct, ESRecord>{static_cast<unsigned int>(Tr), index, productLabel};
0212     }
0213 
0214     template <Transition Tr = Transition::Event>
0215     [[nodiscard]] constexpr auto esConsumes() {
0216       return EDConsumerBaseESAdaptor<Tr>(this);
0217     }
0218 
0219     template <Transition Tr = Transition::Event>
0220     [[nodiscard]] auto esConsumes(ESInputTag tag) {
0221       return EDConsumerBaseWithTagESAdaptor<Tr>(this, std::move(tag));
0222     }
0223 
0224     ///Used with EventSetupRecord::doGet
0225     template <Transition Tr = Transition::Event>
0226     ESGetTokenGeneric esConsumes(eventsetup::EventSetupRecordKey const& iRecord, eventsetup::DataKey const& iKey) {
0227       auto [index, productLabel] = recordESConsumes(Tr, iRecord, iKey.type(), ESInputTag("", iKey.name().value()));
0228       return ESGetTokenGeneric(static_cast<unsigned int>(Tr), index, iRecord.type());
0229     }
0230 
0231     /**The passed functor must take the following signature
0232      *  F( ModuleConsumesInfo const& )
0233      * The functor will be called for each consumed EDProduct registered for the module
0234      */
0235     template <typename F>
0236     void consumedProducts(F&& iFunc) const;
0237 
0238     /**The passed functor must take the following signature
0239      * F(edm::ModuleConsumesMinimalESInfo const& )
0240      * The functor will be called for each consumed ESProduct registered for the module
0241      */
0242     template <typename F>
0243     void consumedESProducts(F&& iFunct) const;
0244 
0245   private:
0246     virtual void extendUpdateLookup(BranchType iBranchType, ProductResolverIndexHelper const&);
0247     virtual void registerLateConsumes(eventsetup::ESRecordsToProductResolverIndices const&) {}
0248     unsigned int recordConsumes(BranchType iBranch, TypeToGet const& iType, edm::InputTag const& iTag, bool iAlwaysGets);
0249     std::tuple<ESTokenIndex, char const*> recordESConsumes(Transition,
0250                                                            eventsetup::EventSetupRecordKey const&,
0251                                                            eventsetup::heterocontainer::HCTypeTag const&,
0252                                                            edm::ESInputTag const& iTag);
0253 
0254     void throwTypeMismatch(edm::TypeID const&, EDGetToken) const;
0255     void throwBranchMismatch(BranchType, EDGetToken) const;
0256     void throwBadToken(edm::TypeID const& iType, EDGetToken iToken) const;
0257     void throwConsumesCallAfterFrozen(TypeToGet const&, InputTag const&) const;
0258     void throwESConsumesCallAfterFrozen(eventsetup::EventSetupRecordKey const&,
0259                                         eventsetup::heterocontainer::HCTypeTag const&,
0260                                         edm::ESInputTag const&) const;
0261     void throwESConsumesInProcessBlock() const;
0262 
0263     edm::InputTag const& checkIfEmpty(edm::InputTag const& tag);
0264 
0265     virtual void doSelectInputProcessBlocks(ProductRegistry const&, ProcessBlockHelperBase const&);
0266 
0267     struct ESTokenLookupInfo {
0268       eventsetup::EventSetupRecordKey m_record;
0269       eventsetup::DataKey m_key;
0270       unsigned int m_startOfComponentName;
0271     };
0272 
0273     enum { kESLookupInfo, kESResolverIndex };
0274 
0275     using ESTokenLookupInfoContainer = edm::SoATuple<ESTokenLookupInfo, ESResolverIndex>;
0276 
0277     ESTokenLookupInfoContainer const& esTokenLookupInfoContainer() const {
0278       return esDataThatCanBeDeletedEarly_->esTokenLookupInfoContainer_;
0279     }
0280 
0281     using ESResolverIndexContainer = std::array<std::vector<ESResolverIndex>, kNumberOfEventSetupTransitions>;
0282 
0283     using ConsumesIndexConverter =
0284         std::vector<std::pair<ESResolverIndexContainer::size_type, std::vector<ESResolverIndex>::size_type>>;
0285 
0286     // This can be used to convert from an index used to access esTokenLookupInfoContainer_
0287     // into the 2 indexes needed to access esItemsToGetFromTransition_
0288     ConsumesIndexConverter const& consumesIndexConverter() const {
0289       return esDataThatCanBeDeletedEarly_->consumesIndexConverter_;
0290     }
0291 
0292     // ---------- member data --------------------------------
0293 
0294     struct TokenLookupInfo {
0295       TokenLookupInfo(edm::TypeID const& iID, ProductResolverIndex iIndex, bool skipCurrentProcess, BranchType iBranch)
0296           : m_type(iID), m_index(iIndex, skipCurrentProcess), m_branchType(iBranch) {}
0297       edm::TypeID m_type;
0298       ProductResolverIndexAndSkipBit m_index;
0299       BranchType m_branchType;
0300     };
0301 
0302     struct LabelPlacement {
0303       LabelPlacement(unsigned int iStartOfModuleLabel,
0304                      unsigned short iDeltaToProductInstance,
0305                      unsigned short iDeltaToProcessName)
0306           : m_startOfModuleLabel(iStartOfModuleLabel),
0307             m_deltaToProductInstance(iDeltaToProductInstance),
0308             m_deltaToProcessName(iDeltaToProcessName) {}
0309       unsigned int m_startOfModuleLabel;
0310       unsigned short m_deltaToProductInstance;
0311       unsigned short m_deltaToProcessName;
0312     };
0313 
0314     //define the purpose of each 'column' in m_tokenInfo
0315     enum { kLookupInfo, kAlwaysGets, kLabels, kKind };
0316     edm::SoATuple<TokenLookupInfo, bool, LabelPlacement, edm::KindOfType> m_tokenInfo;
0317 
0318     //m_tokenStartOfLabels holds the entries into this container
0319     // for each of the 3 labels needed to id the data
0320     std::vector<char> m_tokenLabels;
0321 
0322     std::array<std::vector<ProductResolverIndexAndSkipBit>, edm::NumBranchTypes> itemsToGetFromBranch_;
0323 
0324     struct ESDataThatCanBeDeletedEarly {
0325       ESTokenLookupInfoContainer esTokenLookupInfoContainer_;
0326       ConsumesIndexConverter consumesIndexConverter_;
0327     };
0328 
0329     std::unique_ptr<ESDataThatCanBeDeletedEarly> esDataThatCanBeDeletedEarly_;
0330 
0331     ESResolverIndexContainer esItemsToGetFromTransition_;
0332 
0333     std::array<std::vector<ESRecordIndex>, kNumberOfEventSetupTransitions> esRecordsToGetFromTransition_;
0334 
0335     bool frozen_;
0336     bool containsCurrentProcessAlias_;
0337   };
0338 
0339   template <typename F>
0340   void EDConsumerBase::consumedProducts(F&& iFunc) const {
0341     auto itKind = m_tokenInfo.begin<kKind>();
0342     auto itLabels = m_tokenInfo.begin<kLabels>();
0343     auto itAlways = m_tokenInfo.begin<kAlwaysGets>();
0344     for (auto itInfo = m_tokenInfo.begin<kLookupInfo>(), itEnd = m_tokenInfo.end<kLookupInfo>(); itInfo != itEnd;
0345          ++itInfo, ++itKind, ++itLabels, ++itAlways) {
0346       auto labels = *itLabels;
0347       unsigned int start = labels.m_startOfModuleLabel;
0348       auto module = &(m_tokenLabels[start]);
0349       auto productInstance = module + labels.m_deltaToProductInstance;
0350       auto process = module + labels.m_deltaToProcessName;
0351 
0352       iFunc(ModuleConsumesInfo(itInfo->m_type,
0353                                module,
0354                                productInstance,
0355                                process,
0356                                itInfo->m_branchType,
0357                                *itKind,
0358                                *itAlways,
0359                                itInfo->m_index.skipCurrentProcess()));
0360     }
0361   }
0362 
0363   template <typename F>
0364   void EDConsumerBase::consumedESProducts(F&& iFunc) const {
0365     unsigned int index = 0;
0366     auto itResolverIndex = esTokenLookupInfoContainer().begin<kESResolverIndex>();
0367     for (auto it = esTokenLookupInfoContainer().begin<kESLookupInfo>();
0368          it != esTokenLookupInfoContainer().end<kESLookupInfo>();
0369          ++it, ++index, ++itResolverIndex) {
0370       //NOTE: memory for it->m_key is passed on to call via the ModuleConsumesMinimalESInfo constructor
0371       // this avoids a copy and avoids code later in the call chain accidently using deleted memory
0372       iFunc(ModuleConsumesMinimalESInfo(static_cast<Transition>(consumesIndexConverter()[index].first),
0373                                         it->m_record,
0374                                         it->m_key,
0375                                         &(m_tokenLabels[it->m_startOfComponentName]),
0376                                         *itResolverIndex));
0377     }
0378   }
0379 
0380   template <Transition TR>
0381   class EDConsumerBaseESAdaptor {
0382   public:
0383     template <typename TYPE, typename REC>
0384     ESGetToken<TYPE, REC> consumes() {
0385       return m_consumer->template esConsumes<TYPE, REC, TR>();
0386     }
0387 
0388   private:
0389     //only EDConsumerBase is allowed to make an instance of this class
0390     friend class EDConsumerBase;
0391     EDConsumerBaseESAdaptor(EDConsumerBase* iBase) : m_consumer(iBase) {}
0392 
0393     EDConsumerBase* m_consumer;
0394   };
0395 
0396   template <Transition TR>
0397   class EDConsumerBaseWithTagESAdaptor {
0398   public:
0399     template <typename TYPE, typename REC>
0400     ESGetToken<TYPE, REC> consumes() {
0401       return m_consumer->template esConsumes<TYPE, REC, TR>(m_tag);
0402     }
0403 
0404   private:
0405     //only EDConsumerBase is allowed to make an instance of this class
0406     friend class EDConsumerBase;
0407     EDConsumerBaseWithTagESAdaptor(EDConsumerBase* iBase, ESInputTag iTag) noexcept
0408         : m_consumer(iBase), m_tag(std::move(iTag)) {}
0409 
0410     EDConsumerBase* m_consumer;
0411     ESInputTag const m_tag;
0412   };
0413 
0414   template <BranchType B>
0415   class EDConsumerBaseAdaptor {
0416   public:
0417     template <typename TYPE>
0418     EDGetTokenT<TYPE> consumes() {
0419       return m_consumer->template consumes<TYPE, B>(m_tag);
0420     }
0421 
0422   private:
0423     //only EDConsumerBase is allowed to make an instance of this class
0424     friend class EDConsumerBase;
0425     EDConsumerBaseAdaptor(EDConsumerBase* iBase, edm::InputTag iTag) noexcept
0426         : m_consumer(iBase), m_tag(std::move(iTag)) {}
0427 
0428     EDConsumerBase* m_consumer;
0429     edm::InputTag const m_tag;
0430   };
0431 
0432 }  // namespace edm
0433 
0434 #endif