CMS 3D CMS Logo

eventsetup_dependsOn.h
Go to the documentation of this file.
1 
2 #ifndef Framework_eventsetup_dependsOn_h
3 #define Framework_eventsetup_dependsOn_h
4 // -*- C++ -*-
5 //
6 // Package: Framework
7 // Class : eventsetup_dependsOn
8 //
26 /*
27  Implementation details:
28 
29  The dependsOn function does not have enough information to convert the list of member function pointers directly into the
30  appropriate Decorator class since it is missing the Record type of the Decorator (all it knows are the Record types the
31  Decorator depends on). Therefore we must defer the creation of the Decorator until that Record type is known (which
32  happens within the body of the ESProducer::setWhatProduced method). To allow the deferred construction,
33  the dependsOn method returns a compile time linked list created via the TwoHolder class (if there is only one
34  node you get a OneHolder). The dependsOn method always makes sure that the second type of the TwoHolder is the member
35  function pointer which is needed for the later construction stage.
36 
37  Within the body of ESProducer::setWhatProduced, the proper Decorator is created by calling 'createDecoratorFrom' which is given
38  a pointer to the Producer, a dummy pointer to the proper Record and the linked list of member function pointers. The
39  'createDecoratorFrom' uses the makeCaller and createDependsOnCaller functions to recursively create the proper DependsOnCaller
40  functor which is then used by the ESPreFunctorDecorator to do the work. We use HolderToCaller template class merely to define
41  the return type of the 'createDecoratorFrom' and 'makeCaller' functions.
42 
43  */
44 
45 //
46 // Original Author: Chris Jones
47 // Created: Thu Jun 23 14:06:56 EDT 2005
48 //
49 
50 // system include files
51 
52 // user include files
54 
55 // forward declarations
56 
57 namespace edm {
58  namespace eventsetup {
59 
60  //Simple functor that checks to see if a Record has changed since the last time it was called
61  // and if so, calls the appropriate member method. Multiple callers can be chained together using the
62  // TCallerChain template argument.
63  template <class T, class TRecord, class TDependsOnRecord, class TCallerChain>
64  struct DependsOnCaller {
65  DependsOnCaller(T* iCallee, void (T::*iMethod)(const TDependsOnRecord&), const TCallerChain& iChain)
66  : callee_(iCallee), method_(iMethod), chain_(iChain), cacheID_(0) {}
67 
68  void operator()(const TRecord& iRecord) {
69  const TDependsOnRecord& record = iRecord.template getRecord<TDependsOnRecord>();
70  if (record.cacheIdentifier() != cacheID_) {
71  (callee_->*method_)(record);
72  cacheID_ = record.cacheIdentifier();
73  }
74  //call next 'functor' in our chain
75  chain_(iRecord);
76  }
77 
78  private:
80  void (T::*method_)(const TDependsOnRecord&);
81  TCallerChain chain_;
82  unsigned long long cacheID_;
83  };
84 
85  //helper function to help create a DependsOnCaller
86  template <class T, class TRecord, class TDependsOnRecord, class TCallerChain>
88  T* iCallee, const TRecord*, void (T::*iMethod)(const TDependsOnRecord&), const TCallerChain& iChain) {
89  return DependsOnCaller<T, TRecord, TDependsOnRecord, TCallerChain>(iCallee, iMethod, iChain);
90  }
91 
92  //A 'do nothing' functor that is used to terminate our chain of functors
93  template <class TRecord>
95  void operator()(const TRecord&) {}
96  };
97 
98  //put implementation details used to get the dependsOn method to work into their own namespace
99  namespace depends_on {
100  //class to hold onto one member method pointer
101  template <class T, class TDependsOnRecord>
102  struct OneHolder {
103  typedef T Prod_t;
104  typedef TDependsOnRecord DependsOnRecord_t;
105 
106  OneHolder(void (T::*iHoldee)(const TDependsOnRecord&)) : holdee_(iHoldee) {}
107  void (T::*holdee_)(const TDependsOnRecord&);
108  };
109 
110  //class to create a linked list of member method pointers
111  template <class T, class U>
112  struct TwoHolder {
113  typedef T T1_t;
114  typedef U T2_t;
115  TwoHolder(const T& i1, const U& i2) : h1_(i1), h2_(i2) {}
118  };
119 
120  //allows one to create the linked list by applying operator & to member method pointers
121  template <class T, class U>
122  TwoHolder<T, U> operator&(const T& iT, const U& iU) {
123  return TwoHolder<T, U>(iT, iU);
124  }
125 
126  //HolderToCaller is used to state how a OneHolder or TwoHolder is converted into the appropriate
127  // DependsOnCaller. This class is needed to define the return value of the makeCaller function
128  template <class TRecord, class THolder>
129  struct HolderToCaller {};
130  template <class TRecord, class T, class TDependsOnRecord>
131  struct HolderToCaller<TRecord, OneHolder<T, TDependsOnRecord> > {
133  };
134  template <class TRecord, class T, class T1, class T2>
135  struct HolderToCaller<TRecord, TwoHolder<T1, void (T::*)(const T2&)> > {
137  };
138 
139  //helper function to convert a OneHolder or TwoHolder into a DependsOnCaller.
140  template <class T, class TDependsOnRecord, class TRecord>
142  T* iT, const TRecord* iRec, const OneHolder<T, TDependsOnRecord>& iHolder) {
144  }
145 
146  template <class T, class T1, class T2, class TRecord>
148  T* iT, const TRecord* iRec, const TwoHolder<T1, void (T::*)(const T2&)>& iHolder) {
149  return createDependsOnCaller(iT, iRec, iHolder.h2_, makeCaller(iT, iRec, iHolder.h1_));
150  }
151  } // namespace depends_on
152 
153  //DecoratorFromArg is used to declare the return type of 'createDecoratorFrom' based on the arguments to the function.
154  template <typename T, typename TRecord, typename TArg>
156  typedef TArg Decorator_t;
157  };
158 
159  template <typename T, typename TRecord, typename TDependsOnRecord>
160  struct DecoratorFromArg<T, TRecord, depends_on::OneHolder<T, TDependsOnRecord> > {
161  typedef ESPreFunctorDecorator<TRecord,
164  };
165 
166  template <typename T, typename TRecord, typename TDependsOnRecord>
167  inline ESPreFunctorDecorator<TRecord,
169  createDecoratorFrom(T* iT, const TRecord* iRec, const depends_on::OneHolder<T, TDependsOnRecord>& iHolder) {
172  temp(createDependsOnCaller(iT, iRec, iHolder.holdee_, tCaller));
173  return temp;
174  }
175 
176  template <typename T, typename TRecord, typename T1, typename T2>
177  struct DecoratorFromArg<T, TRecord, depends_on::TwoHolder<T1, T2> > {
178  typedef ESPreFunctorDecorator<
179  TRecord,
182  };
183  template <typename T, typename TRecord, typename T1, typename T2>
184  inline ESPreFunctorDecorator<TRecord,
186  createDecoratorFrom(T* iT, const TRecord* iRec, const depends_on::TwoHolder<T1, T2>& iHolder) {
187  return ESPreFunctorDecorator<
188  TRecord,
190  createDependsOnCaller(iT, iRec, iHolder.h2_, makeCaller(iT, iRec, iHolder.h1_)));
191  }
192 
193  //The actual dependsOn functions which users call
194  template <typename T, typename TDependsOnRecord>
195  depends_on::OneHolder<T, TDependsOnRecord> dependsOn(void (T::*iT)(const TDependsOnRecord&)) {
196  return iT;
197  }
198 
199  template <typename T, typename T1, typename T2>
200  depends_on::TwoHolder<depends_on::OneHolder<T, T1>, T2> dependsOn(void (T::*iT1)(const T1&), T2 iT2) {
201  return depends_on::OneHolder<T, T1>(iT1) & iT2;
202  }
203 
204  template <typename T, typename T1, typename T2, typename T3>
206  void (T::*iT1)(const T1&), T2 iT2, T3 iT3) {
207  return depends_on::OneHolder<T, T1>(iT1) & iT2 & iT3;
208  }
209 
210  } // namespace eventsetup
211 } // namespace edm
212 
213 #endif
ESPreFunctorDecorator< TRecord, typename depends_on::HolderToCaller< TRecord, depends_on::TwoHolder< T1, T2 > >::Caller_t > Decorator_t
depends_on::OneHolder< T, TDependsOnRecord > dependsOn(void(T::*iT)(const TDependsOnRecord &))
void(T::* method_)(const TDependsOnRecord &)
DependsOnCaller(T *iCallee, void(T::*iMethod)(const TDependsOnRecord &), const TCallerChain &iChain)
TEMPL(T2) struct Divides void
Definition: Factorize.h:24
const TDecorator & createDecoratorFrom(T *, const TRecord *, const TDecorator &iDec)
Definition: ESProducer.h:99
TwoHolder< T, U > operator &(const T &iT, const U &iU)
ESPreFunctorDecorator< TRecord, DependsOnCaller< T, TRecord, TDependsOnRecord, DependsOnDoNothingCaller< TRecord > > > Decorator_t
DependsOnCaller< T, TRecord, TDependsOnRecord, DependsOnDoNothingCaller< TRecord > > makeCaller(T *iT, const TRecord *iRec, const OneHolder< T, TDependsOnRecord > &iHolder)
void(T::* holdee_)(const TDependsOnRecord &)
DependsOnCaller< T, TRecord, TDependsOnRecord, TCallerChain > createDependsOnCaller(T *iCallee, const TRecord *, void(T::*iMethod)(const TDependsOnRecord &), const TCallerChain &iChain)
HLT enums.
OneHolder(void(T::*iHoldee)(const TDependsOnRecord &))
DependsOnCaller< T, TRecord, T2, typename HolderToCaller< TRecord, T1 >::Caller_t > makeCaller(T *iT, const TRecord *iRec, const TwoHolder< T1, void(T::*)(const T2 &)> &iHolder)
DependsOnCaller< T, TRecord, TDependsOnRecord, DependsOnDoNothingCaller< TRecord > > Caller_t
long double T
void operator()(const TRecord &iRecord)
DependsOnCaller< T, TRecord, T2, typename HolderToCaller< TRecord, T1 >::Caller_t > Caller_t