CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
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 // $Id: eventsetup_dependsOn.h,v 1.10 2010/09/01 18:24:25 chrjones Exp $
49 //
50 
51 // system include files
52 
53 // user include files
55 
56 // forward declarations
57 
58 
59 namespace edm {
60  namespace eventsetup {
61 
62  //Simple functor that checks to see if a Record has changed since the last time it was called
63  // and if so, calls the appropriate member method. Multiple callers can be chained together using the
64  // TCallerChain template argument.
65  template<class T, class TRecord, class TDependsOnRecord, class TCallerChain >
67  {
68  DependsOnCaller(T* iCallee, void(T::* iMethod)(const TDependsOnRecord&) , const TCallerChain& iChain) :
69  callee_(iCallee), method_(iMethod), chain_(iChain),cacheID_(0){}
70 
71  void operator()(const TRecord& iRecord) {
72  const TDependsOnRecord& record = iRecord.template getRecord<TDependsOnRecord>();
73  if(record.cacheIdentifier() != cacheID_) {
74  (callee_->*method_)(record);
75  cacheID_=record.cacheIdentifier();
76  }
77  //call next 'functor' in our chain
78  chain_(iRecord);
79  }
80  private:
82  void (T::*method_)(const TDependsOnRecord&);
83  TCallerChain chain_;
84  unsigned long long cacheID_;
85  };
86 
87  //helper function to help create a DependsOnCaller
88  template<class T, class TRecord, class TDependsOnRecord, class TCallerChain >
90  createDependsOnCaller(T* iCallee, const TRecord*, void(T::*iMethod)(const TDependsOnRecord&), const TCallerChain& iChain)
91  {
92  return DependsOnCaller<T,TRecord, TDependsOnRecord, TCallerChain>(iCallee, iMethod, iChain);
93  }
94 
95  //A 'do nothing' functor that is used to terminate our chain of functors
96  template<class TRecord>
97  struct DependsOnDoNothingCaller { void operator()(const TRecord&) {} };
98 
99  //put implementation details used to get the dependsOn method to work into their own namespace
100  namespace depends_on {
101  //class to hold onto one member method pointer
102  template <class T, class TDependsOnRecord>
103  struct OneHolder {
104  typedef T Prod_t;
105  typedef TDependsOnRecord DependsOnRecord_t;
106 
107  OneHolder(void (T::*iHoldee)(const TDependsOnRecord&)) : holdee_(iHoldee) {}
108  void (T::*holdee_)(const TDependsOnRecord&);
109 
110  };
111 
112  //class to create a linked list of member method pointers
113  template <class T, class U>
114  struct TwoHolder {
115  typedef T T1_t;
116  typedef U T2_t;
117  TwoHolder(const T& i1, const U& i2) : h1_(i1), h2_(i2) {}
119  U h2_;
120  };
121 
122  //allows one to create the linked list by applying operator & to member method pointers
123  template< class T, class U>
124  TwoHolder<T,U> operator&(const T& iT, const U& iU) {
125  return TwoHolder<T,U>(iT, iU);
126  }
127 
128  //HolderToCaller is used to state how a OneHolder or TwoHolder is converted into the appropriate
129  // DependsOnCaller. This class is needed to define the return value of the makeCaller function
130  template< class TRecord, class THolder>
131  struct HolderToCaller {
132  };
133  template< class TRecord, class T, class TDependsOnRecord >
134  struct HolderToCaller<TRecord, OneHolder<T, TDependsOnRecord> > {
136  };
137  template< class TRecord, class T, class T1, class T2>
138  struct HolderToCaller< TRecord, TwoHolder<T1, void (T::*)(const T2&) > > {
140  };
141 
142  //helper function to convert a OneHolder or TwoHolder into a DependsOnCaller.
143  template<class T, class TDependsOnRecord, class TRecord>
145  makeCaller(T*iT, const TRecord* iRec, const OneHolder<T, TDependsOnRecord>& iHolder) {
147  }
148 
149  template<class T, class T1, class T2, class TRecord>
151  makeCaller(T*iT, const TRecord* iRec, const TwoHolder<T1, void (T::*)(const T2&)>& iHolder) {
152  return createDependsOnCaller(iT, iRec, iHolder.h2_, makeCaller(iT, iRec, iHolder.h1_));
153  }
154  }
155 
156  //DecoratorFromArg is used to declare the return type of 'createDecoratorFrom' based on the arguments to the function.
157  template< typename T, typename TRecord, typename TArg>
158  struct DecoratorFromArg { typedef TArg Decorator_t; };
159 
160  template< typename T, typename TRecord, typename TDependsOnRecord>
161  struct DecoratorFromArg<T,TRecord, depends_on::OneHolder<T,TDependsOnRecord> > {
163  };
164 
165 
166  template< typename T, typename TRecord, typename TDependsOnRecord >
168  createDecoratorFrom(T* iT, const TRecord*iRec, const depends_on::OneHolder<T,TDependsOnRecord>& iHolder) {
171  temp(createDependsOnCaller(iT, iRec, iHolder.holdee_, tCaller));
172  return temp;
173  }
174 
175  template< typename T, typename TRecord, typename T1, typename T2>
176  struct DecoratorFromArg<T,TRecord, depends_on::TwoHolder<T1,T2> > {
179  };
180  template< typename T, typename TRecord, typename T1, typename T2>
182  createDecoratorFrom(T* iT, const TRecord*iRec, const depends_on::TwoHolder<T1,T2>& iHolder) {
184  (createDependsOnCaller(iT, iRec, iHolder.h2_, makeCaller(iT, iRec, iHolder.h1_)));
185  }
186 
187 
188  //The actual dependsOn functions which users call
189  template <typename T, typename TDependsOnRecord>
190  depends_on::OneHolder<T,TDependsOnRecord>
191  dependsOn(void(T::*iT)(const TDependsOnRecord&)) { return iT ; }
192 
193  template< typename T, typename T1, typename T2>
194  depends_on::TwoHolder<depends_on::OneHolder<T,T1>, T2>
195  dependsOn(void (T::* iT1)(const T1&), T2 iT2) { return depends_on::OneHolder<T, T1>(iT1) & iT2; }
196 
197  template< typename T, typename T1, typename T2, typename T3>
198  depends_on::TwoHolder< depends_on::TwoHolder<depends_on::OneHolder<T,T1>, T2>, T3>
199  dependsOn(void(T::* iT1)(const T1&), T2 iT2, T3 iT3) { return depends_on::OneHolder<T,T1>(iT1) & iT2 & iT3; }
200 
201 
202  }
203 }
204 
205 #endif
void(T::* holdee_)(const TDependsOnRecord &)
depends_on::OneHolder< T, TDependsOnRecord > dependsOn(void(T::*iT)(const TDependsOnRecord &))
DependsOnCaller< T, TRecord, TDependsOnRecord, DependsOnDoNothingCaller< TRecord > > Caller_t
JetCorrectorParameters::Record record
Definition: classes.h:11
ESPreFunctorDecorator< TRecord, DependsOnCaller< T, TRecord, TDependsOnRecord, DependsOnDoNothingCaller< TRecord > > > Decorator_t
DependsOnCaller(T *iCallee, void(T::*iMethod)(const TDependsOnRecord &), const TCallerChain &iChain)
void(T::* method_)(const TDependsOnRecord &)
const TDecorator & createDecoratorFrom(T *, const TRecord *, const TDecorator &iDec)
Definition: ESProducer.h:93
DependsOnCaller< T, TRecord, TDependsOnRecord, DependsOnDoNothingCaller< TRecord > > makeCaller(T *iT, const TRecord *iRec, const OneHolder< T, TDependsOnRecord > &iHolder)
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
DependsOnCaller< T, TRecord, T2, typename HolderToCaller< TRecord, T1 >::Caller_t > Caller_t
OneHolder(void(T::*iHoldee)(const TDependsOnRecord &))
TwoHolder< T, U > operator&(const T &iT, const U &iU)
long double T
void operator()(const TRecord &iRecord)