Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 13:27:44

0001 #ifndef FWCore_Framework_ESProducer_h
0002 #define FWCore_Framework_ESProducer_h
0003 // -*- C++ -*-
0004 //
0005 // Package:     Framework
0006 // Class  :     ESProducer
0007 //
0008 /**\class edm::ESProducer
0009 
0010  Description: An EventSetup algorithmic Provider that encapsulates the algorithm as a member method
0011 
0012  Usage:
0013     Inheriting from this class is the simplest way to create an algorithm which gets called when a new
0014   data item is needed for the EventSetup.  This class is designed to call a member method of inheriting
0015   classes each time the algorithm needs to be run.  (A more flexible system in which the algorithms can be
0016   set at run-time instead of compile time can be obtained by inheriting from ESProxyFactoryProducer instead.)
0017 
0018     If only one algorithm is being encapsulated then the user needs to
0019       1) add a method name 'produce' to the class.  The 'produce' takes as its argument a const reference
0020          to the record that is to hold the data item being produced.  If only one data item is being produced,
0021          the 'produce' method must return either an 'std::unique_ptr' or 'std::shared_ptr' to the object being
0022          produced.  (The choice depends on if the EventSetup or the ESProducer is managing the lifetime of
0023          the object).  If multiple items are being Produced they the 'produce' method must return an
0024          ESProducts<> object which holds all of the items.
0025       2) add 'setWhatProduced(this);' to their classes constructor
0026 
0027 Example: one algorithm creating only one object
0028 \code
0029     class FooProd : public edm::ESProducer {
0030        std::unique_ptr<Foo> produce(const FooRecord&);
0031        ...
0032     };
0033     FooProd::FooProd(const edm::ParameterSet&) {
0034        setWhatProduced(this);
0035        ...
0036     }
0037 \endcode
0038 Example: one algorithm creating two objects
0039 \code
0040    class FoosProd : public edm::ESProducer {
0041       edm::ESProducts<std::unique_ptr<Foo1>, std::unique_ptr<Foo2>> produce(const FooRecord&);
0042       ...
0043    };
0044 \endcode
0045 
0046   If multiple algorithms are being encapsulated then
0047       1) like 1 above except the methods can have any names you want
0048       2) add 'setWhatProduced(this, &<class name>::<method name>);' for each method in the class' constructor
0049    NOTE: the algorithms can put data into the same record or into different records
0050 
0051 Example: two algorithms each creating only one objects
0052 \code
0053    class FooBarProd : public edm::eventsetup::ESProducer {
0054       std::unique_ptr<Foo> produceFoo(const FooRecord&);
0055       std::unique_ptr<Bar> produceBar(const BarRecord&);
0056       ...
0057    };
0058    FooBarProd::FooBarProd(const edm::ParameterSet&) {
0059       setWhatProduced(this,&FooBarProd::produceFoo);
0060       setWhatProduced(this,&FooBarProd::produceBar);
0061       ...
0062    }
0063 \endcode
0064 
0065 */
0066 //
0067 // Author:      Chris Jones
0068 // Created:     Thu Apr  7 17:08:14 CDT 2005
0069 //
0070 
0071 // system include files
0072 #include <memory>
0073 #include <string>
0074 #include <optional>
0075 
0076 // user include files
0077 #include "FWCore/Framework/interface/ESConsumesCollector.h"
0078 #include "FWCore/Framework/interface/es_impl/MayConsumeChooserBase.h"
0079 #include "FWCore/Framework/interface/ESProxyFactoryProducer.h"
0080 #include "FWCore/Framework/interface/ProxyArgumentFactoryTemplate.h"
0081 
0082 #include "FWCore/Framework/interface/CallbackProxy.h"
0083 #include "FWCore/Framework/interface/Callback.h"
0084 #include "FWCore/Framework/interface/produce_helpers.h"
0085 #include "FWCore/Framework/interface/eventsetup_dependsOn.h"
0086 #include "FWCore/Framework/interface/es_Label.h"
0087 
0088 #include "FWCore/Framework/interface/SharedResourcesAcquirer.h"
0089 
0090 // forward declarations
0091 namespace edm {
0092   namespace eventsetup {
0093 
0094     class ESRecordsToProxyIndices;
0095     //used by ESProducer to create the proper Decorator based on the
0096     //  argument type passed.  The default it to just 'pass through'
0097     //  the argument as the decorator itself
0098     template <typename T, typename TRecord, typename TDecorator>
0099     inline const TDecorator& createDecoratorFrom(T*, const TRecord*, const TDecorator& iDec) {
0100       return iDec;
0101     }
0102   }  // namespace eventsetup
0103 
0104   class ESProducer : public ESProxyFactoryProducer {
0105   public:
0106     ESProducer();
0107     ~ESProducer() noexcept(false) override;
0108     ESProducer(const ESProducer&) = delete;                   // stop default
0109     ESProducer const& operator=(const ESProducer&) = delete;  // stop default
0110 
0111     void updateLookup(eventsetup::ESRecordsToProxyIndices const&) final;
0112     ESProxyIndex const* getTokenIndices(unsigned int iIndex) const {
0113       if (itemsToGetFromRecords_.empty()) {
0114         return nullptr;
0115       }
0116       return (itemsToGetFromRecords_[iIndex].empty()) ? static_cast<ESProxyIndex const*>(nullptr)
0117                                                       : &(itemsToGetFromRecords_[iIndex].front());
0118     }
0119     ESRecordIndex const* getTokenRecordIndices(unsigned int iIndex) const {
0120       if (recordsUsedDuringGet_.empty()) {
0121         return nullptr;
0122       }
0123       return (recordsUsedDuringGet_[iIndex].empty()) ? static_cast<ESRecordIndex const*>(nullptr)
0124                                                      : &(recordsUsedDuringGet_[iIndex].front());
0125     }
0126     size_t numberOfTokenIndices(unsigned int iIndex) const {
0127       if (itemsToGetFromRecords_.empty()) {
0128         return 0;
0129       }
0130       return itemsToGetFromRecords_[iIndex].size();
0131     }
0132 
0133     bool hasMayConsumes() const noexcept { return hasMayConsumes_; }
0134 
0135     template <typename Record>
0136     std::optional<std::vector<ESProxyIndex>> updateFromMayConsumes(unsigned int iIndex, const Record& iRecord) const {
0137       if (not hasMayConsumes()) {
0138         return {};
0139       }
0140       std::vector<ESProxyIndex> ret = itemsToGetFromRecords_[iIndex];
0141       auto const info = consumesInfos_[iIndex].get();
0142       for (size_t i = 0; i < info->size(); ++i) {
0143         auto chooserBase = (*info)[i].chooser_.get();
0144         if (chooserBase) {
0145           auto chooser = static_cast<eventsetup::impl::MayConsumeChooserBase<Record>*>(chooserBase);
0146           ret[i] = chooser->makeChoice(iRecord);
0147         }
0148       }
0149       return ret;
0150     }
0151 
0152     SerialTaskQueueChain& queue() { return acquirer_.serialQueueChain(); }
0153 
0154   protected:
0155     /** Specify the names of the shared resources used by this ESProducer */
0156     void usesResources(std::vector<std::string> const&);
0157 
0158     /** \param iThis the 'this' pointer to an inheriting class instance
0159         The method determines the Record argument and return value of the 'produce'
0160         method in order to do the registration with the EventSetup
0161     */
0162     template <typename T>
0163     auto setWhatProduced(T* iThis, const es::Label& iLabel = {}) {
0164       return setWhatProduced(iThis, &T::produce, iLabel);
0165     }
0166 
0167     template <typename T>
0168     auto setWhatProduced(T* iThis, const char* iLabel) {
0169       return setWhatProduced(iThis, es::Label(iLabel));
0170     }
0171     template <typename T>
0172     auto setWhatProduced(T* iThis, const std::string& iLabel) {
0173       return setWhatProduced(iThis, es::Label(iLabel));
0174     }
0175 
0176     template <typename T, typename TDecorator>
0177     auto setWhatProduced(T* iThis, const TDecorator& iDec, const es::Label& iLabel = {}) {
0178       return setWhatProduced(iThis, &T::produce, iDec, iLabel);
0179     }
0180     /** \param iThis the 'this' pointer to an inheriting class instance
0181         \param iMethod a member method of then inheriting class
0182         The method determines the Record argument and return value of the iMethod argument
0183         method in order to do the registration with the EventSetup
0184     */
0185     template <typename T, typename TReturn, typename TRecord>
0186     auto setWhatProduced(T* iThis, TReturn (T ::*iMethod)(const TRecord&), const es::Label& iLabel = {}) {
0187       return setWhatProduced(iThis, iMethod, eventsetup::CallbackSimpleDecorator<TRecord>(), iLabel);
0188     }
0189     /** \param iThis the 'this' pointer to an inheriting class instance
0190         \param iMethod a member method of then inheriting class
0191         \param iDecorator a class with 'pre'&'post' methods which are placed around the method call
0192         The method determines the Record argument and return value of the iMethod argument
0193         method in order to do the registration with the EventSetup
0194     */
0195     template <typename T, typename TReturn, typename TRecord, typename TArg>
0196     ESConsumesCollectorT<TRecord> setWhatProduced(T* iThis,
0197                                                   TReturn (T ::*iMethod)(const TRecord&),
0198                                                   const TArg& iDec,
0199                                                   const es::Label& iLabel = {}) {
0200       const auto id = consumesInfos_.size();
0201       using DecoratorType = typename eventsetup::DecoratorFromArg<T, TRecord, TArg>::Decorator_t;
0202       using CallbackType = eventsetup::Callback<T, TReturn, TRecord, DecoratorType>;
0203       unsigned int iovIndex = 0;  // Start with 0, but later will cycle through all of them
0204       auto temp = std::make_shared<CallbackType>(
0205           iThis, iMethod, id, createDecoratorFrom(iThis, static_cast<const TRecord*>(nullptr), iDec));
0206       auto callback =
0207           std::make_shared<std::pair<unsigned int, std::shared_ptr<CallbackType>>>(iovIndex, std::move(temp));
0208       registerProducts(std::move(callback),
0209                        static_cast<const typename eventsetup::produce::product_traits<TReturn>::type*>(nullptr),
0210                        static_cast<const TRecord*>(nullptr),
0211                        iLabel);
0212       consumesInfos_.push_back(std::make_unique<ESConsumesInfo>());
0213       return ESConsumesCollectorT<TRecord>(consumesInfos_.back().get(), id);
0214     }
0215 
0216   private:
0217     template <typename CallbackT, typename TList, typename TRecord>
0218     void registerProducts(std::shared_ptr<std::pair<unsigned int, std::shared_ptr<CallbackT>>> iCallback,
0219                           const TList*,
0220                           const TRecord* iRecord,
0221                           const es::Label& iLabel) {
0222       registerProduct(iCallback, static_cast<const typename TList::tail_type*>(nullptr), iRecord, iLabel);
0223       registerProducts(std::move(iCallback), static_cast<const typename TList::head_type*>(nullptr), iRecord, iLabel);
0224     }
0225 
0226     template <typename CallbackT, typename TRecord>
0227     void registerProducts(std::shared_ptr<std::pair<unsigned int, std::shared_ptr<CallbackT>>>,
0228                           const eventsetup::produce::Null*,
0229                           const TRecord*,
0230                           const es::Label&) {
0231       //do nothing
0232     }
0233 
0234     template <typename CallbackT, typename TProduct, typename TRecord>
0235     void registerProduct(std::shared_ptr<std::pair<unsigned int, std::shared_ptr<CallbackT>>> iCallback,
0236                          const TProduct*,
0237                          const TRecord*,
0238                          const es::Label& iLabel) {
0239       using ProxyType = eventsetup::CallbackProxy<CallbackT, TRecord, TProduct>;
0240       using FactoryType = eventsetup::ProxyArgumentFactoryTemplate<ProxyType, CallbackT>;
0241       registerFactory(std::make_unique<FactoryType>(std::move(iCallback)), iLabel.default_);
0242     }
0243 
0244     template <typename CallbackT, typename TProduct, typename TRecord, int IIndex>
0245     void registerProduct(std::shared_ptr<std::pair<unsigned int, std::shared_ptr<CallbackT>>> iCallback,
0246                          const es::L<TProduct, IIndex>*,
0247                          const TRecord*,
0248                          const es::Label& iLabel) {
0249       if (iLabel.labels_.size() <= IIndex || iLabel.labels_[IIndex] == es::Label::def()) {
0250         Exception::throwThis(errors::Configuration,
0251                              "Unnamed Label\nthe index ",
0252                              IIndex,
0253                              " was never assigned a name in the 'setWhatProduced' method");
0254       }
0255       using ProxyType = eventsetup::CallbackProxy<CallbackT, TRecord, es::L<TProduct, IIndex>>;
0256       using FactoryType = eventsetup::ProxyArgumentFactoryTemplate<ProxyType, CallbackT>;
0257       registerFactory(std::make_unique<FactoryType>(std::move(iCallback)), iLabel.labels_[IIndex]);
0258     }
0259 
0260     std::vector<std::unique_ptr<ESConsumesInfo>> consumesInfos_;
0261     std::vector<std::vector<ESProxyIndex>> itemsToGetFromRecords_;
0262     //need another structure to say which record to get the data from in
0263     // order to make prefetching work
0264     std::vector<std::vector<ESRecordIndex>> recordsUsedDuringGet_;
0265 
0266     SharedResourcesAcquirer acquirer_;
0267     std::unique_ptr<std::vector<std::string>> sharedResourceNames_;
0268     bool hasMayConsumes_ = false;
0269   };
0270 }  // namespace edm
0271 #endif