|  |  | @ -9,55 +9,94 @@ pool_t* tiny_pool_create(uint32_t size) { | 
			
		
	
		
			
				
					|  |  |  |         pool->threads[i] = 0; | 
			
		
	
		
			
				
					|  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     pool->status = PREPARING; | 
			
		
	
		
			
				
					|  |  |  |     pthread_mutex_init(&pool->busy_thread_num_mutex, NULL); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     pool->task_queue_front = NULL; | 
			
		
	
		
			
				
					|  |  |  |     pool->task_queue_rear = NULL; | 
			
		
	
		
			
				
					|  |  |  |     pool->task_queue_size = 0; | 
			
		
	
		
			
				
					|  |  |  |     pthread_mutex_init(&pool->task_queue_busy, NULL); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | //    pthread_cond_init(&pool->task_queue_empty, NULL);
 | 
			
		
	
		
			
				
					|  |  |  |     pthread_cond_init(&pool->task_queue_not_empty, NULL); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     return pool; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | void tiny_pool_submit(pool_t *pool, void* (*func)(void*), void *arg) { | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     task_t *new_task = (task_t*)malloc(sizeof(task_t)); | 
			
		
	
		
			
				
					|  |  |  | void task_queue_push(pool_t *pool, task_t *task) { | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     new_task->func = func; | 
			
		
	
		
			
				
					|  |  |  |     new_task->arg = arg; | 
			
		
	
		
			
				
					|  |  |  |     new_task->next = NULL; | 
			
		
	
		
			
				
					|  |  |  |     printf("push one task\n"); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     // TODO: lock task queue
 | 
			
		
	
		
			
				
					|  |  |  |     pthread_mutex_lock(&pool->task_queue_busy); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     if (pool->task_queue_rear == NULL) { // queue without element
 | 
			
		
	
		
			
				
					|  |  |  |     if (pool->task_queue_rear == NULL) { // empty queue
 | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         pool->task_queue_front = new_task; | 
			
		
	
		
			
				
					|  |  |  |         pool->task_queue_rear = new_task; | 
			
		
	
		
			
				
					|  |  |  |         pool->task_queue_front = task; | 
			
		
	
		
			
				
					|  |  |  |         pool->task_queue_rear = task; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     } else { // queue emplace back
 | 
			
		
	
		
			
				
					|  |  |  |     } else { // queue with element
 | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         pool->task_queue_rear->next = new_task; | 
			
		
	
		
			
				
					|  |  |  |         pool->task_queue_rear = new_task; | 
			
		
	
		
			
				
					|  |  |  |         pool->task_queue_rear->next = task; | 
			
		
	
		
			
				
					|  |  |  |         pool->task_queue_rear = task; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     ++pool->task_queue_size; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     // TODO: unlock task queue
 | 
			
		
	
		
			
				
					|  |  |  |     pthread_mutex_unlock(&pool->task_queue_busy); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     printf("push success\n"); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     if (pool->status == RUNNING) { | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         // TODO: send cond signal
 | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         printf("send signal -> queue not empty\n"); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         pthread_cond_signal(&pool->task_queue_not_empty); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | void tiny_pool_submit(pool_t *pool, void (*func)(void*), void *arg) { | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     task_t *new_task = (task_t*)malloc(sizeof(task_t)); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     new_task->func = func; | 
			
		
	
		
			
				
					|  |  |  |     new_task->arg = arg; | 
			
		
	
		
			
				
					|  |  |  |     new_task->next = NULL; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     // TODO: new task push into task queue
 | 
			
		
	
		
			
				
					|  |  |  |     task_queue_push(pool, new_task); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | task_t* task_queue_pop(pool_t *pool) { | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     printf("try pop one task\n"); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     // TODO: lock task queue
 | 
			
		
	
		
			
				
					|  |  |  |     pthread_mutex_lock(&pool->task_queue_busy); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     while (pool->task_queue_front == NULL) { | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     if (pool->task_queue_front == NULL) { | 
			
		
	
		
			
				
					|  |  |  |         printf("pop enter wait\n"); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         return NULL; // pop failed -> empty queue
 | 
			
		
	
		
			
				
					|  |  |  |         // TODO: wait new task added
 | 
			
		
	
		
			
				
					|  |  |  |         pthread_cond_wait(&pool->task_queue_not_empty, &pool->task_queue_busy); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     task_t *tmp = pool->task_queue_front; | 
			
		
	
		
			
				
					|  |  |  |     printf("pop exit wait\n"); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     task_t *front = pool->task_queue_front; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     if (pool->task_queue_front == pool->task_queue_rear) { | 
			
		
	
		
			
				
					|  |  |  |     if (pool->task_queue_front == pool->task_queue_rear) { // only one element
 | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         // queue is empty now
 | 
			
		
	
		
			
				
					|  |  |  |         pool->task_queue_front = NULL; | 
			
		
	
	
		
			
				
					|  |  | @ -65,18 +104,21 @@ task_t* task_queue_pop(pool_t *pool) { | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     } else { | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         pool->task_queue_front = tmp->next; | 
			
		
	
		
			
				
					|  |  |  |         pool->task_queue_front = front->next; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     // TODO: unlock task queue
 | 
			
		
	
		
			
				
					|  |  |  |     pthread_mutex_unlock(&pool->task_queue_busy); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     return tmp; | 
			
		
	
		
			
				
					|  |  |  |     printf("pop success\n"); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     return front; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | void* thread_working() { | 
			
		
	
		
			
				
					|  |  |  | void* thread_entry(void *pool_ptr) { | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     // TODO: main loop for one thread
 | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  | @ -85,6 +127,23 @@ void* thread_working() { | 
			
		
	
		
			
				
					|  |  |  |     // TODO: pop one task --failed--> blocking wait
 | 
			
		
	
		
			
				
					|  |  |  |     //                    --success--> start running and then free task_t
 | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     pool_t *pool = (pool_t*)pool_ptr; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     while (pool->status != EXITING) { | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         printf("thread working\n"); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         task_t *task = task_queue_pop(pool); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         // task working
 | 
			
		
	
		
			
				
					|  |  |  |         task->func(task->arg); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         free(task); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     printf("sub thread exit\n"); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     return NULL; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
	
		
			
				
					|  |  | @ -96,5 +155,24 @@ void tiny_pool_boot(pool_t *pool) { | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     // TODO: create N work-threads (using N = 8 in dev)
 | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     // TODO: avoid booting multi-times
 | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     pthread_mutex_lock(&pool->task_queue_busy); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     for (uint32_t i = 0; i < 8; ++i) { | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         printf("start thread %d\n", i); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         pthread_create(&(pool->threads[i]), NULL, thread_entry, (void*)pool); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     printf("thread boot complete\n"); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     pool->status = RUNNING; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     pthread_mutex_unlock(&pool->task_queue_busy); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  | 
 |