From af0f2cb1be5aa10bb6a4bdd9f7ef4aa3950ecb31 Mon Sep 17 00:00:00 2001 From: Dirk Engling Date: Sun, 1 Nov 2026 00:53:53 +0100 Subject: Generalize the worker setup/runloop/teardown logic by adding a smol ot_worker helper --- ot_worker.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 ot_worker.c (limited to 'ot_worker.c') diff --git a/ot_worker.c b/ot_worker.c new file mode 100644 index 0000000..97eaeb2 --- /dev/null +++ b/ot_worker.c @@ -0,0 +1,75 @@ +/* This software was written by Dirk Engling + It is considered beerware. Prost. Skol. Cheers or whatever. + + $id$ */ + +/* System */ +#include +#include +#include +#include +#include + +/* Opentracker */ +#include "ot_worker.h" +#include "trackerlogic.h" + +static struct ot_worker **g_workers; +static size_t g_worker_count; + +/* Everything a worker needs doing around its own loop, in one place, so that + a new kind of worker cannot miss a piece of it. */ +static void *worker_trampoline(void *args) { + struct ot_worker *me = args; + + if (workstruct_init(&me->ws) == -1) + fprintf(stderr, "Warning: a worker could not get its buffers and will not run.\n"); + else { + me->run(me); + workstruct_deinit(&me->ws); + } + + atomic_store(&me->left, 1); + return NULL; +} + +int worker_start(ot_worker_run run, int64_t sock) { + struct ot_worker **grown = realloc(g_workers, (g_worker_count + 1) * sizeof(*g_workers)); + struct ot_worker *worker; + + if (!grown) + return -1; + g_workers = grown; + + if (!(worker = calloc(1, sizeof(*worker)))) + return -1; + worker->sock = sock; + worker->run = run; + + if (pthread_create(&worker->thread, NULL, worker_trampoline, worker)) { + free(worker); + return -1; + } + g_workers[g_worker_count++] = worker; + return 0; +} + +void worker_stop_all(void) { + size_t i; + + for (i = 0; i < g_worker_count; ++i) { + struct ot_worker *worker = g_workers[i]; + + /* Repeated because a signal only interrupts a call already under way */ + while (!atomic_load(&worker->left)) { + pthread_kill(worker->thread, OT_SIGNAL_WAKE); + usleep(1000); + } + pthread_join(worker->thread, NULL); + free(worker); + } + + free(g_workers); + g_workers = NULL; + g_worker_count = 0; +} -- cgit v1.3