Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:55:14

0001 //==========================================================================
0002 //  AIDA Detector description implementation 
0003 //--------------------------------------------------------------------------
0004 // Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
0005 // All rights reserved.
0006 //
0007 // For the licensing terms see $DD4hepINSTALL/LICENSE.
0008 // For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
0009 //
0010 // Author     : M.Frank
0011 //
0012 //==========================================================================
0013 #ifndef DD4HEP_CALLBACK_H
0014 #define DD4HEP_CALLBACK_H
0015 
0016 // C/C++ include files
0017 #include <algorithm>
0018 #include <typeinfo>
0019 #include <vector>
0020 
0021 /// Namespace for the AIDA detector description toolkit
0022 namespace dd4hep {
0023 
0024 
0025   /// Definition of the generic callback structure for member functions
0026   /**
0027    *  The callback structure allows to wrap any member function with up to
0028    *  3 arguments into an abstract objects, which could later be called
0029    *  using the argument list. The pointer to the hosting objects is stored
0030    *  in the callback object. The callback objects in this sense behaves
0031    *  very similar to a static function.
0032    *
0033    *  \author  M.Frank
0034    *  \date    01/03/2013
0035    *  \version 1.0
0036    *  \ingroup DD4HEP
0037    */
0038   class Callback {
0039   public:
0040     typedef unsigned long (*func_t)(void* obj, const void* fun, const void* args[]);
0041     /// Structure definition to store callback related data  \ingroup DD4HEP
0042     struct mfunc_t {
0043       void *first, *second;
0044     };
0045     typedef unsigned long ulong;
0046 
0047     void* par;
0048     func_t call;
0049     mfunc_t func;
0050 
0051     /// Default constructor
0052     Callback()
0053       : par(0), call(0) {
0054       func.first = func.second = 0;
0055     }
0056     /// Constructor with object initialization
0057     Callback(void* p)
0058       : par(p), call(0) {
0059       func.first = func.second = 0;
0060     }
0061     /// Constructor with object initialization
0062     Callback(const void* p)
0063       : par((void*)p), call(0) {
0064       func.first = func.second = 0;
0065     }
0066     /// Initializing constructor
0067     Callback(void* p, void* mf, func_t c)
0068       : par(p), call(c) {
0069       func = *(mfunc_t*) mf;
0070     }
0071     /// Check validity of the callback object
0072     operator bool() const {
0073       return (call && par && func.first);
0074     }
0075     /// Execute the callback with the required number of user parameters
0076     unsigned long execute(const void* user_param[]) const {
0077       return (*this) ? call(par, &func, user_param) : 0;
0078     }
0079     /// Template cast function used internally by the wrapper for type conversion to the object's type
0080     template <typename T> static T* cast(void* p) {
0081       return (T*) p;
0082     }
0083     /// Template const cast function used internally by the wrapper for type conversion to the object's type
0084     template <typename T> static const T* c_cast(const void* p) {
0085       return (const T*) p;
0086     }
0087 
0088     /// Wrapper around a C++ member function pointer
0089     /**
0090      *  Generic wrapper around a object member function.
0091      *
0092      *  \author  M.Frank
0093      *  \date    01/03/2013
0094      *  \version 1.0
0095      *  \ingroup DD4HEP
0096      */
0097     template <typename T> class Wrapper {
0098     public:
0099       typedef T pmf_t;
0100       /// Union to store pointers to member functions in callback objects
0101       union Functor {
0102         mfunc_t ptr;
0103         pmf_t pmf;
0104         Functor(const void* f) {
0105           ptr = *(mfunc_t*) f;
0106         }
0107         Functor(pmf_t f) {
0108           pmf = f;
0109         }
0110       };
0111       static mfunc_t pmf(pmf_t f) {
0112         const Functor func(f);
0113         return func.ptr;
0114       }
0115     };
0116 
0117     /** Callback setup with no arguments  */
0118     /// Callback setup function for Callbacks with member functions taking no arguments
0119     template <typename T> const Callback& _make(ulong (*fptr)(void* o, const void* f, const void* u[]), T pmf) {
0120       typename Wrapper<T>::Functor f(pmf);
0121       func = f.ptr;
0122       call = fptr;
0123       return *this;
0124     }
0125     /// Callback setup function for Callbacks with member functions with explicit return type taking no arguments
0126     template <typename R, typename T> const Callback& make(R (T::*pmf)()) {
0127       typedef R (T::*pfunc_t)();
0128       struct _Wrapper : public Wrapper<pfunc_t> {
0129         static ulong call(void* o, const void* f, const void*[]) {
0130           return (ulong) (cast<T>(o)->*(typename Wrapper<pfunc_t>::Functor(f).pmf))();
0131         }
0132       };
0133       return _make(_Wrapper::call, pmf);
0134     }
0135     /// Callback setup function for Callbacks with const member functions with explicit return type taking no arguments
0136     template <typename R, typename T> const Callback& make(R (T::*pmf)() const) {
0137       typedef R (T::*pfunc_t)() const;
0138       struct _Wrapper : public Wrapper<pfunc_t> {
0139         static ulong call(void* o, const void* f, const void*[]) {
0140           return (ulong) (cast<T>(o)->*(typename Wrapper<pfunc_t>::Functor(f).pmf))();
0141         }
0142       };
0143       return _make(_Wrapper::call, pmf);
0144     }
0145     /// Callback setup function for Callbacks with void member functions taking no arguments
0146     template <typename T> const Callback& make(void (T::*pmf)()) {
0147       typedef void (T::*pfunc_t)() const;
0148       struct _Wrapper : public Wrapper<pfunc_t> {
0149         static ulong call(void* o, const void* f, const void*[]) {
0150           (cast<T>(o)->*(typename Wrapper<pfunc_t>::Functor(f).pmf))();
0151           return 1;
0152         }
0153       };
0154       return _make(_Wrapper::call, pmf);
0155     }
0156     /// Callback setup function for Callbacks with const void member functions taking no arguments
0157     template <typename T> const Callback& make(void (T::*pmf)() const) {
0158       typedef void (T::*pfunc_t)() const;
0159       struct _Wrapper : public Wrapper<pfunc_t> {
0160         static ulong call(void* o, const void* f, const void*[]) {
0161           (cast<T>(o)->*(typename Wrapper<pfunc_t>::Functor(f).pmf))();
0162           return 1;
0163         }
0164       };
0165       return _make(_Wrapper::call, pmf);
0166     }
0167 
0168     /** Callbacks with 1 argument  */
0169     /// Callback setup function for Callbacks with member functions with explicit return type taking 1 argument
0170     template <typename R, typename T, typename A> const Callback& make(R (T::*pmf)(A)) {
0171       typedef R (T::*pfunc_t)(A);
0172       struct _Wrapper : public Wrapper<pfunc_t> {
0173         static ulong call(void* o, const void* f, const void* u[]) {
0174           return (ulong) (cast<T>(o)->*(typename Wrapper<pfunc_t>::Functor(f).pmf))((A) u[0]);
0175         }
0176       };
0177       return _make(_Wrapper::call, pmf);
0178     }
0179     /// Callback setup function for Callbacks with const member functions with explicit return type taking 1 argument
0180     template <typename R, typename T, typename A> const Callback& make(R (T::*pmf)(A) const) {
0181       typedef R (T::*pfunc_t)(A) const;
0182       struct _Wrapper : public Wrapper<pfunc_t> {
0183         static ulong call(void* o, const void* f, const void* u[]) {
0184           return (ulong) (cast<T>(o)->*(typename Wrapper<pfunc_t>::Functor(f).pmf))((A) u[0]);
0185         }
0186       };
0187       return _make(_Wrapper::call, pmf);
0188     }
0189     /// Callback setup function for Callbacks with void member functions taking 1 argument
0190     template <typename T, typename A> const Callback& make(void (T::*pmf)(A)) {
0191       typedef void (T::*pfunc_t)(const A);
0192       struct _Wrapper : public Wrapper<pfunc_t> {
0193         static ulong call(void* o, const void* f, const void* u[]) {
0194           (cast<T>(o)->*(typename Wrapper<pfunc_t>::Functor(f).pmf))((A) u[0]);
0195           return 1;
0196         }
0197       };
0198       return _make(_Wrapper::call, pmf);
0199     }
0200     /// Callback setup function for Callbacks with const void member functions taking 1 argument
0201     template <typename T, typename A> const Callback& make(void (T::*pmf)(A) const) {
0202       typedef void (T::*pfunc_t)(const A) const;
0203       struct _Wrapper : public Wrapper<pfunc_t> {
0204         static ulong call(void* o, const void* f, const void* u[]) {
0205           (cast<T>(o)->*(typename Wrapper<pfunc_t>::Functor(f).pmf))((A) u[0]);
0206           return 1;
0207         }
0208       };
0209       return _make(_Wrapper::call, pmf);
0210     }
0211 
0212     /** Callback with 2 arguments     */
0213 
0214     /// Callback setup function for Callbacks with member functions with explicit return type taking 2 arguments
0215     template <typename R, typename T, typename A0, typename A1> const Callback& make(R (T::*pmf)(A0, A1)) {
0216       typedef R (T::*pfunc_t)(A0, A1);
0217       typedef Wrapper<pfunc_t> _W;
0218       struct _Wrapper : public _W {
0219         static ulong call(void* o, const void* f, const void* u[]) {
0220           return (ulong) (cast<T>(o)->*(typename _W::Functor(f).pmf))((A0) u[0], (A1) u[1]);
0221         }
0222       };
0223       return _make(_Wrapper::call, pmf);
0224     }
0225     /// Callback setup function for Callbacks with const member functions with explicit return type taking 2 arguments
0226     template <typename R, typename T, typename A0, typename A1> const Callback& make(R (T::*pmf)(A0, A1) const) {
0227       typedef R (T::*pfunc_t)(A0, A1);
0228       typedef Wrapper<pfunc_t> _W;
0229       struct _Wrapper : public _W {
0230         static ulong call(void* o, const void* f, const void* u[]) {
0231           return (ulong) (cast<T>(o)->*(typename _W::Functor(f).pmf))((A0) u[0], (A1) u[1]);
0232         }
0233       };
0234       return _make(_Wrapper::call, pmf);
0235     }
0236     /// Callback setup function for Callbacks with const void member functions taking 2 arguments
0237     template <typename T, typename A0, typename A1> const Callback& make(void (T::*pmf)(A0, A1)) {
0238       typedef void (T::*pfunc_t)(A0, A1);
0239       typedef Wrapper<pfunc_t> _W;
0240       struct _Wrapper : public _W {
0241         static ulong call(void* o, const void* f, const void* u[]) {
0242           (cast<T>(o)->*(typename _W::Functor(f).pmf))((A0) u[0], (A1) u[1]);
0243           return 1;
0244         }
0245       };
0246       return _make(_Wrapper::call, pmf);
0247     }
0248     /// Callback setup function for Callbacks with const void member functions taking 2 arguments
0249     template <typename T, typename A0, typename A1> const Callback& make(void (T::*pmf)(A0, A1) const) {
0250       typedef void (T::*pfunc_t)(A0, A1);
0251       typedef Wrapper<pfunc_t> _W;
0252       struct _Wrapper : public _W {
0253         static ulong call(void* o, const void* f, const void* u[]) {
0254           (cast<T>(o)->*(typename _W::Functor(f).pmf))((A0) u[0], (A1) u[1]);
0255           return 1;
0256         }
0257       };
0258       return _make(_Wrapper::call, pmf);
0259     }
0260 
0261     /** Callback setup for callbacks with 3 arguments  */
0262 
0263     /// Callback setup function for Callbacks with member functions with explicit return type taking 3 arguments
0264     template <typename R, typename T, typename A0, typename A1, typename A2> const Callback& make(R (T::*pmf)(A0, A1, A2)) {
0265       typedef R (T::*pfunc_t)(A0, A1, A2);
0266       typedef Wrapper<pfunc_t> _W;
0267       struct _Wrapper : public _W {
0268         static ulong call(void* o, const void* f, const void* u[]) {
0269           return (ulong) (cast<T>(o)->*(typename _W::Functor(f).pmf))((A0) u[0], (A1) u[1], (A2) u[2]);
0270         }
0271       };
0272       return _make(_Wrapper::call, pmf);
0273     }
0274     /// Callback setup function for Callbacks with const member functions with explicit return type taking 3 arguments
0275     template <typename R, typename T, typename A0, typename A1, typename A2> const Callback& make(R (T::*pmf)(A0, A1, A2) const) {
0276       typedef R (T::*pfunc_t)(A0, A1, A2);
0277       typedef Wrapper<pfunc_t> _W;
0278       struct _Wrapper : public _W {
0279         static ulong call(void* o, const void* f, const void* u[]) {
0280           return (ulong) (cast<T>(o)->*(typename _W::Functor(f).pmf))((A0) u[0], (A1) u[1], (A2) u[2]);
0281         }
0282       };
0283       return _make(_Wrapper::call, pmf);
0284     }
0285     /// Callback setup function for Callbacks with const void member functions taking 3 arguments
0286     template <typename T, typename A0, typename A1, typename A2> const Callback& make(void (T::*pmf)(A0, A1, A2)) {
0287       typedef void (T::*pfunc_t)(A0, A1, A2);
0288       typedef Wrapper<pfunc_t> _W;
0289       struct _Wrapper : public _W {
0290         static ulong call(void* o, const void* f, const void* u[]) {
0291           (cast<T>(o)->*(typename _W::Functor(f).pmf))((A0) u[0], (A1) u[1], (A2) u[2]);
0292           return 1;
0293         }
0294       };
0295       return _make(_Wrapper::call, pmf);
0296     }
0297     /// Callback setup function for Callbacks with const void member functions taking 3 arguments
0298     template <typename T, typename A0, typename A1, typename A2> const Callback& make(void (T::*pmf)(A0, A1, A2) const) {
0299       typedef void (T::*pfunc_t)(A0, A1, A2);
0300       typedef Wrapper<pfunc_t> _W;
0301       struct _Wrapper : public _W {
0302         static ulong call(void* o, const void* f, const void* u[]) {
0303           (cast<T>(o)->*(typename _W::Functor(f).pmf))((A0) u[0], (A1) u[1], (A2) u[2]);
0304           return 1;
0305         }
0306       };
0307       return _make(_Wrapper::call, pmf);
0308     }
0309 
0310     template <typename T> static Callback make(void* p, T pmf) {
0311       return Callback(p).make(pmf);
0312     }
0313 
0314     template <typename P, typename R, typename T> static T* dyn_cast(P* p, R (T::*)()) {
0315       return dynamic_cast<T*>(p);
0316     }
0317     template <typename P, typename R, typename T> static const T* dyn_cast(const P* p, R (T::*)() const) {
0318       return dynamic_cast<const T*>(p);
0319     }
0320 
0321     template <typename P, typename R, typename T, typename A> static T* dyn_cast(P* p, R (T::*)(A)) {
0322       return dynamic_cast<T*>(p);
0323     }
0324     template <typename P, typename R, typename T, typename A> static const T* dyn_cast(const P* p, R (T::*)(A) const) {
0325       return dynamic_cast<const T*>(p);
0326     }
0327   };
0328 
0329   /// Definition of an actor on sequences of callbacks
0330   /**
0331    *  A callback sequence is a set of callbacks with identical signature, so that
0332    *  the can be called consecutively using the same arguments.
0333    *
0334    *  \author  M.Frank
0335    *  \date    01/03/2013
0336    *  \version 0.1
0337    *  \ingroup DD4HEP
0338    */
0339   struct CallbackSequence {
0340     typedef std::vector<Callback> Callbacks;
0341     enum Location { FRONT, END };
0342     Callbacks callbacks;
0343     /// Default constructor
0344     CallbackSequence() {
0345     }
0346     /// Copy constructor
0347     CallbackSequence(const CallbackSequence& c)
0348       : callbacks(c.callbacks) {
0349     }
0350     /// Assignment operator
0351     CallbackSequence& operator=(const CallbackSequence& c)  {
0352       if ( this != & c ) callbacks = c.callbacks;
0353       return *this;
0354     }
0355 
0356     //template <typename TYPE, typename R, typename OBJECT>
0357     //  CallbackSequence(const std::vector<TYPE*>& objects, R (TYPE::value_type::*pmf)())  {
0358     //}
0359     bool empty() const {
0360       return callbacks.empty();
0361     }
0362     /// Clear the sequence and remove all callbacks
0363     void clear() {
0364       callbacks.clear();
0365     }
0366     /// Generically Add a new callback to the sequence depending on the location arguments
0367     void add(const Callback& cb,Location where) {
0368       if ( where == CallbackSequence::FRONT )
0369         callbacks.insert(callbacks.begin(),cb);
0370       else
0371         callbacks.insert(callbacks.end(),cb);
0372     }
0373     /// Generically Add a new callback to the sequence depending on the location arguments
0374     void add(const Callback& cb) {
0375       callbacks.insert(callbacks.end(),cb);
0376     }
0377     /// Execution overload for callbacks with no arguments
0378     void operator()() const;
0379     /// Execution overload for callbacks with 1 argument
0380     template <typename A0> void operator()(A0 a0) const;
0381     /// Execution overload for callbacks with 2 arguments
0382     template <typename A0, typename A1> void operator()(A0 a0, A1 a1) const;
0383     /// Execution overload for callbacks with 3 arguments
0384     template <typename A0, typename A1, typename A2> void operator()(A0 a0, A1 a1, A2 a2) const;
0385     /// Check the compatibility of two typed objects. The test is the result of a dynamic_cast
0386     static void checkTypes(const std::type_info& typ1, const std::type_info& typ2, void* test);
0387 
0388     /** Callback setup for callbacks with no arguments  */
0389     /// Add a new callback to a member function with explicit return type and no arguments
0390     template <typename TYPE, typename R, typename OBJECT>
0391     void add(TYPE* pointer, R (OBJECT::*pmf)(),Location where=CallbackSequence::END) {
0392       checkTypes(typeid(TYPE), typeid(OBJECT), dynamic_cast<OBJECT*>(pointer));
0393       add(Callback(pointer).make(pmf),where);
0394     }
0395     /// Add a new callback to a const member function with explicit return type and no arguments
0396     template <typename TYPE, typename R, typename OBJECT>
0397     void add(TYPE* pointer, R (OBJECT::*pmf)() const,Location where=CallbackSequence::END) {
0398       checkTypes(typeid(TYPE), typeid(OBJECT), dynamic_cast<OBJECT*>(pointer));
0399       add(Callback(pointer).make(pmf),where);
0400     }
0401     /// Add a new callback to a void member function with no arguments
0402     template <typename TYPE, typename OBJECT>
0403     void add(TYPE* pointer, void (OBJECT::*pmf)(),Location where=CallbackSequence::END) {
0404       checkTypes(typeid(TYPE), typeid(OBJECT), dynamic_cast<OBJECT*>(pointer));
0405       add(Callback(pointer).make(pmf),where);
0406     }
0407     /// Add a new callback to a const void member function and no arguments
0408     template <typename TYPE, typename OBJECT>
0409     void add(TYPE* pointer, void (OBJECT::*pmf)() const,Location where=CallbackSequence::END) {
0410       checkTypes(typeid(TYPE), typeid(OBJECT), dynamic_cast<OBJECT*>(pointer));
0411       add(Callback(pointer).make(pmf),where);
0412     }
0413 
0414     /** Callback setup for callbacks with 1 argument  */
0415     /// Add a new callback to a member function with explicit return type and 1 argument
0416     template <typename TYPE, typename R, typename OBJECT, typename A>
0417     void add(TYPE* pointer, R (OBJECT::*pmf)(A),Location where=CallbackSequence::END) {
0418       checkTypes(typeid(TYPE), typeid(OBJECT), dynamic_cast<OBJECT*>(pointer));
0419       add(Callback(pointer).make(pmf),where);
0420     }
0421     /// Add a new callback to a void member function and 1 argument
0422     template <typename TYPE, typename OBJECT, typename A>
0423     void add(TYPE* pointer, void (OBJECT::*pmf)(A),Location where=CallbackSequence::END) {
0424       checkTypes(typeid(TYPE), typeid(OBJECT), dynamic_cast<OBJECT*>(pointer));
0425       add(Callback(pointer).make(pmf),where);
0426     }
0427     /// Add a new callback to a const member function with explicit return type and 1 argument
0428     template <typename TYPE, typename R, typename OBJECT, typename A>
0429     void add(TYPE* pointer, R (OBJECT::*pmf)(A) const,Location where=CallbackSequence::END) {
0430       checkTypes(typeid(TYPE), typeid(OBJECT), dynamic_cast<OBJECT*>(pointer));
0431       add(Callback(pointer).make(pmf),where);
0432     }
0433     /// Add a new callback to a const void member function and 1 argument
0434     template <typename TYPE, typename OBJECT, typename A>
0435     void add(TYPE* pointer, void (OBJECT::*pmf)(A) const,Location where=CallbackSequence::END) {
0436       checkTypes(typeid(TYPE), typeid(OBJECT), dynamic_cast<OBJECT*>(pointer));
0437       add(Callback(pointer).make(pmf),where);
0438     }
0439 
0440 
0441     /** Callback setup for callbacks with 2 arguments  */
0442     /// Add a new callback to a member function with explicit return type and 2 arguments
0443     template <typename TYPE, typename R, typename OBJECT, typename A1, typename A2>
0444     void add(TYPE* pointer, R (OBJECT::*pmf)(A1, A2),Location where=CallbackSequence::END) {
0445       checkTypes(typeid(TYPE), typeid(OBJECT), dynamic_cast<OBJECT*>(pointer));
0446       add(Callback(pointer).make(pmf),where);
0447     }
0448     /// Add a new callback to a const member function with explicit return type and 2 arguments
0449     template <typename TYPE, typename R, typename OBJECT, typename A1, typename A2>
0450     void add(TYPE* pointer, R (OBJECT::*pmf)(A1, A2) const,Location where=CallbackSequence::END) {
0451       checkTypes(typeid(TYPE), typeid(OBJECT), dynamic_cast<OBJECT*>(pointer));
0452       add(Callback(pointer).make(pmf),where);
0453     }
0454     /// Add a new callback to a void member function with 2 arguments
0455     template <typename TYPE, typename OBJECT, typename A1, typename A2>
0456     void add(TYPE* pointer, void (OBJECT::*pmf)(A1, A2),Location where=CallbackSequence::END) {
0457       checkTypes(typeid(TYPE), typeid(OBJECT), dynamic_cast<OBJECT*>(pointer));
0458       add(Callback(pointer).make(pmf),where);
0459     }
0460     /// Add a new callback to a const void member function with 2 arguments
0461     template <typename TYPE, typename OBJECT, typename A1, typename A2>
0462     void add(TYPE* pointer, void (OBJECT::*pmf)(A1, A2) const,Location where=CallbackSequence::END) {
0463       checkTypes(typeid(TYPE), typeid(OBJECT), dynamic_cast<OBJECT*>(pointer));
0464       add(Callback(pointer).make(pmf),where);
0465     }
0466   };
0467 
0468   /// Execution overload for callbacks with no arguments
0469   inline void CallbackSequence::operator()() const {
0470     if (!callbacks.empty()) {
0471       const void* args[1] = { 0 };
0472       for (Callbacks::const_iterator i = callbacks.begin(); i != callbacks.end(); ++i)
0473         (*i).execute(args);
0474     }
0475   }
0476   /// Execution overload for callbacks with 1 argument
0477   template <typename A0> inline
0478   void CallbackSequence::operator()(A0 a0) const {
0479     if (!callbacks.empty()) {
0480       const void* args[1] = { a0 };
0481       for (Callbacks::const_iterator i = callbacks.begin(); i != callbacks.end(); ++i)
0482         (*i).execute(args);
0483     }
0484   }
0485   /// Execution overload for callbacks with 2 arguments
0486   template <typename A0, typename A1> inline
0487   void CallbackSequence::operator()(A0 a0, A1 a1) const {
0488     if (!callbacks.empty()) {
0489       const void* args[2] = { a0, a1 };
0490       for (Callbacks::const_iterator i = callbacks.begin(); i != callbacks.end(); ++i)
0491         (*i).execute(args);
0492     }
0493   }
0494   /// Execution overload for callbacks with 3 arguments
0495   template <typename A0, typename A1, typename A2> inline
0496   void CallbackSequence::operator()(A0 a0, A1 a1, A2 a2) const {
0497     if (!callbacks.empty()) {
0498       const void* args[3] = { a0, a1, a2 };
0499       for (Callbacks::const_iterator i = callbacks.begin(); i != callbacks.end(); ++i)
0500         (*i).execute(args);
0501     }
0502   }
0503 
0504 }       // End namespace dd4hep
0505 #endif // DD4HEP_CALLBACK_H