1#include <errno.h>
2
3#include "allocator.h"
4#include "sync.h"
5#include "timespec.h"
6
7Event* create_event()
8{
9 int err = 0;
10 Event* event = allocate(sizeof(Event), true);
11 if (!event) {
12 errno = ENOMEM;
13 return nullptr;
14 }
15 switch (cnd_init(&event->cond)) {
16 case thrd_success:
17 break;
18 case thrd_nomem:
19 err = ENOMEM;
20 [[fallthrough]];
21 default:
22 goto err;
23 }
24 switch (mtx_init(&event->mtx, mtx_timed | mtx_recursive)) {
25 case thrd_success:
26 break;
27 case thrd_nomem:
28 err = ENOMEM;
29 [[fallthrough]];
30 default:
31 goto err;
32 }
33 return event;
34
35err:
36 release((void**) &event, sizeof(Event));
37 errno = err;
38 return nullptr;
39}
40
41void delete_event(Event** event_ptr)
42{
43 if (!event_ptr) {
44 return;
45 }
46 Event* event = *event_ptr;
47 if (event) {
48 mtx_destroy(&event->mtx);
49 cnd_destroy(&event->cond);
50 release((void**) &event, sizeof(Event));
51 }
52}
53
54void set_event(Event* event)
55{
56 event->flag = true;
57 cnd_broadcast(&event->cond);
58}
59
60void clear_event(Event* event)
61{
62 event->flag = false;
63}
64
65bool event_is_set(Event* event)
66{
67 return event->flag;
68}
69
70bool wait_event(Event* event, double timeout)
71{
72 mtx_lock(&event->mtx);
73 bool signalled = event->flag;
74 if (signalled) {
75 mtx_unlock(&event->mtx);
76 return true;
77 }
78 if (timeout >= 0.0) {
79 struct timespec time_point;
80 timespec_get(&time_point, TIME_UTC);
81 timespec_add(&time_point, timeout);
82
83 if (cnd_timedwait(&event->cond, &event->mtx, &time_point) == thrd_timedout) {
84 signalled = false;
85 } else {
86 signalled = true;
87 }
88 } else {
89 cnd_wait(&event->cond, &event->mtx);
90 }
91 mtx_unlock(&event->mtx);
92 return signalled;
93}