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\$

locked by Jamal Aug 9 '14 at 23:57

This question exists because it has historical significance, but it is not considered a good, on-topic question for this site so please do not use it as evidence that you can ask similar questions here. This question and its answers are frozen and cannot be changed. See the help center for guidance on writing a good question.

Read more about locked posts here.

migrated from stackoverflow.com Apr 30 '12 at 19:47

This question came from our site for professional and enthusiast programmers.

  • 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.