Game Development Reference
In-Depth Information
That's all there is to creating, running, and waiting for threads in C++. The next task is to work out
how to make sure that threads can share data between each other without causing issues.
Sharing Data Between Threads Using Mutexes
Multithreaded programming introduces problems. What happens if two threads try to access the
same variables at exactly the same time? Data can be inconsistent, data can be wrong, and changes
can be lost. In the very worst examples your programs will crash. The updated main function in
Listing 25-2 shows an example of a program that would crash when both threads access the same
functions at the same time.
Listing 25-2. A Version of
_tmain
That Would Crash
int _tmain(int argc, _TCHAR* argv[])
{
new SerializationManager();
Game game;
std::thread gameThread{ RunGameThread, std::ref{ game } };
assert(gameThread.joinable());
while (!game.HasFinished())
{
// Stick a breakpoint below to see that this code
// is running at the same time as RunGame!
int x = 0;
}
gameThread.join();
delete SerializationManager::GetSingletonPtr();
return 0;
}
This code would crash because the
Game::HasFinished
method is being called repeatedly. It is
guaranteed that both the main
thread
and the game
thread
would try to access the variables inside
HasFinished
at the same time. Listing 25-3 contains the
Game::HasFinished
method.
Listing 25-3.
Game::HasFinished
bool HasFinished() const
{
return (m_playerQuit || m_playerWon);
}
The
Game
class tries to write to the
m_playerWon
variable once every loop. Eventually the main
thread
will try to read the
m_playerWon
variable at the same time as the game thread is writing to it and the
program will close. You solve this problem by using mutual exclusion. C++ provides a
mutex
class
that blocks execution on multiple threads around accesses to shared variables. By adding the code
from Listing 25-4 you can create a
mutex
in the
Game
class.