GCC Code Coverage Report


Directory: src/gate/
File: src/gate/cxx_threading.cpp
Date: 2026-03-20 22:56:14
Exec Total Coverage
Lines: 75 82 91.5%
Functions: 17 19 89.5%
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 4 Thread::Thread()
67
2/2
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 4 times.
12 : ptrhandle(NULL), handle(handle_t())
68 {
69 4 }
70 8 Thread::~Thread() noexcept
71 {
72 4 this->release();
73 4 }
74
75 3 Result<Thread::id_t> Thread::tryStart(gate_runnable_t* executor) noexcept
76 {
77 id_t ret;
78 handle_t h;
79 3 result_t result = gate_thread_start(executor, &h, &ret);
80
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (GATE_FAILED(result))
81 {
82 return makeErr(result);
83 }
84 3 this->release();
85 3 gate_handlestore_move(&this->handle, &h);
86 3 this->ptrhandle = &this->handle;
87 3 return makeOk(ret);
88 }
89
90 1 Result<Thread::id_t> Thread::tryStart(gate_thread_native_entry entry_function, gate_thread_native_param_type entry_param) noexcept
91 {
92 id_t ret;
93 handle_t h;
94 1 result_t result = gate_thread_start_native(entry_function, entry_param, &h, &ret);
95
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (GATE_FAILED(result))
96 {
97 return makeErr(result);
98 }
99 1 this->release();
100 1 gate_handlestore_move(&this->handle, &h);
101 1 this->ptrhandle = &this->handle;
102 1 return makeOk(ret);
103 }
104
105 1 static gate_thread_native_return_type GATE_THREAD_API thread_cpp_dispatcher(gate_thread_native_param_type param)
106 {
107 1 result_t ret = results::Ok;
108
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (param)
109 {
110 1 IRunnable* ptrCode = static_cast<IRunnable*>((void*)param);
111
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 ExceptionInfo xcptInfo = catchException(*ptrCode);
112 1 ret = xcptInfo.result_code;
113 }
114 1 return (gate_thread_native_return_type)(gate_intptr_t)ret;
115 }
116
117 4 Result<Thread::id_t> Thread::tryStart(IRunnable& code) noexcept
118 {
119 #if !defined(GATEXX_NO_RTTI)
120
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 Runnable* ptr_run = dynamic_cast<Runnable*>(&code);
121
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
4 if (ptr_run)
122 {
123 3 return this->tryStart(ptr_run->c_impl());
124 }
125 else
126 #endif
127 {
128 1 return this->tryStart(&thread_cpp_dispatcher, static_cast<void*>(&code));
129 }
130 }
131
132 Thread::id_t Thread::start(gate_runnable_t* executor)
133 {
134 return this->tryStart(executor).valueOrError();
135 }
136
137 Thread::id_t Thread::start(gate_thread_native_entry entry_function, gate_thread_native_param_type entry_param)
138 {
139 return this->tryStart(entry_function, entry_param).valueOrError();
140 }
141
142
143 2 Thread::id_t Thread::start(IRunnable& code)
144 {
145
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 return this->tryStart(code).valueOrError();
146 }
147
148 9 void Thread::release() noexcept
149 {
150
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 8 times.
9 if (this->ptrhandle != NULL)
151 {
152 1 gate_thread_detach(this->ptrhandle);
153 1 this->ptrhandle = NULL;
154 }
155 9 }
156
157 3 Result<result_t> Thread::tryJoin() noexcept
158 {
159 3 result_t threadResult = GATE_RESULT_OK;
160
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (this->ptrhandle != NULL)
161 {
162 3 result_t joinResult = gate_thread_join(this->ptrhandle, &threadResult);
163 3 this->ptrhandle = NULL;
164
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (GATE_FAILED(joinResult))
165 {
166 return makeErr(joinResult);
167 }
168 }
169 3 return makeOk(threadResult);
170 }
171
172 3 result_t Thread::join()
173 {
174
1/2
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
3 return this->tryJoin().valueOrError();
175 }
176
177 2 Thread::id_t Thread::startDispatcher(IRunnableBuilder* methodRunnerPtr)
178 {
179
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());
180
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
4 return Thread::tryStart(runner).valueOrError();
181 }
182
183
184
185 1 ThreadStorage::ThreadStorage()
186 {
187 1 result_t result = gate_thread_storage_alloc(&this->impl);
188
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATEXX_CHECK_ERROR(result);
189 1 }
190 2 ThreadStorage::~ThreadStorage() noexcept
191 {
192 1 result_t result = gate_thread_storage_dealloc(&this->impl);
193
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_DEBUG_TRACE_FAILED(result, "gate_thread_storage_dealloc() failed");
194 1 }
195
196 1 Result<void*> ThreadStorage::tryGet() const noexcept
197 {
198 1 void* data = NULL;
199 1 result_t result = gate_thread_storage_get(const_cast<gate_thread_storage_t*>(&this->impl), &data);
200 1 return makeResult(result, data);
201 }
202
203 1 Result<Void> ThreadStorage::trySet(void* data) noexcept
204 {
205 1 result_t result = gate_thread_storage_set(&this->impl, data);
206 1 return makeResult(result);
207 }
208
209
210 1 void* ThreadStorage::get() const
211 {
212 1 void* data = NULL;
213
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);
214
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
1 GATEXX_CHECK_ERROR(result);
215 1 return data;
216 }
217 1 void ThreadStorage::set(void* data)
218 {
219 1 result_t result = gate_thread_storage_set(&this->impl, data);
220
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATEXX_CHECK_ERROR(result);
221 1 }
222
223 } // end of namespace gate
224