CMS 3D CMS Logo

CMSSW_4_4_3_patch1/src/GeneratorInterface/Core/interface/FortranInstance.h

Go to the documentation of this file.
00001 #ifndef gen_FortranInstance_h
00002 #define gen_FortranInstance_h
00003 
00004 namespace gen {
00005 
00006 // the callbacks from Pythia6/Herwig6 which are passed to the FortranInstance
00007 extern "C" {
00008         void upinit_();
00009         void upevnt_();
00010         void upveto_(int*);
00011 }
00012 
00013 class FortranInstance {
00014     public:
00015         FortranInstance() : instanceNesting(0) {}
00016         virtual ~FortranInstance();
00017 
00018         void call(void(&fn)())
00019         { InstanceWrapper wrapper(this); fn(); }
00020         template<typename T> T call(T(&fn)())
00021         { InstanceWrapper wrapper(this); return fn(); }
00022         template<typename A> void call(void(&fn)(A), A a)
00023         { InstanceWrapper wrapper(this); fn(a); }
00024         template<typename T, typename A> T call(T(&fn)(A), A a)
00025         { InstanceWrapper wrapper(this); return fn(a); }
00026         template<typename A1, typename A2> void call(void(&fn)(A1, A2), A1 a1, A2 a2)
00027         { InstanceWrapper wrapper(this); fn(a1, a2); }
00028         template<typename T, typename A1, typename A2> T call(T(&fn)(A1, A2), A1 a1, A2 a2)
00029         { InstanceWrapper wrapper(this); return fn(a1, a2); }
00030 
00031         // if a member is instantiated at the beginning of a method,
00032         // it makes sure this FortranInstance instance is kept as
00033         // current instance during the execution of the method
00034         // This wrapper makes the enter()..leave() cycle exception-safe
00035         struct InstanceWrapper {
00036                 InstanceWrapper(FortranInstance *instance)
00037                 { this->instance = instance; instance->enter(); }
00038 
00039                 ~InstanceWrapper()
00040                 { instance->leave(); }
00041 
00042                 FortranInstance *instance;
00043         };
00044 
00045         // set this instance to be the current one
00046         // will throw exception when trying to reenter Herwig twice
00047         virtual void enter();
00048 
00049         // leave instance
00050         // will throw if the currently running instance does not match
00051         virtual void leave();
00052 
00053         // get the currently running instance (from enterInstance)
00054         // intended for callbacks from Fortran
00055         template<typename T>
00056         static T *getInstance()
00057         {
00058                 T *instance = dynamic_cast<T*>(currentInstance);
00059                 if (!instance)
00060                         throwMissingInstance();
00061                 return instance;
00062         }
00063 
00064         // Fortran callbacks
00065         virtual void upInit();
00066         virtual void upEvnt();
00067         virtual bool upVeto();
00068 
00069     private:
00070         // list all the Fortran callbacks here
00071         friend void gen::upinit_();
00072         friend void gen::upevnt_();
00073         friend void gen::upveto_(int*);
00074 
00075         // internal methods
00076         static void throwMissingInstance();
00077 
00078         // how many times enter() was called
00079         // this is to make sure leave() will release the instance
00080         // after the same number of calls
00081         // nesting can in theory occur if the Fortran callback calls
00082         // into Herwig again
00083         int                     instanceNesting;
00084 
00085         // this points to the Herwig instance that is currently being executed
00086         static FortranInstance  *currentInstance;
00087 };
00088 
00089 } // namespace gen
00090 
00091 #endif // gen_FortranInstance_h