Record the process of learning the thread pool, the function that the code uses boils down To:
Pthread_mutex_lock
Pthread_mutex_unlock
Pthread_cond_wait
Pthread_cond_signal
Pthread_cond_broadcast
Pthread_create
Pthread_join
The program also uses a linked list,
There is also a knowledge point: any type of data can be of type void,
however, the type of void must be cast before it is Used.
/**author:greens_ren*description: thread Pool *//* header File */#include <pthread.h>#include <stdio.h>/* Begin:add */#include <stdlib.h>#include <unistd.h>#include <assert.h>#include <sys/types.h>/* End:add *//* Data Structure */typedefstruct thread_worker{void * (*worker) (void *arg);void * arg;struct Thread_worker *next;} cthread_worker;typedefstruct thread_pool{pthread_mutex_t queue_lock; pthread_cond_t queue_ready;int max_thread_num; pthread_t *phead_threadid;int cur_queue_size; Cthread_worker *phead;int shutdown;} cthread_pool;/* Global Zone */static Cthread_pool *pool =NULL;/* function */void Pthread_init (int max_thread_num);void *thread_roution (void * arg);void Pthread_add_worker (void * (*worker) (void *arg),void * arg);void Pthread_destroy (void);void* my_process (void *arg);/*main*/int main (Void) {int max_thread_num =3;int worker_num =10;/* Initialize */pthread_init (max_thread_num);/* put into task */int *workernum = (int *) malloc (sizeofInt) * worker_num);int i;For (i =0; I < worker_num; I++) {workernum[i] = i; pthread_add_worker (my_process, &workernum[i]);}/* wait for processing task */sleep (8); Pthread_destroy ();Return0;}void Pthread_init (int Max_thread_num) {pool = (cthread_pool*) malloc (sizeof (cthread_pool));/*free (pool) *//* Begin:modified Initialize the mutex and condition variable */pthread_mutex_init (& (pool->queue_lock),NULL); Pthread_cond_init (& (pool->queue_ready),NULL);/* end:modified *//* Initialize Thread */pool->max_thread_num = max_thread_num; Pool->phead_threadid = (pthread_t *) malloc (sizeof (pthread_t) * max_thread_num);/*free*/int i;For (i =0; I < max_thread_num; i + +) {pthread_create (& (pool->phead_threadid[i]),NULL, thread_roution,NULL); }/* Initialize task wait queue */pool->cur_queue_size =0;Pool->phead = (cthread_worker *) malloc (sizeof (cthread_worker));Pool->phead->next = NULL;/* sin, There's more to consider Here. A pointer is stored in the pool, except that it specifies a list of links */pool->phead =NULL;/* thread pool Destroy flag */pool->shutdown =0;return;}void *thread_roution (void * Arg) {printf ("starting thread 0x%x\n", pthread_self ());While1)/*added threads to run continuously, consider using while (1) to implement */{pthread_mutex_lock (& (pool->queue_lock));/* if no task is currently being processed and the thread pool is not destroyed, wait for the task to be added */If (pool->cur_queue_size = = 0 && pool->shutdown! = 1)While (pool->cur_queue_size = =0 && pool->shutdown! =1)/*modified by*/{Pthread_cond_wait (& (pool->queue_lock), & (pool->queue_ready)); printf"thread 0x%x is waiting\n", pthread_self ()); Pthread_cond_wait (& (pool->queue_ready), & (pool->queue_lock)); }/* If the thread pool has been flagged for destruction, exit the threads */if (pool->shutdown = =1) {pthread_mutex_unlock (& (pool->queue_lock)); printf ("thread 0x%x would exit\n", pthread_self ()); Pthread_exit (NULL); } printf ("thread 0x%x is starting to work\n", pthread_self ());/*assert is a good assistant for debugging, and if it is home, it will print the error message via STDERR and terminate the program */assert (pool->cur_queue_size! =0); Assert (pool->shutdown! =1);/* Start processing tasks in the wait queue *//* callback function */pool->cur_queue_size--; Cthread_worker * worker_waiting = pool->phead; Pool->phead = worker_waiting->next;/* The purpose of this lock is to deal with the task chain list, after processing can be unlocked, so that other threads to process the task linked list */pthread_mutex_unlock (& (pool->queue_lock));/*modified by the beginning of the explanation lock placed behind the callback function, here to do the correction *//* call the callback function to perform the task */(* (worker_waiting->worker)) (worker_waiting->arg);/* Delete the task node already executed in the list */free (worker_waiting); Worker_waiting =NULL; }}void Pthread_add_worker (void * (*worker) (void *arg),void * Arg) {assert (worker! =NULL); Assert (pool->shutdown! =1);/* build a new task insert to the end of the task List */cthread_worker * Worker_insert = (cthread_worker *) malloc (sizeof (cthread_worker));/*free*/worker_insert->worker = worker; Worker_insert->arg = arg; Worker_insert->next =NULL;/* below to process the task chain list, here to lock, protect the linked List. The first time I wrote, I forgot locking. */pthread_mutex_lock (& (pool->queue_lock)); cthread_worker* Phead_worker = pool->phead;/* the head pointer of a linked list is actually a null pointer at first, so if null, the node address of the build will be assigned to it directly.If (phead_worker! =NULL) {While (phead_worker->next! =NULL) {phead_worker = phead_worker->next;} Phead_worker->next = worker_insert;/* This adds the newly built task node to the end of the list of waiting tasks */}else {pool->phead = worker_insert;} assert (pool->phead! =NULL);/* check here to wait for the list is not empty */pool->cur_queue_size++;/* Synchronize the length of the wait queue to modify the information */pthread_mutex_unlock (& (pool->queue_lock));/* wait for the queue to add a new task, here to wake up the thread to handle, if the wireless path sleep, This statement is invalid */pthread_cond_signal (& (pool->queue_ready));return;}void Pthread_destroy (Void) {If (pool->shutdown) {Return/* prevent multiple calls here */}/* This will destroy the thread pool tag First */pool->shutdown =1;/* Wake up so wait for thread, thread pool to be destroyed */pthread_cond_broadcast (& (pool->queue_ready));/* block wait for thread thread to quit or become a Zombie.int i;For (i =0; I < pool->max_thread_num; i + +) {pthread_join (pool->phead_threadid[i],NULL); }/* Release thread number storage footprint */free (pool->phead_threadid); Pool->phead_threadid =NULL;/* release task waiting queue */cthread_worker *pworker_del = NULL; while (pool->phead! = null) {pworker_del = pool->phead; pool->phead = pool->phead->next; Free (pworker_del); Pworker_del = null;} /* destroy the condition variables and mutexes, and just start forgetting the */pthread_mutex_destroy (& (pool->queue_lock)); pthread_ Cond_destroy (& (pool->queue_ready)); /* release thread pool */free (pool), pool = null; return;} void *my_process (void * Arg) {printf ( "thread is 0x%x, working ont task%d\n", pthread_self (), * (int *) arg); Sleep (1); return;}
Thread Pool Learning notes