diff options
| -rw-r--r-- | .Doxyfile | 2 | ||||
| -rw-r--r-- | Makefile | 3 | ||||
| -rw-r--r-- | src/Makefile | 1 | ||||
| -rw-r--r-- | src/encryption.c | 11 | ||||
| -rw-r--r-- | src/encryption.h | 11 | ||||
| -rwxr-xr-x | src/main.c | 13 | ||||
| -rw-r--r-- | src/shared.c | 13 | ||||
| -rw-r--r-- | src/shared.h | 143 | ||||
| -rw-r--r-- | src/threadpool.c | 60 | ||||
| -rw-r--r-- | src/threadpool.h | 11 |
10 files changed, 227 insertions, 41 deletions
| @@ -1140,7 +1140,7 @@ SOURCE_TOOLTIPS = YES | |||
| 1140 | # The default value is: NO. | 1140 | # The default value is: NO. |
| 1141 | # This tag requires that the tag SOURCE_BROWSER is set to YES. | 1141 | # This tag requires that the tag SOURCE_BROWSER is set to YES. |
| 1142 | 1142 | ||
| 1143 | USE_HTAGS = YES | 1143 | USE_HTAGS = NO |
| 1144 | 1144 | ||
| 1145 | # If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a | 1145 | # If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a |
| 1146 | # verbatim copy of the header file for each class for which an include is | 1146 | # verbatim copy of the header file for each class for which an include is |
| @@ -1,8 +1,7 @@ | |||
| 1 | GTAGFILES := $(patsubst %,./src/%,GPATH GRTAGS GTAGS) | ||
| 2 | .PHONY: docs c clean | 1 | .PHONY: docs c clean |
| 3 | 2 | ||
| 4 | docs: | 3 | docs: |
| 5 | doxygen .Doxyfile | 4 | doxygen .Doxyfile |
| 6 | 5 | ||
| 7 | c clean: | 6 | c clean: |
| 8 | rm -rvf docs $(GTAGFILES) \ No newline at end of file | 7 | rm -rvf docs \ No newline at end of file |
diff --git a/src/Makefile b/src/Makefile index ff75a8a..0ee5897 100644 --- a/src/Makefile +++ b/src/Makefile | |||
| @@ -35,7 +35,6 @@ include $(wildcard $(DEPS)) | |||
| 35 | 35 | ||
| 36 | c clean: | 36 | c clean: |
| 37 | @-rm -rv main $(OBJECTS) $(DEPS) $(wildcard *.test*) $(wildcard *.enc) | 37 | @-rm -rv main $(OBJECTS) $(DEPS) $(wildcard *.test*) $(wildcard *.enc) |
| 38 | $(MAKE) -C ../ clean | ||
| 39 | 38 | ||
| 40 | val: | 39 | val: |
| 41 | $(MAKE) all | 40 | $(MAKE) all |
diff --git a/src/encryption.c b/src/encryption.c index 89448e8..fd42929 100644 --- a/src/encryption.c +++ b/src/encryption.c | |||
| @@ -1,3 +1,14 @@ | |||
| 1 | /** | ||
| 2 | * @file encryption.c | ||
| 3 | * @author syxhe (https://t.me/syxhe) | ||
| 4 | * @brief *Implementing `encryption.h`* | ||
| 5 | * @version 0.1 | ||
| 6 | * @date 2025-06-09 | ||
| 7 | * | ||
| 8 | * @copyright Copyright (c) 2025 | ||
| 9 | * | ||
| 10 | */ | ||
| 11 | |||
| 1 | // TODO: Go back and make sure every function has proper error handling | 12 | // TODO: Go back and make sure every function has proper error handling |
| 2 | // Oh fucking christ what have I done | 13 | // Oh fucking christ what have I done |
| 3 | // I need to make sure every single function in this file returns with an indicated error instead of nuking the whole program with | 14 | // I need to make sure every single function in this file returns with an indicated error instead of nuking the whole program with |
diff --git a/src/encryption.h b/src/encryption.h index f6c018c..5c6a08c 100644 --- a/src/encryption.h +++ b/src/encryption.h | |||
| @@ -1,3 +1,14 @@ | |||
| 1 | /** | ||
| 2 | * @file encryption.h | ||
| 3 | * @author syxhe (https://t.me/syxhe) | ||
| 4 | * @brief A collection of all encryption related functions | ||
| 5 | * @version 0.1 | ||
| 6 | * @date 2025-06-09 | ||
| 7 | * | ||
| 8 | * @copyright Copyright (c) 2025 | ||
| 9 | * | ||
| 10 | */ | ||
| 11 | |||
| 1 | #ifndef __VXGG_REWRITE___ENCRYPTION_H___1481879318188___ | 12 | #ifndef __VXGG_REWRITE___ENCRYPTION_H___1481879318188___ |
| 2 | #define __VXGG_REWRITE___ENCRYPTION_H___1481879318188___ | 13 | #define __VXGG_REWRITE___ENCRYPTION_H___1481879318188___ |
| 3 | 14 | ||
| @@ -1,7 +1,16 @@ | |||
| 1 | #include "shared.h" | 1 | /** |
| 2 | * @file main.c | ||
| 3 | * @author syxhe (https://t.me/syxhe) | ||
| 4 | * @brief Putting everything together | ||
| 5 | * @version 0.1 | ||
| 6 | * @date 2025-06-09 | ||
| 7 | * | ||
| 8 | * @copyright Copyright (c) 2025 | ||
| 9 | * | ||
| 10 | */ | ||
| 2 | 11 | ||
| 12 | #include "shared.h" | ||
| 3 | #include "encryption.h" | 13 | #include "encryption.h" |
| 4 | #include "scanner.h" | ||
| 5 | #include "threadpool.h" | 14 | #include "threadpool.h" |
| 6 | 15 | ||
| 7 | #include <errno.h> | 16 | #include <errno.h> |
diff --git a/src/shared.c b/src/shared.c index c02414b..40732f0 100644 --- a/src/shared.c +++ b/src/shared.c | |||
| @@ -1,3 +1,14 @@ | |||
| 1 | /** | ||
| 2 | * @file shared.c | ||
| 3 | * @author syxhe (https://t.me/syxhe) | ||
| 4 | * @brief *Implementing `shared.h`* | ||
| 5 | * @version 0.1 | ||
| 6 | * @date 2025-06-09 | ||
| 7 | * | ||
| 8 | * @copyright Copyright (c) 2025 | ||
| 9 | * | ||
| 10 | */ | ||
| 11 | |||
| 1 | #include "shared.h" | 12 | #include "shared.h" |
| 2 | 13 | ||
| 3 | #include <stdlib.h> | 14 | #include <stdlib.h> |
| @@ -201,7 +212,6 @@ int cleanup_init(cleanup *loc, fcallback callbacks[], void *arguments[], int siz | |||
| 201 | return 0; | 212 | return 0; |
| 202 | } | 213 | } |
| 203 | 214 | ||
| 204 | // registers if flag is NOT set | ||
| 205 | int cleanup_register(cleanup *loc, fcallback cb, void *arg) { | 215 | int cleanup_register(cleanup *loc, fcallback cb, void *arg) { |
| 206 | if(!loc || !cb) ERRRET(EINVAL, -1); | 216 | if(!loc || !cb) ERRRET(EINVAL, -1); |
| 207 | if(loc->used >= loc->size || loc->used < 0) ERRRET(ENOMEM, -1); | 217 | if(loc->used >= loc->size || loc->used < 0) ERRRET(ENOMEM, -1); |
| @@ -213,6 +223,7 @@ int cleanup_register(cleanup *loc, fcallback cb, void *arg) { | |||
| 213 | return 0; | 223 | return 0; |
| 214 | } | 224 | } |
| 215 | 225 | ||
| 226 | // registers if flag is NOT set | ||
| 216 | int cleanup_cndregister(cleanup *loc, fcallback cb, void *arg, unsigned char flag) { | 227 | int cleanup_cndregister(cleanup *loc, fcallback cb, void *arg, unsigned char flag) { |
| 217 | if(flag) return 0; | 228 | if(flag) return 0; |
| 218 | return cleanup_register(loc, cb, arg); | 229 | return cleanup_register(loc, cb, arg); |
diff --git a/src/shared.h b/src/shared.h index 3ff7b2d..6276281 100644 --- a/src/shared.h +++ b/src/shared.h | |||
| @@ -1,28 +1,41 @@ | |||
| 1 | /** | ||
| 2 | * @file shared.h | ||
| 3 | * @author syxhe (https://t.me/syxhe) | ||
| 4 | * @brief A collection of functions and macros shared between files, or without a better place | ||
| 5 | * @version 0.1 | ||
| 6 | * @date 2025-06-09 | ||
| 7 | * | ||
| 8 | * @copyright Copyright (c) 2025 | ||
| 9 | * | ||
| 10 | */ | ||
| 11 | |||
| 1 | #ifndef __VXGG_REWRITE___SHARED_H___3880294315821___ | 12 | #ifndef __VXGG_REWRITE___SHARED_H___3880294315821___ |
| 2 | #define __VXGG_REWRITE___SHARED_H___3880294315821___ 1 | 13 | #define __VXGG_REWRITE___SHARED_H___3880294315821___ 1 |
| 3 | 14 | ||
| 4 | #include <stddef.h> | 15 | #include <stddef.h> |
| 5 | 16 | ||
| 6 | typedef int (*gcallback)(void*); // Generic callback signature | 17 | typedef int (*gcallback)(void*); //!< Generic callback signature |
| 7 | typedef void (*fcallback)(void*); // free()-like callback signature | 18 | typedef void (*fcallback)(void*); //!< free()-like callback signature |
| 8 | 19 | ||
| 20 | //! Get the size of a statically/vla defined array. Doesn't work on arrays allocated via `malloc()` | ||
| 9 | #define STATIC_ARRAY_LEN(arr) (sizeof((arr))/sizeof((arr)[0])) | 21 | #define STATIC_ARRAY_LEN(arr) (sizeof((arr))/sizeof((arr)[0])) |
| 10 | 22 | ||
| 23 | //! Sets errno to `errval`, then returns `retval`. Defined as a macro because it is meant for use inside functions, not as a function itself | ||
| 11 | #define ERRRET(errval, retval) do {\ | 24 | #define ERRRET(errval, retval) do {\ |
| 12 | errno = (errval);\ | 25 | errno = (errval);\ |
| 13 | return (retval);\ | 26 | return (retval);\ |
| 14 | } while (0) | 27 | } while (0) |
| 15 | 28 | ||
| 16 | // Defines how `x___alloc()` functions should exit. `___VXGG___XALLOC_EXIT_ON_ERROR___ > 0` calls `error()`, and thus functions | 29 | /// Defines how `x___alloc()` functions should exit. `___VXGG___XALLOC_EXIT_ON_ERROR___ > 0` calls `error()`, and thus functions |
| 17 | // registered with `atexit()` and `on_exit()`. `___VXGG___XALLOC_EXIT_ON_ERROR___ <= 0` calls `abort()` on error. `x___alloc()` | 30 | /// registered with `atexit()` and `on_exit()`. `___VXGG___XALLOC_EXIT_ON_ERROR___ <= 0` calls `abort()` on error. `x___alloc()` |
| 18 | // type functions will ALWAYS 'abort', doing otherwise defeats the purpose of the function type | 31 | /// type functions will ALWAYS 'abort', doing otherwise defeats the purpose of the function type |
| 19 | #define ___VXGG___XALLOC_EXIT_ON_ERROR___ 1 | 32 | #define ___VXGG___XALLOC_EXIT_ON_ERROR___ 1 |
| 20 | 33 | ||
| 21 | // Defines whether vxgg functions that can error print out a short warning of the error when one is encountered. | 34 | /// Defines whether vxgg functions that can error print out a short warning of the error when one is encountered. |
| 22 | // `___VXGG___VERBOSE_ERRORS___ > 0` will print diagnostic error messages, and will do nothing otherwise | 35 | /// `___VXGG___VERBOSE_ERRORS___ > 0` will print diagnostic error messages, and will do nothing otherwise |
| 23 | #define ___VXGG___VERBOSE_ERRORS___ 1 | 36 | #define ___VXGG___VERBOSE_ERRORS___ 1 |
| 24 | 37 | ||
| 25 | // Macro to exit on an alloc error instead of doing the terrible nested if statement that was being used previously | 38 | //! Macro to exit on an alloc error instead of doing the terrible nested if statement that was being used previously |
| 26 | #define XALLOC_EXIT(msg, ...) do {\ | 39 | #define XALLOC_EXIT(msg, ...) do {\ |
| 27 | if(!___VXGG___XALLOC_EXIT_ON_ERROR___)\ | 40 | if(!___VXGG___XALLOC_EXIT_ON_ERROR___)\ |
| 28 | abort();\ | 41 | abort();\ |
| @@ -33,37 +46,122 @@ typedef void (*fcallback)(void*); // free()-like callback signature | |||
| 33 | } while (0) | 46 | } while (0) |
| 34 | 47 | ||
| 35 | 48 | ||
| 49 | //! Holdover macro because I'm lazy. Used to call either malloc or xmalloc, but the xalloc functions were a bad idea, so I removed them | ||
| 36 | #define VALLOC(nmemb, size) malloc((nmemb) * (size)) | 50 | #define VALLOC(nmemb, size) malloc((nmemb) * (size)) |
| 37 | 51 | ||
| 38 | // Error macro that gcc will not complain about | 52 | //! Error macro that gcc will not complain about |
| 39 | #define ERROR(status, errnum, format, ...) do {error((status), (errnum), (format)__VA_ARGS__); exit((status));} while (0) | 53 | #define ERROR(status, errnum, format, ...) do {error((status), (errnum), (format)__VA_ARGS__); exit((status));} while (0) |
| 40 | // Spit out a warning using `error` | 54 | //! Spit out a warning using `error` |
| 41 | #define WARN(errnum, format, ...) do {error(0, (errnum), (format)__VA_ARGS__);} while (0) | 55 | #define WARN(errnum, format, ...) do {error(0, (errnum), (format)__VA_ARGS__);} while (0) |
| 42 | 56 | ||
| 43 | // Read the entire contents of a file descriptor into a malloc()'ed buffer | 57 | |
| 58 | |||
| 59 | /** | ||
| 60 | * @brief Read the entire contents of a file descriptor into a malloc()'ed buffer | ||
| 61 | * | ||
| 62 | * @param str Pointer to a string. Will be replaced with the malloc()'ed string | ||
| 63 | * @param initsize The initial size of the malloc()'ed string | ||
| 64 | * @param fd A file descriptor to read from | ||
| 65 | * @return int Returns the size of the array on success, or -1 on error | ||
| 66 | * @note The allocated buffer will expand and contract as necessary, but it's recommended to set `initsize` to some value close to or equal to the size of the file being read to reduce the number of resizes | ||
| 67 | */ | ||
| 44 | int rwbuf(char **str, unsigned long int initsize, int fd); | 68 | int rwbuf(char **str, unsigned long int initsize, int fd); |
| 45 | // Write the entire contents of a buffer into a file descriptor | 69 | |
| 70 | /** | ||
| 71 | * @brief Write the entire contents of a buffer into a file descriptor | ||
| 72 | * | ||
| 73 | * @param fd The file descriptor to write to | ||
| 74 | * @param buf The buffer to write from | ||
| 75 | * @param len The length of the buffer | ||
| 76 | * @return int Returns 0 on success, -1 on error | ||
| 77 | */ | ||
| 46 | int wwbuf(int fd, const unsigned char *buf, int len); | 78 | int wwbuf(int fd, const unsigned char *buf, int len); |
| 47 | // `dirname()` reimplementation that returns a malloc()'ed string | 79 | |
| 80 | |||
| 81 | |||
| 82 | /** | ||
| 83 | * @brief `dirname()` reimplementation that returns a malloc()'ed string | ||
| 84 | * | ||
| 85 | * @param path The filepath to be inspected | ||
| 86 | * @return char* Returns a null-terminated string on success, or `null` on error | ||
| 87 | */ | ||
| 48 | char * vxdirname(const char * const path); | 88 | char * vxdirname(const char * const path); |
| 49 | 89 | ||
| 50 | 90 | ||
| 51 | 91 | ||
| 52 | // A locally defined structure designed for easier function cleanup | 92 | /** |
| 93 | * @brief A locally defined structure designed for easier function cleanup | ||
| 94 | * | ||
| 95 | */ | ||
| 53 | typedef struct cl { | 96 | typedef struct cl { |
| 54 | fcallback *callbacks; // Actual Type: fcallback callbacks[] | 97 | fcallback *callbacks; //!< An array of free()-like callbacks. Actual Type: fcallback callbacks[] |
| 55 | void * *arguments; // Actual Type: void *arguments[] | 98 | void * *arguments; //!< An array of void pointers. Actual Type: void *arguments[] |
| 56 | int size; | 99 | int size; //!< The size of each array |
| 57 | int used; | 100 | int used; //!< The current number of used elements in each array |
| 58 | } cleanup; | 101 | } cleanup; |
| 59 | 102 | ||
| 103 | /** | ||
| 104 | * @brief Initialize a cleanup object | ||
| 105 | * | ||
| 106 | * @param loc The cleanup object to be initialized | ||
| 107 | * @param callbacks An array of free()-like callbacks. Must be `size` elements long | ||
| 108 | * @param arguments An array of void pointers. Must be `size` elements long | ||
| 109 | * @param size The number of elements the callbacks and arguments array are long | ||
| 110 | * @return int Returns 0 on success, -1 on error | ||
| 111 | */ | ||
| 60 | int cleanup_init(cleanup *loc, fcallback callbacks[], void *arguments[], int size); | 112 | int cleanup_init(cleanup *loc, fcallback callbacks[], void *arguments[], int size); |
| 113 | |||
| 114 | /** | ||
| 115 | * @brief Register a new callback and argument onto a cleanup stack | ||
| 116 | * | ||
| 117 | * @param loc The cleanup object to modify | ||
| 118 | * @param cb A free()-like callback to run | ||
| 119 | * @param arg A piece of data for the callback to run | ||
| 120 | * @return int Returns 0 on success, -1 on error | ||
| 121 | */ | ||
| 61 | int cleanup_register(cleanup *loc, fcallback cb, void *arg); | 122 | int cleanup_register(cleanup *loc, fcallback cb, void *arg); |
| 123 | |||
| 124 | /** | ||
| 125 | * @brief Conditionally register a callback and argument | ||
| 126 | * | ||
| 127 | * @param loc The cleanup object to modify | ||
| 128 | * @param cb A free()-like callback to run | ||
| 129 | * @param arg A piece of data for the callback to run | ||
| 130 | * @param flag Whether or not the register should take place. Will not run if `flag` is non-zero | ||
| 131 | * @return int Returns 0 on success or skip, -1 on error | ||
| 132 | */ | ||
| 62 | int cleanup_cndregister(cleanup *loc, fcallback cb, void *arg, unsigned char flag); | 133 | int cleanup_cndregister(cleanup *loc, fcallback cb, void *arg, unsigned char flag); |
| 134 | |||
| 135 | /** | ||
| 136 | * @brief Clear a cleanup object | ||
| 137 | * @attention Does not free any registered callbacks or arguments, just marks them as available space | ||
| 138 | * | ||
| 139 | * @param loc The cleanup object to modify | ||
| 140 | * @return int Returns 0 on success, -1 on error | ||
| 141 | */ | ||
| 63 | int cleanup_clear(cleanup *loc); | 142 | int cleanup_clear(cleanup *loc); |
| 143 | |||
| 144 | /** | ||
| 145 | * @brief Fires all the registered callbacks and arguments in a cleanup object in FIFO (stack) order | ||
| 146 | * | ||
| 147 | * @param loc The cleanup object to fire | ||
| 148 | * @return int Returns 0 on success, -1 on error | ||
| 149 | */ | ||
| 64 | int cleanup_fire(cleanup *loc); | 150 | int cleanup_fire(cleanup *loc); |
| 151 | |||
| 152 | /** | ||
| 153 | * @brief Conditionally fires a cleanup object | ||
| 154 | * | ||
| 155 | * @param loc The cleanup object in question | ||
| 156 | * @param flag Whether the object should be fired. Will skip firing if non-zero | ||
| 157 | * @return int Returns 0 on success, -1 on error | ||
| 158 | */ | ||
| 65 | int cleanup_cndfire(cleanup *loc, unsigned char flag); | 159 | int cleanup_cndfire(cleanup *loc, unsigned char flag); |
| 66 | 160 | ||
| 161 | /** | ||
| 162 | * @brief Initializes a set of variables suitable for use in the cleanup macros | ||
| 163 | * @param size The number of elements long each array should be | ||
| 164 | */ | ||
| 67 | #define cleanup_CREATE(size) \ | 165 | #define cleanup_CREATE(size) \ |
| 68 | cleanup __CLEANUP; \ | 166 | cleanup __CLEANUP; \ |
| 69 | fcallback __CLEANUP_FUNCS[(size)]; \ | 167 | fcallback __CLEANUP_FUNCS[(size)]; \ |
| @@ -71,14 +169,23 @@ void *__CLEANUP_ARGS[(size)]; \ | |||
| 71 | unsigned char __FLAG = 0; \ | 169 | unsigned char __FLAG = 0; \ |
| 72 | cleanup_init(&__CLEANUP, __CLEANUP_FUNCS, __CLEANUP_ARGS, (size)) | 170 | cleanup_init(&__CLEANUP, __CLEANUP_FUNCS, __CLEANUP_ARGS, (size)) |
| 73 | 171 | ||
| 172 | //! Register a callback-argument pair using the local cleanup object | ||
| 74 | #define cleanup_REGISTER(cb, arg) cleanup_register(&__CLEANUP, (cb), (arg)) | 173 | #define cleanup_REGISTER(cb, arg) cleanup_register(&__CLEANUP, (cb), (arg)) |
| 174 | //! Conditionally register a callback-argument pair using the local cleanup object | ||
| 75 | #define cleanup_CNDREGISTER(cb, arg) cleanup_cndregister(&__CLEANUP, (cb), (arg), __FLAG) | 175 | #define cleanup_CNDREGISTER(cb, arg) cleanup_cndregister(&__CLEANUP, (cb), (arg), __FLAG) |
| 176 | //! Clean the local cleanup object | ||
| 76 | #define cleanup_CLEAR() cleanup_clear(&__CLEANUP) | 177 | #define cleanup_CLEAR() cleanup_clear(&__CLEANUP) |
| 178 | //! Fire the local cleanup object | ||
| 77 | #define cleanup_FIRE() cleanup_fire(&__CLEANUP) | 179 | #define cleanup_FIRE() cleanup_fire(&__CLEANUP) |
| 180 | //! Conditionally fire the local cleanup object | ||
| 78 | #define cleanup_CNDFIRE() cleanup_cndfire(&__CLEANUP, __FLAG) | 181 | #define cleanup_CNDFIRE() cleanup_cndfire(&__CLEANUP, __FLAG) |
| 182 | //! Set the local cleanup flag to a non-zero number | ||
| 79 | #define cleanup_MARK() (__FLAG = 1) | 183 | #define cleanup_MARK() (__FLAG = 1) |
| 184 | //! Set the local cleanup flag to zero | ||
| 80 | #define cleanup_UNMARK() (__FLAG = 0) | 185 | #define cleanup_UNMARK() (__FLAG = 0) |
| 186 | //! Check if the local cleanup flag is non-zero | ||
| 81 | #define cleanup_ERRORFLAGGED (__FLAG != 0) | 187 | #define cleanup_ERRORFLAGGED (__FLAG != 0) |
| 188 | //! Conditionally execute some `code` if the local cleanup flag has not been marked | ||
| 82 | #define cleanup_CNDEXEC(code) while(!cleanup_ERRORFLAGGED) {code; break;} | 189 | #define cleanup_CNDEXEC(code) while(!cleanup_ERRORFLAGGED) {code; break;} |
| 83 | 190 | ||
| 84 | #endif \ No newline at end of file | 191 | #endif \ No newline at end of file |
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; |
diff --git a/src/threadpool.h b/src/threadpool.h index 1d9a537..91c903c 100644 --- a/src/threadpool.h +++ b/src/threadpool.h | |||
| @@ -1,3 +1,14 @@ | |||
| 1 | /** | ||
| 2 | * @file threadpool.h | ||
| 3 | * @author syxhe (https://t.me/syxhe) | ||
| 4 | * @brief An implementation of a threadpool using libc threads | ||
| 5 | * @version 0.1 | ||
| 6 | * @date 2025-06-09 | ||
| 7 | * | ||
| 8 | * @copyright Copyright (c) 2025 | ||
| 9 | * | ||
| 10 | */ | ||
| 11 | |||
| 1 | #ifndef __VXGG_REWRITE___THREADPOOL_H___193271180830131___ | 12 | #ifndef __VXGG_REWRITE___THREADPOOL_H___193271180830131___ |
| 2 | #define __VXGG_REWRITE___THREADPOOL_H___193271180830131___ 1 | 13 | #define __VXGG_REWRITE___THREADPOOL_H___193271180830131___ 1 |
| 3 | 14 | ||
