10#define _POSIX_C_SOURCE 200809L
21#define CWIST_SCHEDULER_HEAP_INIT 16
29struct cwist_scheduler {
35 scheduled_job_t *heap;
36 _Atomic
size_t heap_count;
70 ts->tv_nsec = (
long)((
ms % 1000ULL) * 1000000ULL);
85#if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
126static void heap_swap(scheduled_job_t *
a, scheduled_job_t *b) {
127 scheduled_job_t
tmp = *
a;
142 if (heap_grow(s) != 0)
return;
148 if (s->heap[
parent].deadline_ms <= s->heap[
i].deadline_ms)
break;
149 heap_swap(&s->heap[
parent], &s->heap[
i]);
162 scheduled_job_t
root = s->heap[0];
165 s->heap[0] = s->heap[
count];
168 size_t left =
i * 2 + 1;
178 heap_swap(&s->heap[
i], &s->heap[
smallest]);
192static void *scheduler_worker_thread(
void *arg) {
206static void *scheduler_timer_thread(
void *arg) {
218 scheduled_job_t
job = heap_pop(s);
266 if (worker_count == 0) worker_count = 1;
287 s->worker_count = worker_count;
290 cond_init_monotonic(&s->delayed_cond);
293 for (
size_t i = 0;
i < worker_count;
i++) {
295 scheduler_cleanup_threads(s,
i);
306 scheduler_cleanup_threads(s, worker_count);
337 for (
size_t i = 0;
i < s->worker_count;
i++) {
361 if (!s || !func || !s->running)
return false;
382 if (!s || !func || !s->running)
return false;
434 scheduled_job_t *detached = s->heap;
437 s->heap_capacity = 0;
442 for (
size_t i = 0;
i < cancelled;
i++) {
Memory allocation wrappers backed by libttak.
void cwist_free(void *ptr)
Free memory obtained via cwist_alloc/cwist_strdup/etc.
void * cwist_realloc(void *ptr, size_t new_size)
Resize an existing allocation (libttak tracked).
void * cwist_alloc_array(size_t count, size_t elem_size)
Allocate zeroed memory for count elements.
void * cwist_alloc(size_t size)
Allocate zeroed memory tracked by libttak.
void(* cwist_job_func)(void *arg)
Job function signature.
struct cwist_io_queue cwist_io_queue
Opaque handle for the IO Queue. Backend implementation depends on OS (io_uring, kqueue,...
void cwist_io_queue_run(cwist_io_queue *q)
Run the event loop. Blocks indefinitely, processing jobs as they complete/trigger.
void cwist_io_queue_stop(cwist_io_queue *q)
Request that all runners stop processing without freeing the queue.
void cwist_io_queue_destroy(cwist_io_queue *q)
Destroy the queue and free resources.
cwist_io_queue * cwist_io_queue_create(size_t capacity)
Initialize the job queue.
bool cwist_io_queue_submit(cwist_io_queue *q, cwist_job_func func, void *arg)
Submit a job to be executed asynchronously.
Epoch-based garbage collection wrapper.
bool cwist_gc_scope_disown(void *ptr)
Remove ptr from the current thread's pending-sweep list without freeing it, because ownership is bein...
bool cwist_full_gc_enabled(void)
Check whether full-GC mode is currently enabled.
void cwist_scheduler_destroy(cwist_scheduler_t *s)
Destroy a scheduler and free all its resources.
bool cwist_scheduler_submit(cwist_scheduler_t *s, cwist_job_func func, void *arg)
Submit a job for immediate execution by a worker thread.
bool cwist_scheduler_schedule(cwist_scheduler_t *s, cwist_job_func func, void *arg, uint64_t delay_ms)
Schedule a job to run after a delay.
size_t cwist_scheduler_pending_count(cwist_scheduler_t *s)
Return the number of jobs waiting on the delayed-job heap.
size_t cwist_scheduler_cancel_pending(cwist_scheduler_t *s, cwist_scheduler_drop_cb drop_cb)
Cancel all delayed jobs that have not yet fired.
cwist_scheduler_t * cwist_scheduler_create(size_t worker_count, size_t queue_capacity)
Create a scheduler with worker and timer threads.
#define CWIST_SCHEDULER_HEAP_INIT
Background job scheduler / delayed task queue for CWIST.
struct cwist_scheduler cwist_scheduler_t
Opaque background job scheduler handle.
void(* cwist_scheduler_drop_cb)(void *arg)
Callback invoked for each pending job that is cancelled.