[C++ using Visual Studio Professional 2012]
Hi All, I am having trouble using std::mutex to prevent main() from changing variables that a second thread is accessing. In the following example (which is a massively simplified representation of my actual program) the function update() runs from the std::thread t2 in main(). update() checks if the vector world.m_grid[i][j].vec is empty and, if it is not, modifies the value contained. main() also accesses and occasionally clears this vector, and as a result if main() clears the vector after the empty check in update() but before world.m_grid[i][j].vec[0] is modified you get a vector subscript out of range error. I am trying to use std::mutex to prevent this from happening by locking barrier before the update() empty check, and releasing it after world.m_grid[i][j].vec[0] has been modified by update(), and after extensive browsing of mutex tutorials and examples I am unable to understand why the following does not have the desired effect:
#include <cstdlib>
#include <thread>
#include <mutex>
#include <vector>
using namespace std;
mutex barrier;
class World
{
public:
int m_rows;
int m_columns;
class Tile
{
public:
vector<int> vec;
int someVar;
};
vector<vector<Tile> > m_grid;
World (int rows = 100, int columns = 200): m_rows(rows), m_columns(columns), m_grid(rows, vector<Tile>(columns)) {}
};
void update(World& world)
{
while (true)
{
for (int i = 0; i < world.m_rows; ++i)
{
for (int j = 0; j < world.m_columns; ++j)
{
if (!world.m_grid[i][j].vec.empty())
{
lock_guard<mutex> guard(barrier);
world.m_grid[i][j].vec[0] += 5;
}
}
}
}
}
int main()
{
World world;
thread t2(update, ref(world));
while (true)
{
for (int i = 0; i < world.m_rows; ++i)
{
for (int j = 0; j < world.m_columns; ++j)
{
int random = rand() % 10;
if (world.m_grid[i][j].vec.empty() && random < 3) world.m_grid[i][j].vec.push_back(1);
else if (!world.m_grid[i][i].vec.empty() && random < 3) world.m_grid[i][j].vec.clear();
}
}
}
t2.join();
return 0;
}
I must be missing something fundamental here. Ideally the solution would just lock down world.m_grid[i][j] (leaving the rest of world.m_grid accessible to main()), which I assume would involve including a mutex in the class “Tile”, but I run into the same problem as described here: Why does std::mutex create a C2248 when used in a struct with WIndows SOCKET? and have been unable to adapt the solution described to my project, so it would be extra helpful if someone was able to help me out there too.
-Thankyou for your time.
[edit] spelling
You need to lock the mutex also in you main function when you access the array:
With mutexes you need to secure all accesses to your data. So far in your code thread 2 generates a mutex when it access the data. However the main thread can change the code as it does not know anything about the mutex. So the main thread can simply change the data.