GCC Code Coverage Report


Directory: src/gate/
File: src/gate/synchronization.c
Date: 2025-09-22 22:57:09
Exec Total Coverage
Lines: 316 429 73.7%
Functions: 37 43 86.0%
Branches: 106 204 52.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/synchronization.h"
30 #include "gate/streams.h"
31 #include "gate/debugging.h"
32 #include "gate/utilities.h"
33 #include "gate/platforms.h"
34 #include "gate/atomics.h"
35 #include "gate/results.h"
36
37 #if defined(GATE_COMPILER_MSVC15) || defined(GATE_COMPILER_GCC)
38 /*# define GATE_SYNCHRONIZATION_USE_STD_C 1*/
39 #endif
40
41 #if defined(GATE_SYNCHRONIZATION_USE_STD_C)
42 # define GATE_SYNCHRONIZATION_C11_IMPL 1
43 #elif defined(GATE_SYS_WIN16)
44 # define GATE_SYNCHRONIZATION_DUMMY_IMPL 1
45 #elif defined(GATE_SYS_WIN)
46 # define GATE_SYNCHRONIZATION_WINAPI_IMPL 1
47 #elif defined(GATE_SYS_BEOS)
48 # define GATE_SYNCHRONIZATION_BEOS_IMPL 1
49 # define GATE_SYNCHRONIZATION_MUTEX_SEMAPHORE 1
50 # define GATE_SYNCHRONIZATION_SYNCEVENT_SEMAPHORE 1
51 # define GATE_SYNCHRONIZATION_CONDITION_SEMAPHORE 1
52 #elif defined(GATE_SYS_DOS)
53 # define GATE_SYNCHRONIZATION_DOS_IMPL 1
54 # define GATE_SYNCHRONIZATION_MUTEX_SEMAPHORE 1
55 # define GATE_SYNCHRONIZATION_SYNCEVENT_SEMAPHORE 1
56 # define GATE_SYNCHRONIZATION_CONDITION_SEMAPHORE 1
57 #elif defined(GATE_SYS_POSIX)
58 # define GATE_SYNCHRONIZATION_POSIX_IMPL 1
59 #else
60 # define GATE_SYNCHRONIZATION_DUMMY_IMPL 1
61 #endif
62
63
64
65 /* Generic synchronized stream implementation */
66
67 GATE_INTERFACE(gate_syncmemstream)
68 {
69 GATE_METHOD0(char const*, get_interface_name);
70 GATE_METHOD0(void, release);
71 GATE_METHOD0(int, retain);
72
73 GATE_METHOD3(gate_result_t, read, char* buffer, gate_size_t bufferlength, gate_size_t * returned);
74 GATE_METHOD3(gate_result_t, peek, char* buffer, gate_size_t bufferlength, gate_size_t * returned);
75 GATE_METHOD3(gate_result_t, write, char const* buffer, gate_size_t bufferlength, gate_size_t * written);
76 GATE_METHOD0(gate_result_t, flush);
77 };
78
79 typedef struct gate_syncmemstream_impl
80 {
81 GATE_INTERFACE_VTBL(gate_syncmemstream)* vbl;
82 gate_atomic_int_t ref_counter;
83 gate_uint32_t timeout;
84 gate_mutex_t mutex;
85 gate_syncevent_t syncevent;
86 gate_memstream_t* memstream;
87 } gate_syncmemstream_impl_t;
88
89 static void gate_syncmemstream_release_impl(void* self);
90 static int gate_syncmemstream_retain_impl(void* self);
91 static char const* gate_syncmemstream_interface_name_impl(void* self);
92 static gate_result_t gate_syncmemstream_read_impl(void* self, char* buffer, gate_size_t bufferlength, gate_size_t* returned);
93 static gate_result_t gate_syncmemstream_peek_impl(void* self, char* buffer, gate_size_t bufferlength, gate_size_t* returned);
94 static gate_result_t gate_syncmemstream_write_impl(void* self, char const* buffer, gate_size_t bufferlength, gate_size_t* written);
95 static gate_result_t gate_syncmemstream_flush_impl(void* self);
96
97 4 void gate_syncmemstream_release_impl(void* self)
98 {
99 4 gate_syncmemstream_impl_t* strm = (gate_syncmemstream_impl_t*)self;
100
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
4 if (gate_atomic_int_dec(&strm->ref_counter) == 0)
101 {
102 /* release syncmemstream */
103
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (strm->memstream != NULL)
104 {
105 2 gate_object_release(strm->memstream);
106 }
107 2 gate_syncevent_destroy(&strm->syncevent);
108 2 gate_mutex_destroy(&strm->mutex);
109 2 gate_mem_dealloc(strm);
110 }
111 4 }
112 2 int gate_syncmemstream_retain_impl(void* self)
113 {
114 2 gate_syncmemstream_impl_t* strm = (gate_syncmemstream_impl_t*)self;
115 2 return gate_atomic_int_inc(&strm->ref_counter);
116 }
117 ✗ static char const* gate_syncmemstream_interface_name_impl(void* self)
118 {
119 (void)self;
120 ✗ return GATE_INTERFACE_NAME_STREAM;
121 }
122 2 static gate_result_t gate_syncmemstream_read_impl(void* self, char* buffer, gate_size_t bufferlength, gate_size_t* returned)
123 {
124 2 gate_syncmemstream_impl_t* strm = (gate_syncmemstream_impl_t*)self;
125 gate_result_t ret;
126 2 gate_size_t memsize = 0;
127 2 gate_size_t bytesreceived = 0;
128
129
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 while (bytesreceived == 0)
130 {
131
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (strm->timeout == 0)
132 {
133 ✗ ret = gate_syncevent_wait(&strm->syncevent);
134 }
135 else
136 {
137 2 ret = gate_syncevent_timed_wait(&strm->syncevent, strm->timeout);
138 }
139
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 GATE_BREAK_IF_FAILED(ret);
140
141
142 1 ret = gate_mutex_acquire(&strm->mutex);
143
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (GATE_FAILED(ret))
144 {
145 ✗ break;
146 }
147
148 do
149 {
150 1 ret = gate_stream_read_block((gate_stream_t*)strm->memstream, buffer, bufferlength, &bytesreceived);
151
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(ret);
152
153 1 memsize = gate_memstream_size(strm->memstream);
154
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (memsize == 0)
155 {
156 1 gate_syncevent_reset(&strm->syncevent);
157 }
158
159 } while (0);
160
161 1 gate_mutex_release(&strm->mutex);
162
163
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (GATE_FAILED(ret))
164 {
165 ✗ break;
166 }
167 };
168
169
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (returned != NULL)
170 {
171 2 *returned = bytesreceived;
172 }
173 2 return ret;
174 }
175 ✗ static gate_result_t gate_syncmemstream_peek_impl(void* self, char* buffer, gate_size_t bufferlength, gate_size_t* returned)
176 {
177 ✗ gate_syncmemstream_impl_t* strm = (gate_syncmemstream_impl_t*)self;
178 gate_result_t ret;
179
180 ✗ ret = gate_mutex_acquire(&strm->mutex);
181 ✗ if (GATE_SUCCEEDED(ret))
182 {
183 /* protected by MUTEX: */
184 ✗ ret = gate_stream_peek(strm->memstream, buffer, bufferlength, returned);
185 ✗ gate_mutex_release(&strm->mutex);
186 }
187
188 ✗ return ret;
189 }
190 1 static gate_result_t gate_syncmemstream_write_impl(void* self, char const* buffer, gate_size_t bufferlength, gate_size_t* written)
191 {
192 1 gate_syncmemstream_impl_t* const strm = (gate_syncmemstream_impl_t*)self;
193 gate_result_t ret;
194 1 gate_size_t byteswritten = 0;
195
196 do
197 {
198
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (bufferlength == 0)
199 {
200 ✗ byteswritten = 0;
201 ✗ ret = GATE_RESULT_OK;
202 ✗ break;
203 }
204
205 1 ret = gate_mutex_acquire(&strm->mutex);
206
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (GATE_SUCCEEDED(ret))
207 {
208 /* protected by MUTEX: */
209 1 ret = gate_stream_write(strm->memstream, buffer, bufferlength, &byteswritten);
210
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (GATE_SUCCEEDED(ret))
211 {
212 1 const gate_result_t result = gate_syncevent_set(&strm->syncevent);
213
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_DEBUG_TRACE_FAILED(result, "gate_syncevent_set() failed");
214 (void)result;
215 }
216 1 gate_mutex_release(&strm->mutex);
217 }
218
219 } while (0);
220
221
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (written != NULL)
222 {
223 1 *written = byteswritten;
224 }
225 1 return ret;
226 }
227 ✗ static gate_result_t gate_syncmemstream_flush_impl(void* self)
228 {
229 ✗ gate_syncmemstream_impl_t* strm = (gate_syncmemstream_impl_t*)self;
230 gate_result_t ret;
231
232 ✗ ret = gate_mutex_acquire(&strm->mutex);
233 ✗ if (GATE_SUCCEEDED(ret))
234 {
235 /* protected by MUTEX: */
236 ✗ ret = gate_syncevent_set(&strm->syncevent);
237
238 ✗ gate_mutex_release(&strm->mutex);
239 }
240
241 ✗ return ret;
242 }
243
244 static GATE_INTERFACE_VTBL(gate_syncmemstream) gate_syncmemstream_vtbl;
245
246 2 static void gate_init_syncmemstream_vtbl()
247 {
248
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (!gate_syncmemstream_vtbl.get_interface_name)
249 {
250 GATE_INTERFACE_VTBL(gate_syncmemstream) const local_vtbl =
251 {
252 &gate_syncmemstream_interface_name_impl,
253 &gate_syncmemstream_release_impl,
254 &gate_syncmemstream_retain_impl,
255 &gate_syncmemstream_read_impl,
256 &gate_syncmemstream_peek_impl,
257 &gate_syncmemstream_write_impl,
258 &gate_syncmemstream_flush_impl
259 };
260 1 gate_syncmemstream_vtbl = local_vtbl;
261 }
262 2 }
263
264 2 gate_result_t gate_syncmemstream_create(gate_size_t prealloc, gate_uint32_t timeoutms, gate_stream_t** ptrtostream)
265 {
266 gate_result_t ret;
267 2 gate_syncmemstream_impl_t* impl = NULL;
268 do
269 {
270 2 impl = (gate_syncmemstream_impl_t*)gate_mem_alloc(sizeof(gate_syncmemstream_impl_t));
271
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (NULL == impl)
272 {
273 ✗ ret = GATE_RESULT_OUTOFMEMORY;
274 ✗ break;
275 }
276 2 gate_mem_clear(impl, sizeof(gate_syncmemstream_impl_t));
277 2 gate_init_syncmemstream_vtbl();
278 2 impl->vbl = &gate_syncmemstream_vtbl;
279 2 gate_atomic_int_init(&impl->ref_counter, 1);
280 2 impl->timeout = timeoutms;
281
282 2 ret = gate_mutex_create(&impl->mutex);
283
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (GATE_FAILED(ret))
284 {
285 ✗ break;
286 }
287 2 ret = gate_syncevent_create(&impl->syncevent, false);
288
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (GATE_FAILED(ret))
289 {
290 ✗ break;
291 }
292
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (NULL == (impl->memstream = gate_memstream_create(prealloc)))
293 {
294 ✗ ret = GATE_RESULT_OUTOFMEMORY;
295 ✗ break;
296 }
297
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (ptrtostream)
298 {
299 2 *ptrtostream = (gate_stream_t*)impl;
300 2 impl = NULL;
301 }
302 2 ret = GATE_RESULT_OK;
303 } while (0);
304
305
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (impl != NULL)
306 {
307 ✗ impl->vbl->release(impl);
308 }
309
310 2 return ret;
311 }
312
313 typedef struct
314 {
315 gate_atomic_int_t ref_counter;
316 gate_atomic_int_t state;
317 gate_result_t result;
318 gate_size_t type_size;
319 gate_bool_t type_constructed;
320 gate_mem_copyctor_t type_cctor;
321 gate_mem_dtor_t type_dtor;
322
323 gate_c_maxalign_t data;
324 } gate_future_impl_t;
325
326 #define GATE_FUTURE_STATE_NULL 0
327 #define GATE_FUTURE_STATE_CONSTRUCTING 1
328 #define GATE_FUTURE_STATE_COMPLETED 2
329
330 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)
331 {
332 2 gate_result_t ret = GATE_RESULT_FAILED;
333 gate_size_t total_len;
334 2 gate_future_impl_t* impl = NULL;
335
336 do
337 {
338
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!future)
339 {
340 ✗ ret = GATE_RESULT_INVALIDARG;
341 ✗ break;
342 }
343
344 2 total_len = sizeof(gate_future_impl_t) + sz;
345 2 impl = gate_mem_alloc(total_len);
346
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!impl)
347 {
348 ✗ ret = GATE_RESULT_OUTOFMEMORY;
349 ✗ break;
350 }
351 2 gate_mem_clear(impl, total_len);
352 2 gate_atomic_int_init(&impl->ref_counter, 1);
353 2 gate_atomic_int_init(&impl->state, GATE_FUTURE_STATE_NULL);
354 2 impl->result = GATE_RESULT_INVALIDSTATE;
355 2 impl->type_size = sz;
356 2 impl->type_constructed = false;
357 2 impl->type_cctor = cctor;
358 2 impl->type_dtor = dtor;
359
360 2 *future = impl;
361 2 ret = GATE_RESULT_OK;
362 } while (0);
363
364 2 return ret;
365 }
366
367 2 gate_result_t gate_future_retain(gate_future_t* future, gate_future_t const* src)
368 {
369 gate_future_impl_t* impl;
370
371
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 if (!future || !src)
372 {
373 ✗ return GATE_RESULT_NULLPOINTER;
374 }
375 2 *future = *src;
376
377
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 impl = future ? ((gate_future_impl_t*)*future) : NULL;
378
379
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (impl)
380 {
381 2 gate_atomic_int_inc(&impl->ref_counter);
382 2 return GATE_RESULT_OK;
383 }
384 else
385 {
386 ✗ return GATE_RESULT_NULLPOINTER;
387 }
388 }
389
390 4 gate_result_t gate_future_release(gate_future_t* future)
391 {
392 4 gate_result_t ret = GATE_RESULT_OK;
393
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 gate_future_impl_t* impl = future ? ((gate_future_impl_t*)*future) : NULL;
394
395
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (impl)
396 {
397
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
4 if (gate_atomic_int_dec(&impl->ref_counter) == 0)
398 {
399
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
2 if (gate_atomic_int_get(&impl->state) == GATE_FUTURE_STATE_COMPLETED)
400 {
401
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)
402 {
403 1 impl->type_dtor(&impl->data);
404 }
405 }
406 2 gate_mem_dealloc(impl);
407 2 *future = NULL;
408 }
409 }
410 else
411 {
412 ✗ ret = GATE_RESULT_NULLPOINTER;
413 }
414 4 return ret;
415 }
416
417 ✗ void* gate_future_get_data_ptr(gate_future_t* future)
418 {
419 ✗ gate_future_impl_t* impl = future ? ((gate_future_impl_t*)*future) : NULL;
420 ✗ if (impl)
421 {
422 ✗ return &impl->data;
423 }
424 ✗ return NULL;
425 }
426
427
428 2 gate_result_t gate_future_set_result(gate_future_t* future, gate_result_t result, void const* data)
429 {
430 2 gate_result_t ret = GATE_RESULT_OK;
431
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 gate_future_impl_t* impl = future ? ((gate_future_impl_t*)*future) : NULL;
432
433 do
434 {
435
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!impl)
436 {
437 ✗ ret = GATE_RESULT_NULLPOINTER;
438 ✗ break;
439 }
440
441
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)
442 {
443 1 ret = GATE_RESULT_INVALIDSTATE;
444 1 break;
445 }
446
447
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (data)
448 {
449
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (impl->type_cctor)
450 {
451 1 ret = impl->type_cctor(&impl->data, data);
452
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (GATE_FAILED(ret))
453 {
454 ✗ gate_atomic_int_set(&impl->state, GATE_FUTURE_STATE_NULL);
455 ✗ break;
456 }
457 1 impl->type_constructed = true;
458 }
459 else
460 {
461 ✗ if (NULL == gate_mem_copy(&impl->data, data, impl->type_size))
462 {
463 ✗ ret = GATE_RESULT_OUTOFMEMORY;
464 ✗ gate_atomic_int_set(&impl->state, GATE_FUTURE_STATE_NULL);
465 ✗ break;
466 }
467 }
468 }
469
470 1 impl->result = result;
471
472 1 gate_atomic_int_set(&impl->state, GATE_FUTURE_STATE_COMPLETED);
473 1 ret = GATE_RESULT_OK;
474 } while (0);
475
476 2 return ret;
477 }
478
479 4 gate_bool_t gate_future_available(gate_future_t const* future)
480 {
481
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 gate_future_impl_t* impl = future ? ((gate_future_impl_t*)*future) : NULL;
482
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (impl)
483 {
484
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
4 if (GATE_FUTURE_STATE_COMPLETED == gate_atomic_int_get(&impl->state))
485 {
486 2 return true;
487 }
488 }
489 2 return false;
490 }
491
492 4 gate_result_t gate_future_await_timed(gate_future_t* future, gate_uint32_t timeout_ms)
493 {
494
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 gate_future_impl_t* impl = future ? ((gate_future_impl_t*)*future) : NULL;
495
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (impl)
496 {
497 4 return gate_util_state_await(&impl->state, GATE_FUTURE_STATE_COMPLETED, timeout_ms);
498 }
499 else
500 {
501 ✗ return GATE_RESULT_NULLPOINTER;
502 }
503 }
504
505 3 gate_result_t gate_future_await(gate_future_t* future)
506 {
507 gate_result_t ret;
508 do
509 {
510 3 ret = gate_future_await_timed(future, 10000);
511
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 } while (ret == GATE_RESULT_TIMEOUT);
512 3 return ret;
513 }
514
515 ✗ gate_result_t gate_future_get_result(gate_future_t const* future)
516 {
517 ✗ gate_future_impl_t* impl = future ? ((gate_future_impl_t*)*future) : NULL;
518 ✗ if (impl)
519 {
520 ✗ return impl->result;
521 }
522 ✗ return GATE_RESULT_NOTAVAILABLE;
523 }
524
525
526 4 void const* gate_future_get_data(gate_future_t const* future)
527 {
528
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 gate_future_impl_t* impl = future ? ((gate_future_impl_t*)*future) : NULL;
529
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (impl)
530 {
531
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 1 times.
4 if (GATE_FUTURE_STATE_COMPLETED == gate_atomic_int_get(&impl->state))
532 {
533 3 return &impl->data;
534 }
535 }
536 1 return NULL;
537 }
538
539
540
541
542 3 gate_result_t gate_semaphore_create(gate_semaphore_t* semaphore, gate_uint32_t count)
543 {
544 gate_result_t result;
545 3 gate_platform_semaphore_t* ptr_sem = GATE_HANDLESTORE_CREATE(semaphore, gate_platform_semaphore_t);
546
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ptr_sem == NULL)
547 {
548 ✗ return GATE_RESULT_OUTOFMEMORY;
549 }
550 3 result = gate_platform_semaphore_create(ptr_sem, count);
551
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (GATE_FAILED(result))
552 {
553 ✗ GATE_HANDLESTORE_DESTROY(semaphore);
554 }
555 3 return result;
556 }
557 4 gate_result_t gate_semaphore_acquire(gate_semaphore_t* semaphore)
558 {
559 4 gate_platform_semaphore_t* ptr_sem = GATE_HANDLESTORE_ACCESS(semaphore, gate_platform_semaphore_t);
560 4 return gate_platform_semaphore_acquire(ptr_sem, NULL);
561 }
562 4 gate_result_t gate_semaphore_timed_acquire(gate_semaphore_t* semaphore, gate_uint32_t timeoutms)
563 {
564 4 gate_platform_semaphore_t* ptr_sem = GATE_HANDLESTORE_ACCESS(semaphore, gate_platform_semaphore_t);
565 4 return gate_platform_semaphore_acquire(ptr_sem, &timeoutms);
566 }
567 6 gate_result_t gate_semaphore_release(gate_semaphore_t* semaphore)
568 {
569 6 gate_platform_semaphore_t* ptr_sem = GATE_HANDLESTORE_ACCESS(semaphore, gate_platform_semaphore_t);
570 6 return gate_platform_semaphore_release(ptr_sem);
571 }
572 3 gate_result_t gate_semaphore_destroy(gate_semaphore_t* semaphore)
573 {
574 3 gate_result_t ret = GATE_RESULT_FAILED;
575 3 gate_platform_semaphore_t* ptr_sem = GATE_HANDLESTORE_ACCESS(semaphore, gate_platform_semaphore_t);
576
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (ptr_sem)
577 {
578 3 ret = gate_platform_semaphore_destroy(ptr_sem);
579 3 GATE_HANDLESTORE_DESTROY(semaphore);
580 }
581 3 return ret;
582 }
583
584
585
586 #if defined(GATE_SYNCHRONIZATION_MUTEX_SEMAPHORE)
587
588 gate_result_t gate_mutex_create(gate_mutex_t* mutex)
589 {
590 gate_platform_semaphore_t* ptr_sem = (gate_platform_semaphore_t*)mutex;
591 return gate_platform_semaphore_create(ptr_sem, 1);
592 }
593
594 gate_result_t gate_mutex_acquire(gate_mutex_t* mutex)
595 {
596 gate_platform_semaphore_t* ptr_sem = (gate_platform_semaphore_t*)mutex;
597 return gate_platform_semaphore_acquire(ptr_sem, NULL);
598 }
599
600 gate_result_t gate_mutex_release(gate_mutex_t* mutex)
601 {
602 gate_platform_semaphore_t* ptr_sem = (gate_platform_semaphore_t*)mutex;
603 return gate_platform_semaphore_release(ptr_sem);
604 }
605
606 gate_result_t gate_mutex_destroy(gate_mutex_t* mutex)
607 {
608 gate_platform_semaphore_t* ptr_sem = (gate_platform_semaphore_t*)mutex;
609 return gate_platform_semaphore_destroy(ptr_sem);
610 }
611
612 #endif /* GATE_SYNCHRONIZATION_MUTEX_SEMAPHORE */
613
614
615
616 #if defined(GATE_SYNCHRONIZATION_SYNCEVENT_SEMAPHORE)
617
618 typedef struct gate_semevent_class
619 {
620 gate_platform_semaphore_t signal;
621 gate_atomic_int_t state;
622 } gate_semevent_t;
623
624 gate_result_t gate_syncevent_create(gate_syncevent_t* syncevent, gate_bool_t autoreset)
625 {
626 gate_result_t result;
627 gate_semevent_t* ptr = GATE_HANDLESTORE_CREATE(syncevent, gate_semevent_t);
628 if (!ptr)
629 {
630 return GATE_RESULT_OUTOFMEMORY;
631 }
632 gate_atomic_int_init(&ptr->state, autoreset ? 0 : 0x80);
633 result = gate_platform_semaphore_create(&ptr->signal, 1);
634 if (GATE_FAILED(result))
635 {
636 GATE_HANDLESTORE_DESTROY(syncevent);
637 }
638 result = gate_platform_semaphore_acquire(&ptr->signal, NULL);
639 if (GATE_FAILED(result))
640 {
641 gate_platform_semaphore_destroy(&ptr->signal);
642 GATE_HANDLESTORE_DESTROY(syncevent);
643 }
644 return result;
645 }
646 gate_result_t gate_syncevent_destroy(gate_syncevent_t* syncevent)
647 {
648 gate_semevent_t* ptr = GATE_HANDLESTORE_ACCESS(syncevent, gate_semevent_t);
649 if (ptr)
650 {
651 gate_platform_semaphore_destroy(&ptr->signal);
652 GATE_HANDLESTORE_DESTROY(syncevent);
653 return GATE_RESULT_OK;
654 }
655 return GATE_RESULT_INVALIDSTATE;
656 }
657
658 gate_result_t gate_syncevent_set(gate_syncevent_t* syncevent)
659 {
660 gate_semevent_t* ptr = GATE_HANDLESTORE_ACCESS(syncevent, gate_semevent_t);
661 gate_result_t result;
662 gate_int32_t old_state = gate_atomic_int_xchg_if(&ptr->state, 0, 1);
663 if (old_state == 1)
664 {
665 /* was already set */
666 return GATE_RESULT_OK;
667 }
668 if (old_state == 0)
669 {
670 /* was reset, is now set */
671 result = gate_platform_semaphore_release(&ptr->signal);
672 if (GATE_FAILED(result))
673 {
674 gate_atomic_int_xchg_if(&ptr->state, 1, 0);
675 }
676 return result;
677 }
678 old_state = gate_atomic_int_xchg_if(&ptr->state, 0x80, 0x81);
679 if (old_state == 0x81)
680 {
681 /* was already set */
682 return GATE_RESULT_OK;
683 }
684 if (old_state == 0x80)
685 {
686 /* was reset, is now set */
687 result = gate_platform_semaphore_release(&ptr->signal);
688 if (GATE_FAILED(result))
689 {
690 gate_atomic_int_xchg_if(&ptr->state, 0x81, 0x80);
691 }
692 return result;
693 }
694 return GATE_RESULT_INVALIDSTATE;
695 }
696
697 gate_result_t gate_syncevent_reset(gate_syncevent_t* syncevent)
698 {
699 gate_semevent_t* ptr = GATE_HANDLESTORE_ACCESS(syncevent, gate_semevent_t);
700 gate_result_t result;
701 gate_int32_t old_state = gate_atomic_int_xchg_if(&ptr->state, 1, 0);
702 if (old_state == 0)
703 {
704 return GATE_RESULT_OK;
705 }
706 if (old_state == 1)
707 {
708 result = gate_platform_semaphore_acquire(&ptr->signal, NULL);
709 if (GATE_FAILED(result))
710 {
711 gate_atomic_int_xchg_if(&ptr->state, 0, 1);
712 }
713 return result;
714 }
715
716 old_state = gate_atomic_int_xchg_if(&ptr->state, 0x81, 0x80);
717 if (old_state == 0x80)
718 {
719 return GATE_RESULT_OK;
720 }
721 if (old_state == 0x81)
722 {
723 result = gate_platform_semaphore_acquire(&ptr->signal, NULL);
724 if (GATE_FAILED(result))
725 {
726 gate_atomic_int_xchg_if(&ptr->state, 0x80, 0x81);
727 }
728 return result;
729 }
730 return GATE_RESULT_INVALIDSTATE;
731 }
732
733 static gate_result_t gate_syncevent_wait_impl(gate_syncevent_t* syncevent, gate_uint32_t const* timeout)
734 {
735 gate_semevent_t* ptr = GATE_HANDLESTORE_ACCESS(syncevent, gate_semevent_t);
736 gate_result_t result;
737 gate_int32_t old_state;
738
739 result = gate_platform_semaphore_acquire(&ptr->signal, timeout);
740
741 if (GATE_FAILED(result))
742 {
743 return result;
744 }
745
746 /* try auto-reset states */
747 old_state = gate_atomic_int_xchg_if(&ptr->state, 1, 0);
748 if (old_state == 1)
749 {
750 /* event was set, we have reset it, now we release the semaphore */
751 result = gate_platform_semaphore_release(&ptr->signal);
752 if (GATE_FAILED(result))
753 {
754 gate_atomic_int_xchg_if(&ptr->state, 0, 1);
755 }
756 return result;
757 }
758 if (old_state == 0)
759 {
760 /* it should be impossoble to acquire the samephore with state zero */
761 result = gate_platform_semaphore_release(&ptr->signal);
762 return GATE_RESULT_INVALIDSTATE;
763 }
764
765 /* try non-auto-reset states */
766 old_state = gate_atomic_int_xchg_if(&ptr->state, 0x81, 0x81);
767 if (old_state == 0x81)
768 {
769 /* event is set, and will remain in this state */
770 result = gate_platform_semaphore_release(&ptr->signal);
771 return result;
772 }
773 if (old_state == 0x80)
774 {
775 /* it should be impossoble to acquire the samephore with state zero */
776 result = gate_platform_semaphore_release(&ptr->signal);
777 return GATE_RESULT_INVALIDSTATE;
778 }
779
780 return GATE_RESULT_INVALIDSTATE;
781 }
782
783 gate_result_t gate_syncevent_wait(gate_syncevent_t* syncevent)
784 {
785 return gate_syncevent_wait_impl(syncevent, NULL);
786 }
787
788 gate_result_t gate_syncevent_timed_wait(gate_syncevent_t* syncevent, gate_uint32_t timeoutms)
789 {
790 return gate_syncevent_wait_impl(syncevent, &timeoutms);
791 }
792
793 #endif /* GATE_SYNCHRONIZATION_SYNCEVENT_SEMAPHORE */
794
795
796
797 #if defined(GATE_SYNCHRONIZATION_CONDITION_SEMAPHORE)
798
799 #define GATE_SYNCHRONIZATION_CONDITION_SEMAPHORE_MAX 1023
800
801 typedef struct gate_semcond_class
802 {
803 gate_platform_semaphore_t waits;
804 gate_platform_semaphore_t signals;
805 gate_atomic_int_t wait_counter;
806 } gate_semcond_t;
807
808 gate_result_t gate_synccondition_create(gate_synccondition_t* cond)
809 {
810 gate_semcond_t* ptr = GATE_HANDLESTORE_CREATE(cond, gate_semcond_t);
811 size_t n;
812 if (!ptr)
813 {
814 return GATE_RESULT_OUTOFMEMORY;
815 }
816
817 gate_atomic_int_init(&ptr->wait_counter, 0);
818
819 /* TODO: error handling */
820 gate_platform_semaphore_create(&ptr->waits, GATE_SYNCHRONIZATION_CONDITION_SEMAPHORE_MAX);
821 for (n = 0; n != GATE_SYNCHRONIZATION_CONDITION_SEMAPHORE_MAX; ++n)
822 {
823 gate_platform_semaphore_acquire(&ptr->waits, NULL);
824 }
825
826 gate_platform_semaphore_create(&ptr->signals, GATE_SYNCHRONIZATION_CONDITION_SEMAPHORE_MAX);
827 for (n = 0; n != GATE_SYNCHRONIZATION_CONDITION_SEMAPHORE_MAX; ++n)
828 {
829 gate_platform_semaphore_acquire(&ptr->signals, NULL);
830 }
831
832 return GATE_RESULT_OK;
833 }
834
835 gate_result_t gate_synccondition_destroy(gate_synccondition_t* cond)
836 {
837 gate_semcond_t* ptr = GATE_HANDLESTORE_ACCESS(cond, gate_semcond_t);
838 if (ptr)
839 {
840 gate_platform_semaphore_destroy(&ptr->signals);
841 gate_platform_semaphore_destroy(&ptr->waits);
842 GATE_HANDLESTORE_DESTROY(cond);
843 return GATE_RESULT_OK;
844 }
845 return GATE_RESULT_INVALIDSTATE;
846 }
847
848 static gate_result_t gate_synccodition_wait_impl(gate_synccondition_t* cond, gate_mutex_t* mutex, gate_uint32_t const* timeout)
849 {
850 gate_result_t result;
851 gate_semcond_t* ptr = GATE_HANDLESTORE_ACCESS(cond, gate_semcond_t);
852
853 gate_atomic_int_inc(&ptr->wait_counter);
854
855 result = gate_mutex_release(mutex);
856 if (GATE_FAILED(result))
857 {
858 gate_atomic_int_dec(&ptr->wait_counter);
859 return result;
860 }
861
862 do
863 {
864 result = gate_platform_semaphore_acquire(&ptr->waits, timeout);
865 if (GATE_FAILED(result))
866 {
867 gate_atomic_int_dec(&ptr->wait_counter);
868 break;
869 }
870
871 result = gate_platform_semaphore_release(&ptr->signals);
872 if (GATE_FAILED(result))
873 {
874 gate_atomic_int_dec(&ptr->wait_counter);
875 gate_platform_semaphore_release(&ptr->waits);
876 break;
877 }
878 } while (0);
879
880 gate_mutex_acquire(mutex);
881
882 return result;
883 }
884
885 gate_result_t gate_synccondition_wait(gate_synccondition_t* cond, gate_mutex_t* mutex)
886 {
887 return gate_synccodition_wait_impl(cond, mutex, NULL);
888 }
889
890 gate_result_t gate_synccondition_timed_wait(gate_synccondition_t* cond, gate_mutex_t* mutex, gate_uint32_t timeoutms)
891 {
892 return gate_synccodition_wait_impl(cond, mutex, &timeoutms);
893 }
894
895 gate_result_t gate_synccondition_signal_one(gate_synccondition_t* cond)
896 {
897 gate_result_t ret = GATE_RESULT_OK;
898 gate_semcond_t* ptr = GATE_HANDLESTORE_ACCESS(cond, gate_semcond_t);
899 gate_int32_t current_counter;
900
901 do
902 {
903 current_counter = gate_atomic_int_dec(&ptr->wait_counter);
904 if (current_counter < 0)
905 {
906 gate_atomic_int_inc(&ptr->wait_counter);
907 break;
908 }
909 gate_platform_semaphore_release(&ptr->waits);
910 gate_platform_semaphore_acquire(&ptr->signals, NULL);
911 } while (0);
912
913 return ret;
914 }
915
916 gate_result_t gate_synccondition_signal_all(gate_synccondition_t* cond)
917 {
918 gate_result_t ret = GATE_RESULT_OK;
919 gate_semcond_t* ptr = GATE_HANDLESTORE_ACCESS(cond, gate_semcond_t);
920 gate_int32_t current_counter;
921
922 do
923 {
924 current_counter = gate_atomic_int_dec(&ptr->wait_counter);
925 if (current_counter < 0)
926 {
927 gate_atomic_int_inc(&ptr->wait_counter);
928 break;
929 }
930 gate_platform_semaphore_release(&ptr->waits);
931 gate_platform_semaphore_acquire(&ptr->signals, NULL);
932 } while (1);
933
934 return ret;
935 }
936
937 #endif /* GATE_SYNCHRONIZATION_CONDITION_SEMAPHORE */
938
939
940
941
942
943 #if defined(GATE_SYNCHRONIZATION_C11_IMPL)
944
945 #if defined(GATE_COMPILER_MSVC)
946
947 #include <time.h>
948
949 #if _MSC_VER >= 1920
950 // MSVC 2019+
951 # include <xthreads.h>
952 #elif _MSC_VER >= 1900
953 // MSVC 2015+
954 # include <thr/xthreads.h>
955 #else
956 #endif
957
958 # define thrd_success _Thrd_success
959 # define thrd_nomem _Thrd_nomem
960 # define thrd_timedout _Thrd_timedout
961 # define thrd_busy _Thrd_busy
962 # define thrd_error _Thrd_error
963
964 # define mtx_t _Mtx_t
965 # define mtx_init(ptr_mtx, mtx_type) _Mtx_init(ptr_mtx, mtx_type)
966 # define mtx_destroy(ptr_mtx) _Mtx_destroy(*ptr_mtx)
967 # define mtx_lock(ptr_mtx) _Mtx_lock(*ptr_mtx)
968 # define mtx_unlock(ptr_mtx) _Mtx_unlock(*ptr_mtx)
969 # define mtx_trylock(ptr_mtx) _Mtx_trylock(*ptr_mtx)
970
971 # define mtx_plain _Mtx_plain
972 # define mtx_timed _Mtx_timed
973 # define mtx_recursive _Mtx_recursive
974
975 # define cnd_t _Cnd_t
976 # define cnd_init(ptr_cnd) _Cnd_init(ptr_cnd)
977 # define cnd_destroy(ptr_cnd) _Cnd_destroy(*ptr_cnd)
978 # define cnd_wait(ptr_cnd, ptr_mtx) _Cnd_wait(*ptr_cnd, *ptr_mtx)
979 # define cnd_timedwait(ptr_cnd, ptr_mtx, ptr_timespec) _Cnd_timedwait(*ptr_cnd, *ptr_mtx, (xtime const*)ptr_timespec)
980 # define cnd_signal(ptr_cnd) _Cnd_signal(*ptr_cnd)
981 # define cnd_broadcast(ptr_cnd) _Cnd_broadcast(*ptr_cnd)
982
983 #else
984 # include <threads.h>
985 #endif
986
987
988 gate_result_t gate_mutex_create(gate_mutex_t* mutex)
989 {
990 mtx_t* ptr = (mtx_t*)mutex;
991 int result = mtx_init(ptr, mtx_plain);
992 if (result == thrd_success)
993 {
994 return GATE_RESULT_OK;
995 }
996 else
997 {
998 return GATE_RESULT_FAILED;
999 }
1000 }
1001
1002 gate_result_t gate_mutex_acquire(gate_mutex_t* mutex)
1003 {
1004 mtx_t* ptr = (mtx_t*)mutex;
1005 int result = mtx_lock(ptr);
1006 if (result == thrd_success)
1007 {
1008 return GATE_RESULT_OK;
1009 }
1010 else
1011 {
1012 return GATE_RESULT_FAILED;
1013 }
1014 }
1015
1016 gate_result_t gate_mutex_release(gate_mutex_t* mutex)
1017 {
1018 mtx_t* ptr = (mtx_t*)mutex;
1019 int result = mtx_unlock(ptr);
1020 if (result == thrd_success)
1021 {
1022 return GATE_RESULT_OK;
1023 }
1024 else
1025 {
1026 return GATE_RESULT_FAILED;
1027 }
1028 }
1029
1030 gate_result_t gate_mutex_destroy(gate_mutex_t* mutex)
1031 {
1032 mtx_t* ptr = (mtx_t*)mutex;
1033 mtx_destroy(ptr);
1034 return GATE_RESULT_OK;
1035 }
1036
1037
1038
1039
1040 gate_result_t gate_synccondition_create(gate_synccondition_t* cond)
1041 {
1042 cnd_t* ptr_cnd = GATE_HANDLESTORE_CREATE(cond, cnd_t);
1043
1044 if (!ptr_cnd)
1045 {
1046 return GATE_RESULT_OUTOFRESOURCES;
1047 }
1048
1049 if (thrd_success == cnd_init(ptr_cnd))
1050 {
1051 return GATE_RESULT_OK;
1052 }
1053 else
1054 {
1055 GATE_HANDLESTORE_DESTROY(cond);
1056 return GATE_RESULT_FAILED;
1057 }
1058 }
1059 gate_result_t gate_synccondition_destroy(gate_synccondition_t* cond)
1060 {
1061 cnd_t* ptr_cnd = GATE_HANDLESTORE_ACCESS(cond, cnd_t);
1062 if (ptr_cnd)
1063 {
1064 cnd_destroy(ptr_cnd);
1065 GATE_HANDLESTORE_DESTROY(cond);
1066 }
1067 return GATE_RESULT_OK;
1068 }
1069 gate_result_t gate_synccondition_wait(gate_synccondition_t* cond, gate_mutex_t* mutex)
1070 {
1071 int result;
1072
1073 mtx_t* ptr_mtx = (mtx_t*)mutex;
1074 cnd_t* ptr_cnd = GATE_HANDLESTORE_ACCESS(cond, cnd_t);
1075
1076 result = cnd_wait(ptr_cnd, ptr_mtx);
1077 switch (result)
1078 {
1079 case thrd_success: return GATE_RESULT_OK;
1080 default: return GATE_RESULT_FAILED;
1081 }
1082 }
1083
1084 static void calc_timeout_timespec(struct timespec* ptr_ts, gate_uint32_t timeoutms)
1085 {
1086 timespec_get(ptr_ts, TIME_UTC);
1087
1088 ptr_ts->tv_sec += timeoutms / 1000;
1089 ptr_ts->tv_nsec += (long)(timeoutms % 1000) * 1000000L;
1090 ptr_ts->tv_sec += (ptr_ts->tv_nsec / 1000000000L);
1091 ptr_ts->tv_nsec %= 1000000000L;
1092 }
1093
1094 gate_result_t gate_synccondition_timed_wait(gate_synccondition_t* cond, gate_mutex_t* mutex, gate_uint32_t timeoutms)
1095 {
1096 struct timespec time_point;
1097 int result;
1098
1099 mtx_t* ptr_mtx = (mtx_t*)mutex;
1100 cnd_t* ptr_cnd = GATE_HANDLESTORE_ACCESS(cond, cnd_t);
1101
1102 calc_timeout_timespec(&time_point, timeoutms);
1103
1104 result = cnd_timedwait(ptr_cnd, ptr_mtx, &time_point);
1105 switch (result)
1106 {
1107 case thrd_success: return GATE_RESULT_OK;
1108 case thrd_timedout: return GATE_RESULT_TIMEOUT;
1109 default: return GATE_RESULT_FAILED;
1110 }
1111 }
1112 gate_result_t gate_synccondition_signal_one(gate_synccondition_t* cond)
1113 {
1114 int result;
1115 cnd_t* ptr_cnd = GATE_HANDLESTORE_ACCESS(cond, cnd_t);
1116
1117 result = cnd_signal(ptr_cnd);
1118 switch (result)
1119 {
1120 case thrd_success: return GATE_RESULT_OK;
1121 default: return GATE_RESULT_FAILED;
1122 }
1123 }
1124 gate_result_t gate_synccondition_signal_all(gate_synccondition_t* cond)
1125 {
1126 int result;
1127 cnd_t* ptr_cnd = GATE_HANDLESTORE_ACCESS(cond, cnd_t);
1128
1129 result = cnd_broadcast(ptr_cnd);
1130 switch (result)
1131 {
1132 case thrd_success: return GATE_RESULT_OK;
1133 default: return GATE_RESULT_FAILED;
1134 }
1135 }
1136
1137
1138
1139 typedef struct gate_syncevent_impl
1140 {
1141 cnd_t cond;
1142 mtx_t mutex;
1143 gate_bool_t state;
1144 gate_bool_t autoreset;
1145 } gate_syncevent_impl_t;
1146
1147 gate_result_t gate_syncevent_create(gate_syncevent_t* syncevent, gate_bool_t autoreset)
1148 {
1149 gate_syncevent_impl_t* ptr_evt = GATE_HANDLESTORE_CREATE(syncevent, gate_syncevent_impl_t);
1150 if (NULL == ptr_evt)
1151 {
1152 return GATE_RESULT_OUTOFRESOURCES;
1153 }
1154 cnd_init(&ptr_evt->cond);
1155 mtx_init(&ptr_evt->mutex, mtx_timed);
1156 ptr_evt->state = false;
1157 ptr_evt->autoreset = autoreset;
1158
1159 return GATE_RESULT_OK;
1160 }
1161 gate_result_t gate_syncevent_destroy(gate_syncevent_t* syncevent)
1162 {
1163 gate_syncevent_impl_t* ptr_evt = GATE_HANDLESTORE_ACCESS(syncevent, gate_syncevent_impl_t);
1164 if (ptr_evt)
1165 {
1166 mtx_destroy(&ptr_evt->mutex);
1167 cnd_destroy(&ptr_evt->cond);
1168 GATE_HANDLESTORE_DESTROY(syncevent);
1169 }
1170 return GATE_RESULT_OK;
1171 }
1172 gate_result_t gate_syncevent_set(gate_syncevent_t* syncevent)
1173 {
1174 gate_syncevent_impl_t* ptr_evt = GATE_HANDLESTORE_ACCESS(syncevent, gate_syncevent_impl_t);
1175 mtx_lock(&ptr_evt->mutex);
1176 ptr_evt->state = true;
1177 if (ptr_evt->autoreset)
1178 {
1179 cnd_signal(&ptr_evt->cond);
1180 }
1181 else
1182 {
1183 cnd_broadcast(&ptr_evt->cond);
1184 }
1185
1186 mtx_unlock(&ptr_evt->mutex);
1187 return GATE_RESULT_OK;
1188 }
1189 gate_result_t gate_syncevent_reset(gate_syncevent_t* syncevent)
1190 {
1191 gate_syncevent_impl_t* ptr_evt = GATE_HANDLESTORE_ACCESS(syncevent, gate_syncevent_impl_t);
1192
1193 do
1194 {
1195 } while (0);
1196
1197 mtx_lock(&ptr_evt->mutex);
1198 ptr_evt->state = false;
1199 mtx_unlock(&ptr_evt->mutex);
1200 return GATE_RESULT_OK;
1201 }
1202 gate_result_t gate_syncevent_wait(gate_syncevent_t* syncevent)
1203 {
1204 gate_result_t ret = GATE_RESULT_OK;
1205 gate_syncevent_impl_t* ptr_evt = GATE_HANDLESTORE_ACCESS(syncevent, gate_syncevent_impl_t);
1206 int status;
1207
1208 do
1209 {
1210 status = mtx_lock(&ptr_evt->mutex);
1211 if (thrd_success != thrd_success)
1212 {
1213 ret = GATE_RESULT_FAILED;
1214 break;
1215 }
1216
1217 while (!ptr_evt->state)
1218 {
1219 status = cnd_wait(&ptr_evt->cond, &ptr_evt->mutex);
1220 if (status != thrd_success)
1221 {
1222 ret = GATE_RESULT_FAILED;
1223 break;
1224 }
1225 }
1226
1227 mtx_unlock(&ptr_evt->mutex);
1228 } while (0);
1229 return ret;
1230 }
1231
1232 gate_result_t gate_syncevent_timed_wait(gate_syncevent_t* syncevent, gate_uint32_t timeoutms)
1233 {
1234 gate_result_t ret = GATE_RESULT_OK;
1235 gate_syncevent_impl_t* ptr_evt = GATE_HANDLESTORE_ACCESS(syncevent, gate_syncevent_impl_t);
1236 int status;
1237 struct timespec time_point;
1238
1239 calc_timeout_timespec(&time_point, timeoutms);
1240
1241 do
1242 {
1243 status = mtx_lock(&ptr_evt->mutex);
1244 if (thrd_success != thrd_success)
1245 {
1246 ret = GATE_RESULT_FAILED;
1247 break;
1248 }
1249
1250 while (!ptr_evt->state)
1251 {
1252 status = cnd_timedwait(&ptr_evt->cond, &ptr_evt->mutex, &time_point);
1253 if (status == thrd_timedout)
1254 {
1255 ret = GATE_RESULT_TIMEOUT;
1256 break;
1257 }
1258 else if (status != thrd_success)
1259 {
1260 ret = GATE_RESULT_FAILED;
1261 break;
1262 }
1263 }
1264
1265 mtx_unlock(&ptr_evt->mutex);
1266 } while (0);
1267
1268 return ret;
1269 }
1270
1271
1272 /*
1273 typedef struct gate_semaphore_impl_class
1274 {
1275 cnd_t cond;
1276 mtx_t mutex;
1277 gate_uint32_t counter;
1278 gate_uint32_t max;
1279 } gate_semaphore_impl_t;
1280
1281 gate_result_t gate_semaphore_create(gate_semaphore_t* semaphore, gate_uint32_t count)
1282 {
1283 gate_semaphore_impl_t* impl = GATE_HANDLESTORE_CREATE(semaphore, gate_semaphore_impl_t);
1284 if(!impl)
1285 {
1286 return GATE_RESULT_OUTOFRESOURCES;
1287 }
1288
1289 cnd_init(&impl->cond);
1290 mtx_init(&impl->mutex, mtx_timed);
1291 impl->counter = count;
1292 impl->max = count;
1293
1294 return GATE_RESULT_OK;
1295 }
1296
1297 gate_result_t gate_semaphore_acquire(gate_semaphore_t* semaphore)
1298 {
1299 gate_result_t ret = GATE_RESULT_OK;
1300 gate_semaphore_impl_t* impl = GATE_HANDLESTORE_ACCESS(semaphore, gate_semaphore_impl_t);
1301 int status;
1302
1303 do
1304 {
1305 mtx_lock(&impl->mutex);
1306 for(;;)
1307 {
1308 if(impl->counter > 0)
1309 {
1310 --impl->counter;
1311 ret = GATE_RESULT_OK;
1312 break;
1313 }
1314
1315 status = cnd_wait(&impl->cond, &impl->mutex);
1316 if(status != thrd_success)
1317 {
1318 ret = GATE_RESULT_FAILED;
1319 break;
1320 }
1321 }
1322 mtx_unlock(&impl->mutex);
1323 } while(0);
1324
1325 return ret;
1326 }
1327
1328 gate_result_t gate_semaphore_timed_acquire(gate_semaphore_t* semaphore, gate_uint32_t timeoutms)
1329 {
1330 gate_result_t ret = GATE_RESULT_OK;
1331 gate_semaphore_impl_t* impl = GATE_HANDLESTORE_ACCESS(semaphore, gate_semaphore_impl_t);
1332 struct timespec time_point;
1333 int status;
1334
1335 calc_timeout_timespec(&time_point, timeoutms);
1336
1337 do
1338 {
1339 mtx_lock(&impl->mutex);
1340 for(;;)
1341 {
1342 if(impl->counter > 0)
1343 {
1344 --impl->counter;
1345 ret = GATE_RESULT_OK;
1346 break;
1347 }
1348 // TODO
1349 status = cnd_timedwait(&impl->cond, &impl->mutex, &time_point);
1350 if(status == thrd_timedout)
1351 {
1352 ret = GATE_RESULT_TIMEOUT;
1353 break;
1354 }
1355 else if(status != thrd_success)
1356 {
1357 ret = GATE_RESULT_FAILED;
1358 break;
1359 }
1360 }
1361
1362 mtx_unlock(&impl->mutex);
1363 } while(0);
1364
1365 return ret;
1366 }
1367
1368 gate_result_t gate_semaphore_release(gate_semaphore_t* semaphore)
1369 {
1370 gate_result_t ret = GATE_RESULT_OK;
1371 gate_semaphore_impl_t* impl = GATE_HANDLESTORE_ACCESS(semaphore, gate_semaphore_impl_t);
1372 mtx_lock(&impl->mutex);
1373 ++impl->counter;
1374 cnd_broadcast(&impl->cond);
1375 mtx_unlock(&impl->mutex);
1376 return ret;
1377 }
1378
1379 gate_result_t gate_semaphore_destroy(gate_semaphore_t* semaphore)
1380 {
1381 gate_semaphore_impl_t* impl = GATE_HANDLESTORE_ACCESS(semaphore, gate_semaphore_impl_t);
1382 if(impl)
1383 {
1384 mtx_destroy(&impl->mutex);
1385 cnd_destroy(&impl->cond);
1386 GATE_HANDLESTORE_DESTROY(semaphore);
1387 }
1388 return GATE_RESULT_OK;
1389 }
1390 */
1391
1392
1393 #endif /* GATE_SYNCHRONIZATION_C11_IMPL */
1394
1395
1396
1397 #if defined(GATE_SYNCHRONIZATION_WINAPI_IMPL)
1398
1399 #include "gate/platforms.h"
1400
1401
1402 #if !defined(GATE_SYNCHRONIZATION_MUTEX_SEMAPHORE)
1403
1404 gate_result_t gate_mutex_create(gate_mutex_t* mutex)
1405 {
1406 LPCRITICAL_SECTION section = (LPCRITICAL_SECTION)&mutex->handles[0];
1407 GATE_DEBUG_ASSERT(sizeof(mutex->handles) >= sizeof(CRITICAL_SECTION));
1408 if (gate_win32_section_create(section))
1409 {
1410 return GATE_RESULT_OK;
1411 }
1412 else
1413 {
1414 return GATE_RESULT_OUTOFRESOURCES;
1415 }
1416 }
1417 gate_result_t gate_mutex_acquire(gate_mutex_t* mutex)
1418 {
1419 LPCRITICAL_SECTION section = (LPCRITICAL_SECTION)&mutex->handles[0];
1420 if (gate_win32_section_enter(section))
1421 {
1422 return GATE_RESULT_OK;
1423 }
1424 else
1425 {
1426 return GATE_RESULT_INVALIDSTATE;
1427 }
1428 }
1429 gate_result_t gate_mutex_release(gate_mutex_t* mutex)
1430 {
1431 LPCRITICAL_SECTION section = (LPCRITICAL_SECTION)&mutex->handles[0];
1432 gate_win32_section_leave(section);
1433 return GATE_RESULT_OK;
1434 }
1435 gate_result_t gate_mutex_destroy(gate_mutex_t* mutex)
1436 {
1437 LPCRITICAL_SECTION section = (LPCRITICAL_SECTION)&mutex->handles[0];
1438 gate_win32_section_delete(section);
1439 return GATE_RESULT_OK;
1440 }
1441 #endif /* GATE_SYNCHRONIZATION_MUTEX_SEMAPHORE */
1442
1443
1444 #if !defined(GATE_SYNCHRONIZATION_SYNCEVENT_SEMAPHORE)
1445 gate_result_t gate_syncevent_create(gate_syncevent_t* syncevent, gate_bool_t autoreset)
1446 {
1447 HANDLE* hevent = GATE_HANDLESTORE_CREATE(syncevent, HANDLE);
1448 if (hevent == NULL)
1449 {
1450 return GATE_RESULT_OUTOFMEMORY;
1451 }
1452 *hevent = CreateEvent(NULL, (autoreset == false) ? TRUE : FALSE, FALSE, NULL);
1453 if (*hevent == NULL)
1454 {
1455 gate_handlestore_destroy(syncevent);
1456 return GATE_RESULT_FAILED;
1457 }
1458 return GATE_RESULT_OK;
1459 }
1460 gate_result_t gate_syncevent_destroy(gate_syncevent_t* syncevent)
1461 {
1462 HANDLE* hevent = GATE_HANDLESTORE_ACCESS(syncevent, HANDLE);
1463 if (CloseHandle(*hevent) == FALSE)
1464 {
1465 return GATE_RESULT_FAILED;
1466 }
1467 *hevent = NULL;
1468 GATE_HANDLESTORE_DESTROY(syncevent);
1469 return GATE_RESULT_OK;
1470 }
1471 gate_result_t gate_syncevent_set(gate_syncevent_t* syncevent)
1472 {
1473 HANDLE* hevent = GATE_HANDLESTORE_ACCESS(syncevent, HANDLE);
1474 if (SetEvent(*hevent) == FALSE)
1475 {
1476 return GATE_RESULT_FAILED;
1477 }
1478 return GATE_RESULT_OK;
1479 }
1480 gate_result_t gate_syncevent_reset(gate_syncevent_t* syncevent)
1481 {
1482 HANDLE* hevent = GATE_HANDLESTORE_ACCESS(syncevent, HANDLE);
1483 if (ResetEvent(*hevent) == FALSE)
1484 {
1485 return GATE_RESULT_FAILED;
1486 }
1487 return GATE_RESULT_OK;
1488 }
1489 gate_result_t gate_syncevent_wait(gate_syncevent_t* syncevent)
1490 {
1491 return gate_syncevent_timed_wait(syncevent, INFINITE);
1492 }
1493 gate_result_t gate_syncevent_timed_wait(gate_syncevent_t* syncevent, gate_uint32_t timeout)
1494 {
1495 HANDLE* hevent = GATE_HANDLESTORE_ACCESS(syncevent, HANDLE);
1496 DWORD result = WaitForSingleObject(*hevent, timeout);
1497 switch (result)
1498 {
1499 case WAIT_OBJECT_0: return GATE_RESULT_OK;
1500 case WAIT_TIMEOUT: return GATE_RESULT_TIMEOUT;
1501 case WAIT_FAILED:
1502 default: return GATE_RESULT_FAILED;
1503 }
1504 }
1505 #endif /* GATE_SYNCHRONIZATION_SYNCEVENT_SEMAPHORE */
1506
1507
1508 #if !defined(GATE_SYNCHRONIZATION_CONDITION_SEMAPHORE)
1509
1510 #if defined(GATE_SYS_WIN_MODERN_ARCH) && !defined(GATE_SYS_WINCE)
1511 /* We do not need NT4/5 workarounds and can use NT6 directly */
1512 # define GATE_SYNCHRONIZATION_CONDITION_NT6_NATIVE 1
1513 #endif
1514
1515 #if defined(GATE_SYS_WINCE)
1516 /* We have no NT6 and always need NT4/5/CE workaround */
1517 # define GATE_SYNCHRONIZATION_CONDITION_NO_NT6 1
1518 #endif
1519
1520
1521 #if !defined(GATE_SYNCHRONIZATION_CONDITION_NT6_NATIVE) || defined(GATE_SYNCHRONIZATION_CONDITION_NO_NT6)
1522
1523 /* WinNT 4 to XP/2K3 compatible workaround for conditions */
1524
1525 typedef struct gate_win32_ntcond_class
1526 {
1527 gate_atomic_int_t wait_counter;
1528 gate_atomic_int_t signal_all;
1529 HANDLE wait_semaphore;
1530 HANDLE wakeup_completed;
1531 } gate_win32_ntcond_t;
1532
1533 static gate_result_t gate_win32_nt4cond_create(gate_synccondition_t* cond)
1534 {
1535 gate_result_t ret = GATE_RESULT_FAILED;
1536 gate_win32_ntcond_t* ntcond;
1537 do
1538 {
1539 ntcond = GATE_HANDLESTORE_CREATE(cond, gate_win32_ntcond_t);
1540 if (NULL == ntcond)
1541 {
1542 ret = GATE_RESULT_OUTOFMEMORY;
1543 break;
1544 }
1545
1546 ntcond->wait_semaphore = CreateSemaphore(NULL, 0, 0x7fffffff, NULL);
1547 if (NULL == ntcond->wait_semaphore)
1548 {
1549 GATE_HANDLESTORE_DESTROY(cond);
1550 ret = GATE_RESULT_OUTOFRESOURCES;
1551 break;
1552 }
1553
1554 ntcond->wakeup_completed = CreateEvent(NULL, FALSE, FALSE, NULL);
1555 if (NULL == ntcond->wakeup_completed)
1556 {
1557 CloseHandle(ntcond->wait_semaphore);
1558 GATE_HANDLESTORE_DESTROY(cond);
1559 ret = GATE_RESULT_OUTOFRESOURCES;
1560 break;
1561 }
1562
1563 gate_atomic_int_init(&ntcond->wait_counter, 0);
1564 gate_atomic_int_init(&ntcond->signal_all, 0);
1565
1566 ret = GATE_RESULT_OK;
1567 } while (0);
1568 return ret;
1569 }
1570 static gate_result_t gate_win32_nt4cond_destroy(gate_synccondition_t* cond)
1571 {
1572 gate_result_t ret = GATE_RESULT_FAILED;
1573 gate_win32_ntcond_t* ntcond = GATE_HANDLESTORE_ACCESS(cond, gate_win32_ntcond_t);
1574 if (ntcond)
1575 {
1576 CloseHandle(ntcond->wakeup_completed);
1577 CloseHandle(ntcond->wait_semaphore);
1578 GATE_HANDLESTORE_DESTROY(cond);
1579 ret = GATE_RESULT_OK;
1580 }
1581 return ret;
1582 }
1583
1584
1585 static gate_result_t gate_win32_nt4cond_timed_wait(gate_synccondition_t* cond, gate_mutex_t* mutex, gate_uint32_t timeoutms)
1586 {
1587 gate_result_t ret = GATE_RESULT_FAILED;
1588 gate_win32_ntcond_t* ntcond = GATE_HANDLESTORE_ACCESS(cond, gate_win32_ntcond_t);
1589 DWORD wait_result;
1590 gate_bool_t is_last_wakeup = false;
1591 gate_int32_t current_wait_counter = 0;
1592
1593 if (!cond || !mutex)
1594 {
1595 return GATE_RESULT_INVALIDARG;
1596 }
1597
1598 gate_atomic_int_inc(&ntcond->wait_counter);
1599
1600 gate_mutex_release(mutex);
1601
1602 wait_result = WaitForSingleObject(ntcond->wait_semaphore, timeoutms);
1603
1604 current_wait_counter = gate_atomic_int_dec(&ntcond->wait_counter);
1605 is_last_wakeup = gate_atomic_int_get(&ntcond->signal_all) && (current_wait_counter == 0);
1606
1607 ret = gate_mutex_acquire(mutex);
1608 is_last_wakeup = ntcond->signal_all && (ntcond->wait_counter == 0);
1609 if (is_last_wakeup)
1610 {
1611 SetEvent(ntcond->wakeup_completed);
1612 }
1613
1614 if (GATE_FAILED(ret))
1615 {
1616 return ret;
1617 }
1618
1619 switch (wait_result)
1620 {
1621 case WAIT_OBJECT_0: return GATE_RESULT_OK;
1622 case WAIT_TIMEOUT: return GATE_RESULT_TIMEOUT;
1623 default: break;
1624 }
1625 return GATE_RESULT_FAILED;
1626 }
1627
1628 static gate_result_t gate_win32_nt4cond_signal(gate_synccondition_t* cond, gate_bool_t signal_all)
1629 {
1630 gate_win32_ntcond_t* ntcond = GATE_HANDLESTORE_ACCESS(cond, gate_win32_ntcond_t);
1631 gate_int32_t waiters;
1632
1633 waiters = gate_atomic_int_get(&ntcond->wait_counter);
1634 if (waiters > 0)
1635 {
1636 if (!signal_all)
1637 {
1638 ReleaseSemaphore(ntcond->wait_semaphore, 1, NULL);
1639 }
1640 else
1641 {
1642 gate_atomic_int_set(&ntcond->signal_all, 1);
1643 ReleaseSemaphore(ntcond->wait_semaphore, waiters, NULL);
1644
1645 WaitForSingleObject(ntcond->wakeup_completed, INFINITE);
1646 /* asure that the semaphore reaches count zero (if some waiters have timedout in between) */
1647 while (waiters-- != 0)
1648 {
1649 if (WAIT_OBJECT_0 != WaitForSingleObject(ntcond->wait_semaphore, 0))
1650 {
1651 break;
1652 }
1653 }
1654 gate_atomic_int_set(&ntcond->signal_all, 0);
1655 }
1656 }
1657 return GATE_RESULT_OK;
1658 }
1659
1660 static gate_result_t gate_win32_nt4cond_signal_one(gate_synccondition_t* cond)
1661 {
1662 return gate_win32_nt4cond_signal(cond, false);
1663 }
1664
1665 static gate_result_t gate_win32_nt4cond_signal_all(gate_synccondition_t* cond)
1666 {
1667 return gate_win32_nt4cond_signal(cond, true);
1668 }
1669
1670 #endif /* !defined(GATE_SYNCHRONIZATION_CONDITION_NT6_NATIVE) || defined(GATE_SYNCHRONIZATION_CONDITION_NO_NT6) */
1671
1672
1673 /* WinNT 6 (Vista+) conditional variables */
1674 #if !defined(GATE_SYNCHRONIZATION_CONDITION_NO_NT6)
1675
1676 #if defined(GATE_SYS_WIN_MODERN_ARCH)
1677
1678 #if !defined(GATE_COMPILER_MSVC) || defined(GATE_COMPILER_MSVC12)
1679 /* NOTICE: MSVC 2010 does ship synchapi.h by default */
1680 # include <synchapi.h>
1681 #endif
1682
1683 #define Win32InitializeConditionVariable(c) InitializeConditionVariable((PCONDITION_VARIABLE)c)
1684 #define Win32SleepConditionVariableCS(c, s, t) SleepConditionVariableCS((PCONDITION_VARIABLE)c, (PCRITICAL_SECTION)s, t)
1685 #define Win32WakeAllConditionVariable(c) WakeAllConditionVariable((PCONDITION_VARIABLE)c)
1686 #define Win32WakeConditionVariable(c) WakeConditionVariable((PCONDITION_VARIABLE)c)
1687
1688 #else
1689
1690 static void (WINAPI* Win32InitializeConditionVariable)(PVOID ConditionVariable);
1691 static BOOL(WINAPI* Win32SleepConditionVariableCS)(PVOID ConditionVariable, PVOID CriticalSection, DWORD dwMilliseconds);
1692 static void (WINAPI* Win32WakeAllConditionVariable)(PVOID ConditionVariable);
1693 static void (WINAPI* Win32WakeConditionVariable)(PVOID ConditionVariable);
1694
1695 static gate_bool_t win32_condition_variable_supported()
1696 {
1697 static gate_atomic_int_t cond_api_load_state = 0;
1698 gate_int32_t state;
1699
1700 do
1701 {
1702 state = gate_atomic_int_xchg_if(&cond_api_load_state, 0, 1);
1703 if (state == 2)
1704 {
1705 /* api successfully loaded */
1706 return true;
1707 }
1708 else if (state >= 3)
1709 {
1710 /* api loader failed */
1711 return false;
1712 }
1713 else if (state == 0)
1714 {
1715 /* try to load api */
1716 const HMODULE hkernel = gate_win32_get_kernel_module();
1717 const gate_bool_t api_loaded
1718 = gate_win32_get_proc_address(hkernel, "InitializeConditionVariable", &Win32InitializeConditionVariable)
1719 && gate_win32_get_proc_address(hkernel, "SleepConditionVariableCS", &Win32SleepConditionVariableCS)
1720 && gate_win32_get_proc_address(hkernel, "WakeAllConditionVariable", &Win32WakeAllConditionVariable)
1721 && gate_win32_get_proc_address(hkernel, "WakeConditionVariable", &Win32WakeConditionVariable)
1722 ;
1723 if (api_loaded)
1724 {
1725 gate_atomic_int_set(&cond_api_load_state, 2);
1726 return true;
1727 }
1728 else
1729 {
1730 gate_atomic_int_set(&cond_api_load_state, 3);
1731 return false;
1732 }
1733 }
1734 else if (state < 0)
1735 {
1736 /* invalid state */
1737 return false;
1738 }
1739
1740 /* state == 1 -> another thread loads, wait/retry*/
1741 Sleep(0);
1742 } while (state == 1);
1743
1744 return false;
1745 }
1746
1747 #endif
1748
1749
1750 /* extracted from synchapi.h and winnt.h */
1751 typedef struct _GATE_CONDITION_VARIABLE {
1752 PVOID Ptr;
1753 } GATE_CONDITION_VARIABLE, * PGATE_CONDITION_VARIABLE;
1754
1755 static gate_result_t gate_win32_nt6cond_create(gate_synccondition_t* cond)
1756 {
1757 GATE_CONDITION_VARIABLE* hcond = GATE_HANDLESTORE_CREATE(cond, GATE_CONDITION_VARIABLE);
1758 Win32InitializeConditionVariable(hcond);
1759 return GATE_RESULT_OK;
1760 }
1761 static gate_result_t gate_win32_nt6cond_destroy(gate_synccondition_t* cond)
1762 {
1763 GATE_HANDLESTORE_DESTROY(cond);
1764 return GATE_RESULT_OK;
1765 }
1766 static gate_result_t gate_win32_nt6cond_timed_wait(gate_synccondition_t* cond, gate_mutex_t* mutex, gate_uint32_t timeoutms)
1767 {
1768 GATE_CONDITION_VARIABLE* hcond = GATE_HANDLESTORE_ACCESS(cond, GATE_CONDITION_VARIABLE);
1769 LPCRITICAL_SECTION section = (LPCRITICAL_SECTION)&mutex->handles[0];
1770 if (FALSE == Win32SleepConditionVariableCS(hcond, section, timeoutms))
1771 {
1772 if (gate_win32_getlasterror() == ERROR_TIMEOUT)
1773 {
1774 return GATE_RESULT_TIMEOUT;
1775 }
1776 else
1777 {
1778 return GATE_RESULT_FAILED;
1779 }
1780 }
1781 else
1782 {
1783 return GATE_RESULT_OK;
1784 }
1785 }
1786 static gate_result_t gate_win32_nt6cond_signal_one(gate_synccondition_t* cond)
1787 {
1788 GATE_CONDITION_VARIABLE* hcond = GATE_HANDLESTORE_ACCESS(cond, GATE_CONDITION_VARIABLE);
1789 Win32WakeConditionVariable(hcond);
1790 return GATE_RESULT_OK;
1791 }
1792 static gate_result_t gate_win32_nt6cond_signal_all(gate_synccondition_t* cond)
1793 {
1794 GATE_CONDITION_VARIABLE* hcond = GATE_HANDLESTORE_ACCESS(cond, GATE_CONDITION_VARIABLE);
1795 Win32WakeAllConditionVariable(hcond);
1796 return GATE_RESULT_OK;
1797 }
1798
1799 #endif /* !defined(GATE_SYNCHRONIZATION_CONDITION_NO_NT6) */
1800
1801 typedef struct gate_win32_cond_impl
1802 {
1803 gate_result_t(*create)(gate_synccondition_t* cond);
1804 gate_result_t(*destroy)(gate_synccondition_t* cond);
1805 gate_result_t(*timed_wait)(gate_synccondition_t* cond, gate_mutex_t* mutex, gate_uint32_t timeoutms);
1806 gate_result_t(*signal_one)(gate_synccondition_t* cond);
1807 gate_result_t(*signal_all)(gate_synccondition_t* cond);
1808 } gate_win32_cond_impl_t;
1809
1810
1811
1812 #if defined(GATE_SYNCHRONIZATION_CONDITION_NT6_NATIVE)
1813
1814 static gate_win32_cond_impl_t gate_win32_cond = {
1815 &gate_win32_nt6cond_create,
1816 &gate_win32_nt6cond_destroy,
1817 &gate_win32_nt6cond_timed_wait,
1818 &gate_win32_nt6cond_signal_one,
1819 &gate_win32_nt6cond_signal_all
1820 };
1821
1822 static void gate_win32_cond_init()
1823 {
1824 }
1825
1826 #else
1827
1828 /* compatibility to NT4 is default*/
1829 static gate_win32_cond_impl_t gate_win32_cond = {
1830 &gate_win32_nt4cond_create,
1831 &gate_win32_nt4cond_destroy,
1832 &gate_win32_nt4cond_timed_wait,
1833 &gate_win32_nt4cond_signal_one,
1834 &gate_win32_nt4cond_signal_all
1835 };
1836
1837 static void gate_win32_cond_init()
1838 {
1839 #if !defined(GATE_SYNCHRONIZATION_CONDITION_NO_NT6)
1840 static gate_bool_t volatile is_initialized = false;
1841 if (!is_initialized)
1842 {
1843 if (win32_condition_variable_supported())
1844 {
1845 /* switch to NT6 condition-var if available on platform */
1846 const gate_win32_cond_impl_t gate_win32_cond_nt6 = {
1847 &gate_win32_nt6cond_create,
1848 &gate_win32_nt6cond_destroy,
1849 &gate_win32_nt6cond_timed_wait,
1850 &gate_win32_nt6cond_signal_one,
1851 &gate_win32_nt6cond_signal_all
1852 };
1853 gate_win32_cond = gate_win32_cond_nt6;
1854 }
1855 is_initialized = true;
1856 }
1857 #endif
1858 }
1859
1860 #endif
1861
1862 gate_result_t gate_synccondition_create(gate_synccondition_t* cond)
1863 {
1864 gate_win32_cond_init();
1865 return gate_win32_cond.create(cond);
1866 }
1867 gate_result_t gate_synccondition_destroy(gate_synccondition_t* cond)
1868 {
1869 return gate_win32_cond.destroy(cond);
1870 }
1871 gate_result_t gate_synccondition_wait(gate_synccondition_t* cond, gate_mutex_t* mutex)
1872 {
1873 return gate_win32_cond.timed_wait(cond, mutex, INFINITE);
1874 }
1875 gate_result_t gate_synccondition_timed_wait(gate_synccondition_t* cond, gate_mutex_t* mutex, gate_uint32_t timeoutms)
1876 {
1877 if (timeoutms == INFINITE)
1878 {
1879 --timeoutms;
1880 }
1881 return gate_win32_cond.timed_wait(cond, mutex, timeoutms);
1882 }
1883 gate_result_t gate_synccondition_signal_one(gate_synccondition_t* cond)
1884 {
1885 return gate_win32_cond.signal_one(cond);
1886 }
1887 gate_result_t gate_synccondition_signal_all(gate_synccondition_t* cond)
1888 {
1889 return gate_win32_cond.signal_all(cond);
1890 }
1891
1892 #endif /* GATE_SYNCHRONIZATION_CONDITION_SEMAPHORE */
1893
1894 #endif /* defined(GATE_SYNCHRONIZATION_WINAPI_IMPL) */
1895
1896
1897
1898
1899 #if defined(GATE_SYNCHRONIZATION_POSIX_IMPL)
1900
1901 #define __USE_GNU
1902 #include <unistd.h>
1903 #include <sys/time.h>
1904 #include <time.h>
1905 #if defined(GATE_SYS_ANDROID) || defined(GATE_SYS_BEOS)
1906 # define GATE_SYS_USE_POSIX_SEMAPHORE
1907 #endif
1908 #include <sys/ipc.h>
1909 #include <sys/types.h>
1910 #include <errno.h>
1911 #include <pthread.h>
1912 #if defined(GATE_SYS_USE_POSIX_SEMAPHORE)
1913 # include <sys/stat.h>
1914 # include <fcntl.h>
1915 # include <semaphore.h>
1916 #else
1917 # include <sys/shm.h>
1918 # include <sys/sem.h>
1919 #endif
1920
1921 #include "gate/platforms.h"
1922
1923 #if !defined(GATE_SYS_DARWIN)
1924 #define GATE_SYNCHRONIZATION_POSIX_MONOTONIC_CLOCK 1
1925 #endif
1926
1927 ✗ static void calc_realtime_timeout_timespec(struct timespec* ptr_ts, gate_uint32_t timeout_ms)
1928 {
1929 #if 0
1930 struct timeval tv;
1931 gate_mem_clear(&tv, sizeof(tv));
1932 gettimeofday(&tv, 0);
1933 ptr_ts->tv_sec = time(0);
1934 ptr_ts->tv_nsec = tv.tv_usec;
1935 #else
1936 ✗ clock_gettime(CLOCK_REALTIME, ptr_ts);
1937 #endif
1938 ✗ ptr_ts->tv_sec += timeout_ms / 1000;
1939 ✗ ptr_ts->tv_nsec = (timeout_ms % 1000) * 1000000;
1940 ✗ ptr_ts->tv_sec += ptr_ts->tv_nsec / 1000000000;
1941 ✗ ptr_ts->tv_nsec %= 1000000000;
1942 ✗ }
1943
1944 #if defined(GATE_SYNCHRONIZATION_POSIX_MONOTONIC_CLOCK)
1945 17 static void calc_timeout_timespec(struct timespec* ptr_ts, gate_uint32_t timeout_ms)
1946 {
1947 17 clock_gettime(CLOCK_MONOTONIC, ptr_ts);
1948 17 ptr_ts->tv_sec += timeout_ms / 1000;
1949 17 ptr_ts->tv_nsec = (timeout_ms % 1000) * 1000000;
1950 17 ptr_ts->tv_sec += ptr_ts->tv_nsec / 1000000000;
1951 17 ptr_ts->tv_nsec %= 1000000000;
1952 17 }
1953 #else
1954 #define calc_timeout_timespec(ptr_ts, timeout_ms) calc_realtime_timeout_timespec(ptr_ts, timeout_ms)
1955 #endif
1956
1957
1958 #if !defined(GATE_SYNCHRONIZATION_MUTEX_SEMAPHORE)
1959
1960 19 gate_result_t gate_mutex_create(gate_mutex_t* mutex)
1961 {
1962 19 gate_result_t ret = GATE_RESULT_FAILED;
1963 pthread_mutexattr_t attrib;
1964 19 pthread_mutex_t* ptr = (pthread_mutex_t*)mutex;
1965 int result;
1966 do
1967 {
1968 19 result = pthread_mutexattr_init(&attrib);
1969
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (result != 0)
1970 {
1971 ✗ break;
1972 }
1973
1974 19 pthread_mutexattr_settype(&attrib, PTHREAD_MUTEX_ERRORCHECK);
1975
1976 19 result = pthread_mutex_init(ptr, &attrib);
1977 19 pthread_mutexattr_destroy(&attrib);
1978
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (0 != result)
1979 {
1980 ✗ ret = GATE_RESULT_OUTOFRESOURCES;
1981 ✗ break;
1982 }
1983
1984 19 ret = GATE_RESULT_OK;
1985 } while (0);
1986
1987 19 return ret;
1988 }
1989
1990 281 gate_result_t gate_mutex_acquire(gate_mutex_t* mutex)
1991 {
1992 gate_result_t ret;
1993 281 pthread_mutex_t* ptr = (pthread_mutex_t*)mutex;
1994 281 int error = pthread_mutex_lock(ptr);
1995
1/3
✓ Branch 0 taken 281 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
281 switch (error)
1996 {
1997 281 case 0:
1998 {
1999 281 ret = GATE_RESULT_OK;
2000 281 break;
2001 }
2002 ✗ case EDEADLK:
2003 {
2004 ✗ ret = GATE_RESULT_INVALIDSTATE;
2005 ✗ break;
2006 }
2007 ✗ default:
2008 {
2009 ✗ ret = GATE_RESULT_FAILED;
2010 ✗ break;
2011 }
2012 }
2013 281 return ret;
2014 }
2015 281 gate_result_t gate_mutex_release(gate_mutex_t* mutex)
2016 {
2017 gate_result_t ret;
2018 281 pthread_mutex_t* ptr = (pthread_mutex_t*)mutex;
2019 281 int error = pthread_mutex_unlock(ptr);
2020
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 281 times.
281 if (error != 0)
2021 {
2022 ✗ ret = GATE_RESULT_FAILED;
2023 }
2024 else
2025 {
2026 281 ret = GATE_RESULT_OK;
2027 }
2028 281 return ret;
2029 }
2030 19 gate_result_t gate_mutex_destroy(gate_mutex_t* mutex)
2031 {
2032 gate_result_t ret;
2033 19 pthread_mutex_t* ptr = (pthread_mutex_t*)mutex;
2034
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 19 times.
19 if (0 != pthread_mutex_destroy(ptr))
2035 {
2036 ✗ ret = GATE_RESULT_FAILED;
2037 }
2038 else
2039 {
2040 19 ret = GATE_RESULT_OK;
2041 }
2042 19 return ret;
2043 }
2044
2045 #endif /* GATE_SYNCHRONIZATION_MUTEX_SEMAPHORE */
2046
2047
2048
2049 #if !defined(GATE_SYNCHRONIZATION_SYNCEVENT_SEMAPHORE)
2050 typedef struct gate_syncevent_impl
2051 {
2052 pthread_cond_t cond;
2053 pthread_mutex_t mutex;
2054 gate_bool_t state;
2055 gate_bool_t autoreset;
2056 } gate_synevent_impl_t;
2057
2058 10 gate_result_t gate_syncevent_create(gate_syncevent_t* syncevent, gate_bool_t autoreset)
2059 {
2060 10 gate_result_t ret = GATE_RESULT_FAILED;
2061 int result;
2062 10 gate_synevent_impl_t* evt = (gate_synevent_impl_t*)gate_handlestore_create(syncevent, sizeof(gate_synevent_impl_t));
2063 pthread_condattr_t cond_attr;
2064
2065 do
2066 {
2067
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (evt == NULL)
2068 {
2069 ✗ ret = GATE_RESULT_OUTOFMEMORY;
2070 ✗ break;
2071 }
2072
2073
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
10 if (0 != pthread_condattr_init(&cond_attr))
2074 {
2075 ✗ ret = GATE_RESULT_OUTOFRESOURCES;
2076 ✗ break;
2077 }
2078 #if defined(GATE_SYNCHRONIZATION_POSIX_MONOTONIC_CLOCK)
2079
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
10 if (0 != pthread_condattr_setclock(&cond_attr, CLOCK_MONOTONIC))
2080 {
2081 ✗ ret = GATE_RESULT_OUTOFRESOURCES;
2082 ✗ break;
2083 }
2084 #endif
2085
2086 10 result = pthread_cond_init(&evt->cond, &cond_attr);
2087 10 pthread_condattr_destroy(&cond_attr);
2088
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (result != 0)
2089 {
2090 ✗ ret = GATE_RESULT_OUTOFRESOURCES;
2091 ✗ break;
2092 }
2093 10 result = pthread_mutex_init(&evt->mutex, 0);
2094
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (result)
2095 {
2096 ✗ pthread_cond_destroy(&evt->cond);
2097 ✗ ret = GATE_RESULT_OUTOFRESOURCES;
2098 ✗ break;
2099 }
2100
2101 10 evt->state = 0;
2102 10 evt->autoreset = autoreset;
2103
2104 10 ret = GATE_RESULT_OK;
2105 } while (0);
2106
2107
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
10 if (GATE_FAILED(ret) && (evt != NULL))
2108 {
2109 ✗ gate_handlestore_destroy(syncevent);
2110 }
2111
2112 10 return ret;
2113 }
2114 10 gate_result_t gate_syncevent_destroy(gate_syncevent_t* syncevent)
2115 {
2116 10 gate_synevent_impl_t* evt = (gate_synevent_impl_t*)gate_handlestore_access(syncevent);
2117
2118 10 pthread_cond_destroy(&evt->cond);
2119 10 pthread_mutex_destroy(&evt->mutex);
2120
2121 10 gate_handlestore_destroy(syncevent);
2122
2123 10 return GATE_RESULT_OK;
2124 }
2125 6 static gate_result_t translate_sync_error(int error)
2126 {
2127
1/7
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
6 switch (error)
2128 {
2129 6 case ETIMEDOUT: return GATE_RESULT_TIMEOUT;
2130 ✗ case EINVAL: return GATE_RESULT_INVALIDARG;
2131 ✗ case EBUSY: return GATE_RESULT_INVALIDSTATE;
2132 ✗ case EAGAIN: return GATE_RESULT_OUTOFRESOURCES;
2133 ✗ case EDEADLK: return GATE_RESULT_LOCKED;
2134 ✗ case EPERM: return GATE_RESULT_NOTREADY;
2135 ✗ default: return GATE_RESULT_FAILED;
2136 }
2137 }
2138
2139 14 gate_result_t gate_syncevent_set(gate_syncevent_t* syncevent)
2140 {
2141 14 gate_synevent_impl_t* evt = (gate_synevent_impl_t*)gate_handlestore_access(syncevent);
2142
2143 14 int error = pthread_mutex_lock(&evt->mutex);
2144
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (error)
2145 {
2146 ✗ return translate_sync_error(error);
2147 }
2148 14 evt->state = true;
2149
2150
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 7 times.
14 if (evt->autoreset)
2151 {
2152 7 error = pthread_cond_signal(&evt->cond);
2153 }
2154 else
2155 {
2156 7 error = pthread_cond_broadcast(&evt->cond);
2157 }
2158
2159 14 pthread_mutex_unlock(&evt->mutex);
2160
2161
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (error)
2162 {
2163 ✗ return translate_sync_error(error);
2164 }
2165 14 return GATE_RESULT_OK;
2166 }
2167 4 gate_result_t gate_syncevent_reset(gate_syncevent_t* syncevent)
2168 {
2169 4 gate_synevent_impl_t* evt = (gate_synevent_impl_t*)gate_handlestore_access(syncevent);
2170
2171 4 int error = pthread_mutex_lock(&evt->mutex);
2172
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (error)
2173 {
2174 ✗ return translate_sync_error(error);
2175 }
2176 4 evt->state = false;
2177
2178 4 pthread_mutex_unlock(&evt->mutex);
2179
2180 4 return GATE_RESULT_OK;
2181 }
2182 5 gate_result_t gate_syncevent_wait(gate_syncevent_t* syncevent)
2183 {
2184 5 gate_synevent_impl_t* evt = (gate_synevent_impl_t*)gate_handlestore_access(syncevent);
2185
2186 5 int error = pthread_mutex_lock(&evt->mutex);
2187
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (error)
2188 {
2189 ✗ return translate_sync_error(error);
2190 }
2191 {
2192
3/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 5 times.
6 while (!error && !evt->state)
2193 {
2194 1 error = pthread_cond_wait(&evt->cond, &evt->mutex);
2195 }
2196
3/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 2 times.
5 if (!error && evt->autoreset)
2197 {
2198 3 evt->state = false;
2199 }
2200 }
2201 5 pthread_mutex_unlock(&evt->mutex);
2202
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (error)
2203 {
2204 ✗ return translate_sync_error(error);
2205 }
2206 5 return GATE_RESULT_OK;
2207 }
2208
2209 12 gate_result_t gate_syncevent_timed_wait(gate_syncevent_t* syncevent, gate_uint32_t timeout)
2210 {
2211 12 gate_synevent_impl_t* evt = (gate_synevent_impl_t*)gate_handlestore_access(syncevent);
2212 int error;
2213 struct timespec tm;
2214
2215 12 calc_timeout_timespec(&tm, timeout);
2216
2217 12 error = pthread_mutex_lock(&evt->mutex);
2218
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (error)
2219 {
2220 ✗ return translate_sync_error(error);
2221 }
2222 {
2223
4/4
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 6 times.
18 while (!error && !evt->state)
2224 {
2225 6 error = pthread_cond_timedwait(&evt->cond, &evt->mutex, &tm);
2226 }
2227
3/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
12 if (!error && evt->autoreset)
2228 {
2229 ✗ evt->state = false;
2230 }
2231 }
2232 12 pthread_mutex_unlock(&evt->mutex);
2233
2234
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 if (error)
2235 {
2236 6 return translate_sync_error(error);
2237 }
2238 else
2239 {
2240 6 return GATE_RESULT_OK;
2241 }
2242 }
2243
2244 #endif /* GATE_SYNCHRONIZATION_SYNCEVENT_SEMAPHORE */
2245
2246
2247
2248 #if !defined(GATE_SYNCHRONIZATION_CONDITION_SEMAPHORE)
2249
2250 5 gate_result_t gate_synccondition_create(gate_synccondition_t* cond)
2251 {
2252 5 gate_result_t ret = GATE_RESULT_FAILED;
2253 5 pthread_cond_t* ptr_cond = GATE_HANDLESTORE_CREATE(cond, pthread_cond_t);
2254 pthread_condattr_t cond_attr;
2255 int failed;
2256
2257 do
2258 {
2259
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (ptr_cond == NULL)
2260 {
2261 ✗ ret = GATE_RESULT_OUTOFMEMORY;
2262 ✗ break;
2263 }
2264 5 failed = pthread_condattr_init(&cond_attr);
2265
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (failed)
2266 {
2267 ✗ ret = GATE_RESULT_OUTOFRESOURCES;
2268 ✗ break;
2269 }
2270 #if defined(GATE_SYNCHRONIZATION_POSIX_MONOTONIC_CLOCK)
2271 5 failed = pthread_condattr_setclock(&cond_attr, CLOCK_MONOTONIC);
2272
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (failed)
2273 {
2274 ✗ ret = GATE_RESULT_OUTOFRESOURCES;
2275 ✗ break;
2276 }
2277 #endif
2278
2279 5 failed = pthread_cond_init(ptr_cond, &cond_attr);
2280 5 pthread_condattr_destroy(&cond_attr);
2281
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (failed)
2282 {
2283 ✗ ret = GATE_RESULT_OUTOFRESOURCES;
2284 ✗ break;
2285 }
2286
2287 5 ret = GATE_RESULT_OK;
2288 } while (0);
2289
2290
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
5 if (GATE_FAILED(ret) && (ptr_cond != NULL))
2291 {
2292 ✗ GATE_HANDLESTORE_DESTROY(cond);
2293 }
2294
2295 5 return ret;
2296 }
2297
2298 5 gate_result_t gate_synccondition_destroy(gate_synccondition_t* cond)
2299 {
2300 5 gate_result_t ret = GATE_RESULT_FAILED;
2301 5 pthread_cond_t* ptr_cond = GATE_HANDLESTORE_ACCESS(cond, pthread_cond_t);
2302 int failed;
2303
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (ptr_cond)
2304 {
2305 5 failed = pthread_cond_destroy(ptr_cond);
2306
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (!failed)
2307 {
2308 5 ret = GATE_RESULT_OK;
2309 }
2310 5 GATE_HANDLESTORE_DESTROY(cond);
2311 }
2312 5 return ret;
2313 }
2314
2315 5 gate_result_t gate_synccondition_wait(gate_synccondition_t* cond, gate_mutex_t* mutex)
2316 {
2317 5 gate_result_t ret = GATE_RESULT_FAILED;
2318 5 pthread_cond_t* ptr_cond = GATE_HANDLESTORE_ACCESS(cond, pthread_cond_t);
2319 5 pthread_mutex_t* ptr_mutex = (pthread_mutex_t*)mutex;
2320 int failed;
2321
2322 do
2323 {
2324 5 failed = pthread_cond_wait(ptr_cond, ptr_mutex);
2325
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (failed)
2326 {
2327 ✗ ret = GATE_RESULT_FAILED;
2328 ✗ break;
2329 }
2330
2331 5 ret = GATE_RESULT_OK;
2332 } while (0);
2333 5 return ret;
2334 }
2335
2336 5 gate_result_t gate_synccondition_timed_wait(gate_synccondition_t* cond, gate_mutex_t* mutex, gate_uint32_t timeoutms)
2337 {
2338 5 gate_result_t ret = GATE_RESULT_FAILED;
2339 5 pthread_cond_t* ptr_cond = GATE_HANDLESTORE_ACCESS(cond, pthread_cond_t);
2340 5 pthread_mutex_t* ptr_mutex = (pthread_mutex_t*)mutex;
2341 struct timespec timeout;
2342 int status;
2343
2344 5 calc_timeout_timespec(&timeout, timeoutms);
2345
2346 5 status = pthread_cond_timedwait(ptr_cond, ptr_mutex, &timeout);
2347 switch (ETIMEDOUT)
2348 {
2349 case 0: ret = GATE_RESULT_OK; break;
2350 5 case ETIMEDOUT: ret = GATE_RESULT_TIMEOUT; break;
2351 default: ret = GATE_RESULT_FAILED; break;
2352 }
2353 5 return ret;
2354 }
2355
2356 19 gate_result_t gate_synccondition_signal_one(gate_synccondition_t* cond)
2357 {
2358 19 pthread_cond_t* ptr_cond = GATE_HANDLESTORE_ACCESS(cond, pthread_cond_t);
2359 19 int failed = pthread_cond_signal(ptr_cond);
2360
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (failed)
2361 {
2362 ✗ return GATE_RESULT_FAILED;
2363 }
2364 19 return GATE_RESULT_OK;
2365 }
2366
2367 5 gate_result_t gate_synccondition_signal_all(gate_synccondition_t* cond)
2368 {
2369 5 pthread_cond_t* ptr_cond = GATE_HANDLESTORE_ACCESS(cond, pthread_cond_t);
2370 5 int failed = pthread_cond_broadcast(ptr_cond);
2371
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (failed)
2372 {
2373 ✗ return GATE_RESULT_FAILED;
2374 }
2375 5 return GATE_RESULT_OK;
2376 }
2377
2378 #endif /* GATE_SYNCHRONIZATION_CONDITION_SEMAPHORE */
2379
2380 #endif /* GATE_SYNCHRONIZATION_POSIX_IMPL */
2381
2382
2383
2384
2385
2386 #if defined(GATE_SYNCHRONIZATION_BEOS_IMPL)
2387
2388 #include <kernel/OS.h>
2389
2390 #if !defined(GATE_SYNCHRONIZATION_MUTEX_SEMAPHORE)
2391
2392 gate_result_t gate_mutex_create(gate_mutex_t* mutex)
2393 {
2394 sem_id* sem = (sem_id*)mutex;
2395 *sem = create_sem(1, "gate_mutex");
2396 if (*sem < B_OK)
2397 {
2398 return GATE_RESULT_FAILED;
2399 }
2400 else
2401 {
2402 return GATE_RESULT_OK;
2403 }
2404 }
2405 gate_result_t gate_mutex_acquire(gate_mutex_t* mutex)
2406 {
2407 sem_id* sem = (sem_id*)mutex;
2408 status_t status = acquire_sem(*sem);
2409 switch (status)
2410 {
2411 case B_NO_ERROR: return GATE_RESULT_OK;
2412 case B_BAD_SEM_ID: return GATE_RESULT_INVALIDARG;
2413 case B_INTERRUPTED: return GATE_RESULT_TIMEOUT;
2414 default: return GATE_RESULT_FAILED;
2415 }
2416 }
2417 gate_result_t gate_mutex_release(gate_mutex_t* mutex)
2418 {
2419 sem_id* sem = (sem_id*)mutex;
2420 status_t status = release_sem(*sem);
2421 switch (status)
2422 {
2423 case B_NO_ERROR: return GATE_RESULT_OK;
2424 case B_BAD_SEM_ID: return GATE_RESULT_INVALIDARG;
2425 default: return GATE_RESULT_FAILED;
2426 }
2427 }
2428 gate_result_t gate_mutex_destroy(gate_mutex_t* mutex)
2429 {
2430 sem_id* sem = (sem_id*)mutex;
2431 status_t status = delete_sem(*sem);
2432 return (status == B_NO_ERROR) ? GATE_RESULT_OK : GATE_RESULT_FAILED;
2433 }
2434 #endif /* GATE_SYNCHRONIZATION_MUTEX_SEMAPHORE */
2435
2436
2437
2438 #if !defined(GATE_SYNCHRONIZATION_SYNCEVENT_SEMAPHORE)
2439
2440 #define GATE_SYNCEVENT_MAX_SEMCOUNT 64
2441 #define GATE_SYNCEVENT_FLAG_SET 0x01
2442 #define GATE_SYNCEVENT_FLAG_AUTORESET 0x80
2443
2444 typedef struct sem_syncevent_class
2445 {
2446 sem_id lock;
2447 sem_id signal;
2448 int state;
2449 } sem_syncevent_t;
2450
2451 gate_result_t gate_syncevent_create(gate_syncevent_t* syncevent, gate_bool_t autoreset)
2452 {
2453 sem_syncevent_t* evt = GATE_HANDLESTORE_CREATE(syncevent, sem_syncevent_t);
2454 status_t status;
2455 if (evt == NULL)
2456 {
2457 return GATE_RESULT_OUTOFMEMORY;
2458 }
2459 evt->lock = create_sem(1, "gate_syncevent");
2460 if (evt->lock < B_OK)
2461 {
2462 GATE_HANDLESTORE_DESTROY(syncevent);
2463 return GATE_RESULT_OUTOFRESOURCES;
2464 }
2465 evt->signal = create_sem(GATE_SYNCEVENT_MAX_SEMCOUNT, "gate_syncevent");
2466 if (evt->signal < B_OK)
2467 {
2468 delete_sem(evt->lock);
2469 GATE_HANDLESTORE_DESTROY(syncevent);
2470 return GATE_RESULT_OUTOFRESOURCES;
2471 }
2472 status = acquire_sem_etc(evt->signal, GATE_SYNCEVENT_MAX_SEMCOUNT, B_RELATIVE_TIMEOUT, B_INFINITE_TIMEOUT);
2473 if (B_NO_ERROR != status)
2474 {
2475 delete_sem(evt->signal);
2476 delete_sem(evt->lock);
2477 GATE_HANDLESTORE_DESTROY(syncevent);
2478 return GATE_RESULT_OUTOFRESOURCES;
2479 }
2480 evt->state = autoreset ? GATE_SYNCEVENT_FLAG_AUTORESET : 0;
2481 return GATE_RESULT_OK;
2482 }
2483
2484 gate_result_t gate_syncevent_destroy(gate_syncevent_t* syncevent)
2485 {
2486 sem_syncevent_t* evt = GATE_HANDLESTORE_ACCESS(syncevent, sem_syncevent_t);
2487 if (evt)
2488 {
2489 delete_sem(evt->signal);
2490 delete_sem(evt->lock);
2491 GATE_HANDLESTORE_DESTROY(syncevent);
2492 }
2493 return GATE_RESULT_OK;
2494 }
2495
2496 gate_result_t gate_syncevent_set(gate_syncevent_t* syncevent)
2497 {
2498 sem_syncevent_t* evt = GATE_HANDLESTORE_ACCESS(syncevent, sem_syncevent_t);
2499 status_t status;
2500 gate_bool_t is_autoreset;
2501
2502 status = acquire_sem(evt->lock);
2503 if (status != B_NO_ERROR)
2504 {
2505 return GATE_RESULT_FAILED;
2506 }
2507 evt->state |= (GATE_SYNCEVENT_FLAG_SET);
2508 is_autoreset = GATE_FLAG_ENABLED(evt->state, GATE_SYNCEVENT_FLAG_AUTORESET);
2509
2510 if (is_autoreset)
2511 {
2512 release_sem(evt->signal);
2513 }
2514 else
2515 {
2516 release_sem_etc(evt->signal, GATE_SYNCEVENT_MAX_SEMCOUNT, B_DO_NOT_RESCHEDULE);
2517 }
2518
2519 release_sem(evt->lock);
2520
2521 if (is_autoreset)
2522 {
2523 status = acquire_sem(evt->signal);
2524 }
2525 else
2526 {
2527 status = acquire_sem_etc(evt->signal, GATE_SYNCEVENT_MAX_SEMCOUNT, B_RELATIVE_TIMEOUT, B_INFINITE_TIMEOUT);
2528 }
2529
2530 return (status != B_NO_ERROR) ? GATE_RESULT_FAILED : GATE_RESULT_OK;
2531 }
2532
2533 gate_result_t gate_syncevent_reset(gate_syncevent_t* syncevent)
2534 {
2535 sem_syncevent_t* evt = GATE_HANDLESTORE_ACCESS(syncevent, sem_syncevent_t);
2536 status_t status;
2537 status = acquire_sem(evt->lock);
2538 if (status != B_NO_ERROR)
2539 {
2540 return GATE_RESULT_FAILED;
2541 }
2542 evt->state &= ~(GATE_SYNCEVENT_FLAG_SET);
2543 release_sem(evt->lock);
2544
2545 return GATE_RESULT_OK;
2546 }
2547 gate_result_t gate_syncevent_wait(gate_syncevent_t* syncevent)
2548 {
2549 return gate_syncevent_timed_wait(syncevent, (gate_uint32_t)0xffffffff);
2550 }
2551 gate_result_t gate_syncevent_timed_wait(gate_syncevent_t* syncevent, gate_uint32_t timeoutms)
2552 {
2553 sem_syncevent_t* evt = GATE_HANDLESTORE_ACCESS(syncevent, sem_syncevent_t);
2554 status_t status;
2555 gate_bool_t is_autoreset;
2556 gate_bool_t is_signaled = false;
2557 bigtime_t now = system_time();
2558 bigtime_t next_timeout;
2559 bigtime_t final_timeout = now + ((bigtime_t)timeoutms * (bigtime_t)1000);
2560
2561 for (;;)
2562 {
2563
2564 status = acquire_sem(evt->lock);
2565 if (status != B_NO_ERROR)
2566 {
2567 break;
2568 }
2569 is_autoreset = GATE_FLAG_ENABLED(evt->state, GATE_SYNCEVENT_FLAG_AUTORESET);
2570 is_signaled = GATE_FLAG_ENABLED(evt->state, GATE_SYNCEVENT_FLAG_SET);
2571 if (is_signaled && is_autoreset)
2572 {
2573 /* autoreset */
2574 evt->state &= ~(GATE_SYNCEVENT_FLAG_SET);
2575 }
2576
2577 if (is_signaled)
2578 {
2579 break;
2580 }
2581
2582 now = system_time();
2583 if (now > final_timeout)
2584 {
2585 /* timeout reached */
2586 break;
2587 }
2588 if (timeoutms == 0xffffffff)
2589 {
2590 next_timeout = B_INFINITE_TIMEOUT;
2591 }
2592 else
2593 {
2594 next_timeout = final_timeout - now;
2595 }
2596 status = acquire_sem_etc(evt->signal, 1, B_RELATIVE_TIMEOUT, next_timeout);
2597 if (status == B_NO_ERROR)
2598 {
2599 release_sem(evt->signal);
2600 }
2601 }
2602 return is_signaled ? GATE_RESULT_OK : GATE_RESULT_TIMEOUT;
2603 }
2604
2605 #endif /* GATE_SYNCHRONIZATION_SYNCEVENT_SEMAPHORE */
2606
2607
2608
2609 #if !defined(GATE_SYNCHRONIZATION_CONDITION_SEMAPHORE)
2610
2611 gate_result_t gate_synccondition_create(gate_synccondition_t* cond)
2612 {
2613 sem_id* ptr_sem = GATE_HANDLESTORE_CREATE(cond, sem_id);
2614 status_t status;
2615 if (ptr_sem == NULL)
2616 {
2617 return GATE_RESULT_OUTOFMEMORY;
2618 }
2619 *ptr_sem = create_sem(GATE_SYNCEVENT_MAX_SEMCOUNT, "gate_synccondition");
2620 if (*ptr_sem < B_OK)
2621 {
2622 GATE_HANDLESTORE_DESTROY(cond);
2623 return GATE_RESULT_OUTOFRESOURCES;
2624 }
2625 status = acquire_sem_etc(*ptr_sem, GATE_SYNCEVENT_MAX_SEMCOUNT, B_RELATIVE_TIMEOUT, B_INFINITE_TIMEOUT);
2626 if (status != B_NO_ERROR)
2627 {
2628 delete_sem(*ptr_sem);
2629 GATE_HANDLESTORE_DESTROY(cond);
2630 return GATE_RESULT_OUTOFRESOURCES;
2631 }
2632 return GATE_RESULT_OK;
2633 }
2634 gate_result_t gate_synccondition_destroy(gate_synccondition_t* cond)
2635 {
2636 sem_id* ptr_sem = GATE_HANDLESTORE_ACCESS(cond, sem_id);
2637 if (ptr_sem)
2638 {
2639 delete_sem(*ptr_sem);
2640 GATE_HANDLESTORE_DESTROY(cond);
2641 }
2642 return GATE_RESULT_OK;
2643 }
2644 gate_result_t gate_synccondition_wait(gate_synccondition_t* cond, gate_mutex_t* mutex)
2645 {
2646 return gate_synccondition_timed_wait(cond, mutex, 0xffffffff);
2647 }
2648 gate_result_t gate_synccondition_timed_wait(gate_synccondition_t* cond, gate_mutex_t* mutex, gate_uint32_t timeoutms)
2649 {
2650 sem_id* ptr_sem = GATE_HANDLESTORE_ACCESS(cond, sem_id);
2651 gate_result_t ret;
2652 status_t status;
2653 bigtime_t timeout_us;
2654
2655 if (timeoutms == 0xffffffff)
2656 {
2657 timeout_us = B_INFINITE_TIMEOUT;
2658 }
2659 else
2660 {
2661 timeout_us = (bigtime_t)timeoutms * (bigtime_t)1000;
2662 }
2663
2664 do
2665 {
2666 if (mutex)
2667 {
2668 ret = gate_mutex_release(mutex);
2669 GATE_BREAK_IF_FAILED(ret);
2670 }
2671
2672 status = acquire_sem_etc(*ptr_sem, 1, B_RELATIVE_TIMEOUT, timeout_us);
2673
2674 if (B_NO_ERROR == status)
2675 {
2676 ret = GATE_RESULT_OK;
2677 }
2678 else if ((B_TIMED_OUT == status) || ((B_WOULD_BLOCK == status) && (timeoutms == 0)) || (B_INTERRUPTED == status))
2679 {
2680 ret == GATE_RESULT_TIMEOUT;
2681 }
2682 else
2683 {
2684 ret = GATE_RESULT_FAILED;
2685 }
2686
2687 if (mutex)
2688 {
2689 gate_mutex_acquire(mutex);
2690 }
2691
2692 if (B_NO_ERROR == status)
2693 {
2694 release_sem(*ptr_sem);
2695 }
2696 } while (0);
2697
2698 return ret;
2699 }
2700 gate_result_t gate_synccondition_signal_one(gate_synccondition_t* cond)
2701 {
2702 sem_id* ptr_sem = GATE_HANDLESTORE_ACCESS(cond, sem_id);
2703 status_t status;
2704 release_sem(*ptr_sem);
2705 do
2706 {
2707 status = acquire_sem(*ptr_sem);
2708 } while (status == B_INTERRUPTED);
2709
2710 return (status == B_NO_ERROR) ? GATE_RESULT_OK : GATE_RESULT_FAILED;
2711 }
2712 gate_result_t gate_synccondition_signal_all(gate_synccondition_t* cond)
2713 {
2714 sem_id* ptr_sem = GATE_HANDLESTORE_ACCESS(cond, sem_id);
2715 status_t status;
2716 unsigned ndx;
2717 release_sem_etc(*ptr_sem, GATE_SYNCEVENT_MAX_SEMCOUNT, 0);
2718 release_sem(*ptr_sem);
2719
2720 for (ndx = 0; ndx != GATE_SYNCEVENT_MAX_SEMCOUNT; ++ndx)
2721 {
2722 do
2723 {
2724 status = acquire_sem(*ptr_sem);
2725 } while (status == B_INTERRUPTED);
2726 }
2727 return (status == B_NO_ERROR) ? GATE_RESULT_OK : GATE_RESULT_FAILED;
2728 }
2729
2730 #endif /* GATE_SYNCHRONIZATION_CONDITION_SEMAPHORE */
2731
2732 #endif /* GATE_SYNCHRONIZATION_BEOS_IMPL */
2733
2734
2735
2736 #if defined(GATE_SYS_DOS)
2737
2738 #endif /* GATE_SYNCHRONIZATION_DOS_IMPL */
2739
2740
2741 #if defined(GATE_SYNCHRONIZATION_DUMMY_IMPL)
2742
2743 #include "gate/atomics.h"
2744
2745
2746 #if !defined(GATE_SYNCHRONIZATION_MUTEX_SEMAPHORE)
2747
2748 gate_result_t gate_mutex_create(gate_mutex_t* mutex)
2749 {
2750 int volatile* lock = (int volatile*)mutex;
2751 gate_mem_clear(mutex, sizeof(gate_mutex_t));
2752 *lock = 0;
2753 return GATE_RESULT_OK;
2754 }
2755 gate_result_t gate_mutex_acquire(gate_mutex_t* mutex)
2756 {
2757 int volatile* lock = (int volatile*)mutex;
2758 if (*lock == 1)
2759 {
2760 return GATE_RESULT_LOCKED;
2761 }
2762 *lock = 1;
2763 return GATE_RESULT_OK;
2764 }
2765 gate_result_t gate_mutex_release(gate_mutex_t* mutex)
2766 {
2767 int volatile* lock = (int volatile*)mutex;
2768 *lock = 0;
2769 return GATE_RESULT_OK;
2770 }
2771 gate_result_t gate_mutex_destroy(gate_mutex_t* mutex)
2772 {
2773 gate_mem_clear(mutex, sizeof(gate_mutex_t));
2774 return GATE_RESULT_OK;
2775 }
2776
2777 #endif /* GATE_SYNCHRONIZATION_MUTEX_SEMAPHORE */
2778
2779
2780
2781 #if !defined(GATE_SYNCHRONIZATION_SYNCEVENT_SEMAPHORE)
2782 typedef struct gate_plain_syncevent_class
2783 {
2784 int autoreset;
2785 int state;
2786 } gate_plain_syncevent_t;
2787
2788 gate_result_t gate_syncevent_create(gate_syncevent_t* syncevent, gate_bool_t autoreset)
2789 {
2790 gate_plain_syncevent_t volatile* evt = GATE_HANDLESTORE_CREATE(syncevent, gate_plain_syncevent_t volatile);
2791 if (evt == NULL)
2792 {
2793 return GATE_RESULT_OUTOFMEMORY;
2794 }
2795 evt->autoreset = autoreset ? 1 : 0;
2796 evt->state = 0;
2797 return GATE_RESULT_OK;
2798 }
2799 gate_result_t gate_syncevent_destroy(gate_syncevent_t* syncevent)
2800 {
2801 GATE_HANDLESTORE_DESTROY(syncevent);
2802 return GATE_RESULT_OK;
2803 }
2804 gate_result_t gate_syncevent_set(gate_syncevent_t* syncevent)
2805 {
2806 gate_plain_syncevent_t volatile* evt = GATE_HANDLESTORE_ACCESS(syncevent, gate_plain_syncevent_t volatile);
2807 evt->state = 1;
2808 return GATE_RESULT_OK;
2809 }
2810 gate_result_t gate_syncevent_reset(gate_syncevent_t* syncevent)
2811 {
2812 gate_plain_syncevent_t volatile* evt = GATE_HANDLESTORE_ACCESS(syncevent, gate_plain_syncevent_t volatile);
2813 evt->state = 0;
2814 return GATE_RESULT_OK;
2815 }
2816 gate_result_t gate_syncevent_wait(gate_syncevent_t* syncevent)
2817 {
2818 return gate_syncevent_timed_wait(syncevent, (gate_uint32_t)0xffffffff);
2819 }
2820 gate_result_t gate_syncevent_timed_wait(gate_syncevent_t* syncevent, gate_uint32_t timeoutms)
2821 {
2822 gate_plain_syncevent_t volatile* evt = GATE_HANDLESTORE_ACCESS(syncevent, gate_plain_syncevent_t volatile);
2823 GATE_UNUSED_ARG(timeoutms);
2824 if (evt->state)
2825 {
2826 if (evt->autoreset)
2827 {
2828 evt->state = 0;
2829 }
2830 return GATE_RESULT_OK;
2831 }
2832 return GATE_RESULT_TIMEOUT;
2833 }
2834
2835 #endif /* GATE_SYNCHRONIZATION_SYNCEVENT_SEMAPHORE */
2836
2837
2838
2839 #if !defined(GATE_SYNCHRONIZATION_CONDITION_SEMAPHORE)
2840
2841 gate_result_t gate_synccondition_create(gate_synccondition_t* cond)
2842 {
2843 int volatile* evt = GATE_HANDLESTORE_CREATE(cond, int volatile);
2844 if (evt == NULL)
2845 {
2846 return GATE_RESULT_OUTOFMEMORY;
2847 }
2848 *evt = 0;
2849 return GATE_RESULT_OK;
2850 }
2851 gate_result_t gate_synccondition_destroy(gate_synccondition_t* cond)
2852 {
2853 GATE_HANDLESTORE_DESTROY(cond);
2854 return GATE_RESULT_OK;
2855 }
2856 gate_result_t gate_synccondition_wait(gate_synccondition_t* cond, gate_mutex_t* mutex)
2857 {
2858 return gate_synccondition_timed_wait(cond, mutex, 0xffffffff);
2859 }
2860 gate_result_t gate_synccondition_timed_wait(gate_synccondition_t* cond, gate_mutex_t* mutex, gate_uint32_t timeoutms)
2861 {
2862 gate_result_t result;
2863 int volatile* evt = GATE_HANDLESTORE_ACCESS(cond, int volatile);
2864 GATE_UNUSED_ARG(timeoutms);
2865 do
2866 {
2867 result = gate_mutex_release(mutex);
2868 GATE_BREAK_IF_FAILED(result);
2869 if (*evt == 0)
2870 {
2871 result = GATE_RESULT_TIMEOUT;
2872 }
2873 else
2874 {
2875 *evt = 1;
2876 result = GATE_RESULT_OK;
2877 }
2878 gate_mutex_acquire(mutex);
2879 } while (0);
2880 return result;
2881 }
2882 gate_result_t gate_synccondition_signal_one(gate_synccondition_t* cond)
2883 {
2884 int volatile* evt = GATE_HANDLESTORE_ACCESS(cond, int volatile);
2885 *evt = 1;
2886 return GATE_RESULT_OK;
2887 }
2888 gate_result_t gate_synccondition_signal_all(gate_synccondition_t* cond)
2889 {
2890 return gate_synccondition_signal_one(cond);
2891 }
2892
2893 #endif /* GATE_SYNCHRONIZATION_CONDITION_SEMAPHORE */
2894
2895 #endif /* GATE_SYNCHRONIZATION_DUMMY_IMPL */
2896