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 
58 namespace edm {
59  namespace eventsetup {
60 
61  //Simple functor that checks to see if a Record has changed since the last time it was called
62  // and if so, calls the appropriate member method. Multiple callers can be chained together using the
63  // TCallerChain template argument.
64  template<class T, class TRecord, class TDependsOnRecord, class TCallerChain >
66  {
67  DependsOnCaller(T* iCallee, void(T::* iMethod)(const TDependsOnRecord&) , const TCallerChain& iChain) :
68  callee_(iCallee), method_(iMethod), chain_(iChain),cacheID_(0){}
69 
70  void operator()(const TRecord& iRecord) {
71  const TDependsOnRecord& record = iRecord.template getRecord<TDependsOnRecord>();
72  if(record.cacheIdentifier() != cacheID_) {
73  (callee_->*method_)(record);
74  cacheID_=record.cacheIdentifier();
75  }
76  //call next 'functor' in our chain
77  chain_(iRecord);
78  }
79  private:
81  void (T::*method_)(const TDependsOnRecord&);
82  TCallerChain chain_;
83  unsigned long long cacheID_;
84  };
85 
86  //helper function to help create a DependsOnCaller
87  template<class T, class TRecord, class TDependsOnRecord, class TCallerChain >
89  createDependsOnCaller(T* iCallee, const TRecord*, void(T::*iMethod)(const TDependsOnRecord&), const TCallerChain& iChain)
90  {
91  return DependsOnCaller<T,TRecord, TDependsOnRecord, TCallerChain>(iCallee, iMethod, iChain);
92  }
93 
94  //A 'do nothing' functor that is used to terminate our chain of functors
95  template<class TRecord>
96  struct DependsOnDoNothingCaller { void operator()(const TRecord&) {} };
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 
111  //class to create a linked list of member method pointers
112  template <class T, class U>
113  struct TwoHolder {
114  typedef T T1_t;
115  typedef U T2_t;
116  TwoHolder(const T& i1, const U& i2) : h1_(i1), h2_(i2) {}
119  };
120 
121  //allows one to create the linked list by applying operator & to member method pointers
122  template< class T, class U>
123  TwoHolder<T,U> operator&(const T& iT, const U& iU) {
124  return TwoHolder<T,U>(iT, iU);
125  }
126 
127  //HolderToCaller is used to state how a OneHolder or TwoHolder is converted into the appropriate
128  // DependsOnCaller. This class is needed to define the return value of the makeCaller function
129  template< class TRecord, class THolder>
130  struct HolderToCaller {
131  };
132  template< class TRecord, class T, class TDependsOnRecord >
133  struct HolderToCaller<TRecord, OneHolder<T, TDependsOnRecord> > {
135  };
136  template< class TRecord, class T, class T1, class T2>
137  struct HolderToCaller< TRecord, TwoHolder<T1, void (T::*)(const T2&) > > {
139  };
140 
141  //helper function to convert a OneHolder or TwoHolder into a DependsOnCaller.
142  template<class T, class TDependsOnRecord, class TRecord>
144  makeCaller(T*iT, const TRecord* iRec, const OneHolder<T, TDependsOnRecord>& iHolder) {
146  }
147 
148  template<class T, class T1, class T2, class TRecord>
150  makeCaller(T*iT, const TRecord* iRec, const TwoHolder<T1, void (T::*)(const T2&)>& iHolder) {
151  return createDependsOnCaller(iT, iRec, iHolder.h2_, makeCaller(iT, iRec, iHolder.h1_));
152  }
153  }
154 
155  //DecoratorFromArg is used to declare the return type of 'createDecoratorFrom' based on the arguments to the function.
156  template< typename T, typename TRecord, typename TArg>
157  struct DecoratorFromArg { typedef TArg Decorator_t; };
158 
159  template< typename T, typename TRecord, typename TDependsOnRecord>
160  struct DecoratorFromArg<T,TRecord, depends_on::OneHolder<T,TDependsOnRecord> > {
162  };
163 
164 
165  template< typename T, typename TRecord, typename TDependsOnRecord >
167  createDecoratorFrom(T* iT, const TRecord*iRec, const depends_on::OneHolder<T,TDependsOnRecord>& iHolder) {
170  temp(createDependsOnCaller(iT, iRec, iHolder.holdee_, tCaller));
171  return temp;
172  }
173 
174  template< typename T, typename TRecord, typename T1, typename T2>
175  struct DecoratorFromArg<T,TRecord, depends_on::TwoHolder<T1,T2> > {
178  };
179  template< typename T, typename TRecord, typename T1, typename T2>
181  createDecoratorFrom(T* iT, const TRecord*iRec, const depends_on::TwoHolder<T1,T2>& iHolder) {
183  (createDependsOnCaller(iT, iRec, iHolder.h2_, makeCaller(iT, iRec, iHolder.h1_)));
184  }
185 
186 
187  //The actual dependsOn functions which users call
188  template <typename T, typename TDependsOnRecord>
190  dependsOn(void(T::*iT)(const TDependsOnRecord&)) { return iT ; }
191 
192  template< typename T, typename T1, typename T2>
194  dependsOn(void (T::* iT1)(const T1&), T2 iT2) { return depends_on::OneHolder<T, T1>(iT1) & iT2; }
195 
196  template< typename T, typename T1, typename T2, typename T3>
198  dependsOn(void(T::* iT1)(const T1&), T2 iT2, T3 iT3) { return depends_on::OneHolder<T,T1>(iT1) & iT2 & iT3; }
199 
200 
201  }
202 }
203 
204 #endif
depends_on::OneHolder< T, TDependsOnRecord > dependsOn(void(T::*iT)(const TDependsOnRecord &))
DependsOnCaller< T, TRecord, TDependsOnRecord, DependsOnDoNothingCaller< TRecord > > Caller_t
void(T::* method_)(const TDependsOnRecord &)
JetCorrectorParameters::Record record
Definition: classes.h:7
ESPreFunctorDecorator< TRecord, DependsOnCaller< T, TRecord, TDependsOnRecord, DependsOnDoNothingCaller< TRecord > > > Decorator_t
mathSSE::Vec4< double > operator&(mathSSE::Vec4< double > a, mathSSE::Vec4< double > b)
Definition: AVXVec.h:119
DependsOnCaller(T *iCallee, void(T::*iMethod)(const TDependsOnRecord &), const TCallerChain &iChain)
DependsOnCaller< T, TRecord, T2, typename HolderToCaller< TRecord, T1 >::Caller_t > makeCaller(T *iT, const TRecord *iRec, const TwoHolder< T1, void(T::*)(const T2 &)> &iHolder)
const TDecorator & createDecoratorFrom(T *, const TRecord *, const TDecorator &iDec)
Definition: ESProducer.h:93
DependsOnCaller< T, TRecord, TDependsOnRecord, TCallerChain > createDependsOnCaller(T *iCallee, const TRecord *, void(T::*iMethod)(const TDependsOnRecord &), const TCallerChain &iChain)
ESPreFunctorDecorator< TRecord, typename depends_on::HolderToCaller< TRecord, depends_on::TwoHolder< T1, T2 > >::Caller_t > Decorator_t
void(T::* holdee_)(const TDependsOnRecord &)
DependsOnCaller< T, TRecord, T2, typename HolderToCaller< TRecord, T1 >::Caller_t > Caller_t
HLT enums.
OneHolder(void(T::*iHoldee)(const TDependsOnRecord &))
long double T
void operator()(const TRecord &iRecord)