1/* @title: Countdown latch (using events) */
2#pragma once
3#include <sync/event.h>
4#include <sync/once_latch.h>
5#include <time/time.h>
6
7struct event_latch {
8 struct once_latch latch;
9 struct event ready;
10};
11
12#define EVENT_LATCH_INIT(name_, n) \
13 (struct event_latch) { \
14 .latch = ONCE_LATCH_INIT(n), \
15 .ready = EVENT_INIT((name_).ready, EVENT_NOTIFICATION, false), \
16 }
17
18static inline void event_latch_init(struct event_latch *el, uint64_t count) {
19 once_latch_init(latch: &el->latch, count);
20 event_init(e: &el->ready, type: EVENT_NOTIFICATION, false);
21}
22
23static inline bool event_latch_count_down(struct event_latch *el) {
24 if (once_latch_count_down(latch: &el->latch)) {
25 event_set(e: &el->ready);
26 return true;
27 }
28 return false;
29}
30
31static inline bool event_latch_is_ready(const struct event_latch *el) {
32 return once_latch_is_ready(latch: &el->latch);
33}
34
35static inline uint64_t event_latch_count(const struct event_latch *el) {
36 return once_latch_get_count(latch: &el->latch);
37}
38
39static inline void event_latch_wait(struct event_latch *el) TSA_MAY_SLEEP {
40 if (event_latch_is_ready(el))
41 return;
42 event_wait(e: &el->ready, type: THREAD_WAIT_UNINTERRUPTIBLE,
43 reason: THREAD_BLOCK_REASON_MANUAL);
44}
45
46static inline bool
47event_latch_wait_timeout(struct event_latch *el,
48 time_ms_t timeout_ms) TSA_MAY_SLEEP {
49 if (event_latch_is_ready(el))
50 return true;
51 return event_wait_timeout(e: &el->ready, type: THREAD_WAIT_UNINTERRUPTIBLE,
52 reason: THREAD_BLOCK_REASON_MANUAL, timeout_ms)
53 .status == THREAD_WAIT_SATISFIED;
54}
55