libclod
C library for interacting with NBTs, region files, LOD data and other things.
Loading...
Searching...
No Matches
daemon.c
1#include "daemon.h"
2#include <assert.h>
3#include <clod/structures/table.h>
4#include <clod/thread.h>
5
6clod_spinlock daemon_lock = CLOD_SPINLOCK_INIT;
7struct clod_table *daemon_table = nullptr;
8
9struct task {
10 uintptr_t id;
11 size_t counter;
12 bool (*task_func)(void *user);
13 void *user;
14};
15
16#define PERIOD_US (200 * 1000)
17
18int daemon_run(int, char **) {
19 // inherit the lock.
20 assert(!daemon_table);
21 daemon_table = clod_table_create(nullptr);
22
23 int empty_loops = 0;
24 int64_t time = clod_timer(nullptr, 0);
25
26 while (empty_loops++ < 5) {
27 clod_spinlock_unlock(&daemon_lock);
28 int64_t current = clod_timer(&time, PERIOD_US);
29 clod_spinlock_lock(&daemon_lock);
30 if (current > time) time = current;
31
32 struct clod_table_iter iter = {0};
33 while (clod_table_iter(daemon_table, &iter)) {
34 struct task *task = iter.element;
35
36 clod_spinlock_unlock(&daemon_lock);
37 bool res = task->task_func(task->user);
38 clod_spinlock_lock(&daemon_lock);
39
40 if (res) free(clod_table_del(daemon_table, iter.element, iter.key_size));
41 }
42
43 if (clod_table_len(daemon_table) > 0)
44 empty_loops = 0;
45 }
46
47 clod_table_destroy(daemon_table);
48 daemon_table = nullptr;
49 clod_spinlock_unlock(&daemon_lock);
50 return 0;
51}
52
53void clod_daemon_add(const uintptr_t id, bool (*task_func)(void *user), void *user) {
54 clod_spinlock_lock(&daemon_lock);
55
56 if (!daemon_table) {
57 struct clod_process_opts proc_opts = {
58 .type = CLOD_DAEMON,
59 .main = daemon_run
60 };
61
62 bool res = clod_process_start(&proc_opts, nullptr);
63 if (!res) {
64 fprintf(stderr, "Failed to start libclod daemon");
65 clod_spinlock_unlock(&daemon_lock);
66 return;
67 }
68
69 // thread inherits the lock.
70 // get it again.
71 clod_spinlock_lock(&daemon_lock);
72 }
73
74 assert(daemon_table);
75 struct task *task = clod_table_get(daemon_table, &id, sizeof(id));
76 if (task) {
77 task->counter++;
78 task->task_func = task_func;
79 task->user = user;
80 } else {
81 task = malloc(sizeof(struct task));
82 task->id = id;
83 task->counter = 1;
84 task->task_func = task_func;
85 task->user = user;
86 clod_table_add(daemon_table, task, sizeof(task->id), nullptr);
87 }
88
89 clod_spinlock_unlock(&daemon_lock);
90}
91
92void clod_daemon_del(const uintptr_t id) {
93 clod_spinlock_lock(&daemon_lock);
94
95 if (daemon_table != nullptr) {
96 struct task *task = clod_table_get(daemon_table, &id, sizeof(id));
97 if (task) {
98 task->counter--;
99 if (task->counter == 0)
100 free(clod_table_del(daemon_table, &id, sizeof(id)));
101 }
102 }
103
104 clod_spinlock_unlock(&daemon_lock);
105}
size_t clod_table_len(const struct clod_table *t)
Definition table.c:209
void clod_table_destroy(struct clod_table *t)
Definition table.c:205
bool clod_table_iter(const struct clod_table *t, struct clod_table_iter *iter)
Definition table.c:258
struct clod_table * clod_table_create(const struct clod_table_opts *opts)
Definition table.c:190
bool clod_table_add(struct clod_table *t, const void *element, size_t key_size, void **existing_out)
Definition table.c:212
void * clod_table_get(const struct clod_table *t, const void *key, size_t key_size)
Definition table.c:236
void * clod_table_del(struct clod_table *t, const void *key, size_t key_size)
Definition table.c:245
int64_t clod_timer(int64_t *time, int64_t duration_us)
Definition timer.c:214
char clod_spinlock
Definition thread.h:124
void clod_spinlock_lock(clod_spinlock *spinlock)
Definition spinlock.c:5
void clod_spinlock_unlock(clod_spinlock *spinlock)
Definition spinlock.c:26
enum clod_process_result clod_process_start(struct clod_process_opts *opts, clod_process *process_out)
Definition thread.c:10
@ CLOD_DAEMON
Definition thread.h:63
Definition daemon.c:9