Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-14 08:50:24

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