GCC Code Coverage Report


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