4

I just tested something like this:

boost::thread workerThread1(boost::bind(&Class::Function, this, ...);
boost::thread workerThread2(boost::bind(&Class::Function, this, ...);

and it works fine. What i now want, is to create as many Threads as i have objects in a list. I have experimentet with boost::foreach and this works fine. But i have problems with the names of the threads.

So simplified the code looks like this:

for
{
    boost:thread name(...);
}

but of course name cant be right here in the loop because it overwrites itself and isnt accessible after the loop. How do i create the threads so that i can join them all after all have been created?

Flo
  • 1,660
  • 4
  • 21
  • 34

5 Answers5

12

Why don't you use boost::thread_group? You can create/add/remove threads and join them all (boost::thread_group::join_all()).

boost::thread_group tgroup;
for(...)
{
  tgroup.create_thread(boost::bind(&Class::Function, this, ...)) ;
}
tgroup.join_all();

But be careful about the number threads you are creating, too many threads may lead to OutOfMemory.

ali_bahoo
  • 4,732
  • 6
  • 41
  • 63
4

Can you not just create a list (or similar) of threads and then just create them and add to the list.

Something like the following (which is likely more pseudo code that anything :-) )

list<boost::thread*> threads;

for
{
    boost::thread* name = new boost::thread(...);
    threads.push_back(name);
}

As mentioned in another answer you can use smart pointers which would be better and you mentioned you have a defined number of threads so an array/vector would be a better choice but as I said the code above isn't perfect anyway

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
Firedragon
  • 3,685
  • 3
  • 35
  • 75
  • @Patrick87 Good catch. I suppose saying it isn't perfect code isn't really a good excuse :-) – Firedragon Jan 05 '12 at 14:53
  • the solution itself works :) but im quite new to this whole c++, what are those smart pointers? Wouldnt it be enough to use something like "threads.clear();" after the "join()"? – Flo Jan 05 '12 at 15:22
  • @Flo: When using smartpointer like `boost::shared_ptr`, `std::tr1::shared_ptr` or (when you compile with C++11 support) `std::shared_ptr` or `std::unique_ptr` using threads.clear() would be enough, since those smartpointer are smart enough to automatically free the memory when they are destroyed. Otherwise you have to manually loop through the list and delete all contained pointers by hand before calling clear (or destroying the list). @Firedragon: Any reason for using `list` instead of a `vector`? – Grizzly Jan 05 '12 at 15:26
  • @Flo You can't clear the list like this as it won't clean up properly, you need to iterate over the list (or array or whatever you use) and clean up. Smart pointers are there to help alleviate a lot of the forgetting to clean up etc and are quite a large topic, there are different types for different needs. You are using boost which offers a variety so is probably a good place to start looking at them. – Firedragon Jan 05 '12 at 15:27
  • @Grizzly Basically as I said in the answer an array or vector is likely a better approach. list was the quickest way to create an example – Firedragon Jan 05 '12 at 15:29
  • ok changed to smartpointers, seems to work fine. Looks a bit wierd though like this: boost::shared_ptr and not to mention a list of that – Flo Jan 05 '12 at 15:41
3

You can keep them in an array:

size_t const thread_count = 5;
boost::thread threads[thread_count];
for (size_t i = 0; i < thread_count; ++i) {
    threads[i] = boost::bind(&Class::Function, this, ...));
}

In C++11, you can keep std::thread in friendlier containers such as std::vector:

std::vector<std::thread> threads;
for (int i = 0; i < 5; ++i) {
    threads.push_back(std::thread(boost::bind(&Class::Function, this, ...))));
}

This won't work with boost::thread in C++03, since boost::thread isn't copyable; the assignment from a temporary in my example works because of some Boost magic that sort-of emulates move semantics. I also couldn't get it to work with boost::thread in C++11, but that might be because I don't have the latest version of Boost. So in C++03, your stuck with either an array, or a container of (preferably smart) pointers.

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
2

Why not put the threads into their own container, such as a vector (by smart pointer assuming they're non-copyable)?

Mark B
  • 95,107
  • 10
  • 109
  • 188
0

Disclaimer: I don't use boost, but if it works like the rest of C++, I believe this might be along the right lines. Will delete if this is garbage.

boost::thread** threads;
threads = new boost::thread*[THREAD_COUNT];

for(int i = 0; i < THREAD_COUNT; i++)
{
   threads[i] = new boost::thread(...);
}

...

for(int i = 0; i < THREAD_COUNT; i++)
   delete threads[i];

delete[] threads;

...

The idea is just to dynamically allocate an array of pointers to your object type, based on how many you want. Then, for each one, dynamically create one and invoke the appropriate constructor in a loop. Eventually, you will/may need to clean these up, so you can use delete[] calls. I don't see why malloc() / free() and/or vector types wouldn't work, either.

Patrick87
  • 27,682
  • 3
  • 38
  • 73
  • 1
    You should be using smart pointers; there's a memory leak here if thread creation fails. – Mike Seymour Jan 05 '12 at 14:56
  • `malloc`/`free` won't work because they don't construct and destroy the `thread` object; they only allocate raw memory, which is why they are (almost) never used in C++. `vector` should work in C++11, but not C++03 where it requires the object type to be copyable and assignable. – Mike Seymour Jan 05 '12 at 15:17