Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:13:25

0001 #ifndef gen_FortranInstance_h
0002 #define gen_FortranInstance_h
0003 
0004 #include <string>
0005 
0006 namespace gen {
0007 
0008   // the callbacks from Pythia6/Herwig6 which are passed to the FortranInstance
0009   extern "C" {
0010   void upinit_();
0011   void upevnt_();
0012   void upveto_(int *);
0013   }
0014 
0015   class FortranInstance {
0016   public:
0017     FortranInstance() : instanceNesting(0) {}
0018     virtual ~FortranInstance() noexcept(false);
0019 
0020     void call(void (&fn)()) {
0021       InstanceWrapper wrapper(this);
0022       fn();
0023     }
0024     template <typename T>
0025     T call(T (&fn)()) {
0026       InstanceWrapper wrapper(this);
0027       return fn();
0028     }
0029     template <typename A>
0030     void call(void (&fn)(A), A a) {
0031       InstanceWrapper wrapper(this);
0032       fn(a);
0033     }
0034     template <typename T, typename A>
0035     T call(T (&fn)(A), A a) {
0036       InstanceWrapper wrapper(this);
0037       return fn(a);
0038     }
0039     template <typename A1, typename A2>
0040     void call(void (&fn)(A1, A2), A1 a1, A2 a2) {
0041       InstanceWrapper wrapper(this);
0042       fn(a1, a2);
0043     }
0044     template <typename T, typename A1, typename A2>
0045     T call(T (&fn)(A1, A2), A1 a1, A2 a2) {
0046       InstanceWrapper wrapper(this);
0047       return fn(a1, a2);
0048     }
0049 
0050     // if a member is instantiated at the beginning of a method,
0051     // it makes sure this FortranInstance instance is kept as
0052     // current instance during the execution of the method
0053     // This wrapper makes the enter()..leave() cycle exception-safe
0054     struct InstanceWrapper {
0055       InstanceWrapper(FortranInstance *instance) {
0056         this->instance = instance;
0057         instance->enter();
0058       }
0059 
0060       ~InstanceWrapper() { instance->leave(); }
0061 
0062       FortranInstance *instance;
0063     };
0064 
0065     // set this instance to be the current one
0066     // will throw exception when trying to reenter Herwig twice
0067     virtual void enter();
0068 
0069     // leave instance
0070     // will throw if the currently running instance does not match
0071     virtual void leave();
0072 
0073     // get the currently running instance (from enterInstance)
0074     // intended for callbacks from Fortran
0075     template <typename T>
0076     static T *getInstance() {
0077       T *instance = dynamic_cast<T *>(currentInstance);
0078       if (!instance)
0079         throwMissingInstance();
0080       return instance;
0081     }
0082 
0083     // Fortran callbacks
0084     virtual void upInit();
0085     virtual void upEvnt();
0086     virtual bool upVeto();
0087 
0088     static const std::string kFortranInstance;
0089 
0090   private:
0091     // list all the Fortran callbacks here
0092     friend void gen::upinit_();
0093     friend void gen::upevnt_();
0094     friend void gen::upveto_(int *);
0095 
0096     // internal methods
0097     static void throwMissingInstance();
0098 
0099     // how many times enter() was called
0100     // this is to make sure leave() will release the instance
0101     // after the same number of calls
0102     // nesting can in theory occur if the Fortran callback calls
0103     // into Herwig again
0104     int instanceNesting;
0105 
0106     // this points to the Herwig instance that is currently being executed
0107     static FortranInstance *currentInstance;
0108   };
0109 
0110 }  // namespace gen
0111 
0112 #endif  // gen_FortranInstance_h