Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2023-04-21 01:53:19

0001 // -*- C++ -*-
0002 #ifndef FWCore_Framework_ESProducerExternalWork_h
0003 #define FWCore_Framework_ESProducerExternalWork_h
0004 //
0005 // Package:     Framework
0006 // Class  :     ESProducerExternalWork
0007 //
0008 /**\class edm::ESProducer
0009 
0010  Description: Module to produce EventSetup data asynchronously in a manner
0011               similar to the ExternalWork feature of EDProducers.
0012 
0013  Usage: Same as ESProducer interface except there is the option to define
0014         a second "acquire" function if you use the setWhatAcquiredProduced
0015         function.
0016 */
0017 //
0018 // Author:      W. David Dagenhart
0019 // Created:     27 February 2023
0020 
0021 #include <memory>
0022 #include <string>
0023 #include <type_traits>
0024 #include <utility>
0025 #include <vector>
0026 
0027 #include "FWCore/Concurrency/interface/WaitingTaskWithArenaHolder.h"
0028 #include "FWCore/Framework/interface/Callback.h"
0029 #include "FWCore/Framework/interface/CallbackExternalWork.h"
0030 #include "FWCore/Framework/interface/ESConsumesCollector.h"
0031 #include "FWCore/Framework/interface/es_Label.h"
0032 #include "FWCore/Framework/interface/ESProducer.h"
0033 #include "FWCore/Framework/interface/produce_helpers.h"
0034 
0035 namespace edm {
0036 
0037   class ESProducerExternalWork : public ESProducer {
0038   public:
0039     ESProducerExternalWork();
0040 
0041     // These replicate the setWhatProduced functions but add a second functor for
0042     // the acquire step. The acquire step is analogous to the acquire step for
0043     // EDProducers with the ExternalWork ability.
0044 
0045     template <typename T>
0046     auto setWhatAcquiredProduced(T* iThis, const es::Label& iLabel = {}) {
0047       return setWhatAcquiredProduced(iThis, &T::acquire, &T::produce, iLabel);
0048     }
0049 
0050     template <typename T>
0051     auto setWhatAcquiredProduced(T* iThis, const char* iLabel) {
0052       return setWhatAcquiredProduced(iThis, es::Label(iLabel));
0053     }
0054     template <typename T>
0055     auto setWhatAcquiredProduced(T* iThis, const std::string& iLabel) {
0056       return setWhatAcquiredProduced(iThis, es::Label(iLabel));
0057     }
0058 
0059     // Note the Decorator pre and post functions are only run before
0060     // and after the 'produce' function, but they are not run before
0061     // and after the 'acquire' function.
0062 
0063     template <typename T, typename TDecorator>
0064     auto setWhatAcquiredProduced(T* iThis, const TDecorator& iDec, const es::Label& iLabel = {}) {
0065       return setWhatAcquiredProduced(iThis, &T::acquire, &T::produce, iDec, iLabel);
0066     }
0067 
0068     /** \param iThis the 'this' pointer to an inheriting class instance
0069         \param iAcquireMethod a member method of the inheriting class
0070         \param iProduceMethod a member method of the inheriting class
0071         The TRecord and TReturn template parameters can be deduced
0072         from iAquireMethod and iPRoduceMethod in order to do the
0073         registration with the EventSetup
0074     */
0075     template <typename T, typename TAcquireReturn, typename TProduceReturn, typename TRecord>
0076     auto setWhatAcquiredProduced(T* iThis,
0077                                  TAcquireReturn (T::*iAcquireMethod)(const TRecord&, WaitingTaskWithArenaHolder),
0078                                  TProduceReturn (T::*iProduceMethod)(const TRecord&, TAcquireReturn),
0079                                  const es::Label& iLabel = {}) {
0080       return setWhatAcquiredProduced(
0081           iThis, iAcquireMethod, iProduceMethod, eventsetup::CallbackSimpleDecorator<TRecord>(), iLabel);
0082     }
0083 
0084     template <typename T, typename TAcquireReturn, typename TProduceReturn, typename TRecord, typename TDecorator>
0085     auto setWhatAcquiredProduced(T* iThis,
0086                                  TAcquireReturn (T::*iAcquireMethod)(const TRecord&, WaitingTaskWithArenaHolder),
0087                                  TProduceReturn (T ::*iProduceMethod)(const TRecord&, TAcquireReturn),
0088                                  const TDecorator& iDec,
0089                                  const es::Label& iLabel = {}) {
0090       return setWhatAcquiredProducedWithLambda<TAcquireReturn, TProduceReturn, TRecord>(
0091           [iThis, iAcquireMethod](TRecord const& iRecord, WaitingTaskWithArenaHolder iHolder) {
0092             return (iThis->*iAcquireMethod)(iRecord, std::move(iHolder));
0093           },
0094           [iThis, iProduceMethod](TRecord const& iRecord, TAcquireReturn iAcquireReturn) {
0095             return (iThis->*iProduceMethod)(iRecord, std::move(iAcquireReturn));
0096           },
0097           createDecoratorFrom(iThis, static_cast<const TRecord*>(nullptr), iDec),
0098           iLabel);
0099     }
0100 
0101     /**
0102      * This overload allows lambdas (functors) to be used as the
0103      * production function. As of now it is not intended for wide use
0104      * (we are thinking for a better API for users)
0105      */
0106     template <typename TAcquireFunc, typename TProduceFunc>
0107     auto setWhatAcquiredProducedWithLambda(TAcquireFunc&& acquireFunc,
0108                                            TProduceFunc&& produceFunc,
0109                                            const es::Label& iLabel = {}) {
0110       using AcquireTypes = eventsetup::impl::ReturnArgumentTypes<TAcquireFunc>;
0111       using TAcquireReturn = typename AcquireTypes::return_type;
0112       using ProduceTypes = eventsetup::impl::ReturnArgumentTypes<TProduceFunc>;
0113       using TProduceReturn = typename ProduceTypes::return_type;
0114       using TRecord = typename ProduceTypes::argument_type;
0115       using DecoratorType = eventsetup::CallbackSimpleDecorator<TRecord>;
0116 
0117       return setWhatAcquiredProducedWithLambda<TAcquireReturn, TProduceReturn, TRecord>(
0118           std::forward<TAcquireFunc>(acquireFunc), std::forward<TProduceFunc>(produceFunc), DecoratorType(), iLabel);
0119     }
0120 
0121     // In this template, TReturn and TRecord cannot be deduced. They must be explicitly provided when called.
0122     // The previous 7 functions all end up calling this one (directly or indirectly).
0123     template <typename TAcquireReturn,
0124               typename TProduceReturn,
0125               typename TRecord,
0126               typename TAcquireFunc,
0127               typename TProduceFunc,
0128               typename TDecorator>
0129     ESConsumesCollectorT<TRecord> setWhatAcquiredProducedWithLambda(TAcquireFunc&& acquireFunc,
0130                                                                     TProduceFunc&& produceFunc,
0131                                                                     TDecorator&& iDec,
0132                                                                     const es::Label& iLabel = {}) {
0133       const auto id = consumesInfoSize();
0134       using DecoratorType = std::decay_t<TDecorator>;
0135       using CallbackType = eventsetup::CallbackExternalWork<ESProducerExternalWork,
0136                                                             TAcquireFunc,
0137                                                             TAcquireReturn,
0138                                                             TProduceFunc,
0139                                                             TProduceReturn,
0140                                                             TRecord,
0141                                                             DecoratorType>;
0142       unsigned int iovIndex = 0;  // Start with 0, but later will cycle through all of them
0143       auto temp = std::make_shared<CallbackType>(this,
0144                                                  std::forward<TAcquireFunc>(acquireFunc),
0145                                                  std::forward<TProduceFunc>(produceFunc),
0146                                                  id,
0147                                                  std::forward<TDecorator>(iDec));
0148       auto callback =
0149           std::make_shared<std::pair<unsigned int, std::shared_ptr<CallbackType>>>(iovIndex, std::move(temp));
0150       registerProducts(std::move(callback),
0151                        static_cast<const typename eventsetup::produce::product_traits<TProduceReturn>::type*>(nullptr),
0152                        static_cast<const TRecord*>(nullptr),
0153                        iLabel);
0154       return ESConsumesCollectorT<TRecord>(consumesInfoPushBackNew(), id);
0155     }
0156   };
0157 }  // namespace edm
0158 #endif