GCC Code Coverage Report


Directory: src/gate/
File: src/gate/delegates.hpp
Date: 2025-09-14 13:10:38
Exec Total Coverage
Lines: 287 320 89.7%
Functions: 188 371 50.7%
Branches: 109 218 50.0%

Line Branch Exec Source
1 /* GATE PROJECT LICENSE:
2 +----------------------------------------------------------------------------+
3 | Copyright(c) 2018-2025, Stefan Meislinger <sm@opengate.at> |
4 | All rights reserved. |
5 | |
6 | Redistribution and use in source and binary forms, with or without |
7 | modification, are permitted provided that the following conditions are met:|
8 | |
9 | 1. Redistributions of source code must retain the above copyright notice, |
10 | this list of conditions and the following disclaimer. |
11 | 2. Redistributions in binary form must reproduce the above copyright |
12 | notice, this list of conditions and the following disclaimer in the |
13 | documentation and/or other materials provided with the distribution. |
14 | |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"|
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
18 | ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
25 | THE POSSIBILITY OF SUCH DAMAGE. |
26 +----------------------------------------------------------------------------+
27 */
28
29 /** @file
30 * @brief Generic encapsulation of callbacks for functions and objects
31 * @ingroup gatecore_cpp
32 */
33
34 #ifndef GATE_DELEGATES_HPP_INCLUDED
35 #define GATE_DELEGATES_HPP_INCLUDED
36
37 #include "gate/gate_core_api.hpp"
38 #include "gate/gatetypes.hpp"
39 #include "gate/memalloc.hpp"
40 #include "gate/arrays.hpp"
41 #include "gate/typetraits.hpp"
42 #include "gate/debugging.h"
43
44 #include "gate/delegates.h"
45
46 namespace gate
47 {
48
49 typedef gate_delegate_t delegate_t;
50
51 typedef gate_va_list_carrier_t va_list_carrier_t;
52
53 namespace details
54 {
55 #if !defined(GATE_COMPILER_SUPPORTS_CPP_PARTIAL_TEMPLATE_SPECIALIZATION)
56
57 template<class T> struct VaArgGetter
58 {
59 static T get(va_list_carrier_t& args)
60 {
61 if (traits::IsReferenceType<T>::value)
62 {
63 void* ptr = va_arg(args.data, void*);
64 traits::RemoveReference<T>::type_t* ptr_arg = static_cast<traits::RemoveReference<T>::type_t*>(ptr);
65 return *ptr_arg;
66 }
67 else
68 {
69 if (sizeof(T) < sizeof(int))
70 {
71 int intref = va_arg(args.data, int);
72 traits::RemoveReference<T>::type_t* ptr_arg = reinterpret_cast<T*>(ptr);
73 return *ptr_arg;
74 }
75 else
76 {
77 T arg = va_arg(args.data, T);
78 return arg;
79 }
80 }
81 }
82 };
83
84 template<class T> struct VaArgBuilder
85 {
86 static T get(T value)
87 {
88 return value;
89 }
90 };
91
92 #else
93 template<class T, bool use_int, bool is_ref> struct VaArgGetterImpl;
94
95 template<class T> struct VaArgGetterImpl<T, true, false>
96 {
97 12 static T get(va_list_carrier_t& args)
98 {
99 12 int intref = va_arg(args.data, int);
100 12 return *reinterpret_cast<typename traits::RemoveReference<T>::type_t*>(&intref);
101 }
102 };
103
104 template<class T> struct VaArgGetterImpl<T, true, true>
105 {
106 static T get(va_list_carrier_t args)
107 {
108 T tref = *reinterpret_cast<typename traits::RemoveReference<T>::type_t*>(va_arg(args.data, int*));
109 return tref;
110 }
111 };
112
113 template<class T> struct VaArgGetterImpl<T, false, false>
114 {
115 258 static T get(va_list_carrier_t& args)
116 {
117 258 T tref = va_arg(args.data, T);
118 258 return tref;
119 }
120 };
121
122 template<class T> struct VaArgGetterImpl<T, false, true>
123 {
124 8 static T get(va_list_carrier_t& args)
125 {
126 8 T tref = *(va_arg(args.data, typename traits::RemoveReference<T>::type_t*));
127 8 return tref;
128 }
129 };
130
131 template<class T> struct VaArgGetter : public VaArgGetterImpl < T, sizeof(T) < sizeof(int), traits::IsReference<T>::value >
132 {
133 };
134
135 template<class T, bool is_ref> struct VaArgBuilderImpl;
136 template<class T> struct VaArgBuilderImpl<T, true>
137 {
138 8 static typename traits::RemoveReference<T>::type_t* get(T value)
139 {
140 8 return &value;
141 }
142 };
143 template<class T> struct VaArgBuilderImpl<T, false>
144 {
145 270 static T get(T value)
146 {
147 270 return value;
148 }
149 };
150
151 template<class T> struct VaArgBuilder : public VaArgBuilderImpl< T, traits::IsReference<T>::value >
152 {
153 };
154
155 #endif
156
157 } // end of namespace details
158
159
160 /// @brief
161 class GATE_CORE_CPP_API Delegate : public SafeBoolBase<Delegate>
162 {
163 protected:
164 delegate_t impl;
165
166 Delegate();
167 Delegate(gate_delegate_dispatcher_t dispatcher, void* obj_ptr, void* function_ptr, size_t function_ptr_size);
168
169 static result_t handle_exception();
170 void translate_result(result_t result) const;
171
172 282 template<class T> static T next_va_arg(va_list_carrier_t& args)
173 {
174 282 return details::VaArgGetter<T>::get(args);
175 }
176
177 public:
178 ~Delegate();
179 delegate_t const* c_impl() const;
180 bool operator!() const;
181 bool operator==(Delegate const& src) const;
182 bool operator!=(Delegate const& src) const;
183
184 };
185
186
187 /// @brief
188 /// @tparam RETTYPE
189 template<class RETTYPE>
190 class GATE_CORE_CPP_API TDelegate0 : public Delegate
191 {
192 protected:
193 template<class FUNC>
194 struct function_dispatcher
195 {
196 8 static gate_result_t impl(gate_delegate_t const* delegate_ptr, gate_va_list_carrier_t* args)
197 {
198 8 FUNC& func = *gate::union_cast<FUNC*>(&delegate_ptr->function_storage);
199
200 try {
201
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 2 times.
8 func();
202 6 return results::Ok;
203 }
204
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 catch (...) { return handle_exception(); }
205 }
206 };
207
208 template<class O>
209 struct method_dispatcher
210 {
211 2 static gate_result_t impl(gate_delegate_t const* delegate_ptr, gate_va_list_carrier_t* args)
212 {
213 typedef RETTYPE(O::* method_t)();
214 2 O* obj = static_cast<O*>(delegate_ptr->object_ptr);
215 2 method_t& method = *gate::union_cast<method_t*>(&delegate_ptr->function_storage);
216
217 try {
218
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
2 (obj->*method)();
219 2 return results::Ok;
220 }
221 catch (...) { return handle_exception(); }
222 }
223 };
224
225 public:
226 1 TDelegate0()
227 1 {
228 1 }
229
230 11 template<class FUNC> TDelegate0(FUNC funcptr)
231 11 : Delegate(&function_dispatcher<FUNC>::impl, NULL, &funcptr, sizeof(funcptr))
232 {
233 11 }
234
235 3 template<class O> TDelegate0(O* obj_ptr, void(O::* method)())
236 3 : Delegate(&method_dispatcher<O>::impl, obj_ptr, &method, sizeof(method))
237 {
238 3 }
239
240 1 VoidResult tryInvoke() const
241 {
242
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 return makeResult(gate_delegate_invoke(this->c_impl()));
243 }
244 8 void invoke() const
245 {
246 8 this->translate_result(gate_delegate_invoke(this->c_impl()));
247 7 }
248 4 void operator()() const
249 {
250 4 this->invoke();
251 3 }
252 };
253 typedef TDelegate0<void> Delegate0;
254
255
256
257 /// @brief
258 /// @tparam A1
259 template<class A1>
260 class GATE_CORE_CPP_API Delegate1 : public Delegate
261 {
262 protected:
263 template<class FUNC>
264 struct function_dispatcher
265 {
266 18 static gate_result_t impl(gate_delegate_t const* delegate_ptr, gate_va_list_carrier_t* args)
267 {
268 18 FUNC& func = *gate::union_cast<FUNC*>(&delegate_ptr->function_storage);
269
270 try {
271
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
18 A1 arg1 = Delegate::next_va_arg<A1>(*args);
272
2/2
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
18 func(arg1);
273 14 return results::Ok;
274 }
275
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
4 catch (...) { return handle_exception(); }
276 }
277 };
278
279 template<class O>
280 struct method_dispatcher
281 {
282 2 static gate_result_t impl(gate_delegate_t const* delegate_ptr, gate_va_list_carrier_t* args)
283 {
284 typedef void(O::* method_t)(A1);
285 2 O* obj = static_cast<O*>(delegate_ptr->object_ptr);
286 2 method_t& method = *gate::union_cast<method_t*>(&delegate_ptr->function_storage);
287
288 try {
289
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 A1 arg1 = Delegate::next_va_arg<A1>(*args);
290
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
2 (obj->*method)(arg1);
291 2 return results::Ok;
292 }
293 catch (...) { return handle_exception(); }
294 }
295 };
296
297 public:
298 Delegate1()
299 {
300 }
301
302 22 template<class FUNC> Delegate1(FUNC funcptr)
303 22 : Delegate(&function_dispatcher<FUNC>::impl, NULL, &funcptr, sizeof(funcptr))
304 {
305 22 }
306
307 3 template<class O> Delegate1(O* obj_ptr, void(O::* method)(A1))
308 3 : Delegate(&method_dispatcher<O>::impl, obj_ptr, &method, sizeof(method))
309 {
310 3 }
311
312 1 VoidResult tryInvoke(A1 arg1) const
313 {
314 2 return makeResult(gate_delegate_invoke(this->c_impl(),
315 details::VaArgBuilder<A1>::get(arg1)
316
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 ));
317 }
318 20 void invoke(A1 arg1) const
319 {
320 20 translate_result(gate_delegate_invoke(this->c_impl(),
321 details::VaArgBuilder<A1>::get(arg1)
322 ));
323 18 }
324 10 void operator()(A1 arg1) const
325 {
326 10 this->invoke(arg1);
327 8 }
328 };
329
330
331
332 /// @brief
333 /// @tparam A1
334 /// @tparam A2
335 template<class A1, class A2>
336 class GATE_CORE_CPP_API Delegate2 : public Delegate
337 {
338 protected:
339 template<class FUNC>
340 struct function_dispatcher
341 {
342 6 static gate_result_t impl(gate_delegate_t const* delegate_ptr, gate_va_list_carrier_t* args)
343 {
344 6 FUNC& func = *gate::union_cast<FUNC*>(&delegate_ptr->function_storage);
345
346 try {
347
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
6 A1 arg1 = Delegate::next_va_arg<A1>(*args);
348
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
6 A2 arg2 = Delegate::next_va_arg<A2>(*args);
349
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
6 func(arg1, arg2);
350 2 return results::Ok;
351 }
352
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
4 catch (...) { return handle_exception(); }
353 }
354 };
355
356 template<class O>
357 struct method_dispatcher
358 {
359 2 static gate_result_t impl(gate_delegate_t const* delegate_ptr, gate_va_list_carrier_t* args)
360 {
361 typedef void(O::* method_t)(A1, A2);
362 2 O* obj = static_cast<O*>(delegate_ptr->object_ptr);
363 2 method_t& method = *gate::union_cast<method_t*>(&delegate_ptr->function_storage);
364
365 try {
366
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 A1 arg1 = Delegate::next_va_arg<A1>(*args);
367
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 A2 arg2 = Delegate::next_va_arg<A2>(*args);
368
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
2 (obj->*method)(arg1, arg2);
369 2 return results::Ok;
370 }
371 catch (...) { return handle_exception(); }
372 }
373 };
374
375 public:
376 Delegate2()
377 {
378 }
379
380 4 template<class FUNC> Delegate2(FUNC funcptr)
381 4 : Delegate(&function_dispatcher<FUNC>::impl, NULL, &funcptr, sizeof(funcptr))
382 {
383 4 }
384
385 2 template<class O> Delegate2(O* obj_ptr, void(O::* method)(A1, A2))
386 2 : Delegate(&method_dispatcher<O>::impl, obj_ptr, &method, sizeof(method))
387 {
388 2 }
389
390 1 VoidResult tryInvoke(A1 arg1, A2 arg2) const
391 {
392 2 return makeResult(gate_delegate_invoke(this->c_impl(),
393 details::VaArgBuilder<A1>::get(arg1),
394 details::VaArgBuilder<A2>::get(arg2)
395
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 ));
396 }
397 8 void invoke(A1 arg1, A2 arg2) const
398 {
399 8 translate_result(gate_delegate_invoke(&this->impl,
400 details::VaArgBuilder<A1>::get(arg1),
401 details::VaArgBuilder<A2>::get(arg2)
402 ));
403 6 }
404 8 void operator()(A1 arg1, A2 arg2) const
405 {
406 8 this->invoke(arg1, arg2);
407 6 }
408 };
409
410
411 /// @brief
412 /// @tparam A1
413 /// @tparam A2
414 /// @tparam A3
415 template<class A1, class A2, class A3>
416 class GATE_CORE_CPP_API Delegate3 : public Delegate
417 {
418 protected:
419 template<class FUNC>
420 struct function_dispatcher
421 {
422 8 static gate_result_t impl(gate_delegate_t const* delegate_ptr, gate_va_list_carrier_t* args)
423 {
424 8 FUNC& func = *gate::union_cast<FUNC*>(&delegate_ptr->function_storage);
425
426 try {
427
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
8 A1 arg1 = Delegate::next_va_arg<A1>(*args);
428
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
8 A2 arg2 = Delegate::next_va_arg<A2>(*args);
429
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
8 A3 arg3 = Delegate::next_va_arg<A3>(*args);
430
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 2 times.
8 func(arg1, arg2, arg3);
431 4 return results::Ok;
432 }
433
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
4 catch (...) { return handle_exception(); }
434 }
435 };
436
437 template<class O>
438 struct method_dispatcher
439 {
440 6 static gate_result_t impl(gate_delegate_t const* delegate_ptr, gate_va_list_carrier_t* args)
441 {
442 typedef void(O::* method_t)(A1, A2, A3);
443 6 O* obj = static_cast<O*>(delegate_ptr->object_ptr);
444 6 method_t& method = *gate::union_cast<method_t*>(&delegate_ptr->function_storage);
445
446 try {
447
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
6 A1 arg1 = Delegate::next_va_arg<A1>(*args);
448
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
6 A2 arg2 = Delegate::next_va_arg<A2>(*args);
449
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
6 A3 arg3 = Delegate::next_va_arg<A3>(*args);
450
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
6 (obj->*method)(arg1, arg2, arg3);
451 6 return results::Ok;
452 }
453 catch (...) { return handle_exception(); }
454 }
455 };
456
457 public:
458 Delegate3()
459 {
460 }
461
462 5 template<class FUNC> Delegate3(FUNC funcptr)
463 5 : Delegate(&function_dispatcher<FUNC>::impl, NULL, &funcptr, sizeof(funcptr))
464 {
465 5 }
466
467 6 template<class O> Delegate3(O* obj_ptr, void(O::* method)(A1, A2, A3))
468 6 : Delegate(&method_dispatcher<O>::impl, obj_ptr, &method, sizeof(method))
469 {
470 6 }
471
472 1 VoidResult tryInvoke(A1 arg1, A2 arg2, A3 arg3) const
473 {
474 2 return makeResult(gate_delegate_invoke(this->c_impl(),
475 details::VaArgBuilder<A1>::get(arg1),
476 details::VaArgBuilder<A2>::get(arg2),
477 details::VaArgBuilder<A3>::get(arg3)
478
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 ));
479 }
480 14 void invoke(A1 arg1, A2 arg2, A3 arg3) const
481 {
482 14 translate_result(gate_delegate_invoke(&this->impl,
483 details::VaArgBuilder<A1>::get(arg1),
484 details::VaArgBuilder<A2>::get(arg2),
485 details::VaArgBuilder<A3>::get(arg3)
486 ));
487 12 }
488 14 void operator()(A1 arg1, A2 arg2, A3 arg3) const
489 {
490 14 this->invoke(arg1, arg2, arg3);
491 12 }
492 };
493
494
495 /// @brief
496 /// @tparam A1
497 /// @tparam A2
498 /// @tparam A3
499 /// @tparam A4
500 template<class A1, class A2, class A3, class A4>
501 class GATE_CORE_CPP_API Delegate4 : public Delegate
502 {
503 protected:
504 template<class FUNC>
505 struct function_dispatcher
506 {
507 6 static gate_result_t impl(gate_delegate_t const* delegate_ptr, gate_va_list_carrier_t* args)
508 {
509 6 FUNC& func = *gate::union_cast<FUNC*>(&delegate_ptr->function_storage);
510
511 try {
512
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
6 A1 arg1 = Delegate::next_va_arg<A1>(*args);
513
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
6 A2 arg2 = Delegate::next_va_arg<A2>(*args);
514
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
6 A3 arg3 = Delegate::next_va_arg<A3>(*args);
515
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
6 A4 arg4 = Delegate::next_va_arg<A4>(*args);
516
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
6 func(arg1, arg2, arg3, arg4);
517 2 return results::Ok;
518 }
519
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
4 catch (...) { return handle_exception(); }
520 }
521 };
522 template<class O>
523 struct method_dispatcher
524 {
525 2 static gate_result_t impl(gate_delegate_t const* delegate_ptr, gate_va_list_carrier_t* args)
526 {
527 typedef void(O::* method_t)(A1, A2, A3, A4);
528 2 O* obj = static_cast<O*>(delegate_ptr->object_ptr);
529 2 method_t& method = *gate::union_cast<method_t*>(&delegate_ptr->function_storage);
530
531 try {
532
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 A1 arg1 = Delegate::next_va_arg<A1>(*args);
533
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 A2 arg2 = Delegate::next_va_arg<A2>(*args);
534
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 A3 arg3 = Delegate::next_va_arg<A3>(*args);
535
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 A4 arg4 = Delegate::next_va_arg<A4>(*args);
536
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
2 (obj->*method)(arg1, arg2, arg3, arg4);
537 2 return results::Ok;
538 }
539 catch (...) { return handle_exception(); }
540 }
541 };
542
543 public:
544 Delegate4()
545 {
546 }
547
548 4 template<class FUNC> Delegate4(FUNC funcptr)
549 4 : Delegate(&function_dispatcher<FUNC>::impl, NULL, &funcptr, sizeof(funcptr))
550 {
551 4 }
552
553 2 template<class O> Delegate4(O* obj_ptr, void(O::* method)(A1, A2, A3, A4))
554 2 : Delegate(&method_dispatcher<O>::impl, obj_ptr, &method, sizeof(method))
555 {
556 2 }
557
558 1 VoidResult tryInvoke(A1 arg1, A2 arg2, A3 arg3, A4 arg4) const
559 {
560 2 return makeResult(gate_delegate_invoke(this->c_impl(),
561 details::VaArgBuilder<A1>::get(arg1),
562 details::VaArgBuilder<A2>::get(arg2),
563 details::VaArgBuilder<A3>::get(arg3),
564 details::VaArgBuilder<A4>::get(arg4)
565
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 ));
566 }
567 8 void invoke(A1 arg1, A2 arg2, A3 arg3, A4 arg4) const
568 {
569 8 translate_result(gate_delegate_invoke(&this->impl,
570 details::VaArgBuilder<A1>::get(arg1),
571 details::VaArgBuilder<A2>::get(arg2),
572 details::VaArgBuilder<A3>::get(arg3),
573 details::VaArgBuilder<A4>::get(arg4)
574 ));
575 6 }
576 8 void operator()(A1 arg1, A2 arg2, A3 arg3, A4 arg4) const
577 {
578 8 this->invoke(arg1, arg2, arg3, arg4);
579 6 }
580 };
581
582
583 /// @brief
584 /// @tparam A1
585 /// @tparam A2
586 /// @tparam A3
587 /// @tparam A4
588 /// @tparam A5
589 template<class A1, class A2, class A3, class A4, class A5>
590 class GATE_CORE_CPP_API Delegate5 : public Delegate
591 {
592 protected:
593 template<class FUNC>
594 struct function_dispatcher
595 {
596 6 static gate_result_t impl(gate_delegate_t const* delegate_ptr, gate_va_list_carrier_t* args)
597 {
598 6 FUNC& func = *gate::union_cast<FUNC*>(&delegate_ptr->function_storage);
599
600 try {
601
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
6 A1 arg1 = Delegate::next_va_arg<A1>(*args);
602
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
6 A2 arg2 = Delegate::next_va_arg<A2>(*args);
603
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
6 A3 arg3 = Delegate::next_va_arg<A3>(*args);
604
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
6 A4 arg4 = Delegate::next_va_arg<A4>(*args);
605
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
6 A5 arg5 = Delegate::next_va_arg<A5>(*args);
606
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
6 func(arg1, arg2, arg3, arg4, arg5);
607 2 return results::Ok;
608 }
609
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
4 catch (...) { return handle_exception(); }
610 }
611 };
612
613 template<class O>
614 struct method_dispatcher
615 {
616 2 static gate_result_t impl(gate_delegate_t const* delegate_ptr, gate_va_list_carrier_t* args)
617 {
618 typedef void(O::* method_t)(A1, A2, A3, A4, A5);
619 2 O* obj = static_cast<O*>(delegate_ptr->object_ptr);
620 2 method_t& method = *gate::union_cast<method_t*>(&delegate_ptr->function_storage);
621
622 try {
623
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 A1 arg1 = Delegate::next_va_arg<A1>(*args);
624
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 A2 arg2 = Delegate::next_va_arg<A2>(*args);
625
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 A3 arg3 = Delegate::next_va_arg<A3>(*args);
626
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 A4 arg4 = Delegate::next_va_arg<A4>(*args);
627
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 A5 arg5 = Delegate::next_va_arg<A5>(*args);
628
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
2 (obj->*method)(arg1, arg2, arg3, arg4, arg5);
629 2 return results::Ok;
630 }
631 catch (...) { return handle_exception(); }
632 }
633 };
634
635 public:
636 Delegate5()
637 {
638 }
639
640 4 template<class FUNC> Delegate5(FUNC funcptr)
641 4 : Delegate(&function_dispatcher<FUNC>::impl, NULL, &funcptr, sizeof(funcptr))
642 {
643 4 }
644
645 2 template<class O> Delegate5(O* obj_ptr, void(O::* method)(A1, A2, A3, A4, A5))
646 2 : Delegate(&method_dispatcher<O>::impl, obj_ptr, &method, sizeof(method))
647 {
648 2 }
649
650 1 VoidResult tryInvoke(A1 arg1, A2 arg2, A3 arg3, A4 arg4, A5 arg5) const
651 {
652 2 return makeResult(gate_delegate_invoke(this->c_impl(),
653 details::VaArgBuilder<A1>::get(arg1),
654 details::VaArgBuilder<A2>::get(arg2),
655 details::VaArgBuilder<A3>::get(arg3),
656 details::VaArgBuilder<A4>::get(arg4),
657 details::VaArgBuilder<A5>::get(arg5)
658
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 ));
659 }
660 8 void invoke(A1 arg1, A2 arg2, A3 arg3, A4 arg4, A5 arg5) const
661 {
662 8 translate_result(gate_delegate_invoke(&this->impl,
663 details::VaArgBuilder<A1>::get(arg1),
664 details::VaArgBuilder<A2>::get(arg2),
665 details::VaArgBuilder<A3>::get(arg3),
666 details::VaArgBuilder<A4>::get(arg4),
667 details::VaArgBuilder<A5>::get(arg5)
668 ));
669 6 }
670 8 void operator()(A1 arg1, A2 arg2, A3 arg3, A4 arg4, A5 arg5) const
671 {
672 8 this->invoke(arg1, arg2, arg3, arg4, arg5);
673 6 }
674 };
675
676
677
678 /// @brief
679 /// @tparam A1
680 /// @tparam A2
681 /// @tparam A3
682 /// @tparam A4
683 /// @tparam A5
684 /// @tparam A6
685 template<class A1, class A2, class A3, class A4, class A5, class A6>
686 class GATE_CORE_CPP_API Delegate6 : public Delegate
687 {
688 protected:
689 template<class FUNC>
690 struct function_dispatcher
691 {
692 12 static gate_result_t impl(gate_delegate_t const* delegate_ptr, gate_va_list_carrier_t* args)
693 {
694 12 FUNC& func = *gate::union_cast<FUNC*>(&delegate_ptr->function_storage);
695
696 try {
697
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
12 A1 arg1 = Delegate::next_va_arg<A1>(*args);
698
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
12 A2 arg2 = Delegate::next_va_arg<A2>(*args);
699
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
12 A3 arg3 = Delegate::next_va_arg<A3>(*args);
700
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
12 A4 arg4 = Delegate::next_va_arg<A4>(*args);
701
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
12 A5 arg5 = Delegate::next_va_arg<A5>(*args);
702
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
12 A6 arg6 = Delegate::next_va_arg<A6>(*args);
703
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 2 times.
12 func(arg1, arg2, arg3, arg4, arg5, arg6);
704 8 return results::Ok;
705 }
706
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
4 catch (...) { return handle_exception(); }
707 }
708 };
709
710 template<class O>
711 struct method_dispatcher
712 {
713 2 static gate_result_t impl(gate_delegate_t const* delegate_ptr, gate_va_list_carrier_t* args)
714 {
715 typedef void(O::* method_t)(A1, A2, A3, A4, A5, A6);
716 2 O* obj = static_cast<O*>(delegate_ptr->object_ptr);
717 2 method_t& method = *gate::union_cast<method_t*>(&delegate_ptr->function_storage);
718
719 try {
720
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 A1 arg1 = Delegate::next_va_arg<A1>(*args);
721
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 A2 arg2 = Delegate::next_va_arg<A2>(*args);
722
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 A3 arg3 = Delegate::next_va_arg<A3>(*args);
723
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 A4 arg4 = Delegate::next_va_arg<A4>(*args);
724
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 A5 arg5 = Delegate::next_va_arg<A5>(*args);
725
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 A6 arg6 = Delegate::next_va_arg<A6>(*args);
726
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
2 (obj->*method)(arg1, arg2, arg3, arg4, arg5, arg6);
727 2 return results::Ok;
728 }
729 catch (...) { return handle_exception(); }
730 }
731 };
732
733 public:
734 Delegate6()
735 {
736 }
737
738 8 template<class FUNC> Delegate6(FUNC funcptr)
739 8 : Delegate(&function_dispatcher<FUNC>::impl, NULL, &funcptr, sizeof(funcptr))
740 {
741 8 }
742
743 2 template<class O> Delegate6(O* obj_ptr, void(O::* method)(A1, A2, A3, A4, A5, A6))
744 2 : Delegate(&method_dispatcher<O>::impl, obj_ptr, &method, sizeof(method))
745 {
746 2 }
747
748 1 VoidResult tryInvoke(A1 arg1, A2 arg2, A3 arg3, A4 arg4, A5 arg5, A6 arg6) const
749 {
750 2 return makeResult(gate_delegate_invoke(this->c_impl(),
751 details::VaArgBuilder<A1>::get(arg1),
752 details::VaArgBuilder<A2>::get(arg2),
753 details::VaArgBuilder<A3>::get(arg3),
754 details::VaArgBuilder<A4>::get(arg4),
755 details::VaArgBuilder<A5>::get(arg5),
756 details::VaArgBuilder<A6>::get(arg6)
757
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 ));
758 }
759 14 void invoke(A1 arg1, A2 arg2, A3 arg3, A4 arg4, A5 arg5, A6 arg6) const
760 {
761 20 translate_result(gate_delegate_invoke(&this->impl,
762 details::VaArgBuilder<A1>::get(arg1),
763 6 details::VaArgBuilder<A2>::get(arg2),
764 6 details::VaArgBuilder<A3>::get(arg3),
765 details::VaArgBuilder<A4>::get(arg4),
766 details::VaArgBuilder<A5>::get(arg5),
767 details::VaArgBuilder<A6>::get(arg6)
768 ));
769 12 }
770 14 void operator()(A1 arg1, A2 arg2, A3 arg3, A4 arg4, A5 arg5, A6 arg6) const
771 {
772 14 this->invoke(arg1, arg2, arg3, arg4, arg5, arg6);
773 12 }
774 };
775
776
777
778
779 /// @brief
780 class GATE_CORE_CPP_API MulticastDelegateBase
781 {
782 protected:
783
784 16 template<class T> static void addSlot(SlotList<T>& lst, T const& item)
785 {
786 16 lst.add(item);
787 16 }
788 1 template<class T> static bool_t removeSlot(SlotList<T>& lst, T const& item)
789 {
790
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 for (typename SlotList<T>::iterator it(lst.begin()), itend(lst.end()); it != itend; ++it)
791 {
792
2/4
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 if ((*it) == item)
793 {
794
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 lst.remove(it);
795 1 return true;
796 }
797 }
798 return false;
799 }
800 template<class T> static void clearSlots(SlotList<T>& lst)
801 {
802 lst.clear();
803 }
804
805 };
806
807
808
809 /// @brief
810 class GATE_CORE_CPP_API MulticastDelegate0 : protected MulticastDelegateBase
811 {
812 public:
813 typedef MulticastDelegate0 self_t;
814 typedef Delegate0 delegator_t;
815 typedef SlotList<delegator_t> list_t;
816
817 private:
818 list_t impl;
819
820 public:
821 1 void invoke() const
822 {
823
2/2
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1 times.
2 for (list_t::const_iterator it(this->impl.begin()), itend(this->impl.end()); it != itend; ++it)
824 {
825
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 try { it->invoke(); }
826 catch (...) {}
827 }
828 1 }
829 1 void operator()() const { this->invoke(); }
830
831 void clear() { clearSlots(this->impl); }
832 1 self_t& operator+=(delegator_t const& del) { addSlot(this->impl, del); return *this; }
833 self_t& operator-=(delegator_t const& del) { removeSlot(this->impl, del); return *this; }
834 };
835
836
837
838 /// @brief
839 /// @tparam A1
840 template<class A1>
841 class GATE_CORE_CPP_API MulticastDelegate1 : protected MulticastDelegateBase
842 {
843 public:
844 typedef MulticastDelegate1<A1> self_t;
845 typedef Delegate1<A1> delegator_t;
846 typedef SlotList<delegator_t> list_t;
847
848 private:
849 list_t impl;
850
851 public:
852 1 void invoke(A1 a1) const
853 {
854
2/2
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1 times.
2 for (typename list_t::const_iterator it(this->impl.begin()), itend(this->impl.end()); it != itend; ++it)
855 {
856
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 try { (*it)(a1); }
857 catch (...) {}
858 }
859 1 }
860 1 void operator()(A1 a1) const { this->invoke(a1); }
861
862 void clear() { clearSlots(this->impl); }
863 1 self_t& operator+=(delegator_t const& del) { addSlot(this->impl, del); return *this; }
864 self_t& operator-=(delegator_t const& del) { removeSlot(this->impl, del); return *this; }
865 };
866
867
868
869 /// @brief
870 /// @tparam A1
871 /// @tparam A2
872 template<class A1, class A2>
873 class GATE_CORE_CPP_API MulticastDelegate2 : protected MulticastDelegateBase
874 {
875 public:
876 typedef MulticastDelegate2<A1, A2> self_t;
877 typedef Delegate2<A1, A2> delegator_t;
878 typedef SlotList<delegator_t> list_t;
879
880 private:
881 list_t impl;
882
883 public:
884 1 void invoke(A1 a1, A2 a2) const
885 {
886
2/2
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1 times.
2 for (typename list_t::const_iterator it(this->impl.begin()), itend(this->impl.end()); it != itend; ++it)
887 {
888
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 try { (*it)(a1, a2); }
889 catch (...) {}
890 }
891 1 }
892 1 void operator()(A1 a1, A2 a2) const { this->invoke(a1, a2); }
893
894 void clear() { clearSlots(this->impl); }
895 1 self_t& operator+=(delegator_t const& del) { addSlot(this->impl, del); return *this; }
896 self_t& operator-=(delegator_t const& del) { removeSlot(this->impl, del); return *this; }
897 };
898
899
900 /// @brief
901 /// @tparam A1
902 /// @tparam A2
903 /// @tparam A3
904 template<class A1, class A2, class A3>
905 class GATE_CORE_CPP_API MulticastDelegate3 : protected MulticastDelegateBase
906 {
907 public:
908 typedef MulticastDelegate3<A1, A2, A3> self_t;
909 typedef Delegate3<A1, A2, A3> delegator_t;
910 typedef SlotList<delegator_t> list_t;
911
912 private:
913 list_t impl;
914
915 public:
916 1 void invoke(A1 a1, A2 a2, A3 a3) const
917 {
918
2/2
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1 times.
2 for (typename list_t::const_iterator it(this->impl.begin()), itend(this->impl.end()); it != itend; ++it)
919 {
920
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 try { (*it)(a1, a2, a3); }
921 catch (...) {}
922 }
923 1 }
924 1 void operator()(A1 a1, A2 a2, A3 a3) const { this->invoke(a1, a2, a3); }
925
926 void clear() { clearSlots(this->impl); }
927 1 self_t& operator+=(delegator_t const& del) { addSlot(this->impl, del); return *this; }
928 self_t& operator-=(delegator_t const& del) { removeSlot(this->impl, del); return *this; }
929 };
930
931
932 /// @brief
933 /// @tparam A1
934 /// @tparam A2
935 /// @tparam A3
936 /// @tparam A4
937 template<class A1, class A2, class A3, class A4>
938 class GATE_CORE_CPP_API MulticastDelegate4 : protected MulticastDelegateBase
939 {
940 public:
941 typedef MulticastDelegate4<A1, A2, A3, A4> self_t;
942 typedef Delegate4<A1, A2, A3, A4> delegator_t;
943 typedef SlotList<delegator_t> list_t;
944
945 private:
946 list_t impl;
947
948 public:
949 1 void invoke(A1 a1, A2 a2, A3 a3, A4 a4) const
950 {
951
2/2
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1 times.
2 for (typename list_t::const_iterator it(this->impl.begin()), itend(this->impl.end()); it != itend; ++it)
952 {
953
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 try { (*it)(a1, a2, a3, a4); }
954 catch (...) {}
955 }
956 1 }
957 1 void operator()(A1 a1, A2 a2, A3 a3, A4 a4) const { this->invoke(a1, a2, a3, a4); }
958
959 void clear() { clearSlots(this->impl); }
960 1 self_t& operator+=(delegator_t const& del) { addSlot(this->impl, del); return *this; }
961 self_t& operator-=(delegator_t const& del) { removeSlot(this->impl, del); return *this; }
962 };
963
964
965 /// @brief
966 /// @tparam A1
967 /// @tparam A2
968 /// @tparam A3
969 /// @tparam A4
970 /// @tparam A5
971 template<class A1, class A2, class A3, class A4, class A5>
972 class GATE_CORE_CPP_API MulticastDelegate5 : protected MulticastDelegateBase
973 {
974 public:
975 typedef MulticastDelegate5<A1, A2, A3, A4, A5> self_t;
976 typedef Delegate5<A1, A2, A3, A4, A5> delegator_t;
977 typedef SlotList<delegator_t> list_t;
978
979 private:
980 list_t impl;
981
982 public:
983 1 void invoke(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) const
984 {
985
2/2
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1 times.
2 for (typename list_t::const_iterator it(this->impl.begin()), itend(this->impl.end()); it != itend; ++it)
986 {
987
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 try { (*it)(a1, a2, a3, a4, a5); }
988 catch (...) {}
989 }
990 1 }
991 1 void operator()(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) const { this->invoke(a1, a2, a3, a4, a5); }
992
993 void clear() { clearSlots(this->impl); }
994 1 self_t& operator+=(delegator_t const& del) { addSlot(this->impl, del); return *this; }
995 self_t& operator-=(delegator_t const& del) { removeSlot(this->impl, del); return *this; }
996 };
997
998
999 /// @brief
1000 /// @tparam A1
1001 /// @tparam A2
1002 /// @tparam A3
1003 /// @tparam A4
1004 /// @tparam A5
1005 /// @tparam A6
1006 template<class A1, class A2, class A3, class A4, class A5, class A6>
1007 class GATE_CORE_CPP_API MulticastDelegate6 : protected MulticastDelegateBase
1008 {
1009 public:
1010 typedef MulticastDelegate6<A1, A2, A3, A4, A5, A6> self_t;
1011 typedef Delegate6<A1, A2, A3, A4, A5, A6> delegator_t;
1012 typedef SlotList<delegator_t> list_t;
1013
1014 private:
1015 list_t impl;
1016
1017 public:
1018 4 void invoke(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) const
1019 {
1020
2/2
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 2 times.
8 for (typename list_t::const_iterator it(this->impl.begin()), itend(this->impl.end()); it != itend; ++it)
1021 {
1022
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
4 try { (*it)(a1, a2, a3, a4, a5, a6); }
1023 catch (...) {}
1024 }
1025 4 }
1026 4 void operator()(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) const { this->invoke(a1, a2, a3, a4, a5, a6); }
1027
1028 void clear() { clearSlots(this->impl); }
1029 4 self_t& operator+=(delegator_t const& del) { addSlot(this->impl, del); return *this; }
1030 1 self_t& operator-=(delegator_t const& del) { removeSlot(this->impl, del); return *this; }
1031 };
1032
1033
1034
1035 } // end of namespace gate
1036
1037 #endif
1038