4#include <ttak/mem/epoch.h>
30typedef struct job_node {
33 struct job_node *_Atomic next;
34 struct job_node *retire_next;
48 unsigned int last_epoch;
59 if (!node)
return NULL;
74static void cwist_job_node_destroy(
job_node_t *node) {
85static void cwist_queue_defer_free(cwist_io_queue *q,
job_node_t *node) {
87 node->retire_next = q->retire_new;
97static void cwist_job_node_free_cb(
void *ptr) {
107static void cwist_queue_reclaim(cwist_io_queue *q) {
112 if (
epoch != q->last_epoch) {
113 q->last_epoch =
epoch;
115 q->retire_old = q->retire_new;
116 q->retire_new =
NULL;
134static void cwist_queue_push(cwist_io_queue *q,
job_node_t *node) {
175static bool cwist_queue_pop(cwist_io_queue *q,
cwist_job_func *func,
void **arg) {
195 cwist_queue_defer_free(q,
head);
211static bool cwist_queue_wait(cwist_io_queue *q) {
245 q->retire_new =
NULL;
246 q->retire_old =
NULL;
250 cwist_job_node_destroy(
stub);
256 cwist_job_node_destroy(
stub);
263 cwist_job_node_destroy(
stub);
278 if (!q || !func)
return false;
283 job_node_t *node = cwist_job_node_create(func, arg);
284 if (!node)
return false;
285 cwist_queue_push(q, node);
300 if (!cwist_queue_pop(q, &func, &arg)) {
301 cwist_queue_reclaim(q);
303 if (!cwist_queue_wait(q)) {
322 cwist_queue_reclaim(q);
353 cwist_job_node_destroy(node);
363 cwist_job_node_destroy(
list);
Memory allocation wrappers backed by libttak.
void cwist_free(void *ptr)
Free memory obtained via cwist_alloc/cwist_strdup/etc.
void * cwist_alloc(size_t size)
Allocate zeroed memory tracked by libttak.
Platform Agnostic Async Job Queue Interface.
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,...
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_gc_scope_flush(void)
Retire every block still on the current thread's pending-sweep list right now, instead of waiting for...
struct job_node job_node_t
void cwist_io_queue_run(cwist_io_queue *q)
Process queued jobs until shutdown is requested and no work remains.
void cwist_io_queue_stop(cwist_io_queue *q)
Request that runners stop without freeing the queue.
void cwist_io_queue_destroy(cwist_io_queue *q)
Stop the queue, wake sleepers, and free all remaining nodes.
cwist_io_queue * cwist_io_queue_create(size_t capacity)
Allocate the queue object and install its sentinel node.
bool cwist_io_queue_submit(cwist_io_queue *q, cwist_job_func func, void *arg)
Submit a callback for asynchronous execution by the queue runner.