Back to home page

Project CMSSW displayed by LXR

 
 

    


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

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 TRecord = typename AcquireTypes::argument_type;
0112       using TAcquireReturn = typename AcquireTypes::return_type;
0113       using TProduceReturn = std::invoke_result_t<TProduceFunc, TRecord const&, TAcquireReturn>;
0114       using DecoratorType = eventsetup::CallbackSimpleDecorator<TRecord>;
0115 
0116       return setWhatAcquiredProducedWithLambda<TAcquireReturn, TProduceReturn, TRecord>(
0117           std::forward<TAcquireFunc>(acquireFunc), std::forward<TProduceFunc>(produceFunc), DecoratorType(), iLabel);
0118     }
0119 
0120     // In this template, TReturn and TRecord cannot be deduced. They must be explicitly provided when called.
0121     // The previous 7 functions all end up calling this one (directly or indirectly).
0122     template <typename TAcquireReturn,
0123               typename TProduceReturn,
0124               typename TRecord,
0125               typename TAcquireFunc,
0126               typename TProduceFunc,
0127               typename TDecorator>
0128     ESConsumesCollectorT<TRecord> setWhatAcquiredProducedWithLambda(TAcquireFunc&& acquireFunc,
0129                                                                     TProduceFunc&& produceFunc,
0130                                                                     TDecorator&& iDec,
0131                                                                     const es::Label& iLabel = {}) {
0132       const auto id = consumesInfoSize();
0133       using DecoratorType = std::decay_t<TDecorator>;
0134       using CallbackType = eventsetup::CallbackExternalWork<ESProducerExternalWork,
0135                                                             TAcquireFunc,
0136                                                             TAcquireReturn,
0137                                                             TProduceFunc,
0138                                                             TProduceReturn,
0139                                                             TRecord,
0140                                                             DecoratorType>;
0141       unsigned int iovIndex = 0;  // Start with 0, but later will cycle through all of them
0142       auto temp = std::make_shared<CallbackType>(this,
0143                                                  std::forward<TAcquireFunc>(acquireFunc),
0144                                                  std::forward<TProduceFunc>(produceFunc),
0145                                                  id,
0146                                                  std::forward<TDecorator>(iDec));
0147       auto callback =
0148           std::make_shared<std::pair<unsigned int, std::shared_ptr<CallbackType>>>(iovIndex, std::move(temp));
0149       registerProducts(std::move(callback),
0150                        static_cast<const typename eventsetup::produce::product_traits<TProduceReturn>::type*>(nullptr),
0151                        static_cast<const TRecord*>(nullptr),
0152                        iLabel);
0153       return ESConsumesCollectorT<TRecord>(consumesInfoPushBackNew(), id);
0154     }
0155   };
0156 }  // namespace edm
0157 #endif