views:

73

answers:

2

I have a newbie question about Boost::Thread and Mutex.

I would like to start many parallel instances of the following Worker, and all of them write to the same std::vector:

struct Worker {
  std::vector<double>* vec;
  Worker(std::vector<double>* v) : vec(v) {}
  void operator() {
    // do some long computation and then add results to *vec, e.g.
    for(std::size_t i = 0; i < vec->size(); ++i) {
      (*vec)[i] += some_value;
    }
  }
};

I understand that the Worker has to lock vec before it write to it and unlock it when it's done (because all Workers write to the same vector). But how do I express that?

+2  A: 

You need a boost::mutex to protect the vector, and you can use a boost::mutex::scoped_lock that'll lock the mutex in its constructor, and unlock it in the destructor

Keep in mind you need to use that same mutex everywhere where you access that instance of vec , be it reads or writes.

To get you going, you could do something like:

struct Worker {
  boost::mutex &vec_mutex;

  Worker(std::vector<double>* v,boost::mutex &v_mutex) : vec(v),vec_mutex(v_mutex) {}
  void operator() {        
    // do some long computation and then add results to *vec, e.g.

    boost::mutex::scoped_lock lock(vec_mutex);
    for(std::size_t i = 0; i < vec->size(); ++i) {
      (*vec)[i] += some_value;
    }
  }

};

For more advanced stuff, you should encapsulate the vector and mutex further, or sooner or later you'll forget that these needs to be connected and you'll access vec somewhere without holding the lock leading to very hard to debug problems. For problems such as this example, I'd rather have the workers use their own individual vectors , and combine the result in the a controlling thread when the workers are done.

nos
Did you mean `vec_mutex` instead of `io_mutex`?
Frank
Yes, fixed now.
nos
A: 

OT but useful info I hope - since you are updating this vector a lot (or just for best practice) consider iterators to iterate over the vector elements. Making the worker code faster by not requiring use of vector<double>::operator[] will reduce the aggregate wait time of your worker threads.

for(std::vector<double>::iterator iter = vec->begin(); iter != vec->end(); ++iter) {
  *iter += some_value;
}
Steve Townsend