Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-07-19 01:43:42

0001 #ifndef FWCore_Framework_PrincipalGetAdapter_h
0002 #define FWCore_Framework_PrincipalGetAdapter_h
0003 
0004 // -*- C++ -*-
0005 //
0006 
0007 // Class  :     PrincipalGetAdapter
0008 //
0009 /**\class PrincipalGetAdapter PrincipalGetAdapter.h FWCore/Framework/interface/PrincipalGetAdapter.h
0010 
0011 Description: This is the implementation for accessing EDProducts and 
0012 inserting new EDProducts.
0013 
0014 Usage:
0015 
0016 Getting Data
0017 
0018 The edm::PrincipalGetAdapter class provides many 'get*" methods for getting data
0019 it contains.  
0020 
0021 The primary method for getting data is to use getByLabel(). The labels are
0022 the label of the module assigned in the configuration file and the 'product
0023 instance label' (which can be omitted in the case the 'product instance label'
0024 is the default value).  The C++ type of the product plus the two labels
0025 uniquely identify a product in the PrincipalGetAdapter.
0026 
0027 We use an event in the examples, but a run or a luminosity block can also
0028 hold products.
0029 
0030 \code
0031 edm::Handle<AppleCollection> apples;
0032 event.getByLabel("tree",apples);
0033 \endcode
0034 
0035 \code
0036 edm::Handle<FruitCollection> fruits;
0037 event.getByLabel("market", "apple", fruits);
0038 \endcode
0039 
0040 
0041 Putting Data
0042 
0043 \code
0044   
0045 //fill the collection
0046 ...
0047 event.put(std::make_unique<AppleCollection>());
0048 \endcode
0049 
0050 \code
0051 
0052 //fill the collection
0053 ...
0054 event.put(std::make_unique<FruitCollection>());
0055 \endcode
0056 
0057 
0058 Getting a reference to a product before that product is put into the
0059 event/lumiBlock/run.
0060 NOTE: The edm::RefProd returned will not work until after the
0061 edm::PrincipalGetAdapter has been committed (which happens after the
0062 EDProducer::produce method has ended)
0063 \code
0064 auto pApples = std::make_unique<AppleCollection>();
0065 
0066 edm::RefProd<AppleCollection> refApples = event.getRefBeforePut<AppleCollection>();
0067 
0068 //do loop and fill collection
0069 for(unsigned int index = 0; .....) {
0070 ....
0071 apples->push_back(Apple(...));
0072   
0073 //create an edm::Ref to the new object
0074 edm::Ref<AppleCollection> ref(refApples, index);
0075 ....
0076 }
0077 \endcode
0078 
0079 */
0080 /*----------------------------------------------------------------------
0081 
0082 ----------------------------------------------------------------------*/
0083 #include <cassert>
0084 #include <typeinfo>
0085 #include <string>
0086 #include <vector>
0087 #include <type_traits>
0088 
0089 #include "DataFormats/Common/interface/EDProductfwd.h"
0090 #include "DataFormats/Provenance/interface/ProvenanceFwd.h"
0091 #include "FWCore/Framework/interface/Frameworkfwd.h"
0092 
0093 #include "DataFormats/Common/interface/traits.h"
0094 
0095 #include "DataFormats/Common/interface/BasicHandle.h"
0096 
0097 #include "DataFormats/Common/interface/ConvertHandle.h"
0098 
0099 #include "DataFormats/Common/interface/Handle.h"
0100 
0101 #include "DataFormats/Common/interface/Wrapper.h"
0102 
0103 #include "FWCore/Utilities/interface/InputTag.h"
0104 #include "FWCore/Utilities/interface/EDGetToken.h"
0105 #include "FWCore/Utilities/interface/EDPutToken.h"
0106 #include "FWCore/Utilities/interface/ProductKindOfType.h"
0107 #include "FWCore/Utilities/interface/ProductLabels.h"
0108 #include "FWCore/Utilities/interface/propagate_const.h"
0109 #include "FWCore/Utilities/interface/Transition.h"
0110 
0111 namespace edm {
0112 
0113   class ModuleCallingContext;
0114   class SharedResourcesAcquirer;
0115   class ProducerBase;
0116 
0117   namespace principal_get_adapter_detail {
0118     void throwOnPutOfNullProduct(char const* principalType,
0119                                  TypeID const& productType,
0120                                  std::string const& productInstanceName);
0121     void throwOnPutOfUninitializedToken(char const* principalType, std::type_info const& productType);
0122     void throwOnPutOfWrongType(std::type_info const& wrongType, TypeID const& rightType);
0123     void throwOnPrematureRead(char const* principalType,
0124                               TypeID const& productType,
0125                               std::string const& moduleLabel,
0126                               std::string const& productInstanceName);
0127     void throwOnPrematureRead(char const* principalType, TypeID const& productType);
0128 
0129     void throwOnPrematureRead(char const* principalType, TypeID const& productType, EDGetToken);
0130 
0131   }  // namespace principal_get_adapter_detail
0132   class PrincipalGetAdapter {
0133   public:
0134     PrincipalGetAdapter(Principal const& pcpl, ModuleDescription const& md, bool isComplete);
0135 
0136     ~PrincipalGetAdapter();
0137 
0138     PrincipalGetAdapter(PrincipalGetAdapter const&) = delete;             // Disallow copying and moving
0139     PrincipalGetAdapter& operator=(PrincipalGetAdapter const&) = delete;  // Disallow copying and moving
0140 
0141     //size_t size() const;
0142 
0143     void setConsumer(EDConsumerBase const* iConsumer) { consumer_ = iConsumer; }
0144     EDConsumerBase const* getConsumer() const { return consumer_; }
0145 
0146     void setSharedResourcesAcquirer(SharedResourcesAcquirer* iSra) { resourcesAcquirer_ = iSra; }
0147     SharedResourcesAcquirer* getSharedResourcesAcquirer() const { return resourcesAcquirer_; }
0148 
0149     void setProducer(ProducerBase const* iProd) { prodBase_ = iProd; }
0150 
0151     size_t numberOfProductsConsumed() const;
0152 
0153     bool isComplete() const { return isComplete_; }
0154 
0155     template <typename PROD>
0156     bool checkIfComplete() const;
0157 
0158     Transition transition() const;
0159 
0160     template <typename PROD>
0161     void getManyByType(std::vector<Handle<PROD> >& results, ModuleCallingContext const* mcc) const;
0162 
0163     ProcessHistory const& processHistory() const;
0164 
0165     Principal const& principal() const { return principal_; }
0166 
0167     BranchDescription const& getBranchDescription(TypeID const& type, std::string const& productInstanceName) const;
0168 
0169     EDPutToken::value_type getPutTokenIndex(TypeID const& type, std::string const& productInstanceName) const;
0170 
0171     TypeID const& getTypeIDForPutTokenIndex(EDPutToken::value_type index) const;
0172     std::string const& productInstanceLabel(EDPutToken) const;
0173     typedef std::vector<BasicHandle> BasicHandleVec;
0174 
0175     BranchDescription const& getBranchDescription(unsigned int iPutTokenIndex) const;
0176     ProductID const& getProductID(unsigned int iPutTokenIndex) const;
0177     ModuleDescription const& moduleDescription() const { return md_; }
0178 
0179     std::vector<edm::ProductResolverIndex> const& putTokenIndexToProductResolverIndex() const;
0180 
0181     //uses the EDPutToken index
0182     std::vector<bool> const& recordProvenanceList() const;
0183     //------------------------------------------------------------
0184     // Protected functions.
0185     //
0186 
0187     // The following 'get' functions serve to isolate the PrincipalGetAdapter class
0188     // from the Principal class.
0189 
0190     BasicHandle getByLabel_(TypeID const& tid, InputTag const& tag, ModuleCallingContext const* mcc) const;
0191 
0192     BasicHandle getByLabel_(TypeID const& tid,
0193                             std::string const& label,
0194                             std::string const& instance,
0195                             std::string const& process,
0196                             ModuleCallingContext const* mcc) const;
0197 
0198     BasicHandle getByToken_(TypeID const& id,
0199                             KindOfType kindOfType,
0200                             EDGetToken token,
0201                             ModuleCallingContext const* mcc) const;
0202 
0203     BasicHandle getMatchingSequenceByLabel_(TypeID const& typeID,
0204                                             InputTag const& tag,
0205                                             ModuleCallingContext const* mcc) const;
0206 
0207     BasicHandle getMatchingSequenceByLabel_(TypeID const& typeID,
0208                                             std::string const& label,
0209                                             std::string const& instance,
0210                                             std::string const& process,
0211                                             ModuleCallingContext const* mcc) const;
0212 
0213     void getManyByType_(TypeID const& tid, BasicHandleVec& results, ModuleCallingContext const* mcc) const;
0214 
0215     // Also isolates the PrincipalGetAdapter class
0216     // from the Principal class.
0217     EDProductGetter const* prodGetter() const;
0218 
0219     void labelsForToken(EDGetToken const& iToken, ProductLabels& oLabels) const;
0220 
0221     unsigned int processBlockIndex(std::string const& processName) const;
0222 
0223   private:
0224     // Is this an Event, a LuminosityBlock, or a Run.
0225     BranchType const& branchType() const;
0226 
0227     BasicHandle makeFailToGetException(KindOfType, TypeID const&, EDGetToken) const;
0228 
0229     void throwAmbiguousException(TypeID const& productType, EDGetToken token) const;
0230 
0231     void throwUnregisteredPutException(TypeID const& type, std::string const& productInstanceLabel) const;
0232 
0233   private:
0234     //------------------------------------------------------------
0235     // Data members
0236     //
0237 
0238     // Each PrincipalGetAdapter must have an associated Principal, used as the
0239     // source of all 'gets' and the target of 'puts'.
0240     Principal const& principal_;
0241 
0242     // Each PrincipalGetAdapter must have a description of the module executing the
0243     // "transaction" which the PrincipalGetAdapter represents.
0244     ModuleDescription const& md_;
0245 
0246     EDConsumerBase const* consumer_;
0247     SharedResourcesAcquirer* resourcesAcquirer_;  // We do not use propagate_const because the acquirer is itself mutable.
0248     ProducerBase const* prodBase_ = nullptr;
0249     bool isComplete_;
0250   };
0251 
0252   template <typename PROD>
0253   inline std::ostream& operator<<(std::ostream& os, Handle<PROD> const& h) {
0254     os << h.product() << " " << h.provenance() << " " << h.id();
0255     return os;
0256   }
0257 
0258   //------------------------------------------------------------
0259   // Metafunction support for compile-time selection of code used in
0260   // PrincipalGetAdapter::put member template.
0261   //
0262 
0263   // has_postinsert is a metafunction of one argument, the type T.  As
0264   // with many metafunctions, it is implemented as a class with a data
0265   // member 'value', which contains the value 'returned' by the
0266   // metafunction.
0267   //
0268   // has_postinsert<T>::value is 'true' if T has the post_insert
0269   // member function (with the right signature), and 'false' if T has
0270   // no such member function.
0271 
0272   namespace detail {
0273     using no_tag = std::false_type;  // type indicating FALSE
0274     using yes_tag = std::true_type;  // type indicating TRUE
0275 
0276     // Definitions forthe following struct and function templates are
0277     // not needed; we only require the declarations.
0278     template <typename T, void (T::*)()>
0279     struct postinsert_function;
0280     template <typename T>
0281     no_tag has_postinsert_helper(...);
0282     template <typename T>
0283     yes_tag has_postinsert_helper(postinsert_function<T, &T::post_insert>* p);
0284 
0285     template <typename T>
0286     struct has_postinsert {
0287       static constexpr bool value = std::is_same<decltype(has_postinsert_helper<T>(nullptr)), yes_tag>::value &&
0288                                     !std::is_base_of<DoNotSortUponInsertion, T>::value;
0289     };
0290 
0291   }  // namespace detail
0292 
0293   //------------------------------------------------------------
0294 
0295   // The following function objects are used by Event::put, under the
0296   // control of a metafunction if, to either call the given object's
0297   // post_insert function (if it has one), or to do nothing (if it
0298   // does not have a post_insert function).
0299   template <typename T>
0300   struct DoPostInsert {
0301     void operator()(T* p) const { p->post_insert(); }
0302   };
0303 
0304   template <typename T>
0305   struct DoNotPostInsert {
0306     void operator()(T*) const {}
0307   };
0308 
0309   // Implementation of  PrincipalGetAdapter  member templates. See  PrincipalGetAdapter.cc for the
0310   // implementation of non-template members.
0311   //
0312 
0313   template <typename PROD>
0314   inline bool PrincipalGetAdapter::checkIfComplete() const {
0315     return isComplete() || !detail::has_mergeProduct_function<PROD>::value;
0316   }
0317 
0318   template <typename PROD>
0319   inline void PrincipalGetAdapter::getManyByType(std::vector<Handle<PROD> >& results,
0320                                                  ModuleCallingContext const* mcc) const {
0321     BasicHandleVec bhv;
0322     this->getManyByType_(TypeID(typeid(PROD)), bhv, mcc);
0323 
0324     // Go through the returned handles; for each element,
0325     //   1. create a Handle<PROD> and
0326     //
0327     // This function presents an exception safety difficulty. If an
0328     // exception is thrown when converting a handle, the "got
0329     // products" record will be wrong.
0330     //
0331     // Since EDProducers are not allowed to use this function,
0332     // the problem does not seem too severe.
0333     //
0334     // Question: do we even need to keep track of the "got products"
0335     // for this function, since it is *not* to be used by EDProducers?
0336     std::vector<Handle<PROD> > products;
0337 
0338     typename BasicHandleVec::iterator it = bhv.begin();
0339     typename BasicHandleVec::iterator end = bhv.end();
0340 
0341     while (it != end) {
0342       products.push_back(convert_handle<PROD>(std::move(*it)));
0343       ++it;
0344     }
0345     results.swap(products);
0346   }
0347 }  // namespace edm
0348 #endif