CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_7/src/FWCore/Framework/interface/eventsetup_dependsOn.h

Go to the documentation of this file.
00001 
00002 #ifndef Framework_eventsetup_dependsOn_h
00003 #define Framework_eventsetup_dependsOn_h
00004 // -*- C++ -*-
00005 //
00006 // Package:     Framework
00007 // Class  :     eventsetup_dependsOn
00008 // 
00026 /*
00027  Implementation details:
00028  
00029  The dependsOn function does not have enough information to convert the list of member function pointers directly into the
00030  appropriate Decorator class since it is missing the Record type of the Decorator (all it knows are the Record types the 
00031  Decorator depends on).  Therefore we must defer the creation of the Decorator until that Record type is known (which
00032  happens within the body of the ESProducer::setWhatProduced method).  To allow the deferred construction, 
00033  the dependsOn method returns a compile time linked list created via the TwoHolder class (if there is only one 
00034  node you get a OneHolder).  The dependsOn method always makes sure that the second type of the TwoHolder is the member
00035  function pointer which is needed for the later construction stage.
00036  
00037  Within the body of ESProducer::setWhatProduced, the proper Decorator is created by calling 'createDecoratorFrom' which is given
00038  a pointer to the Producer, a dummy pointer to the proper Record and the linked list of member function pointers.  The
00039  'createDecoratorFrom' uses the makeCaller and createDependsOnCaller functions to recursively create the proper DependsOnCaller 
00040  functor which is then used by the ESPreFunctorDecorator to do the work.  We use  HolderToCaller template class merely to define 
00041  the return type of the 'createDecoratorFrom' and 'makeCaller' functions.
00042  
00043  */
00044 
00045 //
00046 // Original Author:  Chris Jones
00047 //         Created:  Thu Jun 23 14:06:56 EDT 2005
00048 // $Id: eventsetup_dependsOn.h,v 1.10 2010/09/01 18:24:25 chrjones Exp $
00049 //
00050 
00051 // system include files
00052 
00053 // user include files
00054 #include "FWCore/Framework/interface/ESPreFunctorDecorator.h"
00055 
00056 // forward declarations
00057 
00058 
00059 namespace edm {
00060    namespace eventsetup {
00061       
00062       //Simple functor that checks to see if a Record has changed since the last time it was called
00063       // and if so, calls the appropriate member method.  Multiple callers can be chained together using the
00064       // TCallerChain template argument.
00065      template<class T, class TRecord, class TDependsOnRecord, class TCallerChain >
00066         struct DependsOnCaller
00067         {
00068         DependsOnCaller(T* iCallee, void(T::* iMethod)(const TDependsOnRecord&) , const TCallerChain& iChain) : 
00069           callee_(iCallee), method_(iMethod), chain_(iChain),cacheID_(0){} 
00070       
00071             void operator()(const TRecord& iRecord) {
00072             const TDependsOnRecord& record = iRecord.template getRecord<TDependsOnRecord>();
00073             if(record.cacheIdentifier() != cacheID_) {
00074               (callee_->*method_)(record);
00075               cacheID_=record.cacheIdentifier();
00076             }
00077             //call next 'functor' in our chain
00078             chain_(iRecord);
00079           }
00080         private:
00081           T* callee_;
00082           void (T::*method_)(const TDependsOnRecord&);
00083           TCallerChain chain_;
00084           unsigned long long cacheID_;
00085         };
00086 
00087       //helper function to help create a DependsOnCaller
00088       template<class T, class TRecord, class TDependsOnRecord, class TCallerChain >
00089          DependsOnCaller<T,TRecord, TDependsOnRecord, TCallerChain>
00090          createDependsOnCaller(T* iCallee, const TRecord*, void(T::*iMethod)(const TDependsOnRecord&), const TCallerChain& iChain) 
00091       {
00092             return DependsOnCaller<T,TRecord, TDependsOnRecord, TCallerChain>(iCallee, iMethod, iChain);
00093       }
00094       
00095       //A 'do nothing' functor that is used to terminate our chain of functors
00096       template<class TRecord>
00097          struct DependsOnDoNothingCaller { void operator()(const TRecord&) {} };
00098       
00099       //put implementation details used to get the dependsOn method to work into their own namespace
00100       namespace depends_on {
00101          //class to hold onto one member method pointer
00102          template <class T, class TDependsOnRecord>
00103          struct OneHolder {
00104             typedef T Prod_t;
00105             typedef TDependsOnRecord DependsOnRecord_t;
00106             
00107             OneHolder(void (T::*iHoldee)(const TDependsOnRecord&)) : holdee_(iHoldee) {}
00108             void (T::*holdee_)(const TDependsOnRecord&);
00109             
00110          };
00111          
00112          //class to create a linked list of member method pointers
00113          template <class T, class U>
00114             struct TwoHolder {
00115                typedef T T1_t;
00116                typedef U T2_t;
00117                TwoHolder(const T& i1, const U& i2) : h1_(i1), h2_(i2) {}
00118                T h1_;
00119                U h2_;
00120             };
00121 
00122          //allows one to create the linked list by applying operator & to member method pointers
00123          template< class T, class U>
00124             TwoHolder<T,U> operator&(const T& iT, const U& iU) {
00125                return TwoHolder<T,U>(iT, iU);
00126             }
00127          
00128          //HolderToCaller is used to state how a OneHolder or TwoHolder is converted into the appropriate 
00129          // DependsOnCaller.  This class is needed to define the return value of the makeCaller function
00130          template< class TRecord, class THolder>
00131             struct HolderToCaller {
00132             };
00133          template< class TRecord, class T, class TDependsOnRecord >
00134             struct HolderToCaller<TRecord, OneHolder<T, TDependsOnRecord> > {
00135                typedef DependsOnCaller<T,TRecord, TDependsOnRecord, DependsOnDoNothingCaller<TRecord> > Caller_t;
00136             };
00137          template< class TRecord, class T, class T1, class T2>
00138             struct HolderToCaller< TRecord, TwoHolder<T1, void (T::*)(const T2&) > > {
00139                typedef DependsOnCaller<T, TRecord, T2 , typename HolderToCaller<TRecord,T1>::Caller_t > Caller_t;
00140             };
00141 
00142          //helper function to convert a OneHolder or TwoHolder into a DependsOnCaller.
00143          template<class T, class TDependsOnRecord, class TRecord>
00144             DependsOnCaller<T,TRecord, TDependsOnRecord, DependsOnDoNothingCaller<TRecord> >
00145             makeCaller(T*iT, const TRecord* iRec, const OneHolder<T, TDependsOnRecord>& iHolder) {
00146                return createDependsOnCaller(iT, iRec, iHolder.holdee_, DependsOnDoNothingCaller<TRecord>());
00147             }
00148          
00149          template<class T, class T1, class T2, class TRecord>
00150             DependsOnCaller<T,TRecord, T2, typename HolderToCaller<TRecord, T1>::Caller_t >
00151             makeCaller(T*iT, const TRecord* iRec, const TwoHolder<T1, void (T::*)(const T2&)>& iHolder) {
00152                return createDependsOnCaller(iT, iRec, iHolder.h2_, makeCaller(iT, iRec, iHolder.h1_));
00153             }
00154       }
00155       
00156       //DecoratorFromArg is used to declare the return type of 'createDecoratorFrom' based on the arguments to the function.
00157       template< typename T, typename TRecord, typename TArg>
00158          struct DecoratorFromArg { typedef TArg Decorator_t; };
00159       
00160       template< typename T, typename TRecord, typename TDependsOnRecord>
00161          struct DecoratorFromArg<T,TRecord, depends_on::OneHolder<T,TDependsOnRecord> > { 
00162             typedef ESPreFunctorDecorator<TRecord,DependsOnCaller<T,TRecord, TDependsOnRecord, DependsOnDoNothingCaller<TRecord> > > Decorator_t; 
00163          };
00164       
00165       
00166       template< typename T, typename TRecord, typename TDependsOnRecord >
00167          inline ESPreFunctorDecorator<TRecord,DependsOnCaller<T,TRecord, TDependsOnRecord, DependsOnDoNothingCaller<TRecord> > > 
00168          createDecoratorFrom(T* iT, const TRecord*iRec, const depends_on::OneHolder<T,TDependsOnRecord>& iHolder) {
00169             DependsOnDoNothingCaller<TRecord> tCaller;
00170             ESPreFunctorDecorator<TRecord,DependsOnCaller<T,TRecord, TDependsOnRecord, DependsOnDoNothingCaller<TRecord> > >
00171                temp(createDependsOnCaller(iT, iRec, iHolder.holdee_, tCaller));
00172             return temp;
00173          }
00174       
00175       template< typename T, typename TRecord, typename T1, typename T2>
00176          struct DecoratorFromArg<T,TRecord, depends_on::TwoHolder<T1,T2> > { 
00177             typedef ESPreFunctorDecorator<TRecord,typename depends_on::HolderToCaller<TRecord, depends_on::TwoHolder<T1, T2> >::Caller_t >
00178             Decorator_t; 
00179          };
00180       template< typename T, typename TRecord, typename T1, typename T2>
00181          inline ESPreFunctorDecorator<TRecord,typename depends_on::HolderToCaller<TRecord, depends_on::TwoHolder<T1, T2> >::Caller_t >
00182          createDecoratorFrom(T* iT, const TRecord*iRec, const depends_on::TwoHolder<T1,T2>& iHolder) {
00183             return ESPreFunctorDecorator<TRecord, typename depends_on::HolderToCaller<TRecord,depends_on::TwoHolder< T1, T2> >::Caller_t >
00184             (createDependsOnCaller(iT, iRec, iHolder.h2_, makeCaller(iT, iRec, iHolder.h1_)));
00185          }
00186       
00187       
00188       //The actual dependsOn functions which users call
00189       template <typename T, typename TDependsOnRecord>
00190          depends_on::OneHolder<T,TDependsOnRecord> 
00191          dependsOn(void(T::*iT)(const TDependsOnRecord&)) { return iT ; }
00192       
00193       template< typename T, typename T1, typename T2>
00194          depends_on::TwoHolder<depends_on::OneHolder<T,T1>, T2> 
00195          dependsOn(void (T::* iT1)(const T1&), T2 iT2) { return depends_on::OneHolder<T, T1>(iT1) & iT2; }
00196       
00197       template< typename T, typename T1, typename T2, typename T3>
00198          depends_on::TwoHolder< depends_on::TwoHolder<depends_on::OneHolder<T,T1>, T2>, T3>
00199          dependsOn(void(T::* iT1)(const T1&), T2 iT2, T3 iT3) { return depends_on::OneHolder<T,T1>(iT1) & iT2 & iT3; }
00200       
00201 
00202    }
00203 }
00204 
00205 #endif