title: How to use the same thread pool batch by batch
body: <p>I found a <a href="http://liveworkspace.org/code/3gLtD4$1" rel="nofollow noreferrer">good implementation</a> of boost based thread pool which is an improvement over <a href="http://progsch.net/wordpress/?p=71" rel="nofollow noreferrer">this</a> and <a href="http://think-async.com/Asio/Recipes?skin=clean.nat,asio,pattern#A_thread_pool_for_executing_arbi" rel="nofollow noreferrer">this</a> . it is very easy to understand and test. It looks like this:</p>
  
  <pre><code>#include &lt;boost/thread/thread.hpp&gt;
  #include &lt;boost/asio.hpp&gt;
  // the actual thread pool
  struct ThreadPool {
     ThreadPool(std::size_t);
     template&lt;class F&gt;
     void enqueue(F f);
     ~ThreadPool();    
  
     // the io_service we are wrapping
     boost::asio::io_service io_service;
     // dont let io_service stop
     boost::shared_ptr&lt;boost::asio::io_service::work&gt; work;
     //the threads
     boost::thread_group threads;
  };
  
  // the constructor just launches some amount of workers
  ThreadPool::ThreadPool(size_t nThreads)
     :io_service()
     ,work(new boost::asio::io_service::work(io_service))
  {
     for ( std::size_t i = 0; i &lt; nThreads; ++i ) {
      threads.create_thread(boost::bind(&amp;boost::asio::io_service::run, &amp;io_service));
     }
  }
  
  // add new work item to the pool
  template&lt;class F&gt;
  void ThreadPool::enqueue(F f) {
     io_service.post(f);
  }
  
  // the destructor joins all threads
  ThreadPool::~ThreadPool() {
  work.reset();
  io_service.run();
  }
  
  //tester: 
  void f(int i)
  {
      std::cout &lt;&lt; "hello " &lt;&lt; i &lt;&lt; std::endl;
      boost::this_thread::sleep(boost::posix_time::milliseconds(300));
      std::cout &lt;&lt; "world " &lt;&lt; i &lt;&lt; std::endl;
  }
  
  //it can be tested via:
  
  int main() {
     // create a thread pool of 4 worker threads
     ThreadPool pool(4);
  
     // queue a bunch of "work items"
     for( int i = 0; i &lt; 8; ++i ) {
        std::cout &lt;&lt; "task " &lt;&lt; i &lt;&lt; " created" &lt;&lt; std::endl;
        pool.enqueue(boost::bind(&amp;f,i));
     }
  }
  </code></pre>
  
  <p><code>g++ ThreadPool-4.cpp -lboost_system -lboost_thread</code></p>
  
  <p><strong>Now the question:</strong>
  I need to know how I can modify the implementation to be able to use this thread pool batch by batch- only when the first set of my work is fully completed by the thread pool, I need to supply the second set and so on. I tried to play with <code>.run()</code> and <code>.reset()</code> (found in the destructor) between the batch jobs but no luck:</p>
  
  <pre><code>//adding methods to the tread pool :
  //reset the asio work and thread
  void ThreadPool::reset(size_t nThreads){
  
  work.reset(new boost::asio::io_service::work(io_service));
     for ( std::size_t i = 0; i &lt; nThreads; ++i ) {
      threads.create_thread(boost::bind(&amp;boost::asio::io_service::run, &amp;io_service));
     }
      std::cout &lt;&lt; "group size : " &lt;&lt; threads.size() &lt;&lt; std::endl;
  }
  
  //join, and even , interrupt
  void ThreadPool::joinAll(){   
    threads.join_all();
    threads.interrupt_all();
  }
  
  //tester
  int main() {
     // create a thread pool of 4 worker threads
     ThreadPool pool(4);
  
     // queue a bunch of "work items"
     for( int i = 0; i &lt; 20; ++i ) {
        std::cout &lt;&lt; "task " &lt;&lt; i &lt;&lt; " created" &lt;&lt; std::endl;
            pool.enqueue(boost::bind(&amp;f,i));
     }
     //here i play with the asio work , io_service and and the thread group
     pool.work.reset();
     pool.io_service.run();
     std::cout &lt;&lt; "after run" &lt;&lt; std::endl; 
     pool.joinAll();
     std::cout &lt;&lt; "after join all" &lt;&lt; std::endl; 
     pool.reset(4);
     std::cout &lt;&lt; "new thread group size: " &lt;&lt; pool.threads.size() &lt;&lt; std::endl;///btw: new threa group size is 8. I expected 4! 
      // second batch... never completes
     for( int i = 20; i &lt; 30; ++i ) {
            pool.enqueue(boost::bind(&amp;f,i));
     }
  }
  </code></pre>
  
  <p>The second batch doesn't complete. I will appreciate if you help me fix this.
  thank you</p>
  
  <p><strong>UPDATE- Solution:</strong></p>
  
  <p>based on a solution by <a href="https://stackoverflow.com/users/2112844/nik">Nik</a>, I developed a solution using condition variable. Just add the following code to the original class:</p>
  
  <pre><code>// add new work item to the pool
  template&lt;class F&gt;
  void ThreadPool::enqueue(F f) {
      {
          boost::unique_lock&lt;boost::mutex&gt; lock(mutex_);
          nTasks ++;
      }
      //forwarding the job to wrapper()
      void (ThreadPool::*ff)(boost::tuple&lt;F&gt;) = &amp;ThreadPool::wrapper&lt;F&gt;;
      io_service.post(boost::bind(ff, this, boost::make_tuple(f))); //using a tuple seems to be the only practical way. it is mentioned in boost examples.
  }
  //run+notfiy
  template&lt;class F&gt;
  void ThreadPool::wrapper(boost::tuple&lt;F&gt; f) {
      boost::get&lt;0&gt;(f)();//this is the task (function and its argument) that has to be executed by a thread
      {
          boost::unique_lock&lt;boost::mutex&gt; lock(mutex_);
          nTasks --;
          cond.notify_one();
      }
  }
  
  void ThreadPool::wait(){
      boost::unique_lock&lt;boost::mutex&gt; lock(mutex_);
      while(nTasks){
          cond.wait(lock);
      }
  }
  </code></pre>
  
  <p>Now you may call <code>wait()</code> method between batches of work.
  one problem however:
  Even after the last batch, I have to call <code>pool.wait()</code> because the thread pool's scope will end after that and thread pool's destructor will be invoked. During destruction, some of the jobs are done and it will be the time to call the <code>.notify()</code>. As the <code>Threadpool::mutex</code> during destruction is invalidated, exceptions occur during locking. your suggestion will be appreciated. </p>