基于C++11的线程池

来源:互联网 发布:金山画王软件下载 编辑:程序博客网 时间:2024/05/16 15:16

转自http://blog.csdn.net/love_newzai/article/details/25135533

  • 1.封装的线程对象
[cpp] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. class task : public std::tr1::enable_shared_from_this<task>  
  2. {  
  3. public:  
  4.     task():exit_(false){}  
  5.     task( const task & ) = delete;  
  6.     ~task(){}  
  7.     task & operator =( const task &) = delete;  
  8.   
  9.     void start();  
  10.     void stop()  
  11.     {  
  12.         exit_ = true;  
  13.         sync_.notify_one();  
  14.     }  
  15.     void set_job( const std::function<void()> & job, const std::string & file, int line)  
  16.     {//提交任务  
  17.         {  
  18.             std::unique_lock<std::mutex> lock(mutex_);  
  19.             job_ = job;  
  20.             file_ = file;  
  21.             line_ = line;  
  22.         }  
  23.         sync_.notify_one();//通知主线程有任务要执行....  
  24.     }  
  25.     void print_job(){  
  26.         LOG(INFO)<<"sumbit from:"<<file_<<":"<<line_;  
  27.     }  
  28. private:  
  29.   
  30.     bool exit_;  
  31.     std::mutex mutex_;  
  32.     std::condition_variable sync_;  
  33.     std::function< void()> job_;          //线程执行的任务,线程任意时刻,最多只能执行一个任务。  
  34.     std::thread::id       id_;  
  35.     std::string          file_;  
  36.     int                   line_;  
  37.   
  38.   
  39. };<pre code_snippet_id="329966" snippet_file_name="blog_20140506_1_7374667" name="code" class="cpp">void task::start()  
  40. {  
  41.     auto job_proxy = [this] (){  
  42.   
  43.   
  44.         id_ = std::this_thread::get_id();  
  45.   
  46.   
  47.         while( !exit_ )  
  48.         {  
  49.   
  50.   
  51.             std::unique_lock<std::mutex> lock(mutex_);  
  52.               
  53.             if( job_ )  
  54.             {//有任务了,需要执行任务了  
  55.                 try  
  56.                 {  
  57.                     job_(); //执行任务的代码  
  58.                 }catch( std::exception & e)  
  59.                 {  
  60.                       
  61.                 }catch(...)  
  62.                 {  
  63.                       
  64.                 }  
  65.                 job_ = std::function<void()>(); //释放任务绑定的资源,主要为闭包捕获的资源,特别是shared_ptr对象.  
  66.                 tasks->job_completed( shared_from_this() ); //任务执行完成,通知线程池  
  67.             }else{  
  68.                    //没有任务的时候,等待其他线程提交任务。。  
  69.                 sync_.wait(lock);  
  70.   
  71.             }  
  72.         }  
  73.     };  
  74.   
  75.   
  76.     std::thread t(job_proxy); //创建并启动与task管理的线程  
  77.     t.detach();               //分离模式,thread对象销毁了,但是其创建的线程还活着。。。  
  78. }  
  79. </pre>  
  80. <div><br>  
  81. </div>  
  82. <pre></pre>  
  83. <pre code_snippet_id="329966" snippet_file_name="blog_20140506_2_6023437" name="code" class="cpp"></pre>  
  • 2.线程池管理对象
