2013-10-21 16 views
38

Come si crea un pool di thread utilizzando boost in C++ e come si assegnano le attività al threadpool?Come creare un pool di thread usando boost in C++?

+0

possibile duplicato di [Creazione di un pool di thread utilizzando Boost] (http://stackoverflow.com/ domande/4084777/creating-a-thread-pool-using-boost) –

+0

L'unica cosa è che non mi permette di rispondere all'altra domanda, e la risposta personale è consentita e incoraggiata. –

+0

Dovresti riuscire a inviare una risposta a [l'altra domanda] (http://stackoverflow.com/questions/4084777/creating-a-thread-pool-using-boost), non è chiusa o [protetta] (http://meta.stackexchange.com/questions/52764/what-is-a-protected-question). –

risposta

59

Il processo è piuttosto semplice. Per prima cosa create un asio :: io_service e un thread_group. Riempi il thread_group con i thread collegati al io_service. Assegnare le attività ai thread utilizzando la funzione boost::bind.

Per interrompere i thread (in genere quando si sta uscendo dal programma) è sufficiente interrompere io_service e unire tutti i thread.

Dovreste solo bisogno di queste intestazioni:

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

Ecco un esempio:

/* 
* 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(); 

Fonte: Recipes < Asio

+12

L'oggetto ['boost :: asio :: io_service :: work'] (http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/io_service__work.html) è un pezzo fondamentale per farlo funzionare correttamente. Anche ['io_service :: stop()'] (http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/io_service/stop.html) impedirà l'esecuzione di qualsiasi attività aggiuntiva, indipendentemente dal momento in cui l'attività viene pubblicata in 'io_service'. Ad esempio, mentre 'getSocialUpdates()' viene aggiunto alla coda 'io_service' prima di' stop() ', se non è l'esecuzione mid quando viene richiamato' stop() ', rimarrà in coda. –

+2

È necessario creare l'oggetto 'work' * prima * di creare i thread worker, altrimenti possono immediatamente terminare senza fare nulla. – Miral

+6

@TannerSansbury In realtà questa ricetta mi rende molto confuso, dal momento che dopo io_service.stop() tutti i miei lavori incompiuti vengono uccisi. Un modo corretto dovrebbe essere quello di rimuovere ioservice.stop() ma distruggere l'oggetto di lavoro, quindi chiamare threadpool.join_all() per lasciare terminare tutti i lavori. – CyberSnoopy

10

So che ti piace il codice.

mia versione

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 
    }; 
} 

pezzo di codice per usarlo:

{ 
    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

Scusa, devo solo chiedertelo, come fai a sapere che il mittente piace il codice? – x29a

+11

@ x29a come fai a sapere che non conosco il codice piace al richiedente? – squid

+20

come leggi dal mio commento che so che non sai se al richiedente piace il codice? – x29a

Problemi correlati