GCC Code Coverage Report


Directory: src/gate/
File: src/gate/cxx_runnables.cpp
Date: 2025-12-12 23:40:09
Exec Total Coverage
Lines: 197 249 79.1%
Functions: 43 45 95.6%
Branches: 44 77 57.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 12 IRunnableBuilder::~IRunnableBuilder() noexcept
37 {
38 12 }
39
40 6 result_t IRunnableBuilder::runnable_run(void* this_ptr)
41 {
42 6 cpp_object* dispatcher = static_cast<cpp_object*>(this_ptr);
43 6 IRunnableBuilder* obj = getInterface<IRunnableBuilder>(dispatcher);
44 try
45 {
46
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 obj->run();
47 6 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 5 IRunnableBuilder::VtblRunnable::VtblRunnable()
60 {
61 5 obj_vtbl_t* this_ptr = reinterpret_cast<obj_vtbl_t*>(this);
62 5 this_ptr->run = &IRunnableBuilder::runnable_run;
63 5 }
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 6 IRunnableBuilder::IRunnableBuilder()
73
1/2
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
6 : object_builder_t(&cpp_vtbl_runnable, GATE_INTERFACE_NAME_RUNNABLE)
74 {
75 6 }
76
77
78
79 22 Runnable::~Runnable() noexcept
80 {
81 22 }
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 6 Runnable::Runnable(gate_runnable_t* ptr_runnable)
93 6 : object_impl_t(ptr_runnable)
94 {
95 6 }
96
97 5 Runnable::Runnable(Runnable const& src)
98 5 : object_impl_t(src)
99 {
100 5 }
101
102 1 Runnable& Runnable::operator=(Runnable const& src)
103 {
104 1 object_impl_t::operator=(src);
105 1 return *this;
106 }
107
108
109
110 10 Task::~Task() noexcept
111 {
112 10 }
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 3 Task::Task(Task const& src)
130 3 : object_impl_t(src)
131 {
132
133 3 }
134 1 Task& Task::operator=(Task const& src)
135 {
136 1 object_impl_t::operator=(src);
137 1 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 10 ITaskBuilder::~ITaskBuilder() noexcept
187 {
188
189 10 }
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 5 ITaskBuilder::VtblTask::VtblTask()
346 {
347 5 obj_vtbl_t* this_ptr = reinterpret_cast<obj_vtbl_t*>(this);
348 5 this_ptr->run = &ITaskBuilder::task_run;
349 5 this_ptr->cancel = ITaskBuilder::task_cancel;
350 5 this_ptr->get_status = ITaskBuilder::task_get_status;
351 5 this_ptr->completed = ITaskBuilder::task_completed;
352 5 this_ptr->get_result = ITaskBuilder::task_get_result;
353 5 this_ptr->wait = ITaskBuilder::task_wait;
354 5 this_ptr->timed_wait = ITaskBuilder::task_timed_wait;
355 5 }
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 5 ITaskBuilder::ITaskBuilder()
364
1/2
✓ Branch 3 taken 5 times.
✗ Branch 4 not taken.
5 : object_builder_t(&cpp_vtbl_task, GATE_INTERFACE_NAME_TASK)
365 {
366 5 }
367
368
369
370
371 5 ITaskBase::ITaskBase()
372 : statusvalue(static_cast<int32_t>(Task::Status_Prepared)),
373 completionsignal(false),
374 taskResult(results::Ok),
375
1/2
✓ Branch 3 taken 5 times.
✗ Branch 4 not taken.
5 taskData(NULL)
376 {
377 5 }
378
379 10 ITaskBase::~ITaskBase() noexcept
380 {
381 10 }
382
383 3 void ITaskBase::runImpl()
384 {
385 3 }
386 1 void ITaskBase::cancelImpl()
387 {
388 1 }
389
390 14 static bool_t updateTaskStatus(AtomicInt& status, Task::StatusEnum fromStatus, Task::StatusEnum toStatus)
391 {
392 14 int32_t oldStatus = status.changeIf(static_cast<int32_t>(fromStatus), static_cast<int32_t>(toStatus));
393 14 return oldStatus == static_cast<int32_t>(fromStatus);
394 }
395
396 5 void ITaskBase::run()
397 {
398
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 4 times.
5 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 4 Task::StatusEnum nextStatus = Task::Status_Completed;
404 4 result_t nextTaskResult = results::Ok;
405
406 try
407 {
408
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 1 times.
4 this->runImpl();
409 }
410 2 catch (Throwable const& xcpt)
411 {
412 1 nextStatus = Task::Status_Failed;
413 1 nextTaskResult = xcpt.getResult();
414 }
415 catch (...)
416 {
417 nextStatus = Task::Status_Failed;
418 nextTaskResult = results::UnknownException;
419 }
420
421
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 1 times.
4 if (updateTaskStatus(this->statusvalue, Task::Status_Running, nextStatus))
422 {
423 3 this->taskResult = nextTaskResult;
424 3 this->completionsignal.set();
425 }
426 4 }
427
428 1 void ITaskBase::setTaskData(void const* data)
429 {
430 1 this->taskData = data;
431 1 }
432
433
434 3 void ITaskBase::cancel()
435 {
436
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
3 if (updateTaskStatus(this->statusvalue, Task::Status_Prepared, Task::Status_Canceled))
437 {
438 1 this->completionsignal.set();
439 }
440
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
2 else if (updateTaskStatus(this->statusvalue, Task::Status_Running, Task::Status_Canceled))
441 {
442 try
443 {
444
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 this->cancelImpl();
445 }
446 catch (...) {}
447 1 this->completionsignal.set();
448 }
449 else
450 {
451 1 GATEXX_RAISE_EXCEPTION(results::InvalidState, "Cannot cancel task", 0);
452 }
453 2 }
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 5 void const* ITaskBase::getResult()
477 {
478 5 Task::StatusEnum state = static_cast<Task::StatusEnum>(this->statusvalue.get());
479
4/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
5 switch (state)
480 {
481 2 case Task::Status_Completed:
482 {
483
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (GATE_FAILED(this->taskResult))
484 {
485 GATEXX_RAISE_EXCEPTION(this->taskResult, "Task execution failed", 0);
486 }
487 else
488 {
489 2 return this->taskData;
490 }
491 break;
492 }
493 1 case Task::Status_Canceled:
494 {
495 1 GATEXX_RAISE_EXCEPTION(results::Canceled, "Task canceled", 0);
496 break;
497 }
498 1 case Task::Status_Failed:
499 {
500 1 GATEXX_RAISE_EXCEPTION(this->taskResult, "Task execution failed", 0);
501 break;
502 }
503 1 default:
504 {
505 1 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