[cpp] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. class task_pool  
  2. {  
  3. public:  
  4.     task_pool(unsigned int pool_size = 128):max_size_(pool_size),stop_all_(true)  
  5.     {  
  6.   
  7.     }  
  8.     ~task_pool()  
  9.     {  
  10.     }  
  11.     void job_completed( const std::tr1::shared_ptr<task> & t)//回收task对象  
  12.     {  
  13.   
  14.         std::lock_guard<std::mutex> lock(mutex_);  
  15.         bool need_to_notify = idle_tasks_.empty() && (!wait_for_running_jobs_.empty());  
  16.         busying_tasks_.erase(t);  
  17.         idle_tasks_.push_back(t);  
  18.         LOG(INFO)<<"after job_completed, current idle tasks size:"<< idle_tasks_.size()  
  19.             <<" busying tasks size:"<<busying_tasks_.size()  
  20.             <<" wait for running jobs size:"<<wait_for_running_jobs_.size();  
  21.         if( !busying_tasks_.empty() ){  
  22.             (*busying_tasks_.begin())->print_job();  
  23.         }  
  24.         if( need_to_notify )//任务太多了,之前空闲线程使用完了,有任务在等待执行,需要通知  
  25.         {  
  26.             sync_.notify_one();  
  27.         }  
  28.     };  
  29. <span style="white-space:pre">  </span>//提交任务  
  30.     void submit_job( const std::function<void()> & job, const std::string file, int line)  
  31.     {  
  32.         if( stop_all_ )  
  33.         {  
  34.             return;  
  35.         }  
  36.         std::lock_guard<std::mutex> lock(mutex_);  
  37.         bool need_notify = wait_for_running_jobs_.empty();  
  38.         wait_for_running_jobs_.push(std::make_tuple(job,file,line));  
  39.   
  40.         if( need_notify )//等待执行的任务为空时,需要通知,其他情况不需要通知.  
  41.         {  
  42.             sync_.notify_one();  
  43.         }  
  44.           
  45.     }  
  46.     void execute_job()  
  47.     {  
  48.   
  49.   
  50.         while(true)  
  51.         {  
  52.             std::unique_lock<std::mutex> lock(mutex_);  
  53.             while(!stop_all_ && wait_for_running_jobs_.empty() )  
  54.             {  
  55.                 //等待其他线程提交任务  
  56.                 sync_.wait(lock);  
  57.             }  
  58.   
  59.             if( stop_all_ )  
  60.             {  
  61.                 return;  
  62.             }  
  63.             while(!stop_all_ && idle_tasks_.empty())  
  64.             {  
  65.                 //有任务要执行,但是没有空闲线程,等待其他任务执行完成。  
  66.                 sync_.wait(lock);  
  67.             }  
  68.             if( stop_all_ )  
  69.             {  
  70.                 return;  
  71.             }  
  72.   
  73.             //有任务,也有空闲线程了  
  74.             auto t = get_task();  
  75.             auto job =wait_for_running_jobs_.front();  
  76.             wait_for_running_jobs_.pop();  
  77. <span style="white-space:pre">          </span>//分发任务到task 线程.  
  78.             t->set_job(std::get<0>(job), std::get<1>(job), std::get<2>(job));  
  79.         }  
  80.     }  
  81.     void stop_all()  
  82.     {  
  83.   
  84.         std::lock_guard<std::mutex> lock(mutex_);  
  85.         stop_all_ = true;  
  86.         for( auto t : idle_tasks_ )  
  87.         {  
  88.             t->stop();  
  89.         }  
  90.         idle_tasks_.clear();  
  91.         for( auto t : busying_tasks_ )  
  92.         {  
  93.             t->stop();  
  94.         }  
  95.         while(!wait_for_running_jobs_.empty()){  
  96.             wait_for_running_jobs_.pop();  
  97.         }  
  98.   
  99.         sync_.notify_one();  
  100.     }  
  101.   
  102.     void start()  
  103.     {// 初始化启动线程池主线程  
  104.         try  
  105.         {  
  106.             std::thread t( [this]{ execute_job();});  
  107.             t.detach();  
  108.   
  109.             stop_all_ = false;  
  110.             allocate_tasks();  
  111.   
  112.         }catch( std::exception & e )  
  113.         {  
  114.             LOG(FATAL) << "start tasks pool ... error"<<e.what();  
  115.         }  
  116.     }  
  117. protected:  
  118.     std::tr1::shared_ptr<task> get_task()  
  119.     {  
  120.         //获取task对象  
  121.         if( ! idle_tasks_.empty() )  
  122.         {  
  123.             auto t = *idle_tasks_.begin();  
  124.             idle_tasks_.pop_front();  //从空闲队列移除  
  125.             busying_tasks_.insert(t); //加入忙队列  
  126.               
  127.             return t;  
  128.         }  
  129.   
  130.         return std::tr1::shared_ptr<task>();  
  131.   
  132.     }  
  133.   
  134.     void allocate_tasks() //初始化线程池  
  135.     {  
  136.         forint i = 0 ; i < max_size_; i ++ )  
  137.         {  
  138.             std::tr1::shared_ptr<task> t( new task());  
  139.             try{  
  140.                 t->start();  
  141.                 idle_tasks_.push_back(t);  
  142.             }catch( std::exception & e)   
  143.             {   //超过进程最大线程数限制时,会跑出异常。。。       
  144.                 break;  
  145.             }  
  146.         }  
  147.     }  
  148. private :  
  149.     unsigned int                              max_size_;  
  150.     std::list  < std::tr1::shared_ptr<task> > idle_tasks_;   //空闲任务队列  
  151.     std::set  <  std::tr1::shared_ptr<task> > busying_tasks_;//正在执行任务的队列  
  152.     std::queue< std::tuple< std::function<void()> , std::string, int   >  > wait_for_running_jobs_; //等待执行的任务  
  153.     std::mutex                              mutex_;  
  154.     std::condition_variable                 sync_;  
  155.     bool stop_all_;  
  156. };  

  • usage
[cpp] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. static task_pool *  tasks = nullptr;  
  2. static std::once_flag init_flag;  
  3. static std::once_flag finit_flag;  
  4.   
  5. void run_job(const std::function<void()> & job , const std::string &  file, int line )  
  6. {  
  7.     if( tasks != nullptr)  
  8.         tasks->submit_job(job, file,line);  
  9.   
  10. }  
  11. void task_pool_init( unsigned max_task_size)  
  12. {  
  13.     std::call_once(init_flag,[max_task_size]{  
  14.         tasks = new task_pool(max_task_size);  
  15.         tasks->start();  
  16.     });  
  17. }  
  18. void task_pool_finit()  
  19. {  
  20.    std::call_once(finit_flag,[]{ tasks->stop_all();});  
  21. }  

0 0