Since this is threaded, you can assume that
thread1add and thread1recieve will be called in order (their order dictated by the first thread). But thread1loop could be anywhere in there. You could have any one of these scenarios:
1:
thread1loop
thread1add
thread1recieve
2:
thread1add
thread1loop
thread1recieve
3:
thread1add
thread1recieve
thread1loop
And, if you read your code carefully, only the second one results in loaded data. Otherwise you add then receive from the queue without loading anything.
You'll need more states for your data, instead of "exists" something more like:
enum eLoaderState
{
LoadState_Empty,
LoadState_Queued,
LoadState_Loading,
LoadState_Loaded
};
It would also probably be more obvious what is going on if you just queue on both ends (notice you don't need a loaderstate if you do it this way):
class world
{
// ... stuff
struct ChunkInfo
{
int m_x,m_y,m_z;
int m_offx, m_offy, m_offz;
chunk *m_pChunk;
ChunkInfo( int x, int y, int z
int offx, int offy, int offz ) : m_x(x), m_y(y), m_z(z), m_offx(offx), m_offy(offy), m_offz(offz), m_pChunk(NULL) {}
};
boost::mutex m_loaderInMutex;
std::dequeue<ChunkInfo> m_loaderInQueue;
boost::mutex m_loaderOutMutex;
std::dequeue<ChunkInfo> m_loaderOutQueue;
}
void world::thread1add(int x, int y, int z)
{
boost::mutex::scoped_lock( m_loaderInMutex );
loaderInQueue.push_back( ChunkInfo( x, y, z, xOffset, yOffset, zOffset ) );
}
//Called by Thread0 - Main
void world::thread1recieve()
{
ChunkInfo info;
{
boost::mutex::scoped_lock lock(m_loaderOutMutex);
if( m_loaderOutQueue.empty() )
return;
info = m_loaderOutQueue.front();
m_loaderOutQueue.pop_front();
}
Chunk[info.m_x][info.m_y][info.m_z] = info.m_pChunk; // I assume this is your world map?
chunkExists[info.m_x][info.m_y][info.m_z] = true; // And now your map knows it has an item there?
}
//Called by Thread1 - Loader
void world::thread1loop()
{
while (running)
{
ChunkInfo info;
{
m_loaderInMutex.lock();
if( m_loaderInQueue.empty() )
{
// here, you'd really want to setup a CV to sleep on instead of just unlock+yield+loop, it would be cv.wait(); loop;
m_loaderInMutex.unlock();
boost::thread::yield();
continue;
}
info = m_loaderInQueue.front();
m_loaderInQueue.pop_front();
m_loaderInMutex.unlock();
}
signed int xCur=info.m_x + info.m_offx - HALFCLIPDIST;
signed int yCur=info.m_y + info.m_offy - HALFCLIPDIST;
signed int zCur=info.m_z + info.m_offz - HALFCLIPDIST;
info.m_pChunk = new chunk(xCur,yCur,zCur);
Writer_thing->read_chunk( info.m_pChunk, xCur, yCur, zCur ); // here you'd do the exact file IO to load this particular chunk
{
boost::mutex::scopted_lock lock( m_loaderOutMutex );
m_loaderOutQueue.push_bacK( info );
}
bufferInitAll();
cout << "-------------------------------------------------! New Chunks added by thread 2!-------------------------------------------------\n";
}
}
Sorry this stuff isn't tested but hopefully it will help you find the bugs.