diff options
| author | @syxhe <https://t.me/syxhe> | 2025-06-09 17:43:50 -0500 |
|---|---|---|
| committer | @syxhe <https://t.me/syxhe> | 2025-06-09 17:51:14 -0500 |
| commit | 1444c72db8505340c0988ea286a29bc261297933 (patch) | |
| tree | 22d52285ab36b440d02b20aa5f680c75c0c0dbaf /src/threadpool.c | |
| parent | 682c6e29e5b2546ff586a55cea8b81a8c072d3ee (diff) | |
We do a little documentation
Diffstat (limited to 'src/threadpool.c')
| -rw-r--r-- | src/threadpool.c | 60 |
1 files changed, 44 insertions, 16 deletions
diff --git a/src/threadpool.c b/src/threadpool.c index 681428e..02cd945 100644 --- a/src/threadpool.c +++ b/src/threadpool.c | |||
| @@ -1,3 +1,14 @@ | |||
| 1 | /** | ||
| 2 | * @file threadpool.c | ||
| 3 | * @author syxhe (https://t.me/syxhe) | ||
| 4 | * @brief *Implementing `threadpool.h`* | ||
| 5 | * @version 0.1 | ||
| 6 | * @date 2025-06-09 | ||
| 7 | * | ||
| 8 | * @copyright Copyright (c) 2025 | ||
| 9 | * | ||
| 10 | */ | ||
| 11 | |||
| 1 | #include "threadpool.h" | 12 | #include "threadpool.h" |
| 2 | 13 | ||
| 3 | #include <threads.h> | 14 | #include <threads.h> |
| @@ -5,32 +16,48 @@ | |||
| 5 | #include <errno.h> | 16 | #include <errno.h> |
| 6 | #include <error.h> | 17 | #include <error.h> |
| 7 | 18 | ||
| 19 | /** | ||
| 20 | * @brief A generic task - A function, data for that function, and a way to free the data | ||
| 21 | * | ||
| 22 | */ | ||
| 8 | typedef struct task { | 23 | typedef struct task { |
| 9 | gcallback callback; | 24 | gcallback callback; //!< A generic callback to be ran when executing the task |
| 10 | fcallback freecb; | 25 | fcallback freecb; //!< A free()-like callback to deal with the data |
| 11 | void *data; | 26 | void *data; //!< Some generic data for the generic callback |
| 12 | } task; | 27 | } task; |
| 13 | 28 | ||
| 29 | /** | ||
| 30 | * @brief An internal structure used for the `taskqueue`. Analogous to a doubly-linked list's internal node | ||
| 31 | * | ||
| 32 | */ | ||
| 14 | typedef struct tqnode { | 33 | typedef struct tqnode { |
| 15 | struct tqnode *next; | 34 | struct tqnode *next; //!< The next element in the `taskqueue` |
| 16 | struct tqnode *prev; | 35 | struct tqnode *prev; //!< The previous element in the `taskqueue` |
| 17 | task *task; | 36 | task *task; //!< The current element's `task` |
| 18 | } tqnode; | 37 | } tqnode; |
| 19 | 38 | ||
| 39 | /** | ||
| 40 | * @brief A FIFO queue of tasks | ||
| 41 | * | ||
| 42 | */ | ||
| 20 | typedef struct taskqueue { | 43 | typedef struct taskqueue { |
| 21 | tqnode *start; | 44 | tqnode *start; //!< The first element of the queue |
| 22 | tqnode *end; | 45 | tqnode *end; //!< The final element of the queue |
| 23 | unsigned int size; | 46 | unsigned int size; //!< The number of elements in the queue |
| 24 | } taskqueue; | 47 | } taskqueue; |
| 25 | 48 | ||
| 49 | /** | ||
| 50 | * @brief A `taskqueue` built for concurrent access. Essentially a threadpool | ||
| 51 | * | ||
| 52 | */ | ||
| 26 | typedef struct ctqueue { | 53 | typedef struct ctqueue { |
| 27 | mtx_t mutex; | 54 | mtx_t mutex; //!< A mutex for locking sensitive resources |
| 28 | cnd_t cond; | 55 | cnd_t cond; //!< A conditional for waiting on / sending a signal |
| 29 | unsigned char canceled; | 56 | unsigned char canceled; //!< Whether the threads are currently canceled or not |
| 30 | 57 | ||
| 31 | taskqueue *tq; | 58 | taskqueue *tq; //!< A taskqueue to be accessed concurrently |
| 32 | thrd_t *thrdarr; | 59 | thrd_t *thrdarr; //!< An array of threads to be dispatched as consumers |
| 33 | int talen; | 60 | int talen; //!< The length of the thread array |
| 34 | } ctqueue; | 61 | } ctqueue; |
| 35 | 62 | ||
| 36 | 63 | ||
| @@ -221,7 +248,7 @@ int taskqueue_size(taskqueue *tq) { | |||
| 221 | 248 | ||
| 222 | 249 | ||
| 223 | 250 | ||
| 224 | // Internal helper macro for ctq functions. Acquires a lock via the ctq's mutex, checks to see if the queue has been canceled, then executes "code" as written | 251 | //! Internal helper macro for ctq functions. Acquires a lock via the ctq's mutex, checks to see if the queue has been canceled, then executes "code" as written |
| 225 | #define __CTQ_INLOCK(ctq, retval, code) do {\ | 252 | #define __CTQ_INLOCK(ctq, retval, code) do {\ |
| 226 | mtx_lock(&(ctq)->mutex); \ | 253 | mtx_lock(&(ctq)->mutex); \ |
| 227 | if((ctq)->canceled) { \ | 254 | if((ctq)->canceled) { \ |
| @@ -356,6 +383,7 @@ task * ctqueue_waitpop(ctqueue *ctq) { | |||
| 356 | return retval; | 383 | return retval; |
| 357 | } | 384 | } |
| 358 | 385 | ||
| 386 | //! Simple consumer for eating and executing tasks from the ctq | ||
| 359 | static int __CTQ_CONSUMER(void *ctq) { | 387 | static int __CTQ_CONSUMER(void *ctq) { |
| 360 | if(!ctq) {errno = EINVAL; thrd_exit(-1);} | 388 | if(!ctq) {errno = EINVAL; thrd_exit(-1);} |
| 361 | ctqueue *real = (ctqueue *)ctq; | 389 | ctqueue *real = (ctqueue *)ctq; |
