views:

217

answers:

2

Hi,

I´m using a class that encapsulates a thread_group, and have some questions about it

class MyGroup{

private:
     boost::this_thread::id _id;
     boost::thread::thread_group group;
     int abc;
     //other attributes
public:

     void foo();


};

In the class constructor, i launch N threads

for (size_t i=0;i<N;i++){
      group.add(new boost::thread(boost::bind(&foo,this)));
}


void foo(){

   _id = boost::this_thread::get_id();
   //more code.
   abc++ //needs to be sync?
}

So, here are my questions.

Do class attributes need to be synchronized?

Do every thread get a different id? For example, if I have

void bar(){
  this->id_;
}

will this result in different ids for each thread, or the same for everyone?

Thanks in advance !

+1  A: 

Yes, shared data access must be protected even if you use thread creation helpers as boost.

In the end they all will execute the same code at the same time, and there is nothing a library can do to put protection around a variable you own and you manage.

If this->_id prints the current thread id then yes, it will print different values while different threads access it.

Arkaitz Jimenez
If bar() is called from a function other than foo() (i.e, one that runs in a single thread), will it still print different values, or it will print the id of the thread calling bar()?
Tom
If that function is called from any function called from foo() in a chain, it'll be effectively executed from different threads, and have different _ids.
Arkaitz Jimenez
A: 

I don't know what you are doing with this thread_group so this may or may not apply.

Yes, all threads will have a unique ID.

Yes, you need to protect your shared state, you can do this with synchronization or by 'avoiding' shared state by copying it or with message passing.

A relevant pattern here is the 'actor' pattern.

Essentially rather than just create threads in your constructor, consider either:

a) have a class that derives from boost::thread and store thread specific members there. you can then access the member variables in the thread which won't be global to the group.

e.g.

class MyThreadClass : public boost::thread
{
   private:
   int thread_local_int;
   ...
}

b) have a class that contains a boost::thread as a member variable

class MyThreadClass : public boost::thread
{
   private:
      int thread_local_int;
      boost::thread t;
   public:
      boost::thread& GetThread()
      {
          return t;
      }
   ...
}

store a collection of either of these in your MyGroup class and use thread_group::add_thread to put the threads in the thread_group.

You can now be incredibly thoughtful about which state is shared in the thread_group (it should be synchronized or read-only) and which state is local to your actor (or thread) and how it's accessible.

Note, I have a personal reluctance against using TLS because I like having some control and guarantees over lifetimes of objects and threads and I just find this easier when I don't use it; YMMV and its great for some uses...

Rick