diff options
| -rw-r--r-- | src/ll.c | 12 | ||||
| -rw-r--r-- | src/ll.h | 3 | ||||
| -rw-r--r-- | src/shared.h | 5 | ||||
| -rw-r--r-- | src/threadpool.c | 95 |
4 files changed, 107 insertions, 8 deletions
| @@ -196,4 +196,16 @@ int dlinkedlist_foreach(dlinkedlist *ll, int (*callback)(void*)) { | |||
| 196 | callback(p->data); | 196 | callback(p->data); |
| 197 | 197 | ||
| 198 | return 0; | 198 | return 0; |
| 199 | } | ||
| 200 | |||
| 201 | void * dlinkedlist_poplast(dlinkedlist *ll) { | ||
| 202 | if(!ll) | ||
| 203 | RETURNWERR(EINVAL, NULL); | ||
| 204 | if(dlinkedlist_isempty(ll)) | ||
| 205 | RETURNWERR(ENODATA, NULL); | ||
| 206 | |||
| 207 | void *data = dlinkedlist_get(ll, ll->size - 1); | ||
| 208 | dlinkedlist_remove(ll, ll->size - 1); | ||
| 209 | |||
| 210 | return data; | ||
| 199 | } \ No newline at end of file | 211 | } \ No newline at end of file |
| @@ -25,6 +25,7 @@ typedef void (*dll_freecb)(void*); | |||
| 25 | typedef struct dlinked dlinkedlist; | 25 | typedef struct dlinked dlinkedlist; |
| 26 | 26 | ||
| 27 | #ifndef __VXGG_REWRITE___LL_INTERNAL___ | 27 | #ifndef __VXGG_REWRITE___LL_INTERNAL___ |
| 28 | |||
| 28 | dlinkedlist * dlinkedlist_init(void); | 29 | dlinkedlist * dlinkedlist_init(void); |
| 29 | void dlinkedlist_free(dlinkedlist *ll); | 30 | void dlinkedlist_free(dlinkedlist *ll); |
| 30 | int dlinkedlist_append(dlinkedlist * const ll, void *data, dll_freecb fcb); | 31 | int dlinkedlist_append(dlinkedlist * const ll, void *data, dll_freecb fcb); |
| @@ -32,11 +33,13 @@ int dlinkedlist_prepend(dlinkedlist * const ll, void *data, dll_freecb fcb); | |||
| 32 | int dlinkedlist_insert(dlinkedlist * const ll, void *data, dll_freecb fcb, int index); | 33 | int dlinkedlist_insert(dlinkedlist * const ll, void *data, dll_freecb fcb, int index); |
| 33 | void* dlinkedlist_get(const dlinkedlist * const ll, int index); | 34 | void* dlinkedlist_get(const dlinkedlist * const ll, int index); |
| 34 | int dlinkedlist_remove(dlinkedlist * const ll, int index); | 35 | int dlinkedlist_remove(dlinkedlist * const ll, int index); |
| 36 | void * dlinkedlist_poplast(dlinkedlist *ll); | ||
| 35 | 37 | ||
| 36 | int dlinkedlist_size(const dlinkedlist * const ll); | 38 | int dlinkedlist_size(const dlinkedlist * const ll); |
| 37 | #define dlinkedlist_isempty(ll) (dlinkedlist_size((ll)) == 0) | 39 | #define dlinkedlist_isempty(ll) (dlinkedlist_size((ll)) == 0) |
| 38 | 40 | ||
| 39 | int dlinkedlist_foreach(dlinkedlist *ll, int (*callback)(void*)); | 41 | int dlinkedlist_foreach(dlinkedlist *ll, int (*callback)(void*)); |
| 42 | |||
| 40 | #endif | 43 | #endif |
| 41 | 44 | ||
| 42 | #endif \ No newline at end of file | 45 | #endif \ No newline at end of file |
diff --git a/src/shared.h b/src/shared.h index 1a629e6..3b0a5f7 100644 --- a/src/shared.h +++ b/src/shared.h | |||
| @@ -76,10 +76,13 @@ int cleanup_fire(cleanup * const loc); | |||
| 76 | 76 | ||
| 77 | /* Cleanup environment creator. Automatically defines the variables `__CLEANUP`, `__CLEANUP_FUNCS`, and `__CLEANUP_ARGS` and initializes | 77 | /* Cleanup environment creator. Automatically defines the variables `__CLEANUP`, `__CLEANUP_FUNCS`, and `__CLEANUP_ARGS` and initializes |
| 78 | // via `cleanup_init()` using these variables. */ | 78 | // via `cleanup_init()` using these variables. */ |
| 79 | #define cleanup_create(size) \ | 79 | #define cleanup_CREATE(size) \ |
| 80 | cleanup __CLEANUP; \ | 80 | cleanup __CLEANUP; \ |
| 81 | cleanup_callback __CLEANUP_FUNCS[(size)]; \ | 81 | cleanup_callback __CLEANUP_FUNCS[(size)]; \ |
| 82 | void *__CLEANUP_ARGS[(size)]; \ | 82 | void *__CLEANUP_ARGS[(size)]; \ |
| 83 | cleanup_init(&__CLEANUP, (size), __CLEANUP_FUNCS, __CLEANUP_ARGS) | 83 | cleanup_init(&__CLEANUP, (size), __CLEANUP_FUNCS, __CLEANUP_ARGS) |
| 84 | 84 | ||
| 85 | #define cleanup_REGISTER(cb, arg) cleanup_register(&__CLEANUP, (cb), (arg)) | ||
| 86 | #define cleanup_CNDREGISTER(flag, cb, arg) cleanup_cndregister(&__CLEANUP, (flag), (cb), (arg)) | ||
| 87 | |||
| 85 | #endif \ No newline at end of file | 88 | #endif \ No newline at end of file |
diff --git a/src/threadpool.c b/src/threadpool.c index e230ebb..808dd5d 100644 --- a/src/threadpool.c +++ b/src/threadpool.c | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | #include "ll.h" | 5 | #include "ll.h" |
| 6 | 6 | ||
| 7 | #include <asm-generic/errno-base.h> | ||
| 7 | #include <threads.h> | 8 | #include <threads.h> |
| 8 | #include <stdlib.h> | 9 | #include <stdlib.h> |
| 9 | #include <errno.h> | 10 | #include <errno.h> |
| @@ -161,34 +162,34 @@ static void ___ucleanup_dll(void *dll) { | |||
| 161 | 162 | ||
| 162 | cqueue * cqueue_init(int mtx_type) { | 163 | cqueue * cqueue_init(int mtx_type) { |
| 163 | unsigned char flag = 0; | 164 | unsigned char flag = 0; |
| 164 | cleanup_create(10); | 165 | cleanup_CREATE(10); |
| 165 | 166 | ||
| 166 | cqueue *cq = VALLOC(1, sizeof(*cq)); | 167 | cqueue *cq = VALLOC(1, sizeof(*cq)); |
| 167 | if(!cq) | 168 | if(!cq) |
| 168 | return NULL; | 169 | return NULL; |
| 169 | cleanup_register(&__CLEANUP, free, cq); | 170 | cleanup_REGISTER(free, cq); |
| 170 | 171 | ||
| 171 | cq->mutex = VALLOC(1, sizeof(*(cq->mutex))); | 172 | cq->mutex = VALLOC(1, sizeof(*(cq->mutex))); |
| 172 | if(!(cq->mutex)) | 173 | if(!(cq->mutex)) |
| 173 | flag++; | 174 | flag++; |
| 174 | cleanup_cndregister(&__CLEANUP, flag, free, cq->mutex); | 175 | cleanup_CNDREGISTER(flag, free, cq->mutex); |
| 175 | 176 | ||
| 176 | if(!flag && mtx_init(cq->mutex, mtx_type) != thrd_success) | 177 | if(!flag && mtx_init(cq->mutex, mtx_type) != thrd_success) |
| 177 | flag++; | 178 | flag++; |
| 178 | cleanup_cndregister(&__CLEANUP, flag, ___ucleanup_mtxd, cq->mutex); | 179 | cleanup_CNDREGISTER(flag, ___ucleanup_mtxd, cq->mutex); |
| 179 | 180 | ||
| 180 | if(!flag && !(cq->conditional = VALLOC(1, sizeof(*(cq->conditional))))) | 181 | if(!flag && !(cq->conditional = VALLOC(1, sizeof(*(cq->conditional))))) |
| 181 | flag++; | 182 | flag++; |
| 182 | cleanup_cndregister(&__CLEANUP, flag, free, cq->conditional); | 183 | cleanup_CNDREGISTER(flag, free, cq->conditional); |
| 183 | 184 | ||
| 184 | if(!flag && cnd_init(cq->conditional) != thrd_success) | 185 | if(!flag && cnd_init(cq->conditional) != thrd_success) |
| 185 | flag++; | 186 | flag++; |
| 186 | cleanup_cndregister(&__CLEANUP, flag, ___ucleanup_cndd, cq->conditional); | 187 | cleanup_CNDREGISTER(flag, ___ucleanup_cndd, cq->conditional); |
| 187 | 188 | ||
| 188 | cq->list = dlinkedlist_init(); | 189 | cq->list = dlinkedlist_init(); |
| 189 | if(!flag && !cq->list) | 190 | if(!flag && !cq->list) |
| 190 | flag++; | 191 | flag++; |
| 191 | cleanup_cndregister(&__CLEANUP, flag, ___ucleanup_dll, cq->list); | 192 | cleanup_CNDREGISTER(flag, ___ucleanup_dll, cq->list); |
| 192 | 193 | ||
| 193 | if(flag) | 194 | if(flag) |
| 194 | cleanup_fire(&__CLEANUP); | 195 | cleanup_fire(&__CLEANUP); |
| @@ -210,4 +211,84 @@ void cqueue_free(cqueue *cq) { | |||
| 210 | free(cq); | 211 | free(cq); |
| 211 | 212 | ||
| 212 | return; | 213 | return; |
| 214 | } | ||
| 215 | |||
| 216 | int cqueue_append(cqueue * const cq, task *tsk) { | ||
| 217 | if(!cq || !tsk) | ||
| 218 | RETURNWERR(EINVAL, -1); | ||
| 219 | |||
| 220 | mtx_lock(cq->mutex); | ||
| 221 | dlinkedlist_append(cq->list, tsk, free); | ||
| 222 | mtx_unlock(cq->mutex); | ||
| 223 | cnd_signal(cq->conditional); | ||
| 224 | |||
| 225 | return 0; | ||
| 226 | } | ||
| 227 | |||
| 228 | int cqueue_prepend(cqueue * const cq, task *tsk) { | ||
| 229 | if(!cq || !tsk) | ||
| 230 | RETURNWERR(EINVAL, -1); | ||
| 231 | |||
| 232 | mtx_lock(cq->mutex); | ||
| 233 | dlinkedlist_prepend(cq->list, tsk, free); | ||
| 234 | mtx_unlock(cq->mutex); | ||
| 235 | cnd_signal(cq->conditional); | ||
| 236 | |||
| 237 | return 0; | ||
| 238 | } | ||
| 239 | |||
| 240 | int cqueue_insert(cqueue * const cq, task *tsk, int index) { | ||
| 241 | if(!cq || !tsk || index < 0) // Can't check to see if the index is too high without locking the mutex first | ||
| 242 | RETURNWERR(EINVAL, -1); | ||
| 243 | |||
| 244 | mtx_lock(cq->mutex); | ||
| 245 | dlinkedlist_insert(cq->list, tsk, free, index); | ||
| 246 | mtx_unlock(cq->mutex); | ||
| 247 | cnd_signal(cq->conditional); | ||
| 248 | |||
| 249 | return 0; | ||
| 250 | } | ||
| 251 | |||
| 252 | int cqueue_size(cqueue const * const cq) { | ||
| 253 | if(!cq) | ||
| 254 | RETURNWERR(EINVAL, -1); | ||
| 255 | |||
| 256 | mtx_lock(cq->mutex); | ||
| 257 | int retval = dlinkedlist_size(cq->list); | ||
| 258 | mtx_unlock(cq->mutex); | ||
| 259 | |||
| 260 | return retval; | ||
| 261 | } | ||
| 262 | |||
| 263 | int cqueue_isempty(cqueue const * const cq) { | ||
| 264 | return (cqueue_size(cq) == 0); | ||
| 265 | } | ||
| 266 | |||
| 267 | int cqueue_trypop(cqueue * const cq, task **ret) { | ||
| 268 | if(!cq || !ret || !*ret) | ||
| 269 | RETURNWERR(EINVAL, -1); | ||
| 270 | |||
| 271 | int retval = 0; | ||
| 272 | |||
| 273 | mtx_lock(cq->mutex); | ||
| 274 | if(!dlinkedlist_isempty(cq->list)) { | ||
| 275 | *ret = (task*)dlinkedlist_poplast(cq->list); | ||
| 276 | retval = 1; | ||
| 277 | } | ||
| 278 | mtx_unlock(cq->mutex); | ||
| 279 | |||
| 280 | return retval; | ||
| 281 | } | ||
| 282 | |||
| 283 | int cqueue_waitpop(cqueue * const cq, task **ret) { | ||
| 284 | if(!cq || !ret || !*ret) | ||
| 285 | RETURNWERR(EINVAL, -1); | ||
| 286 | |||
| 287 | mtx_lock(cq->mutex); | ||
| 288 | while(!dlinkedlist_isempty(cq->list)) | ||
| 289 | cnd_wait(cq->conditional, cq->mutex); // Unlocks mutex while waiting, acquires lock once waiting is done | ||
| 290 | *ret = dlinkedlist_poplast(cq->list); | ||
| 291 | mtx_unlock(cq->mutex); | ||
| 292 | |||
| 293 | return 0; | ||
| 213 | } \ No newline at end of file | 294 | } \ No newline at end of file |
