|
||||
File indexing completed on 2024-04-06 12:12:01
0001 #ifndef FWCore_Framework_ESProductHost_h 0002 #define FWCore_Framework_ESProductHost_h 0003 // -*- C++ -*- 0004 // 0005 // Package: Framework 0006 // Class: ESProductHost 0007 // 0008 /**\class edm::ESProductHost 0009 0010 Description: Helps an ESProducer produce an ESProduct that has 0011 complex dependences on multiple record types. In particular, 0012 it helps it manage what is executed in the produce function 0013 based on which records changed and which did not. 0014 0015 This was designed as a replacement for the EventSetup "dependsOn" 0016 functionality and is needed in some cases where the "dependsOn" 0017 callbacks would not work well when processing multiple IOVs 0018 concurrently. 0019 0020 Usage: 0021 0022 An ESProducer class would use this class. 0023 0024 1. Add to the ESProducer header 0025 0026 #include "FWCore/Framework/interface/ESProductHost.h" 0027 #include "FWCore/Utilities/interface/ReusableObjectHolder.h" 0028 0029 2. Assume the following only for purposes of this usage example 0030 (the actual types in your case would be different). If the produced 0031 function was defined as follows: 0032 0033 std::shared_ptr<ESTestDataB> produce(ESTestRecordB const&); 0034 0035 and assume there is some special dependence on ESTestRecordC and 0036 ESTestRecordD. 0037 0038 3. Then you would add a data member to the ESProducer similar 0039 to the following: 0040 0041 using HostType = edm::ESProductHost<ESTestDataB, 0042 ESTestRecordC, 0043 ESTestRecordD>; 0044 0045 edm::ReusableObjectHolder<HostType> holder_; 0046 0047 4. Then the produce function would be defined something similar 0048 to this: 0049 0050 std::shared_ptr<ESTestDataB> ESTestProducerBUsingHost::produce(ESTestRecordB const& record) { 0051 0052 auto host = holder_.makeOrGet([]() { 0053 return new HostType; 0054 }); 0055 0056 host->ifRecordChanges<ESTestRecordC>(record, 0057 [this, h=host.get()](auto const& rec) { 0058 // Do whatever special needs to be done only when record C changes 0059 // (If you are using this class to replace a dependsOn callback, you could 0060 // call the function that dependsOn used as a callback here) 0061 }); 0062 0063 host->ifRecordChanges<ESTestRecordD>(record, 0064 [this, h=host.get()](auto const& rec) { 0065 // Do whatever special needs to be done only when record D changes 0066 }); 0067 0068 ... repeat for as many record types as you need. 0069 */ 0070 // 0071 // Author: W. David Dagenhart 0072 // Created: 28 August 2018 0073 // 0074 0075 #include <cstddef> 0076 #include <type_traits> 0077 #include <vector> 0078 0079 namespace edm { 0080 0081 // The parameter pack RecordTypes should contain all the 0082 // record types which you want to use when calling the 0083 // function "ifRecordChanges" as the first template parameter 0084 // to that function (the RecordType). The list of types in 0085 // RecordTypes is used only to size the vector of cacheIDs_ and 0086 // to establish an order of the types in RecordTypes. The 0087 // order is only used to establish a one to one correspondence 0088 // between cacheIDs_ and the types. The particular order 0089 // selected does not mattter, just that some order exists 0090 // so we know which cacheID corresponds to which type. 0091 0092 template <typename Product, typename... RecordTypes> 0093 class ESProductHost final : public Product { 0094 public: 0095 template <typename... Args> 0096 ESProductHost(Args&&... args) : Product(std::forward<Args>(args)...), cacheIDs_(numberOfRecordTypes(), 0) {} 0097 0098 // Execute FUNC if the cacheIdentifier in the EventSetup RecordType 0099 // has changed since the last time we called FUNC for 0100 // this EventSetup product. 0101 0102 template <typename RecordType, typename ContainingRecordType, typename FUNC> 0103 void ifRecordChanges(ContainingRecordType const& containingRecord, FUNC func) { 0104 RecordType const& record = containingRecord.template getRecord<RecordType>(); 0105 unsigned long long cacheIdentifier = record.cacheIdentifier(); 0106 std::size_t iRecord = index<RecordType>(); 0107 if (cacheIdentifier != cacheIDs_[iRecord]) { 0108 cacheIDs_[iRecord] = cacheIdentifier; 0109 func(record); 0110 } 0111 } 0112 0113 // The rest of the functions are not intended for public use. 0114 // The only reason they are not private is that test code 0115 // uses them. 0116 0117 // Return the number of record types for which we want to check 0118 // if the cache identifier changed. 0119 0120 constexpr static std::size_t numberOfRecordTypes() { return sizeof...(RecordTypes); } 0121 0122 // Return the index of a record type in the types in the parameter pack RecordTypes. 0123 // The first type in the template parameters after the Product type 0124 // will have an index of 0, the next 1, and so on. 0125 // (There must be at least one type after Product if you want to call the 0126 // "ifRecordChanges" function). 0127 0128 template <typename U> 0129 constexpr static std::size_t index() { 0130 static_assert(numberOfRecordTypes() > 0, "no record types in ESProductHost"); 0131 return indexLoop<0, U, RecordTypes...>(); 0132 } 0133 0134 template <std::size_t I, typename U, typename TST, typename... M> 0135 constexpr static std::size_t indexLoop() { 0136 if constexpr (std::is_same_v<U, TST>) { 0137 return I; 0138 } else { 0139 static_assert(I + 1 < numberOfRecordTypes(), "unknown record type passed to ESProductHost::index"); 0140 return indexLoop<I + 1, U, M...>(); 0141 } 0142 } 0143 0144 private: 0145 // Data member, this holds the cache identifiers from the record which 0146 // are used to determine whether the EventSetup cache for that record has 0147 // been updated since this Product was lasted updated. 0148 0149 std::vector<unsigned long long> cacheIDs_; 0150 }; 0151 } // namespace edm 0152 #endif
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.2.1 LXR engine. The LXR team |