ascii-chat
Binary v0.15.83-53-gb711d8720
Library lib/v0.3.2-701-gb711d8720
Video chat in your terminal
Loading...
Searching...
No Matches
worker.c
Go to the documentation of this file.
1#include "worker.h"
2
3#include <libplatform/atomic.h>
4#include <ascii-chat/common.h>
5#include <libplatform/thread.h>
7
24
25static void *quic_worker_main(void *arg) {
26 quic_worker_t *worker = arg;
27 while (!atomic_load_u64(&worker->stopping)) {
28 uint64_t wait_ns = NS_PER_SEC_INT;
29 bool want_write = false;
30 quic_connection_t *failed = NULL;
31 mutex_lock(worker->lane);
32 uint64_t now = time_get_ns();
33 asciichat_error_t result = quic_udp_pump(worker->endpoint, now, &failed);
34 bool handled = false;
35 if (result != ASCIICHAT_OK && worker->failure && worker->failure_on_lane) {
36 bool recovered = worker->failure(failed, result, worker->context);
37 if (failed && recovered)
38 handled = !quic_udp_contains(worker->endpoint, failed);
39 if (failed && !handled)
40 (void)worker->failure(NULL, result, worker->context);
41 }
42 atomic_store_u64(&worker->wake_pending, 0);
43 if (result == ASCIICHAT_OK)
44 result = quic_udp_wait_parameters(worker->endpoint, now, NS_PER_SEC_INT, &wait_ns, &want_write);
45 mutex_unlock(worker->lane);
46 if (result != ASCIICHAT_OK) {
47 if (handled)
48 continue;
49 if (failed && worker->failure && !worker->failure_on_lane && worker->failure(failed, result, worker->context)) {
50 mutex_lock(worker->lane);
51 bool still_present = quic_udp_contains(worker->endpoint, failed);
52 mutex_unlock(worker->lane);
53 if (!still_present)
54 continue;
55 }
56 asciichat_error_context_t error_context;
57 if (HAS_ERRNO(&error_context))
58 log_error("QUIC worker stopped: %s", error_context.context_message);
59 worker->result = result;
60 break;
61 }
62 if (atomic_load_u64(&worker->stopping))
63 break;
64 bool ready = false;
65 result = quic_udp_wait(worker->endpoint, wait_ns, want_write, &ready);
66 if (result != ASCIICHAT_OK) {
67 if (worker->failure_on_lane && worker->failure) {
68 mutex_lock(worker->lane);
69 (void)worker->failure(NULL, result, worker->context);
70 mutex_unlock(worker->lane);
71 }
72 worker->result = result;
73 break;
74 }
75 }
76 return NULL;
77}
78
79static asciichat_error_t worker_start(quic_udp_endpoint_t *endpoint, mutex_t *lane, quic_worker_failure_fn failure,
80 void *context, bool failure_on_lane, quic_worker_t **out) {
81 if (!out)
82 return SET_ERRNO(ERROR_INVALID_PARAM, "Missing QUIC worker output");
83 *out = NULL;
84 if (!endpoint || !lane)
85 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid QUIC worker endpoint or lane");
86 quic_worker_t *worker = SAFE_CALLOC(1, sizeof(*worker), quic_worker_t *);
87 if (!worker)
88 return SET_ERRNO(ERROR_MEMORY, "Cannot allocate QUIC worker");
89 worker->endpoint = endpoint;
90 worker->lane = lane;
91 worker->failure = failure;
92 worker->context = context;
93 worker->failure_on_lane = failure_on_lane;
94 if (platform_thread_create(&worker->thread, "quic_udp_worker", quic_worker_main, worker) != 0) {
95 SAFE_FREE(worker);
96 return SET_ERRNO(ERROR_THREAD, "Cannot start QUIC worker");
97 }
98 *out = worker;
99 return ASCIICHAT_OK;
100}
101
103 void *context, quic_worker_t **out) {
104 return worker_start(endpoint, lane, failure, context, false, out);
105}
106
108 quic_worker_failure_fn failure, void *context, quic_worker_t **out) {
109 return worker_start(endpoint, lane, failure, context, true, out);
110}
111
112void quic_worker_wake(void *arg) {
113 quic_worker_t *worker = arg;
114 if (worker && atomic_exchange_u64(&worker->wake_pending, 1) == 0 && quic_udp_wake(worker->endpoint) != ASCIICHAT_OK)
115 atomic_store_u64(&worker->wake_pending, 0);
116}
117
119 if (!worker || !*worker)
120 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid QUIC worker stop");
121 atomic_store_u64(&(*worker)->stopping, 1);
122 quic_worker_wake(*worker);
123 if (thread_join(&(*worker)->thread, NULL) != 0)
124 return SET_ERRNO(ERROR_THREAD, "Cannot join QUIC worker");
125 asciichat_error_t result = (*worker)->result;
126 SAFE_FREE(*worker);
127 *worker = NULL;
128 return result;
129}
#define SET_ERRNO(code,...)
#define HAS_ERRNO(context)
⚙️ Common definitions, error codes, macros, and types shared throughout the application
#define SAFE_FREE(ptr)
Definition common.h:377
#define SAFE_CALLOC(count, size, cast)
Definition common.h:275
unsigned long long uint64_t
Definition common.h:63
asciichat_error_t
Error and exit codes - unified status values (0-255).
Definition error_codes.h:44
@ ERROR_MEMORY
Definition error_codes.h:51
@ ASCIICHAT_OK
Definition error_codes.h:46
@ ERROR_INVALID_PARAM
@ ERROR_THREAD
#define log_error(...)
Log an ERROR message.
Definition log/log.h:634
#define NS_PER_SEC_INT
Definition time.h:169
struct quic_connection quic_connection_t
static bool size_t gotel_query_t * out
Definition queries.h:8
void * context
Definition udp.c:40
For acip quic worker, this is the live record that ties endpoint, lane, failure, context together....
Definition worker.c:13
bool failure_on_lane
Definition worker.c:21
asciichat_error_t result
Definition worker.c:22
void * context
Definition worker.c:17
quic_worker_failure_fn failure
Definition worker.c:16
atomic_t wake_pending
Definition worker.c:20
mutex_t * lane
Definition worker.c:15
atomic_t stopping
Definition worker.c:19
quic_udp_endpoint_t * endpoint
Definition worker.c:14
platform_thread_t thread
Definition worker.c:18
⏱️ High-precision timing utilities using sokol_time.h and uthash
bool quic_udp_contains(const quic_udp_endpoint_t *endpoint, const quic_connection_t *connection)
Definition udp.c:330
asciichat_error_t quic_udp_wake(quic_udp_endpoint_t *endpoint)
Definition udp.c:319
asciichat_error_t quic_udp_wait_parameters(const quic_udp_endpoint_t *endpoint, uint64_t now_ns, uint64_t maximum_wait_ns, uint64_t *wait_ns, bool *want_write)
Definition udp.c:286
asciichat_error_t quic_udp_pump(quic_udp_endpoint_t *endpoint, uint64_t now, quic_connection_t **failed)
Definition udp.c:222
asciichat_error_t quic_udp_wait(quic_udp_endpoint_t *endpoint, uint64_t wait_ns, bool want_write, bool *ready)
Definition udp.c:304
struct quic_udp_endpoint quic_udp_endpoint_t
Definition udp.h:14
void quic_worker_wake(void *arg)
Definition worker.c:112
asciichat_error_t quic_worker_start_locked_failure(quic_udp_endpoint_t *endpoint, mutex_t *lane, quic_worker_failure_fn failure, void *context, quic_worker_t **out)
Definition worker.c:107
asciichat_error_t quic_worker_start(quic_udp_endpoint_t *endpoint, mutex_t *lane, quic_worker_failure_fn failure, void *context, quic_worker_t **out)
Definition worker.c:102
asciichat_error_t quic_worker_stop(quic_worker_t **worker)
Definition worker.c:118
struct quic_worker quic_worker_t
Definition worker.h:11
bool(* quic_worker_failure_fn)(quic_connection_t *, asciichat_error_t, void *)
Definition worker.h:12