Boost logo

Boost Users :

Subject: [Boost-users] [boost 1.42, gcc 4.4, ubuntu 10.10] Program hangs when using barrier.wait() even though all threads have reached wait.
From: Gareth (gareth.tpc_at_[hidden])
Date: 2011-06-23 05:32:28


I'm having problems with boost::barrier. I've written a class that
creates a thread pool to map evaluate an array of functions to an
array of results. I've used barriers in the synchronisation. The
problem is that the threads are all getting stuck at the barrier::wait
calls. I've verified with gdb that all the worker threads and the
manager thread are sitting in barrier::wait() however, there all
stuck. I have no idea what's causing this. I've put the source code in
the following github gist and also pasted it to the end of the email.

https://gist.github.com/1041351

I've also checked the bugs list for any known bugs, fixed or
otherwise, to do with threading and I haven't found anything. I'm not
sure what I'm doing wrong.

-Gareth Charnock

/*
compile: g++ thread_template.cpp -lboost_thread

Outputs:

BOOST_VERSION = 104200
Starting thread 0
Starting thread 1
Thread 0 waiting for work
Thread 1 waiting for work
Threads have work...
*/

#include <boost/version.hpp>
#include <boost/thread.hpp>
#include <boost/thread/barrier.hpp>
#include <boost/function.hpp>
#include <iostream>
#include <vector>

template<typename T>
class Multithreader {
public:
   Multithreader()
               : numCPU(sysconf(_SC_NPROCESSORS_ONLN)),
                 _barrier(numCPU+1),
                 mFuncs(NULL),
                 mMapTo(NULL) {
               std::cout << "BOOST_VERSION = " << BOOST_VERSION << std::endl;
               //Start the thread pool
               for(long i = 0;i<numCPU;i++) {
                       std::cout << "Starting thread "<<i<< std::endl;
                       boost::thread(WorkerThread(i,this));
               }
       }

       ~Multithreader() {
               //Terminate the threads

               //todo
       }

   void map(const std::vector<boost::function<T ()> >&
funcs,std::vector<T>& mapTo) {
               mFuncs = &funcs;
               mMapTo = &mapTo;

               std::cout << "Threads have work..." << std::endl;
               _barrier.wait();
               //Workers are working at this point
               std::cout << "Threads are working..." << std::endl;
               _barrier.wait();
               std::cout << "Threads have finished" << std::endl;
   }
private:
       const std::vector<boost::function<T ()> >* mFuncs;
       std::vector<T>* mMapTo;
   boost::barrier _barrier;

       size_t numCPU;

       class WorkerThread {
       public:
               WorkerThread(long _id,Multithreader* _parent)
                       : id(_id),parent(_parent) {
               }
               void operator()() {
                       while(true) {
                               std::cout << "Thread "<<id<<" waiting
for work" << std::endl;
                               parent->_barrier.wait();
                               std::cout << "Thread "<<id<<" has work"
<< std::endl;
                               //Do work
                               for(long i =
id;i<parent->mFuncs->size();i+=parent->numCPU) {
                                       parent->mMapTo->at(i) =
parent->mFuncs->at(i)();
                               }
                               parent->_barrier.wait();
                               std::cout << "Thread "<<id<<" finished
the work" << std::endl;
                       }
               }
               long id;
               Multithreader* parent;
       };

};

#include <boost/bind.hpp>

double f(double x) {
       return x*2;
}

int main() {
       //Start the thread pool
       Multithreader<double> mt;

       std::vector<boost::function<double()> > work;work.resize(20);
       std::vector<double> results;results.resize(20);

       //Prepare the work
       for(unsigned long i = 0;i<20;i++) {
               work[i] = boost::bind(f,i);
       }
       //Execute in parallel
       mt.map(work,results);

       while(true) {
               //For the purposes of the example, keep the main thread alive
               //so we don't delete mt
       }
}


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net