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}