/* 小規模的Linux線程池 written by luoxiongwei E-mail:luo6620378li@qq.com Welcom to report bugs! 下一步計劃給工作隊列中的任務添加優先順序 實現一個優先隊列。*/#ifndef __THREADPOOLS#define __THREADPOOLS#include <sys/types.h>#include <pthread.h>#include <unistd.h>#include <vector>#include <cstdio>#include <cstdlib>#include <cstring>using std::vector;struct task//隊列中的任務結點{ void (*handler)(void *);//任務函數 void * data;//任務資料 //int prority;//任務優先順序};struct work_queue_t//工作隊列{ struct work_queue_t * next ; struct work_queue_t * head ; struct work_queue_t * tail ; struct task * elment ;};//工作隊列操作work_queue_t * init_work_queue();//初始化工作隊列void destory_work_queue();//銷毀工作隊列work_queue_t * remove_task();//取隊首任務int add_tast(task * new_task);//在工作隊列尾部新增工作bool empty();//線程池資源void *thread_rounter(void *);//線程執行函數struct work_queue_t * work_queue=NULL;//工作隊列int work_count=0;//工作隊列中的元素個數vector<pthread_t> threads;//記錄所有線程的idpthread_cond_t pool_cond;//喚醒相應線程開始工作pthread_mutex_t queue_lock;//保護工作隊列,以及池中的互斥資源int idles;//空閑線程數目int busy;//正在執行任務的線程數目int max_thread;//池中維持的最大線程數目bool to_exit;//銷毀線程池標誌bool validate;//線程池是否可用//線程池操作,提供給使用者操作的四個函數void thread_pool(int init_threads_num);//建立線程池void destroy_thread_pool();//銷毀線程池/*組裝任務處理函數和處理函數參數,注意一旦該任務完成之後, 資料將會被系統釋放掉,所以下一次向線程池加入任務時, 請重新組裝。請保證處理函數是線程可重新進入的。*/task * prod_task(void (*handler)(void *), void * data);int exec_task(task * new_task);//留給使用者的調用介面#endif//樣本的工作函數void task1(void *arg);int main(){ //現在測試了池中有10個線程,12個任務。 //任務參數 char *ptr1="I am task one\n"; char *ptr2="I am task two\n"; char *ptr3="I am task three\n"; char *ptr4="I am task four\n"; char *ptr5="I am task five\n"; char *ptr6="I am task six\n"; char *ptr7="I am task seven\n"; char *ptr8="I am task eight\n"; char *ptr9="I am task nine\n"; char *ptr10="I am task ten\n"; char *ptr11="I am task eleven\n"; char *ptr12="I am task twltle\n"; //組裝任務 task * task_p1=prod_task(task1,ptr1); task * task_p2=prod_task(task1,ptr2); task * task_p3=prod_task(task1,ptr3); task * task_p4=prod_task(task1,ptr4); task * task_p5=prod_task(task1,ptr5); task * task_p6=prod_task(task1,ptr6); task * task_p7=prod_task(task1,ptr7); task * task_p8=prod_task(task1,ptr8); task * task_p9=prod_task(task1,ptr9); task * task_p10=prod_task(task1,ptr10); task * task_p11=prod_task(task1,ptr11); task * task_p12=prod_task(task1,ptr12); thread_pool(10);//建立線程池,池中最多10個線程 //12個任務 exec_task(task_p1); exec_task(task_p2); exec_task(task_p3); exec_task(task_p4); exec_task(task_p5); exec_task(task_p6); exec_task(task_p7); exec_task(task_p8); exec_task(task_p9); exec_task(task_p10); exec_task(task_p11); exec_task(task_p12); /*延時,讓所有任務執行完。也可以不延時, 但是可能任務還沒有完成,線程池就被銷毀。 */ sleep(20); destroy_thread_pool();//銷毀線程池 return 0;}void task1(void *arg){ char *ptr=(char *)arg; write(STDOUT_FILENO,ptr,strlen(ptr));}//提供給使用者的外部介面之一,產生任務task * prod_task(void (*handler)(void *), void * data){ struct task * new_task=new task; if(!new_task) return NULL; new_task->handler=handler; new_task->data=data; return new_task;}//工作隊列的相應操作work_queue_t * init_work_queue(){ work_queue_t *work_queue_=new work_queue_t ; if(!work_queue_) return NULL; work_queue_->head=work_queue_->tail=NULL; work_queue_->next=NULL; work_queue_->elment=NULL; work_count=0; return work_queue_;}work_queue_t * remove_task()//取隊首任務{ work_queue_t * temp; if(empty())//工作隊列空 return NULL; temp=work_queue->head; work_queue->head=work_queue->head->next; work_count--; return temp;}//在工作隊列尾部新增工作int add_tast(task * new_task){ work_queue_t * temp=NULL; if(empty())//隊列為空白 { temp=new work_queue_t ; temp->next=NULL; temp->elment=new_task; work_queue->head=work_queue->tail=temp; work_count++; return 0; } else//隊列不空 { temp=new work_queue_t ; temp->next=NULL; temp->elment=new_task; work_queue->tail->next=temp; work_queue->tail=temp; work_count++; return 0; } return -1;//添加不成功}void destory_work_queue(){ work_queue_t * temp; if(work_count!=0) { while(work_queue->head) { temp=work_queue->head; work_queue->head=work_queue->head->next; delete temp->elment; delete temp; } }}bool empty(){bool flage=false; if(work_count==0) flage=true; return flage;}//線程池的操作//初始化線程池void thread_pool(int init_threads_num){ pthread_mutex_init(&queue_lock,NULL);//初始化鎖 if(pthread_cond_init(&pool_cond,NULL)!=0) return ; work_queue=init_work_queue();//工作隊列 if(!work_queue) return ; max_thread=init_threads_num; idles=0; busy=0; to_exit=false; validate=true;}//銷毀線程池和工作隊列,條件變數,鎖void destroy_thread_pool(){ pthread_mutex_lock(&queue_lock); //改變條件 to_exit=true; validate=false; //取消線程池中的所有線程 for(size_t i=0;i!=threads.size();++i) pthread_cancel(threads[i]); //銷毀工作隊列 destory_work_queue(); pthread_mutex_unlock(&queue_lock); //銷毀鎖和條件變數 pthread_mutex_destroy(&queue_lock); pthread_cond_destroy(&pool_cond);}int exec_task(task * new_task){ pthread_t tid; pthread_mutex_lock(&queue_lock); //將新任務添加至工作隊列 if(add_tast(new_task)!=0) { pthread_mutex_unlock(&queue_lock); return -1; } pthread_cond_signal(&pool_cond);//工作隊列中有任務了,喚醒一個阻塞線程 //是否建立線程,視條件而定 if(validate&&!to_exit&&(idles==0||(idles+busy)<max_thread)) { if(pthread_create(&tid,NULL,thread_rounter,NULL)!=0) { pthread_mutex_unlock(&queue_lock); return -1; } threads.push_back(tid);//記錄線程id idles++;//多了一個空閑線程 pthread_mutex_unlock(&queue_lock); return 0; } pthread_mutex_unlock(&queue_lock); return 0;}void *thread_rounter(void *){ pthread_detach(pthread_self());//分離自己 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL); pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,NULL);//到達取消點處才取消線程 work_queue_t * work_item=NULL; for(;;)//去檢查工作隊列中是否有需要處理的工作項目 { pthread_mutex_lock(&queue_lock); while(validate&&!to_exit&&((work_item=remove_task())==NULL))//工作隊列為空白,則一直等待 pthread_cond_wait(&pool_cond,&queue_lock);//這裡將會是一個取消點 pthread_mutex_unlock(&queue_lock); if(validate&&!to_exit&&work_item->elment->data) { pthread_mutex_lock(&queue_lock); busy++;//該線程忙 idles--; pthread_mutex_unlock(&queue_lock); work_item->elment->handler(work_item->elment->data);//處理函數調用 pthread_mutex_lock(&queue_lock); busy--; idles++; pthread_mutex_unlock(&queue_lock); //釋放資源 delete work_item->elment; delete work_item; } } return NULL;}