From df4c07f5181ce22cf77e2c9eda77697875f19012 Mon Sep 17 00:00:00 2001 From: Dnomd343 Date: Thu, 2 Feb 2023 12:00:40 +0800 Subject: [PATCH] update: show thread id in debug log --- tiny_pool.c | 93 ++++++++++++++++++++++++++++++----------------------- tiny_pool.h | 6 ++-- 2 files changed, 55 insertions(+), 44 deletions(-) diff --git a/tiny_pool.c b/tiny_pool.c index a8b3798..a4ae63c 100644 --- a/tiny_pool.c +++ b/tiny_pool.c @@ -93,22 +93,22 @@ void task_queue_push(pool_t *pool, task_t *task) { task_t* task_queue_pop(pool_t *pool) { // pop one task with blocking wait - printf("try pop one task\n"); + printf("%lu -> try pop one task\n", pthread_self()); pthread_mutex_lock(&pool->task_queue_busy); // lock task queue while (pool->task_queue_front == NULL) { // loop until task queue not empty - printf("pop start wait\n"); + printf("%lu -> pop start wait\n", pthread_self()); // TODO: at EXITING process may receive active broadcast -> we should stop pop task here // should we cancel thread here directly, or return NULL for sub thread loop? pthread_cond_wait(&pool->task_queue_not_empty, &pool->task_queue_busy); // wait new task added - printf("pop exit wait\n"); + printf("%lu -> pop exit wait\n", pthread_self()); } - printf("pop new task\n"); + printf("%lu -> pop new task\n", pthread_self()); bool queue_empty = false; task_t *front = pool->task_queue_front; @@ -121,7 +121,7 @@ task_t* task_queue_pop(pool_t *pool) { // pop one task with blocking wait } --pool->task_queue_size; - printf("pop success -> size = %d\n", pool->task_queue_size); + printf("%lu -> pop success -> size = %d\n", pthread_self(), pool->task_queue_size); pthread_mutex_unlock(&pool->task_queue_busy); // unlock task queue @@ -132,9 +132,6 @@ task_t* task_queue_pop(pool_t *pool) { // pop one task with blocking wait } bool tiny_pool_submit(pool_t *pool, void (*func)(void*), void *arg) { - if (pool->status > RUNNING) { - return false; // adding task is prohibited after STOPPING - } task_t *new_task = (task_t*)malloc(sizeof(task_t)); if (new_task == NULL) { return false; // malloc new task error -> stop submit @@ -142,15 +139,27 @@ bool tiny_pool_submit(pool_t *pool, void (*func)(void*), void *arg) { new_task->func = func; // load custom task new_task->arg = arg; new_task->next = NULL; - task_queue_push(pool, new_task); // push into task queue + + // TODO: warning -> check dead lock here + pthread_mutex_lock(&pool->status_mutex); + if (pool->status > RUNNING) { + free(new_task); + return false; // adding task is prohibited after STOPPING + } else { + task_queue_push(pool, new_task); // push into task queue + } + pthread_mutex_unlock(&pool->status_mutex); return true; // task push success } void* thread_entry(void *pool_ptr) { // main loop for sub thread pool_t *pool = (pool_t*)pool_ptr; + + printf("start thread %lu\n", pthread_self()); + while (pool->status != EXITING) { // loop until enter EXITING mode - printf("sub thread working\n"); + printf("%lu -> sub thread working\n", pthread_self()); task_t *task = task_queue_pop(pool); // pop one task -> blocking function @@ -167,7 +176,7 @@ void* thread_entry(void *pool_ptr) { // main loop for sub thread free(task); // free allocated memory } - printf("sub thread exit\n"); + printf("%lu -> sub thread exit\n", pthread_self()); return NULL; // sub thread exit } @@ -175,62 +184,64 @@ void* thread_entry(void *pool_ptr) { // main loop for sub thread // TODO: should we return a bool value? void tiny_pool_boot(pool_t *pool) { - // TODO: create admin thread - - // TODO: create N work-threads (using N = 8 in dev) - // TODO: avoid booting multi-times + pthread_mutex_lock(&pool->status_mutex); + + if (pool->status != PREPARING) { + pthread_mutex_unlock(&pool->status_mutex); + return; + } pthread_mutex_lock(&pool->task_queue_busy); for (uint32_t i = 0; i < pool->thread_num; ++i) { - - printf("start thread %d\n", i); - pthread_create(&(pool->threads[i]), NULL, thread_entry, (void*)pool); - } printf("thread boot complete\n"); - pthread_mutex_lock(&pool->status_mutex); pool->status = RUNNING; - pthread_mutex_unlock(&pool->status_mutex); pthread_mutex_unlock(&pool->task_queue_busy); + pthread_mutex_unlock(&pool->status_mutex); } +bool tiny_pool_join(pool_t *pool) { -//void tiny_pool_kill(pool_t *pool) { -// -// printf("pool enter EXITING status\n"); -// -// pthread_mutex_lock(&pool->status_changing); -// -// pool->status = EXITING; -// -// pthread_mutex_unlock(&pool->status_changing); -// -//} + // TODO: set status -> JOINING -> avoid submit -void tiny_pool_wait(pool_t *pool) { + // TODO: wait --until--> queue empty - // TODO: wait all tasks exit + // TODO: set status -> EXITING -> some thread may exit - // TODO: check `busy_thread_num` == 0 and queue empty + // TODO: signal broadcast -> wait all thread exit -} -void tiny_pool_join(pool_t *pool) { + printf("start pool join\n"); - // TODO: set status -> JOINING -> avoid submit + pthread_mutex_lock(&pool->status_mutex); - // TODO: wait --until--> queue empty + if (pool->status != RUNNING) { - // TODO: set status -> EXITING -> some thread may exit + pthread_mutex_unlock(&pool->status_mutex); - // TODO: signal broadcast -> wait all thread exit + return false; + } + pool->status = STOPPING; + + + // TODO: join process + + return true; } + +//void tiny_pool_wait(pool_t *pool) { + + // TODO: wait all tasks exit + + // TODO: check `busy_thread_num` == 0 and queue empty + +//} diff --git a/tiny_pool.h b/tiny_pool.h index 34d643d..a9b5497 100644 --- a/tiny_pool.h +++ b/tiny_pool.h @@ -92,10 +92,10 @@ bool tiny_pool_submit(pool_t *pool, void (*func)(void*), void *arg); void tiny_pool_boot(pool_t *pool); /// This function will change the thread pool from `RUNNING` to `STOPPING`, and enter the -/// `EXITING` state when the queue is empty, likewise, if the state is non `RUNNING` when -/// entered, it will also have no effect. All tasks will automatically free resources after +/// `EXITING` state when the queue is empty. If the state is non `RUNNING` when entered, +/// it will return `false` value. All tasks will automatically free resources after /// completion. Note that it is blocking and may take a considerable amount of time. -void tiny_pool_join(pool_t *pool); +bool tiny_pool_join(pool_t *pool); /// It is basically the same as `tiny_pool_join` in function, the difference is that it is /// non-blocking, that is, it will automatically handle the remaining tasks and complete