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