Header file Head.h
#ifndef __threadpool_h_#define __threadpool_h_typedef struct threadpool_t threadpool_t;/** * @function Threadpool_ Create * @descCreates a threadpool_t object. * @param thr_num Thread num * @param max_thr_num max thread size * @param queue_max_size size of the queue. * @return A newly created thread pool or NULL */threadpool_t *threadpool_create (int min_thr_num, int max_thr_num, int queu e_max_size)/** * @function Threadpool_add * @desc Add a new task in the queue of a thread pool * @param pool thread P Ool to which add the task. * @param function Pointer to the function, that would perform the task. * @param argument argument to being passed to the function. * @return 0 if all goes well,else-1 */int threadpool_add (threadpool_t *pool, void* (*function) (void *arg), void *arg);/** * @function Threadpool_destroy * @desc Stops and destroys a thread pool. * @param pool Thread pool to destroy. * @return 0 if destory success else-1 */int Threadpool_destroy (threadpool_t *pool);/** * @desc gET the thread num * @pool Pool ThreadPool * @return # of the thread */int threadpool_all_threadnum (threadpool_t *pool);/** * desc Get the busy thread num * @param pool ThreadPool * Return # of the busy thread */int threadpool_busy_threadnum (THR eadpool_t *pool); #endif
Main.c
#include <stdlib.h> #include <pthread.h> #include <unistd.h> #include <assert.h> #include < stdio.h> #include <string.h> #include <signal.h> #include <errno.h> #include "threadpool.h" # Define Default_time/*10s Detection once */#define MIN_WAIT_TASK_NUM 10/* If queue_size > Min_wait_tas K_num add a new thread to the thread pool */#define DEFAULT_THREAD_VARY 10/* Each time the number of threads created and destroyed */#define TRUE 1#define false 0typedef struct { void * (*function) (void *); /* function pointer, callback function */void *arg; /* The parameters of the above function */} threadpool_task_t; /* Each sub-thread task structure body *//* describes thread pool related information */struct threadpool_t {pthread_mutex_t lock; /* For locking the structure */pthread_mutex_t thread_counter; /* Record the number of busy threads de-busy_thr_num */pthread_cond_t queue_not_full; /* When the task queue is full, the thread that added the task is blocked, waiting for this condition variable */pthread_cond_t queue_not_empty; /* When the task queue is not empty, notify the thread waiting for the task */pthread_t *threads; /* Store the TID for each thread in the thread pool. Array */Pthread_t Adjust_tid; /* Save admin thread tid */threadpool_task_t *task_queue; /* Task Queue */int min_thr_num; /* thread pool minimum number of threads */int max_thr_num; /* thread pool maximum thread count */int live_thr_num; /* Current number of surviving threads */int busy_thr_num; /* Number of busy threads */int wait_exit_thr_num; /* Number of threads to destroy */int queue_front; /* Task_queue Team head subscript */int queue_rear; /* Task_queue tail subscript */int queue_size; /* Number of actual tasks in Task_queue team */int queue_max_size; /* Task_queue queue can hold the maximum number of tasks */int shutdown; /* flag bit, thread pool usage state, true or false */};/** * @function void *threadpool_thread (void *threadpool) * @desc the worker thread * @param ThreadPool the pool which own the thread */void *threadpool_thread (void *threadpool);/** * @function void *adjust_thread ( void *threadpool); * @desc Manager Thread * @param threadpool the ThreadPool */void *adjust_thread (void *threadpool);/** * Check a thread is Alive */int is_thread_alive (pthread_t tid); int Threadpool_free (threadpool_t *poo l); threadpool_t *threadpool_create (int min_thr_num, int max_thr_num, int queue_max_size) {int i; threadpool_t *pool = NULL; Do {if (pool = (threadpool_t *) malloc (sizeof (threadpool_t)) = = NULL) {printf ("malloc ThreadPool FAI L "); break;/* jump out do while*/} pool->min_thr_num = Min_thr_num; Pool->max_thr_num = Max_thr_num; Pool->busy_thr_num = 0; Pool->live_thr_num = Min_thr_num; /* Number of active threads initial value = minimum number of threads */pool->queue_size = 0; /* There are 0 products */pool->queue_max_size = queue_max_size; Pool->queue_front = 0; pool->queue_rear = 0; Pool->shutdown = false; /* Do not close the thread pool */* to open up space for the working thread array based on the maximum number of threads, and clear 0 */pool->threads = (pthread_t *) malloc (sizeof (pthread_t) *max_ Thr_num); if (pool->threads = = NULL) {printf ("malloc threads Fail"); Break } memset (pool->threads, 0, sizeof (pthread_t) *max_thr_num); /* Queue Open space */Pool->task_queue = (threadpool_task_t *) malloc (sizeof (threadpool_task_t) *queue_max_size); if (Pool->task_queue = = NULL) {printf ("malloc task_queue fail"); Break }/* Initialize mutex, condition variable */if (Pthread_mutex_init (& (Pool->lock), NULL)! = 0 | | pthread_mutex_ Init (& (Pool->thread_counter), NULL)! = 0 | | Pthread_cond_init (& (Pool->queue_not_empty), NULL)! = 0 | | Pthread_cond_init (& (Pool->queue_not_full), NULL)! = 0) {printf ("Init the Lock or cond fail"); Break }/* Start min_thr_num work thread */for (i = 0; i < Min_thr_num; i++) {Pthread_create (& ( Pool->threads[i]), NULL, Threadpool_thread, (void *) pool);/*pool points to the current thread pool */printf ("Start Thread 0x%x...\n", (unsigned int) pool->threads[i]); } pthread_create (& (Pool->adjust_tid), NULL, Adjust_thread, (void *) pool);/* Start the manager thread */return pool; } while (0); Threadpool_free (pool); /* When the preceding code call fails, free the poll storage space */return NULL;} /* Add a task to the thread pool */int threadpool_add (threadpool_t *pool, void* (*function) (void *arg), void *arg) {Pthread_mutex_lock (&A MP; (Pool->lock)); /* = = True, queue is full, wait is blocked */while ((pool->queue_size = = pool->queue_max_size) && (!pool->shutdown)) { Pthread_cond_wait (& (Pool->queue_not_full), & (Pool->lock)); } if (Pool->shutdown) {Pthread_mutex_unlock (& (Pool->lock)); }/* Clears the parameters of the callback function called by the worker thread Arg */if (pool->task_queue[pool->queue_rear].arg! = NULL) {Free (pool->task _QUEUE[POOL->QUEUE_REAR].ARG); Pool->task_queue[pool->queue_rear].arg = NULL; }/* Add task to Task queue */pool->tAsk_queue[pool->queue_rear].function = function; Pool->task_queue[pool->queue_rear].arg = arg; Pool->queue_rear = (pool->queue_rear + 1)% pool->queue_max_size; /* tail pointer movement, analog ring */pool->queue_size++; /* After the task is added, the queue is not empty, and the thread that waits for processing tasks in the thread pool is awakened */pthread_cond_signal (& (Pool->queue_not_empty)); Pthread_mutex_unlock (& (Pool->lock)); return 0;} /* Each worker thread in the thread pool */void *threadpool_thread (void *threadpool) {threadpool_t *pool = (threadpool_t *) ThreadPool; threadpool_task_t task; while (true) {/* Lock must be taken-to-wait on conditional variable/* * Just create the thread, wait for tasks in the task queue, or block wait for tasks in the task queue before Wake-Up Reception task */Pthread_mutex_lock (& (Pool->lock)); /*queue_size = = 0 indicates no task, the wait is blocked on the condition variable, if there is a task, skip the while*/while ((pool->queue_size = = 0) && (!pool->s Hutdown) {printf ("Thread 0x%x is waiting\n", (unsigned int) pthread_self ()); Pthread_cond_wait (& (Pool->queue_not_empty), & (POol->lock)); /* Clears the specified number of idle threads, if the number of threads to end is greater than 0, end thread */if (Pool->wait_exit_thr_num > 0) {pool->wait_exit_t hr_num--; /* If the number of thread constructor threads is greater than the minimum value, you can end the current thread */if (Pool->live_thr_num > Pool->min_thr_num) {prin TF ("Thread 0x%x is exiting\n", (unsigned int) pthread_self ()); pool->live_thr_num--; Pthread_mutex_unlock (& (Pool->lock)); Pthread_exit (NULL); }}}//If you specify true, to close each thread of the line constructor, self-exits processing */if (Pool->shutdown) {pthread_mutex_ Unlock (& (Pool->lock)); printf ("Thread 0x%x is exiting\n", (unsigned int) pthread_self ()); Pthread_exit (NULL); /* thread ends itself */}/* Get task from Task queue, is an out of team operation */task.function = Pool->task_queue[pool->queue_front].func tion; Task.arg = pool->task_queue[pool->queue_front].arg; Pool->queue_front = (pool->queue_front + 1)% pool->queue_max_size; /* Out of the team, simulate the ring queue */pool->queue_size--; /* Notifications can have new tasks added in */Pthread_cond_broadcast (& (Pool->queue_not_full)); /* The thread pool is released immediately after the task is removed/Pthread_mutex_unlock (& (Pool->lock)); /* Perform task */printf ("Thread 0x%x start working\n", (unsigned int) pthread_self ()); Pthread_mutex_lock (& (Pool->thread_counter)); /* Busy number of threads variable */pool->busy_thr_num++; /* Number of busy threads +1*/Pthread_mutex_unlock (& (Pool->thread_counter)); (* (task.function)) (Task.arg); /* Perform callback function task *///task.function (TASK.ARG); /* Perform a callback function task//////* Task End processing */printf ("Thread 0x%x End working\n", (unsigned int) pthread_self ()); Pthread_mutex_lock (& (Pool->thread_counter)); pool->busy_thr_num--; /* Dispose of a task, number of busy states Threads -1*/Pthread_mutex_unlock (& (Pool->thread_counter)); } pthread_exit (NULL);} /* Manage thread */void *adjust_thread (void *threadpool) {int i; threadpool_t *pool = (threadpool_t *) ThreadPool; while (!pool->shutdown) {sleep (default_time); /* Timed to thread pool management */Pthread_mutex_lock (& (Pool->lock)); int queue_size = pool->queue_size; /* Focus on tasks */int live_thr_num = pool->live_thr_num; /* Number of surviving threads */Pthread_mutex_unlock (& (Pool->lock)); Pthread_mutex_lock (& (Pool->thread_counter)); int busy_thr_num = pool->busy_thr_num; /* Number of busy threads */Pthread_mutex_unlock (& (Pool->thread_counter)); /* Create a new threading algorithm: The number of tasks is greater than the minimum number of thread pools, and the number of threads surviving is less than the maximum thread count: 30>=10 && 40<100*/if (queue_size >= min_wait_task_n UM && Live_thr_num < Pool->max_thr_num) {Pthread_mutex_lock (& (Pool->lock)); int add = 0; /* Add Default_thread threads at a time */for (i = 0; i < pool->max_thr_num && Add < Default_thread_vary && Pool->live_thr_num < pool->max_thr_num; i++) {if (pool->threads[i] = = 0 | |!is_thread_alive (pool->threads[i])) {Pthread_ Create (& (Pool->threads[i]), NULL, Threadpool_thread, (void *) pool); add++; pool->live_thr_num++; }} pthread_mutex_unlock (& (Pool->lock)); }/* Destroys redundant idle threading algorithm: The busy thread X2 is less than the number of surviving threads and the number of surviving threads is greater than the minimum number of threads */if ((Busy_thr_num * 2) < Live_thr_num && Live_thr_num > Pool->min_thr_num) {/* Destroy Default_thread threads one at a time, at random 10 */Pthread_mutex_lock (& amp; (pool->lock)); Pool->wait_exit_thr_num = default_thread_vary; /* Number of threads to destroy setis ten */Pthread_mutex_unlock (& (Pool->lock)); for (i = 0; i < default_thread_vary; i++) {/* Notifies threads that are idle, they will terminate by themselves */pthread_cond_signal (& (Pool->queue_not_empty)); }}} return NULL;} int Threadpool_destroy (threadpool_t *pool) {int i; if (pool = = NULL) {return-1; } Pool->shutdown = true; /* First destroy the management thread */Pthread_join (Pool->adjust_tid, NULL); for (i = 0; i < pool->live_thr_num; i++) {/* Notifies all idle threads */Pthread_cond_broadcast (& (Pool->queue_n Ot_empty)); } for (i = 0; i < pool->live_thr_num; i++) {pthread_join (pool->threads[i], NULL); } threadpool_free (pool); return 0;} int Threadpool_free (threadpool_t *pool) {if (pool = = NULL) {return-1; } if (Pool->task_queue) {free (pool->task_queue); } if (pool->threads) {free (pool->threads); Pthread_mutex_lock (& (POOL->lock)); Pthread_mutex_destroy (& (Pool->lock)); Pthread_mutex_lock (& (Pool->thread_counter)); Pthread_mutex_destroy (& (Pool->thread_counter)); Pthread_cond_destroy (& (Pool->queue_not_empty)); Pthread_cond_destroy (& (Pool->queue_not_full)); } free (pool); Pool = NULL; return 0;} int Threadpool_all_threadnum (threadpool_t *pool) {int all_threadnum =-1; Pthread_mutex_lock (& (Pool->lock)); All_threadnum = pool->live_thr_num; Pthread_mutex_unlock (& (Pool->lock)); return all_threadnum;} int Threadpool_busy_threadnum (threadpool_t *pool) {int busy_threadnum =-1; Pthread_mutex_lock (& (Pool->thread_counter)); Busy_threadnum = pool->busy_thr_num; Pthread_mutex_unlock (& (Pool->thread_counter)); return busy_threadnum;} int is_thread_alive (pthread_t tid) {int kill_rc = Pthread_kill (tid, 0); Send signal number NO. 0 to test if the thread survives if (KILL_RC = = Esrch) {return false; } return true;} /* Test */#if thread in 1/* thread pool, simulate processing business */void *process (void *arg) {printf ("Thread 0x%x working on Task%d\n", (unsigned int) pthr Ead_self (), * (int *) arg); Sleep (1); printf ("Task%d is end\n", * (int *) arg); return NULL;} int main (void) {/*threadpool_t *threadpool_create (int min_thr_num, int max_thr_num, int queue_max_size); */Threadpoo l_t *THP = threadpool_create (3,100,100);/* Create thread pool, minimum 3 threads in pool, max 100, queue max 100*/printf ("Pool inited"); int *num = (int *) malloc (sizeof (int) *20); int num[20], I; for (i = 0; i <; i++) {num[i]=i; printf ("Add Task%d\n", i); Threadpool_add (THP, process, (void*) &num[i]); /* Add a task to the thread pool */} sleep (10); /* Wait for child threads to complete tasks */Threadpool_destroy (THP); return 0;}
Thread Pool Code