Boost logo

Boost Users :

Subject: Re: [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 12:27:37


I've just tried the same program with a fresh compile of boost 1.46.1
and got the same hanging problem.

On Thu, Jun 23, 2011 at 10:32 AM, Gareth <gareth.tpc_at_[hidden]> wrote:
> 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