GCC Code Coverage Report


Directory: src/gate/
File: src/gate/cxx_threading.cpp
Date: 2025-09-14 13:10:38
Exec Total Coverage
Lines: 90 101 89.1%
Functions: 22 24 91.7%
Branches: 28 56 50.0%

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