2013-10-21 49 views
38

如何在C++中使用boost來創建線程池,以及如何將任務分配給線程池?如何在C++中使用boost來創建線程池?

+0

[創建使用boost線程池(可能重複http://stackoverflow.com/問題/ 4084777 /創建線程池使用提升) –

+0

唯一的事情是它不允許我回答其他問題,並允許和鼓勵自我回答。 –

+0

你應該能夠發佈[其他問題]的答案(http://stackoverflow.com/questions/4084777/creating-a-thread-pool-using-boost),它不是關閉或[保護] (http://meta.stackexchange.com/questions/52764/what-is-a-protected-question)。 –

回答

59

該過程非常簡單。首先創建一個asio :: io_service和一個thread_group。使用鏈接到io_service的線程填充thread_group。使用boost::bind函數將任務分配給線程。

要停止線程(通常在退出程序時),停止io_service並加入所有線程。

你應該只需要這些標題:

#include <boost/asio/io_service.hpp> 
#include <boost/bind.hpp> 
#include <boost/thread/thread.hpp> 

這裏有一個例子:

/* 
* Create an asio::io_service and a thread_group (through pool in essence) 
*/ 
boost::asio::io_service ioService; 
boost::thread_group threadpool; 


/* 
* This will start the ioService processing loop. All tasks 
* assigned with ioService.post() will start executing. 
*/ 
boost::asio::io_service::work work(ioService); 

/* 
* This will add 2 threads to the thread pool. (You could just put it in a for loop) 
*/ 
threadpool.create_thread(
    boost::bind(&boost::asio::io_service::run, &ioService) 
); 
threadpool.create_thread(
    boost::bind(&boost::asio::io_service::run, &ioService) 
); 

/* 
* This will assign tasks to the thread pool. 
* More about boost::bind: "http://www.boost.org/doc/libs/1_54_0/libs/bind/bind.html#with_functions" 
*/ 
ioService.post(boost::bind(myTask, "Hello World!")); 
ioService.post(boost::bind(clearCache, "./cache")); 
ioService.post(boost::bind(getSocialUpdates, "twitter,gmail,facebook,tumblr,reddit")); 

/* 
* This will stop the ioService processing loop. Any tasks 
* you add behind this point will not execute. 
*/ 
ioService.stop(); 

/* 
* Will wait till all the threads in the thread pool are finished with 
* their assigned tasks and 'join' them. Just assume the threads inside 
* the threadpool will be destroyed by this method. 
*/ 
threadpool.join_all(); 

來源:Recipes < Asio

+12

['boost :: asio :: io_service :: work'](http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/io_service__work.html)object is a critical piece使其正常運作。另外['io_service :: stop()'](http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/io_service/stop.html)將阻止執行任何其他任務,而不管任務何時發佈到'io_service'中。例如,'getSocialUpdates()'在'stop()'之前被添加到'io_service'隊列中,如果調用'stop()'時不是中等執行,那麼它將保持排隊。 –

+2

您需要在創建工作線程之前創建'work'對象*,否則它們可能會立即終止而無需執行任何操作。 – Miral

+6

@TannerSansbury其實這個配方讓我非常困惑,因爲在io_service.stop()之後,所有未完成的工作都會被殺死。正確的方法應該是除去ioservice.stop(),但是破壞工作對象,然後調用threadpool.join_all()讓所有作業完成。 – CyberSnoopy

10

我知道你喜歡的代碼。

我的版本

namespace bamthread 
{ 
    typedef std::unique_ptr<boost::asio::io_service::work> asio_worker; 

    struct ThreadPool { 
     ThreadPool(size_t threads) :service(), working(new asio_worker::element_type(service)) { 
      while(threads--) 
      { 
       auto worker = boost::bind(&boost::asio::io_service::run, &(this->service)); 
       g.add_thread(new boost::thread(worker)); 
      } 
     } 

     template<class F> 
      void enqueue(F f){ 
       service.post(f); 
      } 

     ~ThreadPool() { 
      working.reset(); //allow run() to exit 
      g.join_all(); 
      service.stop(); 
     } 

     private: 
     boost::asio::io_service service; //< the io_service we are wrapping 
     asio_worker working; 
     boost::thread_group g; //< need to keep track of threads so we can join them 
    }; 
} 

代碼至少要使用它:

{ 
    bamthread::ThreadPool tp(n_threads); 
    BOOST_FOREACH(int y, boost::irange(starty, endy, step)){ 
     int im_x = 0; 
     BOOST_FOREACH(int x, boost::irange(startx, endx, step)){ 
      tp.enqueue (boost::bind(&camera_view_depth::threaded_intersection, this, 
         intersections, 
         intersected, 
         im_x, 
         im_y, 
         _faces, x, y)); 
      ++im_x; 
     } 
     ++im_y; 
    } 
} 
+17

對不起,我只是問,你怎麼知道提問者喜歡的代碼? – x29a

+11

@ x29a你怎麼知道我不知道asker喜歡的代碼? – squid

+20

你如何從我的評論中讀到我知道你不知道提問者是否喜歡代碼? – x29a