GCC Code Coverage Report


Directory: src/gate/
File: src/gate/asyncexecution.c
Date: 2026-08-06 22:46:24
Exec Total Coverage
Lines: 76 93 81.7%
Functions: 9 9 100.0%
Branches: 33 58 56.9%

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/asyncexecution.h"
30 #include "gate/results.h"
31 #include "gate/atomics.h"
32 #include "gate/utilities.h"
33
34 typedef struct
35 {
36 gate_atomic_int_t ref_counter;
37 gate_atomic_int_t state;
38 gate_result_t result;
39 gate_size_t type_size;
40 gate_bool_t type_constructed;
41 gate_mem_copyctor_t type_cctor;
42 gate_mem_dtor_t type_dtor;
43
44 gate_c_maxalign_t data;
45 } gate_future_impl_t;
46
47 #define GATE_FUTURE_STATE_NULL 0
48 #define GATE_FUTURE_STATE_CONSTRUCTING 1
49 #define GATE_FUTURE_STATE_COMPLETED 2
50
51 2 gate_result_t gate_future_create(gate_future_t* future, gate_size_t sz, gate_mem_copyctor_t cctor, gate_mem_dtor_t dtor)
52 {
53 2 gate_result_t ret = GATE_RESULT_FAILED;
54 gate_size_t total_len;
55 2 gate_future_impl_t* impl = NULL;
56
57 do
58 {
59
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!future)
60 {
61 ret = GATE_RESULT_INVALIDARG;
62 break;
63 }
64
65 2 total_len = sizeof(gate_future_impl_t) + sz;
66 2 impl = gate_mem_alloc(total_len);
67
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!impl)
68 {
69 ret = GATE_RESULT_OUTOFMEMORY;
70 break;
71 }
72 2 gate_mem_clear(impl, total_len);
73 2 gate_atomic_int_init(&impl->ref_counter, 1);
74 2 gate_atomic_int_init(&impl->state, GATE_FUTURE_STATE_NULL);
75 2 impl->result = GATE_RESULT_INVALIDSTATE;
76 2 impl->type_size = sz;
77 2 impl->type_constructed = false;
78 2 impl->type_cctor = cctor;
79 2 impl->type_dtor = dtor;
80
81 2 *future = (gate_future_t)impl;
82 2 ret = GATE_RESULT_OK;
83 } while (0);
84
85 2 return ret;
86 }
87
88 2 gate_result_t gate_future_retain(gate_future_t* future, gate_future_t const* src)
89 {
90 gate_future_impl_t* impl;
91
92
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 if (!future || !src)
93 {
94 return GATE_RESULT_NULLPOINTER;
95 }
96 2 *future = *src;
97
98 2 impl = (gate_future_impl_t*)*future;
99
100
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (impl)
101 {
102 2 gate_atomic_int_inc(&impl->ref_counter);
103 2 return GATE_RESULT_OK;
104 }
105 else
106 {
107 return GATE_RESULT_NULLPOINTER;
108 }
109 }
110
111 4 gate_result_t gate_future_release(gate_future_t* future)
112 {
113 4 gate_result_t ret = GATE_RESULT_OK;
114
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 gate_future_impl_t* impl = future ? ((gate_future_impl_t*)*future) : NULL;
115
116
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (impl)
117 {
118
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
4 if (gate_atomic_int_dec(&impl->ref_counter) == 0)
119 {
120
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
2 if (gate_atomic_int_get(&impl->state) == GATE_FUTURE_STATE_COMPLETED)
121 {
122
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 if (impl->type_constructed && impl->type_dtor)
123 {
124 1 impl->type_dtor(&impl->data);
125 }
126 }
127 2 gate_mem_dealloc(impl);
128 2 *future = NULL;
129 }
130 }
131 else
132 {
133 ret = GATE_RESULT_NULLPOINTER;
134 }
135 4 return ret;
136 }
137
138 2 gate_result_t gate_future_set_result(gate_future_t* future, gate_result_t result, void const* data)
139 {
140 2 gate_result_t ret = GATE_RESULT_OK;
141
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 gate_future_impl_t* const impl = future ? ((gate_future_impl_t*)*future) : NULL;
142
143 do
144 {
145
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!impl)
146 {
147 ret = GATE_RESULT_NULLPOINTER;
148 break;
149 }
150
151
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
2 if (gate_atomic_int_xchg_if(&impl->state, GATE_FUTURE_STATE_NULL, GATE_FUTURE_STATE_CONSTRUCTING) != GATE_FUTURE_STATE_NULL)
152 {
153 1 ret = GATE_RESULT_INVALIDSTATE;
154 1 break;
155 }
156
157
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (data)
158 {
159
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (impl->type_cctor)
160 {
161 1 ret = impl->type_cctor(&impl->data, data);
162
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (GATE_FAILED(ret))
163 {
164 gate_atomic_int_set(&impl->state, GATE_FUTURE_STATE_NULL);
165 break;
166 }
167 1 impl->type_constructed = true;
168 }
169 else
170 {
171 if (NULL == gate_mem_copy(&impl->data, data, impl->type_size))
172 {
173 ret = GATE_RESULT_OUTOFMEMORY;
174 gate_atomic_int_set(&impl->state, GATE_FUTURE_STATE_NULL);
175 break;
176 }
177 }
178 }
179
180 1 impl->result = result;
181
182 1 gate_atomic_int_set(&impl->state, GATE_FUTURE_STATE_COMPLETED);
183 1 ret = GATE_RESULT_OK;
184 } while (0);
185
186 2 return ret;
187 }
188
189 5 gate_bool_t gate_future_available(gate_future_t const* future)
190 {
191
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 gate_future_impl_t* const impl = future ? ((gate_future_impl_t*)*future) : NULL;
192
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (impl)
193 {
194
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 3 times.
5 if (GATE_FUTURE_STATE_COMPLETED == gate_atomic_int_get(&impl->state))
195 {
196 2 return true;
197 }
198 }
199 3 return false;
200 }
201
202 4 gate_result_t gate_future_await_timed(gate_future_t* future, gate_uint32_t timeout_ms)
203 {
204
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 gate_future_impl_t* impl = future ? ((gate_future_impl_t*)*future) : NULL;
205
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (impl)
206 {
207 4 return gate_util_state_await(&impl->state, GATE_FUTURE_STATE_COMPLETED, timeout_ms);
208 }
209 else
210 {
211 return GATE_RESULT_NULLPOINTER;
212 }
213 }
214
215 3 gate_result_t gate_future_await(gate_future_t* future)
216 {
217 gate_result_t ret;
218 do
219 {
220 3 ret = gate_future_await_timed(future, 10000);
221
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 } while (ret == GATE_RESULT_TIMEOUT);
222 3 return ret;
223 }
224
225 1 gate_result_t gate_future_get_result(gate_future_t const* future)
226 {
227
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 gate_future_impl_t* impl = future ? ((gate_future_impl_t*)*future) : NULL;
228
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (impl)
229 {
230 1 return impl->result;
231 }
232 return GATE_RESULT_NOTAVAILABLE;
233 }
234
235
236 4 void const* gate_future_get_data(gate_future_t const* future)
237 {
238
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 gate_future_impl_t* impl = future ? ((gate_future_impl_t*)*future) : NULL;
239
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (impl)
240 {
241
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 1 times.
4 if (GATE_FUTURE_STATE_COMPLETED == gate_atomic_int_get(&impl->state))
242 {
243 3 return &impl->data;
244 }
245 }
246 1 return NULL;
247 }
248