CMS 3D CMS Logo

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.8 2008/03/20 18:52:10 chrjones Exp $
00049 //
00050 
00051 // system include files
00052 
00053 // user include files
00054 #include "FWCore/Framework/interface/ESPreFunctorDecorator.h"
00055 #include "FWCore/Framework/interface/IOVSyncValue.h"
00056 #include "FWCore/Framework/interface/EventSetupRecord.h"
00057 
00058 // forward declarations
00059 
00060 
00061 namespace edm {
00062    namespace eventsetup {
00063       
00064       //Simple functor that checks to see if a Record has changed since the last time it was called
00065       // and if so, calls the appropriate member method.  Multiple callers can be chained together using the
00066       // TCallerChain template argument.
00067      template<class T, class TRecord, class TDependsOnRecord, class TCallerChain >
00068         struct DependsOnCaller
00069         {
00070         DependsOnCaller(T* iCallee, void(T::* iMethod)(const TDependsOnRecord&) , const TCallerChain& iChain) : 
00071           callee_(iCallee), method_(iMethod), chain_(iChain),cacheID_(0){} 
00072       
00073             void operator()(const TRecord& iRecord) {
00074             const TDependsOnRecord& record = iRecord.template getRecord<TDependsOnRecord>();
00075             if(record.cacheIdentifier() != cacheID_) {
00076               (callee_->*method_)(record);
00077               cacheID_=record.cacheIdentifier();
00078             }
00079             //call next 'functor' in our chain
00080             chain_(iRecord);
00081           }
00082         private:
00083           T* callee_;
00084           void (T::*method_)(const TDependsOnRecord&);
00085           TCallerChain chain_;
00086           unsigned long long cacheID_;
00087         };
00088 
00089       //helper function to help create a DependsOnCaller
00090       template<class T, class TRecord, class TDependsOnRecord, class TCallerChain >
00091          DependsOnCaller<T,TRecord, TDependsOnRecord, TCallerChain>
00092          createDependsOnCaller(T* iCallee, const TRecord*, void(T::*iMethod)(const TDependsOnRecord&), const TCallerChain& iChain) 
00093       {
00094             return DependsOnCaller<T,TRecord, TDependsOnRecord, TCallerChain>(iCallee, iMethod, iChain);
00095       }
00096       
00097       //A 'do nothing' functor that is used to terminate our chain of functors
00098       template<class TRecord>
00099          struct DependsOnDoNothingCaller { void operator()(const TRecord&) {} };
00100       
00101       //put implementation details used to get the dependsOn method to work into their own namespace
00102       namespace depends_on {
00103          //class to hold onto one member method pointer
00104          template <class T, class TDependsOnRecord>
00105          struct OneHolder {
00106             typedef T Prod_t;
00107             typedef TDependsOnRecord DependsOnRecord_t;
00108             
00109             OneHolder(void (T::*iHoldee)(const TDependsOnRecord&)) : holdee_(iHoldee) {}
00110             void (T::*holdee_)(const TDependsOnRecord&);
00111             
00112          };
00113          
00114          //class to create a linked list of member method pointers
00115          template <class T, class U>
00116             struct TwoHolder {
00117                typedef T T1_t;
00118                typedef U T2_t;
00119                TwoHolder(T i1, U i2) : h1_(i1), h2_(i2) {}
00120                T h1_;
00121                U h2_;
00122             };
00123 
00124          //allows one to create the linked list by applying operator & to member method pointers
00125          template< class T, class U>
00126             TwoHolder<T,U> operator&(const T& iT, const U& iU) {
00127                return TwoHolder<T,U>(iT, iU);
00128             }
00129          
00130          //HolderToCaller is used to state how a OneHolder or TwoHolder is converted into the appropriate 
00131          // DependsOnCaller.  This class is needed to define the return value of the makeCaller function
00132          template< class TRecord, class THolder>
00133             struct HolderToCaller {
00134             };
00135          template< class TRecord, class T, class TDependsOnRecord >
00136             struct HolderToCaller<TRecord, OneHolder<T, TDependsOnRecord> > {
00137                typedef DependsOnCaller<T,TRecord, TDependsOnRecord, DependsOnDoNothingCaller<TRecord> > Caller_t;
00138             };
00139          template< class TRecord, class T, class T1, class T2>
00140             struct HolderToCaller< TRecord, TwoHolder<T1, void (T::*)(const T2&) > > {
00141                typedef DependsOnCaller<T, TRecord, T2 , typename HolderToCaller<TRecord,T1>::Caller_t > Caller_t;
00142             };
00143 
00144          //helper function to convert a OneHolder or TwoHolder into a DependsOnCaller.
00145          template<class T, class TDependsOnRecord, class TRecord>
00146             DependsOnCaller<T,TRecord, TDependsOnRecord, DependsOnDoNothingCaller<TRecord> >
00147             makeCaller(T*iT, const TRecord* iRec, const OneHolder<T, TDependsOnRecord>& iHolder) {
00148                return createDependsOnCaller(iT, iRec, iHolder.holdee_, DependsOnDoNothingCaller<TRecord>());
00149             }
00150          
00151          template<class T, class T1, class T2, class TRecord>
00152             DependsOnCaller<T,TRecord, T2, typename HolderToCaller<TRecord, T1>::Caller_t >
00153             makeCaller(T*iT, const TRecord* iRec, const TwoHolder<T1, void (T::*)(const T2&)>& iHolder) {
00154                return createDependsOnCaller(iT, iRec, iHolder.h2_, makeCaller(iT, iRec, iHolder.h1_));
00155             }
00156       }
00157       
00158       //DecoratorFromArg is used to declare the return type of 'createDecoratorFrom' based on the arguments to the function.
00159       template< typename T, typename TRecord, typename TArg>
00160          struct DecoratorFromArg { typedef TArg Decorator_t; };
00161       
00162       template< typename T, typename TRecord, typename TDependsOnRecord>
00163          struct DecoratorFromArg<T,TRecord, depends_on::OneHolder<T,TDependsOnRecord> > { 
00164             typedef ESPreFunctorDecorator<TRecord,DependsOnCaller<T,TRecord, TDependsOnRecord, DependsOnDoNothingCaller<TRecord> > > Decorator_t; 
00165          };
00166       
00167       
00168       template< typename T, typename TRecord, typename TDependsOnRecord >
00169          inline ESPreFunctorDecorator<TRecord,DependsOnCaller<T,TRecord, TDependsOnRecord, DependsOnDoNothingCaller<TRecord> > > 
00170          createDecoratorFrom(T* iT, const TRecord*iRec, const depends_on::OneHolder<T,TDependsOnRecord>& iHolder) {
00171             DependsOnDoNothingCaller<TRecord> tCaller;
00172             ESPreFunctorDecorator<TRecord,DependsOnCaller<T,TRecord, TDependsOnRecord, DependsOnDoNothingCaller<TRecord> > >
00173                temp(createDependsOnCaller(iT, iRec, iHolder.holdee_, tCaller));
00174             return temp;
00175          }
00176       
00177       template< typename T, typename TRecord, typename T1, typename T2>
00178          struct DecoratorFromArg<T,TRecord, depends_on::TwoHolder<T1,T2> > { 
00179             typedef ESPreFunctorDecorator<TRecord,typename depends_on::HolderToCaller<TRecord, depends_on::TwoHolder<T1, T2> >::Caller_t >
00180             Decorator_t; 
00181          };
00182       template< typename T, typename TRecord, typename T1, typename T2>
00183          inline ESPreFunctorDecorator<TRecord,typename depends_on::HolderToCaller<TRecord, depends_on::TwoHolder<T1, T2> >::Caller_t >
00184          createDecoratorFrom(T* iT, const TRecord*iRec, const depends_on::TwoHolder<T1,T2>& iHolder) {
00185             return ESPreFunctorDecorator<TRecord, typename depends_on::HolderToCaller<TRecord,depends_on::TwoHolder< T1, T2> >::Caller_t >
00186             (createDependsOnCaller(iT, iRec, iHolder.h2_, makeCaller(iT, iRec, iHolder.h1_)));
00187          }
00188       
00189       
00190       //The actual dependsOn functions which users call
00191       template <typename T, typename TDependsOnRecord>
00192          depends_on::OneHolder<T,TDependsOnRecord> 
00193          dependsOn(void(T::*iT)(const TDependsOnRecord&)) { return iT ; }
00194       
00195       template< typename T, typename T1, typename T2>
00196          depends_on::TwoHolder<depends_on::OneHolder<T,T1>, T2> 
00197          dependsOn(void (T::* iT1)(const T1&), T2 iT2) { return depends_on::OneHolder<T, T1>(iT1) & iT2; }
00198       
00199       template< typename T, typename T1, typename T2, typename T3>
00200          depends_on::TwoHolder< depends_on::TwoHolder<depends_on::OneHolder<T,T1>, T2>, T3>
00201          dependsOn(void(T::* iT1)(const T1&), T2 iT2, T3 iT3) { return depends_on::OneHolder<T,T1>(iT1) & iT2 & iT3; }
00202       
00203 
00204    }
00205 }
00206 
00207 #endif

Generated on Tue Jun 9 17:35:36 2009 for CMSSW by  doxygen 1.5.4