GCC Code Coverage Report


Directory: src/gate/
File: src/gate/cxx_coroutines.cpp
Date: 2025-09-14 13:10:38
Exec Total Coverage
Lines: 89 93 95.7%
Functions: 17 17 100.0%
Branches: 35 86 40.7%

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/coroutines.hpp"
30 #include "gate/exceptions.hpp"
31
32 namespace gate
33 {
34
35 2 bool_t Coroutine::supported()
36 {
37 2 return gate_coroutine_supported();
38 }
39
40 struct GATE_API_LOCAL CoroutineDispatcher : private NonCopyable
41 {
42 gate_coroutine_function_t func;
43 void* param;
44 IRunnable* runnable;
45 Ptr<IRunnable> runnableManager;
46
47 3 CoroutineDispatcher(gate_coroutine_function_t f, void* p)
48 3 : func(f), param(p), runnable(NULL)
49 {
50 3 }
51 3 CoroutineDispatcher(IRunnable* r)
52 3 : func(NULL), param(NULL), runnable(r), runnableManager(r)
53 {
54 3 }
55 3 CoroutineDispatcher(IRunnable& r)
56 3 : func(NULL), param(NULL), runnable(&r)
57 {
58 3 }
59
60 9 void run()
61 {
62
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 6 times.
9 if (this->func)
63 {
64 3 result_t result = this->func(this->param);
65
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 GATEXX_CHECK_EXCEPTION(result);
66 }
67
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 else if (this->runnable)
68 {
69 6 this->runnable->run();
70 }
71 9 }
72
73 9 static gate_result_t dispatcher(void* param)
74 {
75 18 Ptr<CoroutineDispatcher> disp(static_cast<CoroutineDispatcher*>(param));
76
77 try
78 {
79
1/2
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
9 disp->run();
80 9 return GATE_RESULT_OK;
81 }
82 catch (Throwable const& except)
83 {
84 return except.getResult();
85 }
86 catch (...)
87 {
88 return GATE_RESULT_UNKNOWNEXCEPTION;
89 }
90 }
91
92 };
93
94 1 void Coroutine::run(gate_coroutine_function_t func, void* param)
95 {
96
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 Ptr<CoroutineDispatcher> ptr(new CoroutineDispatcher(func, param));
97
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 result_t ret = gate_coroutine_run(&CoroutineDispatcher::dispatcher, ptr.get());
98
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (GATE_SUCCEEDED(ret))
99 {
100 1 ptr.release();
101 }
102
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
1 GATEXX_CHECK_ERROR(ret);
103 1 }
104 1 void Coroutine::run(IRunnable& code)
105 {
106
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 Ptr<CoroutineDispatcher> ptr(new CoroutineDispatcher(code));
107
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 result_t ret = gate_coroutine_run(&CoroutineDispatcher::dispatcher, ptr.get());
108
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (GATE_SUCCEEDED(ret))
109 {
110 1 ptr.release();
111 }
112
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
1 GATEXX_CHECK_ERROR(ret);
113 1 }
114 1 void Coroutine::run(Ptr<IRunnable>& codeptr)
115 {
116
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 Ptr<CoroutineDispatcher> ptr(new CoroutineDispatcher(codeptr.get()));
117 1 codeptr.release();
118
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 result_t ret = gate_coroutine_run(&CoroutineDispatcher::dispatcher, ptr.get());
119
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (GATE_SUCCEEDED(ret))
120 {
121 1 ptr.release();
122 }
123
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
1 GATEXX_CHECK_ERROR(ret);
124 1 }
125
126 2 bool_t Coroutine::enabled()
127 {
128 2 return gate_coroutine_enabled();
129 }
130 1 Coroutine::id_t Coroutine::getCurrent()
131 {
132 1 id_t id = 0;
133
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 result_t result = gate_coroutine_get_current(&id);
134
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
1 GATEXX_CHECK_ERROR(result);
135 1 return id;
136 }
137 10 void Coroutine::yield()
138 {
139 10 result_t result = gate_coroutine_yield();
140
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 GATEXX_CHECK_ERROR(result);
141 10 }
142 2 Coroutine::id_t Coroutine::create(gate_coroutine_function_t func, void* param)
143 {
144 2 id_t ret = 0;
145
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 Ptr<CoroutineDispatcher> ptr(new CoroutineDispatcher(func, param));
146
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 result_t result = gate_coroutine_create(&CoroutineDispatcher::dispatcher, ptr.get(), &ret);
147
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (GATE_SUCCEEDED(result))
148 {
149 2 ptr.release();
150 }
151
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
2 GATEXX_CHECK_ERROR(result);
152 4 return ret;
153 }
154 2 Coroutine::id_t Coroutine::create(IRunnable& code)
155 {
156 2 id_t ret = 0;
157
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 Ptr<CoroutineDispatcher> ptr(new CoroutineDispatcher(code));
158
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 result_t result = gate_coroutine_create(&CoroutineDispatcher::dispatcher, ptr.get(), &ret);
159
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (GATE_SUCCEEDED(result))
160 {
161 2 ptr.release();
162 }
163
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
2 GATEXX_CHECK_ERROR(result);
164 4 return ret;
165 }
166 2 Coroutine::id_t Coroutine::create(Ptr<IRunnable>& codeptr)
167 {
168 2 id_t ret = 0;
169
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 Ptr<CoroutineDispatcher> ptr(new CoroutineDispatcher(codeptr.get()));
170 2 codeptr.release();
171
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 result_t result = gate_coroutine_create(&CoroutineDispatcher::dispatcher, ptr.get(), &ret);
172
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (GATE_SUCCEEDED(result))
173 {
174 2 ptr.release();
175 }
176
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
2 GATEXX_CHECK_ERROR(result);
177 4 return ret;
178 }
179
180 5 void Coroutine::switchTo(id_t context_id)
181 {
182 5 result_t result = gate_coroutine_switch_to(context_id);
183
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 GATEXX_CHECK_ERROR(result);
184 5 }
185
186 4 result_t Coroutine::await(id_t id)
187 {
188 4 result_t co_result = GATE_RESULT_FAILED;
189
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 result_t result = gate_coroutine_await(id, &co_result);
190
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
4 GATEXX_CHECK_ERROR(result);
191 4 return co_result;
192 }
193
194 } // end of namespace gate
195