/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only */
/* Copyright (c) 2023 Brett Sheffield <bacs@librecast.net> */

/* smolq - a very simple threadpool and job queue
 *
 * Uses a fixed size ring buffer style queue of 65536. Uses just over 1MiB.
 *
 * A job consists of a start function and argument for a thread.
 *
 * The job queue is initialized with q_init() and freed with q_free().
 * This can be passed to a threadpool as the argument when calling
 * q_pool_create().
 */

#ifndef _SMOL_Q
#define _SMOL_Q 1

#include <errno.h>
#include <fcntl.h>
#include <librecast/types.h>
#include <pthread.h>
#include <sched.h>
#include <semaphore.h>
#include <stdint.h>
#include <unistd.h>

struct q_job_s {
        void *(*f)(void *);
        void *arg;
};

struct q_s {
        q_job_t job[UINT16_MAX + 1]; /* 1 MiB => ~256 pages */
        uint16_t ridx; /*  read index (HEAD) */
        uint16_t widx; /* write index (TAIL) */
        sem_t rlock;   /* read semaphore */
        sem_t wlock;   /* write semaphore */
};

int q_init(q_t *q);
int q_free(q_t *q);
void *q_job_seek(void *arg);
int q_pool_create(pthread_t tid[], int nthreads, void *(*f)(void *), void *restrict arg);
int q_pool_destroy(pthread_t tid[], int nthreads);
int q_push(q_t *q, void *(*f)(void *), void *restrict arg);
int q_search(q_t *q, void *(*f)(void *), void *restrict arg);
int q_trypush(q_t *q, void *(*f)(void *), void *restrict arg);
int q_trywait(q_t *q, q_job_t *job);
int q_wait(q_t *q, q_job_t *job);

#endif /* _SMOL_Q */
