GCC Code Coverage Report


Directory: src/gate/
File: src/gate/asyncexecution.c
Date: 2026-06-21 00:38:37
Exec Total Coverage
Lines: 72 98 73.5%
Functions: 8 10 80.0%
Branches: 31 62 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/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 void* gate_future_get_data_ptr(gate_future_t* future)
139 {
140 gate_future_impl_t* impl = future ? ((gate_future_impl_t*)*future) : NULL;
141 if (impl)
142 {
143 return &impl->data;
144 }
145 return NULL;
146 }
147
148
149 2 gate_result_t gate_future_set_result(gate_future_t* future, gate_result_t result, void const* data)
150 {
151 2 gate_result_t ret = GATE_RESULT_OK;
152
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;
153
154 do
155 {
156
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!impl)
157 {
158 ret = GATE_RESULT_NULLPOINTER;
159 break;
160 }
161
162
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)
163 {
164 1 ret = GATE_RESULT_INVALIDSTATE;
165 1 break;
166 }
167
168
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (data)
169 {
170
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (impl->type_cctor)
171 {
172 1 ret = impl->type_cctor(&impl->data, data);
173
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (GATE_FAILED(ret))
174 {
175 gate_atomic_int_set(&impl->state, GATE_FUTURE_STATE_NULL);
176 break;
177 }
178 1 impl->type_constructed = true;
179 }
180 else
181 {
182 if (NULL == gate_mem_copy(&impl->data, data, impl->type_size))
183 {
184 ret = GATE_RESULT_OUTOFMEMORY;
185 gate_atomic_int_set(&impl->state, GATE_FUTURE_STATE_NULL);
186 break;
187 }
188 }
189 }
190
191 1 impl->result = result;
192
193 1 gate_atomic_int_set(&impl->state, GATE_FUTURE_STATE_COMPLETED);
194 1 ret = GATE_RESULT_OK;
195 } while (0);
196
197 2 return ret;
198 }
199
200 4 gate_bool_t gate_future_available(gate_future_t const* future)
201 {
202
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 gate_future_impl_t* const impl = future ? ((gate_future_impl_t*)*future) : NULL;
203
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (impl)
204 {
205
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
4 if (GATE_FUTURE_STATE_COMPLETED == gate_atomic_int_get(&impl->state))
206 {
207 2 return true;
208 }
209 }
210 2 return false;
211 }
212
213 4 gate_result_t gate_future_await_timed(gate_future_t* future, gate_uint32_t timeout_ms)
214 {
215
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 gate_future_impl_t* impl = future ? ((gate_future_impl_t*)*future) : NULL;
216
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (impl)
217 {
218 4 return gate_util_state_await(&impl->state, GATE_FUTURE_STATE_COMPLETED, timeout_ms);
219 }
220 else
221 {
222 return GATE_RESULT_NULLPOINTER;
223 }
224 }
225
226 3 gate_result_t gate_future_await(gate_future_t* future)
227 {
228 gate_result_t ret;
229 do
230 {
231 3 ret = gate_future_await_timed(future, 10000);
232
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 } while (ret == GATE_RESULT_TIMEOUT);
233 3 return ret;
234 }
235
236 gate_result_t gate_future_get_result(gate_future_t const* future)
237 {
238 gate_future_impl_t* impl = future ? ((gate_future_impl_t*)*future) : NULL;
239 if (impl)
240 {
241 return impl->result;
242 }
243 return GATE_RESULT_NOTAVAILABLE;
244 }
245
246
247 4 void const* gate_future_get_data(gate_future_t const* future)
248 {
249
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 gate_future_impl_t* impl = future ? ((gate_future_impl_t*)*future) : NULL;
250
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (impl)
251 {
252
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 1 times.
4 if (GATE_FUTURE_STATE_COMPLETED == gate_atomic_int_get(&impl->state))
253 {
254 3 return &impl->data;
255 }
256 }
257 1 return NULL;
258 }
259