Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c++11 threads don't modify same values

I'm writing a program that (ideally) requires two threads to run simultaneously.

I have a global vector variable myObjects to keep track of my Objects:

vector<Object> myObjects;

And a object of type MoND that will be doing the heavy lifting. It is initialized with the vector as an argument and it pushes "Objects" into the vector. No problem so far.

MoND  mySim =  MoND(myObjects);

In main, a method of mySim needs to be called with myObjects as an argument. In a non-threaded version I used for testing, this works (run bails out after 100 iterations):

int main(int argc, char** argv) {
  ...
  mySim.Run(myObjects);// Run simulation on Objects
  glutMainLoop();      // Enter the event-processing loop                                                                                            
  return 0;
}

By works I mean changes the properties of the Objects stored in myObjects. This needs to run persistently and concurrently so it's not ideal.

Using threading:

int main(int argc, char** argv) {
  ...
  thread t1(&MoND::Run, mySim, myObjects);// Run simulation on Objects
  glutMainLoop();      // Enter the event-processing loop                                                                                            
  return 0;
}

This doesn't have the desired effect. Run() receives myObjects and changes their values, but these are not translated to the myObjects being used by the main thread. Is another instance of myObjects created in memory for the new thread? (yes, I did pass by reference and the non-threaded version does update the values just fine)

So I know the logic works (everything works as expected without threading). I have tried to use atomic but to be honest I can't get it to work with a vector or its contents.

How can I force the two threads to work on the same instance of myObjects in memory (i.e. get them to share the variable)?

Some points:

  • No, I'm not worried about thread safety as only one thread writes, the other just reads (order of reading/writing is unimportant)

  • Run() updates the values of private variables in objects of class Object through methods SetPos(args..) and SetVel(args..)

like image 837
fnands Avatar asked Dec 15 '22 22:12

fnands


1 Answers

The std::thread constructor copies its arguments to make sure that they are still alive when they are being operated on.

To avoid that, you can use std::ref:

thread t1(&MoND::Run, mySim, std::ref(myObjects));

Here you promise that you take care of your object's lifetime.

std::bind and std::async exhibit the same behavior out of the same reasons.

Note that mySim is also being copied, here however you could also pass a pointer if don't want the copy.

like image 86
Stephan Dollberg Avatar answered Dec 31 '22 16:12

Stephan Dollberg