GCC Code Coverage Report


Directory: src/gate/
File: src/gate/cxx_runnables.cpp
Date: 2026-09-21 06:26:40
Exec Total Coverage
Lines: 200 229 87.3%
Functions: 43 45 95.6%
Branches: 63 127 49.6%

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