Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:12:05

0001 #ifndef FWCore_Framework_ProcessBlock_h
0002 #define FWCore_Framework_ProcessBlock_h
0003 
0004 /** \class edm::ProcessBlock
0005 
0006 \author W. David Dagenhart, created 19 March, 2020
0007 
0008 */
0009 
0010 #include "DataFormats/Common/interface/Handle.h"
0011 #include "DataFormats/Common/interface/Wrapper.h"
0012 #include "DataFormats/Common/interface/WrapperBase.h"
0013 #include "FWCore/Framework/interface/PrincipalGetAdapter.h"
0014 #include "FWCore/Utilities/interface/EDGetToken.h"
0015 #include "FWCore/Utilities/interface/EDPutToken.h"
0016 #include "FWCore/Utilities/interface/ProductResolverIndex.h"
0017 #include "FWCore/Utilities/interface/propagate_const.h"
0018 
0019 #include <memory>
0020 #include <type_traits>
0021 #include <utility>
0022 #include <vector>
0023 
0024 namespace edm {
0025 
0026   class ModuleCallingContext;
0027   class ModuleDescription;
0028   class ProcessBlockPrincipal;
0029   class ProducerBase;
0030 
0031   namespace stream {
0032     template <typename T>
0033     class ProducingModuleAdaptorBase;
0034   }
0035 
0036   class ProcessBlock {
0037   public:
0038     ProcessBlock(ProcessBlockPrincipal const&, ModuleDescription const&, ModuleCallingContext const*, bool isAtEnd);
0039 
0040     template <typename PROD>
0041     bool getByToken(EDGetToken token, Handle<PROD>& result) const;
0042 
0043     template <typename PROD>
0044     bool getByToken(EDGetTokenT<PROD> token, Handle<PROD>& result) const;
0045 
0046     template <typename PROD>
0047     Handle<PROD> getHandle(EDGetTokenT<PROD> token) const;
0048 
0049     template <typename PROD>
0050     PROD const& get(EDGetTokenT<PROD> token) const noexcept(false);
0051 
0052     //Used in conjunction with EDGetToken
0053     void setConsumer(EDConsumerBase const* iConsumer) { provRecorder_.setConsumer(iConsumer); }
0054 
0055     void setProducer(ProducerBase const* iProducer);
0056 
0057     /**If you are caching data from the ProcessBlock, you should also keep
0058      this number.  If this number changes then you know that
0059      the data you have cached is invalid.
0060      The value of '0' will never be returned so you can use that to
0061      denote that you have not yet checked the value.
0062      */
0063     using CacheIdentifier_t = unsigned long;
0064     CacheIdentifier_t cacheIdentifier() const;
0065 
0066     template <typename PROD>
0067     void put(EDPutTokenT<PROD> token, std::unique_ptr<PROD> product);
0068 
0069     template <typename PROD>
0070     void put(EDPutToken token, std::unique_ptr<PROD> product);
0071 
0072     template <typename PROD, typename... Args>
0073     void emplace(EDPutTokenT<PROD> token, Args&&... args);
0074 
0075     template <typename PROD, typename... Args>
0076     void emplace(EDPutToken token, Args&&... args);
0077 
0078     ModuleCallingContext const* moduleCallingContext() const { return moduleCallingContext_; }
0079 
0080     std::string const& processName() const;
0081 
0082   private:
0083     ProcessBlockPrincipal const& processBlockPrincipal() const;
0084 
0085     template <typename PROD>
0086     void putImpl(EDPutToken::value_type token, std::unique_ptr<PROD> product);
0087 
0088     template <typename PROD, typename... Args>
0089     void emplaceImpl(EDPutToken::value_type token, Args&&... args);
0090 
0091     friend class ProducerBase;
0092     template <typename T>
0093     friend class stream::ProducingModuleAdaptorBase;
0094 
0095     void commit_(std::vector<edm::ProductResolverIndex> const& iShouldPut);
0096 
0097     using ProductPtrVec = std::vector<edm::propagate_const<std::unique_ptr<WrapperBase>>>;
0098     ProductPtrVec& putProducts() { return putProducts_; }
0099     ProductPtrVec const& putProducts() const { return putProducts_; }
0100 
0101     PrincipalGetAdapter provRecorder_;
0102     ProductPtrVec putProducts_;
0103     ModuleCallingContext const* moduleCallingContext_;
0104   };
0105 
0106   template <typename PROD>
0107   bool ProcessBlock::getByToken(EDGetToken token, Handle<PROD>& result) const {
0108     result.clear();
0109     BasicHandle bh = provRecorder_.getByToken_(TypeID(typeid(PROD)), PRODUCT_TYPE, token, moduleCallingContext_);
0110     result = convert_handle<PROD>(std::move(bh));  // throws on conversion error
0111     if (result.failedToGet()) {
0112       return false;
0113     }
0114     return true;
0115   }
0116 
0117   template <typename PROD>
0118   bool ProcessBlock::getByToken(EDGetTokenT<PROD> token, Handle<PROD>& result) const {
0119     result.clear();
0120     BasicHandle bh = provRecorder_.getByToken_(TypeID(typeid(PROD)), PRODUCT_TYPE, token, moduleCallingContext_);
0121     result = convert_handle<PROD>(std::move(bh));  // throws on conversion error
0122     if (result.failedToGet()) {
0123       return false;
0124     }
0125     return true;
0126   }
0127 
0128   template <typename PROD>
0129   Handle<PROD> ProcessBlock::getHandle(EDGetTokenT<PROD> token) const {
0130     BasicHandle bh = provRecorder_.getByToken_(TypeID(typeid(PROD)), PRODUCT_TYPE, token, moduleCallingContext_);
0131     return convert_handle<PROD>(std::move(bh));
0132   }
0133 
0134   template <typename PROD>
0135   PROD const& ProcessBlock::get(EDGetTokenT<PROD> token) const noexcept(false) {
0136     BasicHandle bh = provRecorder_.getByToken_(TypeID(typeid(PROD)), PRODUCT_TYPE, token, moduleCallingContext_);
0137     return *convert_handle<PROD>(std::move(bh));
0138   }
0139 
0140   template <typename PROD>
0141   void ProcessBlock::put(EDPutTokenT<PROD> token, std::unique_ptr<PROD> product) {
0142     if (UNLIKELY(product.get() == 0)) {  // null pointer is illegal
0143       TypeID typeID(typeid(PROD));
0144       principal_get_adapter_detail::throwOnPutOfNullProduct(
0145           "ProcessBlock", typeID, provRecorder_.productInstanceLabel(token));
0146     }
0147     if (UNLIKELY(token.isUninitialized())) {
0148       principal_get_adapter_detail::throwOnPutOfUninitializedToken("ProcessBlock", typeid(PROD));
0149     }
0150     putImpl(token.index(), std::move(product));
0151   }
0152 
0153   template <typename PROD>
0154   void ProcessBlock::put(EDPutToken token, std::unique_ptr<PROD> product) {
0155     if (UNLIKELY(product.get() == 0)) {  // null pointer is illegal
0156       TypeID typeID(typeid(PROD));
0157       principal_get_adapter_detail::throwOnPutOfNullProduct(
0158           "ProcessBlock", typeID, provRecorder_.productInstanceLabel(token));
0159     }
0160     if (UNLIKELY(token.isUninitialized())) {
0161       principal_get_adapter_detail::throwOnPutOfUninitializedToken("ProcessBlock", typeid(PROD));
0162     }
0163     if (UNLIKELY(provRecorder_.getTypeIDForPutTokenIndex(token.index()) != TypeID{typeid(PROD)})) {
0164       principal_get_adapter_detail::throwOnPutOfWrongType(typeid(PROD),
0165                                                           provRecorder_.getTypeIDForPutTokenIndex(token.index()));
0166     }
0167     putImpl(token.index(), std::move(product));
0168   }
0169 
0170   template <typename PROD, typename... Args>
0171   void ProcessBlock::emplace(EDPutTokenT<PROD> token, Args&&... args) {
0172     if (UNLIKELY(token.isUninitialized())) {
0173       principal_get_adapter_detail::throwOnPutOfUninitializedToken("ProcessBlock", typeid(PROD));
0174     }
0175     emplaceImpl<PROD>(token.index(), std::forward<Args>(args)...);
0176   }
0177 
0178   template <typename PROD, typename... Args>
0179   void ProcessBlock::emplace(EDPutToken token, Args&&... args) {
0180     if (UNLIKELY(token.isUninitialized())) {
0181       principal_get_adapter_detail::throwOnPutOfUninitializedToken("ProcessBlock", typeid(PROD));
0182     }
0183     if (UNLIKELY(provRecorder_.getTypeIDForPutTokenIndex(token.index()) != TypeID{typeid(PROD)})) {
0184       principal_get_adapter_detail::throwOnPutOfWrongType(typeid(PROD),
0185                                                           provRecorder_.getTypeIDForPutTokenIndex(token.index()));
0186     }
0187     emplaceImpl<PROD>(token.index(), std::forward<Args>(args)...);
0188   }
0189 
0190   template <typename PROD>
0191   void ProcessBlock::putImpl(EDPutToken::value_type index, std::unique_ptr<PROD> product) {
0192     // The following will call post_insert if T has such a function,
0193     // and do nothing if T has no such function.
0194     std::conditional_t<detail::has_postinsert<PROD>::value, DoPostInsert<PROD>, DoNotPostInsert<PROD>> maybe_inserter;
0195     maybe_inserter(product.get());
0196 
0197     assert(index < putProducts().size());
0198 
0199     std::unique_ptr<Wrapper<PROD>> wp(new Wrapper<PROD>(std::move(product)));
0200     putProducts()[index] = std::move(wp);
0201   }
0202 
0203   template <typename PROD, typename... Args>
0204   void ProcessBlock::emplaceImpl(EDPutToken::value_type index, Args&&... args) {
0205     assert(index < putProducts().size());
0206 
0207     std::unique_ptr<Wrapper<PROD>> wp(new Wrapper<PROD>(WrapperBase::Emplace{}, std::forward<Args>(args)...));
0208 
0209     // The following will call post_insert if T has such a function,
0210     // and do nothing if T has no such function.
0211     std::conditional_t<detail::has_postinsert<PROD>::value, DoPostInsert<PROD>, DoNotPostInsert<PROD>> maybe_inserter;
0212     maybe_inserter(&(wp->bareProduct()));
0213 
0214     putProducts()[index] = std::move(wp);
0215   }
0216 
0217   template <typename T>
0218   T const& get(ProcessBlock const& processBlock, EDGetToken const& token) {
0219     Handle<T> handle;
0220     processBlock.getByToken(token, handle);
0221     // throw if the handle is not valid
0222     return *handle.product();
0223   }
0224 
0225   template <typename T>
0226   T const& get(ProcessBlock const& processBlock, EDGetTokenT<T> const& token) {
0227     Handle<T> handle;
0228     processBlock.getByToken(token, handle);
0229     // throw if the handle is not valid
0230     return *handle.product();
0231   }
0232 
0233 }  // namespace edm
0234 #endif  // FWCore_Framework_ProcessBlock_h