GCC Code Coverage Report


Directory: src/gate/
File: src/gate/runnables.hpp
Date: 2025-09-14 13:10:38
Exec Total Coverage
Lines: 39 40 97.5%
Functions: 17 17 100.0%
Branches: 7 14 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 Runnable interface generators
31 * @ingroup gatecore_cpp
32 */
33
34
35 #ifndef GATE_RUNNABLES_HPP_INCLUDED
36 #define GATE_RUNNABLES_HPP_INCLUDED
37
38 #include "gate/gatetypes.hpp"
39 #include "gate/objects.hpp"
40 #include "gate/delegates.hpp"
41 #include "gate/runnables.h"
42 #include "gate/synchronization.hpp"
43
44 namespace gate
45 {
46
47 /// @brief Base class that generates a C-runnable for a C++-runnable interface.
48 class GATE_CORE_CPP_API IRunnableBuilder : public IRunnable, public IObjectBuilder<gate_runnable_t, GATE_INTERFACE_VTBL(gate_runnable) >
49 {
50 public:
51 typedef IObjectBuilder<gate_runnable_t, GATE_INTERFACE_VTBL(gate_runnable) > object_builder_t;
52
53 virtual ~IRunnableBuilder() noexcept;
54
55 protected:
56
57 static result_t runnable_run(void* this_ptr);
58
59 struct GATE_CORE_CPP_API VtblRunnable : public VtblObject
60 {
61 VtblRunnable();
62 };
63
64 static VtblRunnable cpp_vtbl_runnable;
65
66 IRunnableBuilder(obj_vtbl_t const* vtbl_ptr, char const* name);
67 IRunnableBuilder();
68 };
69
70
71 /// @brief C++ wrapper for C-Runnable objects.
72 class GATE_CORE_CPP_API Runnable : public IRunnable, public ObjectImpl<gate_runnable_t>
73 {
74 public: // inherited interface
75 virtual ~Runnable() noexcept;
76 virtual void run();
77
78 public:
79 typedef ObjectImpl<gate_runnable_t> object_impl_t;
80
81 Runnable(gate_runnable_t* ptr_runnable = NULL); ///< Ctor: Take ownership of runnable-C-pointer
82 Runnable(Runnable const& src); ///< CCtor: Share ownership of existing runnable
83 Runnable& operator=(Runnable const& src);
84 };
85
86
87 /// @brief Runnable wrapper covering a prepared call with no arguments
88 /// @tparam T
89 template<class T>
90 class GATE_CORE_CPP_API TRunnableDispatcher0 : public IRunnableBuilder
91 {
92 private:
93 typedef Delegate0 delegate_t;
94 delegate_t func;
95
96 public:
97 2 TRunnableDispatcher0(delegate_t const& del)
98 2 : func(del)
99 {
100 2 }
101 8 virtual ~TRunnableDispatcher0() noexcept {}
102 2 virtual void run() { func(); }
103 };
104
105 typedef TRunnableDispatcher0<void> RunnableDispatcher0;
106
107
108 /// @brief Runnable wrapper covering a prepared call with 1 argument
109 /// @tparam A1
110 template<class A1>
111 class GATE_CORE_CPP_API RunnableDispatcher1 : public IRunnableBuilder
112 {
113 private:
114 typedef Delegate1<A1> delegate_t;
115 delegate_t f;
116 A1 a1;
117
118 public:
119 2 RunnableDispatcher1(delegate_t const& func, A1 p1)
120 2 : f(func), a1(p1)
121 {
122 2 }
123 8 virtual ~RunnableDispatcher1() noexcept {}
124 2 virtual void run() { f(a1); }
125 };
126
127
128 /// @brief Runnable wrapper covering a prepared call with 2 arguments
129 /// @tparam A1
130 /// @tparam A2
131 template<class A1, class A2>
132 class GATE_CORE_CPP_API RunnableDispatcher2 : public IRunnableBuilder
133 {
134 private:
135 typedef Delegate2<A1, A2> delegate_t;
136 delegate_t f;
137 A1 a1;
138 A2 a2;
139
140 public:
141 RunnableDispatcher2(delegate_t const& func, A1 p1, A2 p2)
142 : f(func), a1(p1), a2(p2)
143 {
144 }
145 virtual ~RunnableDispatcher2() noexcept {}
146 virtual void run() { f(a1, a2); }
147 };
148
149
150 /// @brief Runnable wrapper covering a prepared call with 3 arguments
151 /// @tparam A1
152 /// @tparam A2
153 /// @tparam A3
154 template<class A1, class A2, class A3>
155 class GATE_CORE_CPP_API RunnableDispatcher3 : public IRunnableBuilder
156 {
157 private:
158 typedef Delegate3<A1, A2, A3> delegate_t;
159 delegate_t f;
160 A1 a1;
161 A2 a2;
162 A3 a3;
163
164 public:
165 1 RunnableDispatcher3(delegate_t const& func, A1 p1, A2 p2, A3 p3)
166 1 : f(func), a1(p1), a2(p2), a3(p3)
167 {
168 1 }
169 4 virtual ~RunnableDispatcher3() noexcept {}
170 1 virtual void run() { f(a1, a2, a3); }
171 };
172
173
174 /// @brief Runnable wrapper covering a prepared call with 4 arguments
175 /// @tparam A1
176 /// @tparam A2
177 /// @tparam A3
178 /// @tparam A4
179 template<class A1, class A2, class A3, class A4>
180 class GATE_CORE_CPP_API RunnableDispatcher4 : public IRunnableBuilder
181 {
182 private:
183 typedef Delegate4<A1, A2, A3, A4> delegate_t;
184 delegate_t f;
185 A1 a1;
186 A2 a2;
187 A3 a3;
188 A4 a4;
189
190 public:
191 RunnableDispatcher4(delegate_t const& func, A1 p1, A2 p2, A3 p3, A4 p4)
192 : f(func), a1(p1), a2(p2), a3(p3), a4(p4)
193 {
194 }
195 virtual ~RunnableDispatcher4() noexcept {}
196 virtual void run() { f(a1, a2, a3, a4); }
197 };
198
199
200 /// @brief Helper class to create wrappers covering object method calls
201 struct GATE_CORE_CPP_API RunnableMethod
202 {
203 public:
204 template<class O>
205 static Runnable createMethod(void(O::* method)(), O* obj)
206 {
207 IRunnableBuilder* ptr = new RunnableDispatcher0(
208 Delegate0(obj, method));
209 return Runnable(ptr->c_impl());
210 }
211
212 template<class O, class A1>
213 static Runnable createMethod(void(O::* method)(A1), O* obj, A1 a1)
214 {
215 IRunnableBuilder* ptr = new RunnableDispatcher1<A1>(
216 Delegate1<A1>(obj, method), a1);
217 return Runnable(ptr->c_impl());
218 }
219
220 template<class O, class A1, class A2>
221 static Runnable createMethod(void(O::* method)(A1, A2), O* obj, A1 a1, A2 a2)
222 {
223 IRunnableBuilder* ptr = new RunnableDispatcher2<A1, A2>(
224 Delegate2<A1, A2>(obj, method), a1, a2);
225 return Runnable(ptr->c_impl());
226 }
227
228 template<class O, class A1, class A2, class A3>
229 1 static Runnable createMethod(void(O::* method)(A1, A2, A3), O* obj, A1 a1, A2 a2, A3 a3)
230 {
231
2/4
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
1 IRunnableBuilder* ptr = new RunnableDispatcher3<A1, A2, A3>(
232 Delegate3<A1, A2, A3>(obj, method), a1, a2, a3);
233 1 return Runnable(ptr->c_impl());
234 }
235
236 template<class O, class A1, class A2, class A3, class A4>
237 static Runnable createMethod(void(O::* method)(A1, A2, A3, A4), O* obj, A1 a1, A2 a2, A3 a3, A4 a4)
238 {
239 IRunnableBuilder* ptr = new RunnableDispatcher4<A1, A2, A3, A4>(
240 Delegate4<A1, A2, A3, A4>(obj, method), a1, a2, a3, a4);
241 return Runnable(ptr->c_impl());
242 }
243
244 };
245
246
247
248 /// @brief
249 struct GATE_CORE_CPP_API RunnableFunction
250 {
251 public:
252
253 template<class F>
254 2 static Runnable create(F func)
255 {
256
2/4
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
2 IRunnableBuilder* ptr = new RunnableDispatcher0(
257 Delegate0(func));
258 2 return Runnable(ptr->c_impl());
259 }
260
261 template<class F, class A1>
262 static Runnable create(F func, A1 a1)
263 {
264 IRunnableBuilder* ptr = new RunnableDispatcher1<A1>(
265 Delegate1<A1>(func), a1);
266 return Runnable(ptr->c_impl());
267 }
268
269
270 template<class F, class A1, class A2>
271 static Runnable create(F func, A1 a1, A2 a2)
272 {
273 IRunnableBuilder* ptr = new RunnableDispatcher2<A1, A2>(
274 Delegate2<A1, A2>(func), a1, a2);
275 return Runnable(ptr->c_impl());
276 }
277
278
279 template<class F, class A1, class A2, class A3>
280 static Runnable create(F func, A1 a1, A2 a2, A3 a3)
281 {
282 IRunnableBuilder* ptr = new RunnableDispatcher3<A1, A2, A3>(
283 Delegate3<A1, A2, A3>(func), a1, a2, a3);
284 return Runnable(ptr->c_impl());
285 }
286
287 template<class F, class A1, class A2, class A3, class A4>
288 static Runnable create(F func, A1 a1, A2 a2, A3 a3, A4 a4)
289 {
290 IRunnableBuilder* ptr = new RunnableDispatcher4<A1, A2, A3, A4>(
291 Delegate4<A1, A2, A3, A4>(func), a1, a2, a3, a4);
292 return Runnable(ptr->c_impl());
293 }
294 };
295
296
297 /// @brief
298 struct GATE_CORE_CPP_API RunnableBuilder : public RunnableFunction, public RunnableMethod
299 {
300 };
301
302
303
304
305 /// @brief
306 class GATE_CORE_CPP_API Task : public IRunnable, public ICancelable, public ObjectImpl<gate_task_t>
307 {
308 public: // inherited interface
309 enum StatusEnum
310 {
311 Status_Prepared = GATE_TASK_STATUS_PREPARED,
312 Status_Running = GATE_TASK_STATUS_RUNNING,
313 Status_Completed = GATE_TASK_STATUS_COMPLETED,
314 Status_Canceled = GATE_TASK_STATUS_CANCELED,
315 Status_Failed = GATE_TASK_STATUS_FAILED
316 };
317
318 virtual ~Task() noexcept;
319 virtual void run();
320 virtual void cancel();
321
322 public:
323 typedef ObjectImpl<gate_task_t> object_impl_t;
324
325 Task(gate_task_t* ptr_task);
326 Task(Task const& src);
327 Task& operator=(Task const& src);
328
329 StatusEnum status();
330 bool_t completed();
331 void const* getResult();
332 void wait();
333 bool waitFor(uint32_t timeoutMs);
334
335 template<class T> bool_t getResult(T& refResult)
336 {
337 void const* ptr = this->getResult();
338 if (ptr)
339 {
340 refResult = *static_cast<T const*>(ptr);
341 return true;
342 }
343 return false;
344 }
345 };
346
347
348 /// @brief
349 /// @tparam T
350 template<class T>
351 class GATE_CORE_CPP_API TypedTask : public Task
352 {
353 public:
354 typedef TypedTask<T> self_t;
355
356 1 TypedTask(gate_task_t* ptr_runnable)
357 1 : Task(ptr_runnable)
358 {
359 1 }
360 TypedTask(self_t const& src)
361 : Task(src)
362 {
363
364 }
365 self_t& operator=(self_t const& src)
366 {
367 Task::operator=(src);
368 return *this;
369 }
370
371 1 T getResult()
372 {
373 1 void const* ptrResult = Task::getResult();
374
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (ptrResult)
375 {
376 1 return *static_cast<T const*>(ptrResult);
377 }
378 return T();
379 }
380
381 };
382
383
384
385 /// @brief
386 class GATE_CORE_CPP_API ITaskBuilder : public IRunnable, public ICancelable, public IObjectBuilder<gate_task_t, GATE_INTERFACE_VTBL(gate_task) >
387 {
388 public:
389 typedef IObjectBuilder<gate_task_t, GATE_INTERFACE_VTBL(gate_task) > object_builder_t;
390
391 virtual ~ITaskBuilder() noexcept;
392
393 public:
394 virtual void run() = 0;
395 virtual void cancel() = 0;
396 virtual Task::StatusEnum status() = 0;
397 virtual bool_t completed() = 0;
398 virtual void const* getResult() = 0;
399 virtual void wait() = 0;
400 virtual bool waitFor(uint32_t timeoutMs) = 0;
401
402 protected:
403
404 static result_t task_run(void* this_ptr);
405 static result_t task_cancel(void* this_ptr);
406 static int task_get_status(void* this_ptr);
407 static gate_bool_t task_completed(void* this_ptr);
408 static gate_result_t task_get_result(void* this_ptr, gate_result_t* ptr_task_result, void const** ptr_task_data);
409 static gate_result_t task_wait(void* this_ptr);
410 static gate_result_t task_timed_wait(void* this_ptr, gate_uint32_t timeout_ms);
411
412 struct GATE_CORE_CPP_API VtblTask : public VtblObject
413 {
414 VtblTask();
415 };
416
417 static VtblTask cpp_vtbl_task;
418
419 ITaskBuilder(obj_vtbl_t const* vtbl_ptr, char const* name);
420 ITaskBuilder();
421 };
422
423
424 /// @brief
425 class GATE_CORE_CPP_API ITaskBase : public ITaskBuilder
426 {
427 public:
428 virtual ~ITaskBase() noexcept;
429
430 virtual void run();
431 virtual void cancel();
432 virtual Task::StatusEnum status();
433 virtual bool_t completed();
434 virtual void const* getResult();
435 virtual void wait();
436 virtual bool waitFor(uint32_t timeoutMs);
437
438 protected:
439 virtual void runImpl(); ///< To be overwritten by derived implementation class
440 virtual void cancelImpl(); ///< To be overwritten by derived implementation class
441 virtual void setTaskData(void const* data = NULL);
442
443 protected:
444 ITaskBase();
445
446 private:
447 AtomicInt statusvalue;
448 SyncEvent completionsignal;
449 result_t taskResult;
450 void const* taskData;
451 };
452
453
454 /// @brief
455 /// @tparam OUTARG
456 template<class OUTARG>
457 class GATE_CORE_CPP_API TaskDispatcher0 : public ITaskBase
458 {
459 private:
460 typedef Delegate1<OUTARG&> delegate_t;
461 delegate_t func;
462 OUTARG a_out;
463
464 public:
465 TaskDispatcher0(delegate_t const& del)
466 : func(del)
467 {
468 }
469 virtual ~TaskDispatcher0() noexcept {}
470 virtual void runImpl()
471 {
472 this->func(a_out);
473 this->setTaskData(&a_out);
474 }
475 };
476
477
478 /// @brief
479 /// @tparam A1
480 /// @tparam OUTARG
481 template<class A1, class OUTARG>
482 class GATE_CORE_CPP_API TaskDispatcher1 : public ITaskBase
483 {
484 private:
485 typedef Delegate2<A1, OUTARG&> delegate_t;
486 delegate_t func;
487 A1 a_1;
488 OUTARG a_out;
489
490 public:
491 TaskDispatcher1(delegate_t const& del, A1 a1)
492 : func(del), a_1(a1)
493 {
494 }
495 virtual ~TaskDispatcher1() noexcept {}
496 virtual void runImpl()
497 {
498 this->func(a_1, a_out);
499 this->setTaskData(&a_out);
500 }
501 };
502
503
504 /// @brief
505 /// @tparam A1
506 /// @tparam A2
507 /// @tparam OUTARG
508 template<class A1, class A2, class OUTARG>
509 class GATE_CORE_CPP_API TaskDispatcher2 : public ITaskBase
510 {
511 private:
512 typedef Delegate3<A1, A2, OUTARG&> delegate_t;
513 delegate_t func;
514 A1 a_1;
515 A2 a_2;
516 OUTARG a_out;
517
518 public:
519 1 TaskDispatcher2(delegate_t const& del, A1 a1, A2 a2)
520 1 : func(del), a_1(a1), a_2(a2), a_out(OUTARG())
521 {
522 1 }
523 4 virtual ~TaskDispatcher2() noexcept {}
524 1 virtual void runImpl()
525 {
526 1 this->func(a_1, a_2, a_out);
527 1 this->setTaskData(&a_out);
528 1 }
529 };
530
531
532 /// @brief
533 /// @tparam A1
534 /// @tparam A2
535 /// @tparam A3
536 /// @tparam OUTARG
537 template<class A1, class A2, class A3, class OUTARG>
538 class GATE_CORE_CPP_API TaskDispatcher3 : public ITaskBase
539 {
540 private:
541 typedef Delegate4<A1, A2, A3, OUTARG&> delegate_t;
542 delegate_t func;
543 A1 a_1;
544 A2 a_2;
545 A3 a_3;
546 OUTARG a_out;
547
548 public:
549 TaskDispatcher3(delegate_t const& del, A1 a1, A2 a2, A3 a3)
550 : func(del), a_1(a1), a_2(a2), a_3(a3)
551 {
552 }
553 virtual ~TaskDispatcher3() noexcept {}
554 virtual void runImpl()
555 {
556 this->func(a_1, a_2, a_3, a_out);
557 this->setTaskData(&a_out);
558 }
559 };
560
561
562 /// @brief
563 /// @tparam A1
564 /// @tparam A2
565 /// @tparam A3
566 /// @tparam A4
567 /// @tparam OUTARG
568 template<class A1, class A2, class A3, class A4, class OUTARG>
569 class GATE_CORE_CPP_API TaskDispatcher4 : public ITaskBase
570 {
571 private:
572 typedef Delegate5<A1, A2, A3, A4, OUTARG&> delegate_t;
573 delegate_t func;
574 A1 a_1;
575 A2 a_2;
576 A3 a_3;
577 A4 a_4;
578 OUTARG a_out;
579
580 public:
581 TaskDispatcher4(delegate_t const& del, A1 a1, A2 a2, A3 a3, A4 a4)
582 : func(del), a_1(a1), a_2(a2), a_3(a3), a_4(a4)
583 {
584 }
585 virtual ~TaskDispatcher4() noexcept {}
586 virtual void runImpl()
587 {
588 this->func(a_1, a_2, a_3, a_4, a_out);
589 this->setTaskData(&a_out);
590 }
591 };
592
593
594 /// @brief
595 struct GATE_CORE_CPP_API TaskBuilder
596 {
597 public:
598 static Task create(Runnable const& runnable);
599
600 template<class O, class OUTARG>
601 static TypedTask<OUTARG> createMethod(void(O::* method)(OUTARG&), O* obj)
602 {
603 ITaskBase* ptr = new TaskDispatcher0<OUTARG>(
604 Delegate1<OUTARG&>(obj, method));
605 return TypedTask<OUTARG>(ptr->c_impl());
606 }
607
608 template<class O, class A1, class OUTARG>
609 static TypedTask<OUTARG> createMethod(void(O::* method)(A1, OUTARG&), O* obj, A1 a1)
610 {
611 ITaskBase* ptr = new TaskDispatcher1<A1, OUTARG>(
612 Delegate2<A1, OUTARG&>(obj, method), a1);
613 return TypedTask<OUTARG>(ptr->c_impl());
614 }
615
616 template<class O, class A1, class A2, class OUTARG>
617 1 static TypedTask<OUTARG> createMethod(void(O::* method)(A1, A2, OUTARG&), O* obj, A1 a1, A2 a2)
618 {
619
2/4
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
1 ITaskBase* ptr = new TaskDispatcher2<A1, A2, OUTARG>(
620 Delegate3<A1, A2, OUTARG&>(obj, method), a1, a2);
621 1 return TypedTask<OUTARG>(ptr->c_impl());
622 }
623
624 template<class O, class A1, class A2, class A3, class OUTARG>
625 static TypedTask<OUTARG> createMethod(void(O::* method)(A1, A2, A3, OUTARG&), O* obj, A1 a1, A2 a2, A3 a3)
626 {
627 ITaskBase* ptr = new TaskDispatcher3<A1, A2, A3, OUTARG>(
628 Delegate4<A1, A2, A3, OUTARG&>(obj, method), a1, a2, a3);
629 return TypedTask<OUTARG>(ptr->c_impl());
630 }
631
632 template<class O, class A1, class A2, class A3, class A4, class OUTARG>
633 static TypedTask<OUTARG> createMethod(void(O::* method)(A1, A2, A3, A4, OUTARG&), O* obj, A1 a1, A2 a2, A3 a3, A4 a4)
634 {
635 ITaskBase* ptr = new TaskDispatcher4<A1, A2, A3, A4, OUTARG>(
636 Delegate5<A1, A2, A3, A4, OUTARG&>(obj, method), a1, a2, a3, a4);
637 return TypedTask<OUTARG>(ptr->c_impl());
638 }
639
640 };
641
642
643
644
645 } // end of namespace gate
646
647
648 #endif
649