GCC Code Coverage Report


Directory: src/gate/
File: src/gate/cxx_threading.cpp
Date: 2026-10-19 17:06:30
Exec Total Coverage
Lines: 79 88 89.8%
Functions: 19 22 86.4%
Branches: 23 46 50.0%

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/threading.hpp"
30 #include "gate/exceptions.hpp"
31 #include "gate/results.hpp"
32 #include "gate/debugging.h"
33 #include "gate/runnables.hpp"
34
35 namespace gate
36 {
37
38 /*
39 ThisThread::handle_t ThisThread::self(id_t* ptr_id)
40 {
41 gate_thread_t th;
42 result_t result = gate_thread_current(&th, ptr_id);
43 GATEXX_CHECK_ERROR(result);
44 return th;
45 }
46 void ThisThread::sleep(uint32_t milliseconds)
47 {
48 gate_thread_sleep(milliseconds);
49 }
50 void ThisThread::yield()
51 {
52 gate_thread_yield();
53 }
54 void ThisThread::yieldIfPreemptive()
55 {
56 gate_thread_yield_if_preemptive();
57 }
58 ThisThread::ModelEnum ThisThread::supportedModel()
59 {
60 enumint_t model = gate_thread_model();
61 return ThisThread::ModelEnum(model);
62 }
63 */
64
65
66 6 Thread::Thread()
67
2/2
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 6 times.
18 : ptrhandle(NULL), handle(handle_t())
68 {
69 6 }
70 12 Thread::~Thread() noexcept
71 {
72 6 this->release();
73 6 }
74
75 1 Thread::handle_t* Thread::c_impl() noexcept
76 {
77 1 return this->ptrhandle;
78 }
79 ✗ Thread::handle_t const* Thread::c_impl() const noexcept
80 {
81 ✗ return this->ptrhandle;
82 }
83
84 5 Result<Thread::id_t> Thread::tryStart(gate_runnable_t* executor) noexcept
85 {
86 id_t ret;
87 handle_t h;
88 5 result_t result = gate_thread_start(executor, &h, &ret);
89
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (GATE_FAILED(result))
90 {
91 ✗ return makeErr(result);
92 }
93 5 this->release();
94 5 gate_handlestore_move(&this->handle, &h);
95 5 this->ptrhandle = &this->handle;
96 5 return makeOk(ret);
97 }
98
99 1 Result<Thread::id_t> Thread::tryStart(gate_thread_native_entry entry_function, gate_thread_native_param_type entry_param) noexcept
100 {
101 id_t ret;
102 handle_t h;
103 1 result_t result = gate_thread_start_native(entry_function, entry_param, &h, &ret);
104
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (GATE_FAILED(result))
105 {
106 ✗ return makeErr(result);
107 }
108 1 this->release();
109 1 gate_handlestore_move(&this->handle, &h);
110 1 this->ptrhandle = &this->handle;
111 1 return makeOk(ret);
112 }
113
114 1 static gate_thread_native_return_type GATE_THREAD_API thread_cpp_dispatcher(gate_thread_native_param_type param)
115 {
116 1 result_t ret = results::Ok;
117
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (param)
118 {
119 1 IRunnable* ptrCode = static_cast<IRunnable*>((void*)param);
120
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 ExceptionInfo xcptInfo = Catch::exception(*ptrCode);
121 1 ret = xcptInfo.result_code;
122 }
123 1 return (gate_thread_native_return_type)(gate_intptr_t)ret;
124 }
125
126 6 Result<Thread::id_t> Thread::tryStart(IRunnable& code) noexcept
127 {
128 #if !defined(GATEXX_NO_RTTI)
129
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 Runnable* ptr_run = dynamic_cast<Runnable*>(&code);
130
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1 times.
6 if (ptr_run)
131 {
132 5 return this->tryStart(ptr_run->c_impl());
133 }
134 else
135 #endif
136 {
137 1 return this->tryStart(&thread_cpp_dispatcher, static_cast<void*>(&code));
138 }
139 }
140
141 ✗ Thread::id_t Thread::start(gate_runnable_t* executor)
142 {
143 ✗ return this->tryStart(executor).valueOrError();
144 }
145
146 ✗ Thread::id_t Thread::start(gate_thread_native_entry entry_function, gate_thread_native_param_type entry_param)
147 {
148 ✗ return this->tryStart(entry_function, entry_param).valueOrError();
149 }
150
151
152 2 Thread::id_t Thread::start(IRunnable& code)
153 {
154
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 return this->tryStart(code).valueOrError();
155 }
156
157 13 void Thread::release() noexcept
158 {
159
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 12 times.
13 if (this->ptrhandle != NULL)
160 {
161 1 gate_thread_detach(this->ptrhandle);
162 1 this->ptrhandle = NULL;
163 }
164 13 }
165
166 5 Result<result_t> Thread::tryJoin() noexcept
167 {
168 5 result_t threadResult = GATE_RESULT_OK;
169
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (this->ptrhandle != NULL)
170 {
171 5 result_t joinResult = gate_thread_join(this->ptrhandle, &threadResult);
172 5 this->ptrhandle = NULL;
173
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (GATE_FAILED(joinResult))
174 {
175 ✗ return makeErr(joinResult);
176 }
177 }
178 5 return makeOk(threadResult);
179 }
180
181 5 result_t Thread::join()
182 {
183
1/2
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
5 return this->tryJoin().valueOrError();
184 }
185
186 4 Thread::id_t Thread::startDispatcher(IRunnableBuilder* methodRunnerPtr)
187 {
188
2/4
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
4 Runnable runner(methodRunnerPtr->c_impl());
189
1/2
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
8 return Thread::tryStart(runner).valueOrError();
190 }
191
192 1 bool_t Thread::equals(Thread const& otherThread) const noexcept
193 {
194 1 return gate_thread_equals(this->ptrhandle, otherThread.ptrhandle);
195 }
196
197
198
199 1 ThreadStorage::ThreadStorage()
200 {
201 1 result_t result = gate_thread_storage_alloc(&this->impl);
202
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATEXX_CHECK_ERROR(result);
203 1 }
204 2 ThreadStorage::~ThreadStorage() noexcept
205 {
206 1 result_t result = gate_thread_storage_dealloc(&this->impl);
207
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_DEBUG_TRACE_FAILED(result, "gate_thread_storage_dealloc() failed");
208 1 }
209
210 1 Result<void*> ThreadStorage::tryGet() const noexcept
211 {
212 1 void* data = NULL;
213 1 result_t result = gate_thread_storage_get(const_cast<gate_thread_storage_t*>(&this->impl), &data);
214 1 return makeResult(result, data);
215 }
216
217 1 Result<Void> ThreadStorage::trySet(void* data) noexcept
218 {
219 1 result_t result = gate_thread_storage_set(&this->impl, data);
220 1 return makeResult(result);
221 }
222
223
224 1 void* ThreadStorage::get() const
225 {
226 1 void* data = NULL;
227
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 result_t result = gate_thread_storage_get(const_cast<gate_thread_storage_t*>(&this->impl), &data);
228
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
1 GATEXX_CHECK_ERROR(result);
229 1 return data;
230 }
231 1 void ThreadStorage::set(void* data)
232 {
233 1 result_t result = gate_thread_storage_set(&this->impl, data);
234
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATEXX_CHECK_ERROR(result);
235 1 }
236
237 } // end of namespace gate
238