Skip to content

Commit 3e6498e

Browse files
committed
v.h: v_threadpool: Handle allocation & thread creation failures
Also inlined some trivial helper functions.
1 parent 520e035 commit 3e6498e

File tree

1 file changed

+43
-43
lines changed

1 file changed

+43
-43
lines changed

include/v.h

Lines changed: 43 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -789,21 +789,6 @@ struct v_threadpool {
789789
#include <signal.h>
790790
#endif
791791

792-
static struct v_threadpool_task *s_threadpool_get(v_threadpool *pool) {
793-
if (!pool)
794-
return NULL;
795-
struct v_threadpool_task *task = pool->first;
796-
if (!task)
797-
return NULL;
798-
if (!task->next) {
799-
pool->first = NULL;
800-
pool->last = NULL;
801-
} else {
802-
pool->first = task->next;
803-
}
804-
return task;
805-
}
806-
807792
static void *v_threadpool_worker(void *arg) {
808793
#if !defined(WINDOWS) && !defined(__APPLE__)
809794
/* Block all signals, we linux may deliver them to any thread randomly.
@@ -813,13 +798,21 @@ static void *v_threadpool_worker(void *arg) {
813798
sigprocmask(SIG_SETMASK, &mask, 0);
814799
#endif
815800
v_threadpool *pool = arg;
801+
if (!pool)
802+
return NULL;
816803
while (1) {
817804
v_mutex_lock(pool->mutex);
818805
while (!pool->first && !pool->stop_flag)
819806
v_cond_wait(pool->work_available, pool->mutex);
820807
if (pool->stop_flag)
821808
break;
822-
struct v_threadpool_task *task = s_threadpool_get(pool);
809+
struct v_threadpool_task *task = pool->first;
810+
if (!task->next) {
811+
pool->first = NULL;
812+
pool->last = NULL;
813+
} else {
814+
pool->first = task->next;
815+
}
823816
pool->active_threads++;
824817
v_mutex_release(pool->mutex);
825818
if (task) {
@@ -841,33 +834,42 @@ static void *v_threadpool_worker(void *arg) {
841834
v_threadpool *v_threadpool_create(size_t n_threads) {
842835
if (!n_threads)
843836
n_threads = v_sys_get_cores() + 1;
844-
struct v_threadpool *pool = calloc(1, sizeof(*pool));
845-
pool->alive_threads = n_threads;
846-
pool->mutex = v_mutex_create();
847-
pool->work_available = v_cond_create();
848-
pool->work_ongoing = v_cond_create();
837+
v_threadpool *pool = calloc(1, sizeof(*pool));
838+
if (!pool)
839+
goto fail;
840+
if (!(pool->mutex = v_mutex_create()))
841+
goto fail;
842+
if (!(pool->work_available = v_cond_create()))
843+
goto fail;
844+
if (!(pool->work_ongoing = v_cond_create()))
845+
goto fail;
849846

850847
v_thread_ctx ctx = {
851848
.thread_fn = v_threadpool_worker,
852849
.ctx = pool,
853850
};
854-
for (size_t i = 0; i < pool->alive_threads; ++i) {
855-
v_thread *ret = v_thread_create(ctx, v_thread_type_detached);
856-
if (!ret)
851+
for (size_t i = 0; i < n_threads; ++i) {
852+
v_thread *success = v_thread_create(ctx, v_thread_type_detached);
853+
if (!success)
857854
goto fail;
855+
pool->alive_threads++;
858856
}
859857
return pool;
860858
fail:
861-
v_mutex_destroy(pool->mutex);
862-
v_cond_destroy(pool->work_available);
863-
v_cond_destroy(pool->work_ongoing);
864-
free(pool);
859+
v_threadpool_destroy(pool);
865860
return NULL;
866861
}
867862

868863
void v_threadpool_destroy(v_threadpool *pool) {
869864
if (!pool)
870865
return;
866+
if (!pool->mutex)
867+
goto no_mutex;
868+
if (!pool->work_available)
869+
goto no_work_available;
870+
if (!pool->work_ongoing)
871+
goto no_work_ongoing;
872+
871873
v_mutex_lock(pool->mutex);
872874
/* Clear queued tasks */
873875
struct v_threadpool_task *head = pool->first;
@@ -886,32 +888,30 @@ void v_threadpool_destroy(v_threadpool *pool) {
886888
v_threadpool_wait(pool);
887889

888890
/* Finish up */
889-
v_mutex_destroy(pool->mutex);
890-
v_cond_destroy(pool->work_available);
891891
v_cond_destroy(pool->work_ongoing);
892+
no_work_ongoing:
893+
v_cond_destroy(pool->work_available);
894+
no_work_available:
895+
v_mutex_destroy(pool->mutex);
896+
no_mutex:
892897
free(pool);
893898
}
894899

895-
static struct v_threadpool_task *s_threadpool_task_create(void (*fn)(void *arg), void *arg) {
900+
int v_threadpool_enqueue(v_threadpool *pool, void (*fn)(void *arg), void *arg) {
896901
if (!fn)
897-
return NULL;
902+
return 1;
903+
if (!pool) {
904+
fn(arg);
905+
return 0;
906+
}
898907
struct v_threadpool_task *task = malloc(sizeof(*task));
908+
if (!task)
909+
return 1;
899910
*task = (struct v_threadpool_task){
900911
.fn = fn,
901912
.arg = arg,
902913
.next = NULL,
903914
};
904-
return task;
905-
}
906-
907-
int v_threadpool_enqueue(v_threadpool *pool, void (*fn)(void *arg), void *arg) {
908-
if (!pool && fn) {
909-
fn(arg);
910-
return 0;
911-
}
912-
struct v_threadpool_task *task = s_threadpool_task_create(fn, arg);
913-
if (!task)
914-
return 1;
915915
v_mutex_lock(pool->mutex);
916916
if (!pool->first) {
917917
pool->first = task;

0 commit comments

Comments
 (0)