GCC Code Coverage Report


Directory: src/gate/
File: src/gate/cxx_runnables.cpp
Date: 2025-09-22 22:57:09
Exec Total Coverage
Lines: 176 249 70.7%
Functions: 39 45 86.7%
Branches: 37 77 48.1%

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 #include "gate/runnables.hpp"
30
31 namespace gate
32 {
33
34
35
36 10 IRunnableBuilder::~IRunnableBuilder() noexcept
37 {
38 10 }
39
40 5 result_t IRunnableBuilder::runnable_run(void* this_ptr)
41 {
42 5 cpp_object* dispatcher = static_cast<cpp_object*>(this_ptr);
43 5 IRunnableBuilder* obj = getInterface<IRunnableBuilder>(dispatcher);
44 try
45 {
46
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
5 obj->run();
47 5 return results::Ok;
48 }
49 ✗ catch (Throwable const& xcpt)
50 {
51 ✗ return xcpt.getResult();
52 }
53 ✗ catch (...)
54 {
55 ✗ return results::UnknownError;
56 }
57 }
58
59 2 IRunnableBuilder::VtblRunnable::VtblRunnable()
60 {
61 2 obj_vtbl_t* this_ptr = reinterpret_cast<obj_vtbl_t*>(this);
62 2 this_ptr->run = &IRunnableBuilder::runnable_run;
63 2 }
64
65 IRunnableBuilder::VtblRunnable IRunnableBuilder::cpp_vtbl_runnable;
66
67 ✗ IRunnableBuilder::IRunnableBuilder(obj_vtbl_t const* vtbl_ptr, char const* name)
68 ✗ : object_builder_t(vtbl_ptr, name)
69 {
70 ✗ }
71
72 5 IRunnableBuilder::IRunnableBuilder()
73
1/2
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
5 : object_builder_t(&cpp_vtbl_runnable, GATE_INTERFACE_NAME_RUNNABLE)
74 {
75 5 }
76
77
78
79 16 Runnable::~Runnable() noexcept
80 {
81 16 }
82 1 void Runnable::run()
83 {
84
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (this->empty())
85 {
86 ✗ GATEXX_RAISE_ERROR(results::NullPointer);
87 }
88 1 gate_result_t result = gate_runnable_run(this->c_impl());
89
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATEXX_CHECK_EXCEPTION(result);
90 1 }
91
92 5 Runnable::Runnable(gate_runnable_t* ptr_runnable)
93 5 : object_impl_t(ptr_runnable)
94 {
95 5 }
96
97 3 Runnable::Runnable(Runnable const& src)
98 3 : object_impl_t(src)
99 {
100 3 }
101
102 ✗ Runnable& Runnable::operator=(Runnable const& src)
103 {
104 ✗ object_impl_t::operator=(src);
105 ✗ return *this;
106 }
107
108
109
110 6 Task::~Task() noexcept
111 {
112 6 }
113 2 void Task::run()
114 {
115 2 result_t result = gate_task_run(this->c_impl());
116
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 GATEXX_CHECK_EXCEPTION(result);
117 1 }
118
119 2 void Task::cancel()
120 {
121 2 result_t result = gate_task_cancel(this->c_impl());
122
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 GATEXX_CHECK_EXCEPTION(result);
123 1 }
124
125 2 Task::Task(gate_task_t* ptr_task)
126 2 : object_impl_t(ptr_task)
127 {
128 2 }
129 1 Task::Task(Task const& src)
130 1 : object_impl_t(src)
131 {
132
133 1 }
134 ✗ Task& Task::operator=(Task const& src)
135 {
136 ✗ object_impl_t::operator=(src);
137 ✗ return *this;
138 }
139
140 3 Task::StatusEnum Task::status()
141 {
142 3 return static_cast<Task::StatusEnum>(gate_task_get_status(this->c_impl()));
143 }
144
145 4 bool_t Task::completed()
146 {
147 4 return gate_task_completed(this->c_impl());
148 }
149
150 1 void const* Task::getResult()
151 {
152 1 void const* ptrTaskData = NULL;
153 1 result_t taskResult = results::Failed;
154
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 result_t result = gate_task_get_result(this->c_impl(), &taskResult, &ptrTaskData);
155
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
1 GATEXX_CHECK_EXCEPTION(result);
156
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
1 GATEXX_CHECK_EXCEPTION(taskResult);
157 1 return ptrTaskData;
158 }
159
160 1 void Task::wait()
161 {
162 1 result_t result = gate_task_wait(this->c_impl());
163
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATEXX_CHECK_EXCEPTION(result);
164 1 }
165
166 1 bool Task::waitFor(uint32_t timeoutMs)
167 {
168 1 result_t result = gate_task_timed_wait(this->c_impl(), timeoutMs);
169
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (GATE_FAILED(result))
170 {
171 ✗ if (result == GATE_RESULT_TIMEOUT)
172 {
173 ✗ return false;
174 }
175 else
176 {
177 ✗ GATEXX_RAISE_EXCEPTION(result, NULL, 0);
178 }
179 }
180 1 return true;
181 }
182
183
184
185
186 4 ITaskBuilder::~ITaskBuilder() noexcept
187 {
188
189 4 }
190
191 2 result_t ITaskBuilder::task_run(void* this_ptr)
192 {
193 2 cpp_object* dispatcher = static_cast<cpp_object*>(this_ptr);
194 2 ITaskBuilder* obj = getInterface<ITaskBuilder>(dispatcher);
195 try
196 {
197
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
2 obj->run();
198 1 return results::Ok;
199 }
200 2 catch (Throwable const& xcpt)
201 {
202 1 return xcpt.getResult();
203 }
204 ✗ catch (...)
205 {
206 ✗ return results::UnknownError;
207 }
208 }
209 2 result_t ITaskBuilder::task_cancel(void* this_ptr)
210 {
211 2 cpp_object* dispatcher = static_cast<cpp_object*>(this_ptr);
212 2 ITaskBuilder* obj = getInterface<ITaskBuilder>(dispatcher);
213 try
214 {
215
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
2 obj->cancel();
216 1 return results::Ok;
217 }
218 2 catch (Throwable const& xcpt)
219 {
220 1 return xcpt.getResult();
221 }
222 ✗ catch (...)
223 {
224 ✗ return results::UnknownError;
225 }
226 }
227 3 int ITaskBuilder::task_get_status(void* this_ptr)
228 {
229 3 cpp_object* dispatcher = static_cast<cpp_object*>(this_ptr);
230 3 ITaskBuilder* obj = getInterface<ITaskBuilder>(dispatcher);
231 3 return static_cast<int>(obj->status());
232 }
233 4 gate_bool_t ITaskBuilder::task_completed(void* this_ptr)
234 {
235 4 cpp_object* dispatcher = static_cast<cpp_object*>(this_ptr);
236 4 ITaskBuilder* obj = getInterface<ITaskBuilder>(dispatcher);
237 4 return static_cast<int>(obj->completed());
238
239 }
240 1 gate_result_t ITaskBuilder::task_get_result(void* this_ptr, gate_result_t* ptr_task_result, void const** ptr_task_data)
241 {
242 1 result_t ret = results::Ok;
243 1 cpp_object* dispatcher = static_cast<cpp_object*>(this_ptr);
244 1 ITaskBuilder* obj = getInterface<ITaskBuilder>(dispatcher);
245
246 1 result_t taskResult = results::Failed;
247 1 void const* taskData = NULL;
248
249 1 Task::StatusEnum status = obj->status();
250
1/5
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
1 switch (status)
251 {
252 ✗ case Task::Status_Prepared:
253 case Task::Status_Running:
254 {
255 ✗ taskResult = results::InvalidState;
256 ✗ break;
257 }
258 1 case Task::Status_Completed:
259 {
260 try
261 {
262
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 taskData = obj->getResult();
263 1 taskResult = results::Ok;
264 }
265 ✗ catch (Throwable const& xcpt)
266 {
267 ✗ taskResult = xcpt.getResult();
268 }
269 ✗ catch (...)
270 {
271 ✗ taskResult = results::UnknownError;
272 }
273 1 ret = results::Ok;
274 1 break;
275 }
276 ✗ case Task::Status_Canceled:
277 {
278 ✗ taskResult = results::Canceled;
279 ✗ ret = results::Ok;
280 ✗ break;
281 }
282 ✗ case Task::Status_Failed:
283 {
284 ✗ taskResult = results::Failed;
285 ✗ ret = results::Ok;
286 ✗ break;
287 }
288 }
289
290
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (ptr_task_result)
291 {
292 1 *ptr_task_result = taskResult;
293 }
294
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (ptr_task_data)
295 {
296 1 *ptr_task_data = taskData;
297 }
298
299 1 return ret;
300 }
301 1 gate_result_t ITaskBuilder::task_wait(void* this_ptr)
302 {
303 1 cpp_object* dispatcher = static_cast<cpp_object*>(this_ptr);
304 1 ITaskBuilder* obj = getInterface<ITaskBuilder>(dispatcher);
305 try
306 {
307
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 obj->wait();
308 1 return results::Ok;
309 }
310 ✗ catch (Throwable const& xcpt)
311 {
312 ✗ return xcpt.getResult();
313 }
314 ✗ catch (...)
315 {
316 ✗ return results::UnknownError;
317 }
318 }
319 1 gate_result_t ITaskBuilder::task_timed_wait(void* this_ptr, gate_uint32_t timeout_ms)
320 {
321 1 cpp_object* dispatcher = static_cast<cpp_object*>(this_ptr);
322 1 ITaskBuilder* obj = getInterface<ITaskBuilder>(dispatcher);
323 try
324 {
325
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 bool_t signaled = obj->waitFor(timeout_ms);
326
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (signaled)
327 {
328 1 return results::Ok;
329 }
330 else
331 {
332 ✗ return results::Timeout;
333 }
334 }
335 ✗ catch (Throwable const& xcpt)
336 {
337 ✗ return xcpt.getResult();
338 }
339 ✗ catch (...)
340 {
341 ✗ return results::UnknownError;
342 }
343 }
344
345 2 ITaskBuilder::VtblTask::VtblTask()
346 {
347 2 obj_vtbl_t* this_ptr = reinterpret_cast<obj_vtbl_t*>(this);
348 2 this_ptr->run = &ITaskBuilder::task_run;
349 2 this_ptr->cancel = ITaskBuilder::task_cancel;
350 2 this_ptr->get_status = ITaskBuilder::task_get_status;
351 2 this_ptr->completed = ITaskBuilder::task_completed;
352 2 this_ptr->get_result = ITaskBuilder::task_get_result;
353 2 this_ptr->wait = ITaskBuilder::task_wait;
354 2 this_ptr->timed_wait = ITaskBuilder::task_timed_wait;
355 2 }
356
357 ITaskBuilder::VtblTask ITaskBuilder::cpp_vtbl_task;
358
359 ✗ ITaskBuilder::ITaskBuilder(obj_vtbl_t const* vtbl_ptr, char const* name)
360 ✗ : object_builder_t(vtbl_ptr, name)
361 {
362 ✗ }
363 2 ITaskBuilder::ITaskBuilder()
364
1/2
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
2 : object_builder_t(&cpp_vtbl_task, GATE_INTERFACE_NAME_TASK)
365 {
366 2 }
367
368
369
370
371 2 ITaskBase::ITaskBase()
372 : statusvalue(static_cast<int32_t>(Task::Status_Prepared)),
373 completionsignal(false),
374 taskResult(results::Ok),
375
1/2
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
2 taskData(NULL)
376 {
377 2 }
378
379 4 ITaskBase::~ITaskBase() noexcept
380 {
381 4 }
382
383 ✗ void ITaskBase::runImpl()
384 {
385 ✗ }
386 ✗ void ITaskBase::cancelImpl()
387 {
388 ✗ }
389
390 6 static bool_t updateTaskStatus(AtomicInt& status, Task::StatusEnum fromStatus, Task::StatusEnum toStatus)
391 {
392 6 int32_t oldStatus = status.changeIf(static_cast<int32_t>(fromStatus), static_cast<int32_t>(toStatus));
393 6 return oldStatus == static_cast<int32_t>(fromStatus);
394 }
395
396 2 void ITaskBase::run()
397 {
398
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
2 if (!updateTaskStatus(this->statusvalue, Task::Status_Prepared, Task::Status_Running))
399 {
400 1 GATEXX_RAISE_EXCEPTION(results::InvalidState, "Cannot start task", 0);
401 }
402
403 1 Task::StatusEnum nextStatus = Task::Status_Completed;
404 1 result_t nextTaskResult = results::Ok;
405
406 try
407 {
408
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 this->runImpl();
409 }
410 ✗ catch (Throwable const& xcpt)
411 {
412 ✗ nextStatus = Task::Status_Failed;
413 ✗ nextTaskResult = xcpt.getResult();
414 }
415 ✗ catch (...)
416 {
417 ✗ nextStatus = Task::Status_Failed;
418 ✗ nextTaskResult = results::UnknownException;
419 }
420
421
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if (updateTaskStatus(this->statusvalue, Task::Status_Running, nextStatus))
422 {
423 1 this->taskResult = nextTaskResult;
424 1 this->completionsignal.set();
425 }
426 1 }
427
428 1 void ITaskBase::setTaskData(void const* data)
429 {
430 1 this->taskData = data;
431 1 }
432
433
434 2 void ITaskBase::cancel()
435 {
436
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
2 if (updateTaskStatus(this->statusvalue, Task::Status_Prepared, Task::Status_Canceled))
437 {
438 1 this->completionsignal.set();
439 }
440
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 else if (updateTaskStatus(this->statusvalue, Task::Status_Running, Task::Status_Canceled))
441 {
442 try
443 {
444 ✗ this->cancelImpl();
445 }
446 ✗ catch (...) {}
447 ✗ this->completionsignal.set();
448 }
449 else
450 {
451 1 GATEXX_RAISE_EXCEPTION(results::InvalidState, "Cannot cancel task", 0);
452 }
453 1 }
454 4 Task::StatusEnum ITaskBase::status()
455 {
456 4 return static_cast<Task::StatusEnum>(this->statusvalue.get());
457 }
458 4 bool_t ITaskBase::completed()
459 {
460 4 Task::StatusEnum state = static_cast<Task::StatusEnum>(this->statusvalue.get());
461
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 switch (state)
462 {
463 2 case Task::Status_Completed:
464 case Task::Status_Canceled:
465 case Task::Status_Failed:
466 {
467 2 return true;
468 }
469 2 default:
470 {
471 2 break;
472 }
473 }
474 2 return false;
475 }
476 1 void const* ITaskBase::getResult()
477 {
478 1 Task::StatusEnum state = static_cast<Task::StatusEnum>(this->statusvalue.get());
479
1/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 switch (state)
480 {
481 1 case Task::Status_Completed:
482 {
483
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (GATE_FAILED(this->taskResult))
484 {
485 ✗ GATEXX_RAISE_EXCEPTION(this->taskResult, "Task execution failed", 0);
486 }
487 else
488 {
489 1 return this->taskData;
490 }
491 ✗ break;
492 }
493 ✗ case Task::Status_Canceled:
494 {
495 ✗ GATEXX_RAISE_EXCEPTION(results::Canceled, "Task canceled", 0);
496 ✗ break;
497 }
498 ✗ case Task::Status_Failed:
499 {
500 ✗ GATEXX_RAISE_EXCEPTION(this->taskResult, "Task execution failed", 0);
501 ✗ break;
502 }
503 ✗ default:
504 {
505 ✗ GATEXX_RAISE_EXCEPTION(results::InvalidState, "Task not completed", 0);
506 ✗ break;
507 }
508 }
509 ✗ return NULL;
510 }
511 1 void ITaskBase::wait()
512 {
513 1 this->completionsignal.wait();
514 1 }
515 1 bool ITaskBase::waitFor(uint32_t timeoutMs)
516 {
517 1 return this->completionsignal.waitFor(timeoutMs);
518 }
519
520 } // end of namespace gate
521