10
votes
\$\begingroup\$

I have a class bar that keeps track of N instances of class foo in a std::map (so N = map.size()). When I call bar::func I want to have N threads that call foo::foo_func.

foo::foo_func requires multiple arguments though, namely the instance of bar that it's related to.

I was thinking of doing something like:

void * _threaded_foo_func(void *);

struct box {
  bar * the_bar;
  foo * the_foo;
};

class bar {
  class sub_bar {
    // stuff
  };

  map<foo*, sub_bar*> foo_mappings;

  void func() {
    pthread_t threads[ foo_mappings.size() ];
    map<foo*, sub_bar*>::iterator it = foo_mappings.begin();
    int i=0;
    for(it; it != foo_mappings.end() && i < foo_mappings.size(); ++it, ++i) {
      box * args = new args();
      args->the_bar = this;
      args->the_foo = it->first;
      pthread_create( &threads[i], NULL, _threaded_foo_func, (void*) args);
    }

    for(int i=0; i<bar_mappings.size(); ++i) {
      pthread_join(threads[i], NULL);
    }

  }

};

void * _threaded_foo_func(void * args) {
  box * b = (box*) args;
  bar * the_bar = b->the_bar;
  foo * the_foo = b->the_foo;
  the_foo->foo_func(the_bar);
  return NULL;
}

My questions are:

  • Is there a better way to do this? Cleaner? Thoughts on using fork()?
  • Does this look like a poor design of the relationship between foo & bar?

To make this fun, you're only allowed to use pthread.h, no C++11 stuff :)

\$\endgroup\$
  • 1
    \$\begingroup\$ Can you use C++11's std::thread? \$\endgroup\$ – Rob Apr 30 '12 at 16:55
  • 1
    \$\begingroup\$ If your threads are cpu bound, starting one for every element in the map will overload the CPU. A better technique is to create a pipe/mailbox with the number of worker threads for the number of cores on the machine and then feeding the arguments into the pipe. Each thread is a loop reading from the pipe and then exits when the pipe is empty. \$\endgroup\$ – Burton Samograd Apr 30 '12 at 16:57
  • \$\begingroup\$ I'd like to, but let's say that we're a special kind of lazy and would just rather use pthread.h \$\endgroup\$ – K-RAN Apr 30 '12 at 16:57
  • \$\begingroup\$ @K-RAN: Then look into (for one example) Anthony Williams's implementation of a thread-safe queue using condition variables. \$\endgroup\$ – Jerry Coffin Apr 30 '12 at 17:02
  • \$\begingroup\$ @BurtonSamograd -- How do I ensure that the threads are not CPU bound, if possible? Also, say that I were to implement the pipe/mailbox schema with worker threads: is there a way to find out the number of cores that the native machine has? I'm kinda new to this particular side of C/C++ programming so any kind of reference would be greatly appreciated. \$\endgroup\$ – K-RAN Apr 30 '12 at 17:03
3
votes
\$\begingroup\$

How many instances of foo are you going to have? Spawning a large number of threads or forking a large number of processes isn't going to scale well in terms of both CPU and memory resources.

Another approach that generally has better scalability is a thread pool. The basic idea is that you have a fixed number of threads that pull and execute tasks from a queue, resulting in better resource utilization.

\$\endgroup\$
1
vote
\$\begingroup\$

You might want to take a look at C++'s new std::thread class, which is part of the C++11 standard library. Its constructor is scheduled to run the created thread immediately and takes a function object such as a function pointer or lambda function and function arguments. It has the same mechanisms and functionality as pthreads but is platform-independent and object-oriented, making your code cleaner and more consistent with C++ style.

std::thread can be used in gcc by compiling with the -std=c++0x flag for gcc 4.6 and earlier (I believe back to 4.4) and with std=c++11 on gcc 4.7. Visual Studio 2010 doesn't support it, and it can be used in Visual Studio 11 by default.

\$\endgroup\$
  • \$\begingroup\$ I didn't specify in the question that you're only allowed to use pthread.h, sorry about the confusion. I'll definitely take a look at C++11 though so thanks! \$\endgroup\$ – K-RAN Apr 30 '12 at 17:05

Not the answer you're looking for? Browse other questions tagged or ask your own question.