File indexing completed on 2025-01-18 09:55:14
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #ifndef DD4HEP_CALLBACK_H
0014 #define DD4HEP_CALLBACK_H
0015
0016
0017 #include <algorithm>
0018 #include <typeinfo>
0019 #include <vector>
0020
0021
0022 namespace dd4hep {
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038 class Callback {
0039 public:
0040 typedef unsigned long (*func_t)(void* obj, const void* fun, const void* args[]);
0041
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
0052 Callback()
0053 : par(0), call(0) {
0054 func.first = func.second = 0;
0055 }
0056
0057 Callback(void* p)
0058 : par(p), call(0) {
0059 func.first = func.second = 0;
0060 }
0061
0062 Callback(const void* p)
0063 : par((void*)p), call(0) {
0064 func.first = func.second = 0;
0065 }
0066
0067 Callback(void* p, void* mf, func_t c)
0068 : par(p), call(c) {
0069 func = *(mfunc_t*) mf;
0070 }
0071
0072 operator bool() const {
0073 return (call && par && func.first);
0074 }
0075
0076 unsigned long execute(const void* user_param[]) const {
0077 return (*this) ? call(par, &func, user_param) : 0;
0078 }
0079
0080 template <typename T> static T* cast(void* p) {
0081 return (T*) p;
0082 }
0083
0084 template <typename T> static const T* c_cast(const void* p) {
0085 return (const T*) p;
0086 }
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097 template <typename T> class Wrapper {
0098 public:
0099 typedef T pmf_t;
0100
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
0118
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
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
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
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
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
0169
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
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
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
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
0213
0214
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
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
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
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
0262
0263
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
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
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
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
0330
0331
0332
0333
0334
0335
0336
0337
0338
0339 struct CallbackSequence {
0340 typedef std::vector<Callback> Callbacks;
0341 enum Location { FRONT, END };
0342 Callbacks callbacks;
0343
0344 CallbackSequence() {
0345 }
0346
0347 CallbackSequence(const CallbackSequence& c)
0348 : callbacks(c.callbacks) {
0349 }
0350
0351 CallbackSequence& operator=(const CallbackSequence& c) {
0352 if ( this != & c ) callbacks = c.callbacks;
0353 return *this;
0354 }
0355
0356
0357
0358
0359 bool empty() const {
0360 return callbacks.empty();
0361 }
0362
0363 void clear() {
0364 callbacks.clear();
0365 }
0366
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
0374 void add(const Callback& cb) {
0375 callbacks.insert(callbacks.end(),cb);
0376 }
0377
0378 void operator()() const;
0379
0380 template <typename A0> void operator()(A0 a0) const;
0381
0382 template <typename A0, typename A1> void operator()(A0 a0, A1 a1) const;
0383
0384 template <typename A0, typename A1, typename A2> void operator()(A0 a0, A1 a1, A2 a2) const;
0385
0386 static void checkTypes(const std::type_info& typ1, const std::type_info& typ2, void* test);
0387
0388
0389
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
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
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
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
0415
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
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
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
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
0442
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
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
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
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
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
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
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
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 }
0505 #endif