Game::Game( int _gameType , std::vector< Player > _player )
{
player = _player;
state = GAME_STATE_WAITCONNECT;
std::cout << "-- Game created!\n"
<< "\t" << player.size() << "\n"
<< "\t" << player[0].netID << "\n"
<< "\t" << this << "\n"
<< "\t" << state << "\n";
thread = new boost::thread( &Game::main , &this[0] );
}
void Game::main()
{
std::cout << "Loop of: " << this << "\n" //Same as constructor//
<< "\t" << player.size() << "\n" //ALWAYS ZERO
<< "\t" << state << "\n"; //Same as constructor//
}
The problem is that state (class variable) gets changed and read properly from both ends, player does NOT. Player, when printed its ".size()" inside the thread, always produces 0, regardless of how many is fed into the constructor.
To reiterate myself:
The constructor outputs everything expected, whereas in main (called when thread starts) player (a vector) is always empty.
My assumption is that the Game object is being destructed before main(). Define a destructor, output something there, and see if that's the case. Can you show us the code where Game objects are being created and loaded into your vector? Also of note - vectors often have to re-allocate storage, if they grow beyond their bounds, which is going to invalidate the 'this' pointers you are storing when creating new boost::threads. Change your containing vector from vector<Game> to vector<Game *>, and load it via myVector.push_back(new Game(...));
I don't think reallocating will be a problem here because he isn't referring to a vector via a pointer to its elements, he's referring to it through to the object itself... so there's no way it could be out of sync (provided there aren't any issues with multiple threads accessing it at once, but I don't see any indication of that here).
@OP:
Is this code the actual code that produces the problem? Or is this a simplified version? If it's simplified, did you try actually running it and making sure the problems still exists?
The reason I ask is that I don't see any reason why this code wouldn't work as posted. So I really think you are doing something else wrong that isn't posted here.
EDIT:
I just tried out your minimal example and it works without a problem:
Note the last section of output - mId == -2! This means the destructor was called on the object, but it's still executing. What I suggested may be happening is, OP has a vector size=3, then goes to add a 4th item. The vector needs to resize, so in order to do so, it calls the copy constructor for each element to move it into the new storage. But the original storage (now deleted) is still there, and available for re-allocation. However, the boost thread is still running, and has a pointer to the de-allocated object. When the object's main() is called, it is still in the same location, so the object outputs the same 'this' pointer.
You may be right...I took "Its the constructor for the class that is being put in a vector (not shown)." to mean that he was doing something along these lines
Yep, changing the vectors to std::vector< Game* > fixed the problem. I think it was a problem is vector reallocating for resizing.
This is good that I found this problem this early, because I plan on there being many games being created and ending constantly, so this method will make that safe.
Also, what is a good way to end a thread from outside of the thread? My idea that I'm trying right now is having a boolean instance variable for when if its flipped (from the outside) that the thread will check every once in a while for if it needs to end. Is this the best way?
My idea that I'm trying right now is having a boolean instance variable for when if its flipped (from the outside) that the thread will check every once in a while for if it needs to end. Is this the best way?
Most solutions are variations of this with varying degrees of sophistication.
A better solution for your particular case might be to give each thread a (thread-safe) message queue, and have the thread respond to certain messages in specific ways. For example, it will respond to the message QUIT by cleanly terminating itself.
Arg! It seems that calling game.erase( game.begin() + 0 ) to delete one of the objects is NOT calling the destructor of that game. Is this true that if you have a vector of pointers that it will not delete the object at the pointer that you call to erase?
Is this true that if you have a vector of pointers that it will not delete the object at the pointer that you call to erase?
Yes, you have to delete the pointer before removing it from the container.
1 2
delete game.front();
game.erase(game.begin());
By the way, if you're going to be removing objects from the front very often, it may be better to use a list (if you don't need random access) or a deque (if you do).
Yet another possibility, that may or may not be a good idea in your particular case, could be to just leave the vector unshrunken, but zero out deleted pointers so they can be reused later on.