[ ] Chunk management [ ]

Started by
11 comments, last by coderWalker 13 years, 1 month ago
I'd say it probably comes down to "thread1Quene[a].exists". When you enqueue an item, you set it to true. When you look to deque an item you check if it is true, then set it to false. So... how do you know it has any data in it? You don't, since there isn't a flag for that.

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.
Advertisement
Hey man I have never worked with Quenes before so, I kinda want to stick to the array method.
I have changed the Mutex's and how it works. However the new code still gives a segmentation Fault.
(It has to be setting a ChunkExists to true when a chunk does not exist?

The main ~ (~0) creates the loader ~ (~1).
~0 adds tasks to thread1Quene[]
when ~1 sees a task it performs it and writes results in thread1Done[]
~0 checks the results array ( thread1Done[] ) if it sees a result it moves it to the game world (chunk* chunk[] and chunkExists=true)

Has to be a problem with how I am moving the data?


//Called by Thread0 - Main
void world::thread1add(int x, int y, int z)
{
boost::mutex::scoped_lock( mWrite );
for(int a=0;a<thread1QueneLimit;a++)
{
if (thread1Quene[a].state==NOTEXIST)
{
thread1Quene[a].x = x;
thread1Quene[a].y = y;
thread1Quene[a].z = z;
thread1Quene[a].state = NEW;
return;
}
}
cout << "/!\\ Thread1 Buffer Full!!!";
}
//Called by Thread1 - Loader
void world::thread1addDone(int x, int y, int z, chunk* chk)
{
boost::mutex::scoped_lock( mRead );
for(int a=0;a<thread1QueneLimit;a++)
{
if (thread1Done[a].state==NOTEXIST)
{
thread1Done[a].x = x;
thread1Done[a].y = y;
thread1Done[a].z = z;
thread1Done[a].chk = chk;
thread1Done[a].chk->bufferInit();
thread1Done[a].state = EXIST;
return;
}
}
cout << "/!\\ Thread1 Done Buffer Full!!!";
}
//Called by Thread0 - Main
void world::thread1recieve()
{
//boost::mutex::scoped_lock lock(mMain);
boost::mutex::scoped_lock lock(mRead);
//boost::scoped_lock( mMapLoading );
//loader_cv.wait( mMapLoading );
for(int a=0;a<thread1QueneLimit;a++)
{
if (thread1Done[a].state==EXIST)
{
Chunk[thread1Done[a].x][thread1Done[a].y][thread1Done[a].z] = thread1Done[a].chk;
chunkExists[thread1Done[a].x][thread1Done[a].y][thread1Done[a].z] = true;
//delete thread1Quene[a].chk;
thread1Done[a].state = NOTEXIST;
}
}
}
//Shift Thread 1
void world::thread1shift(signed int x, signed int y, signed int z)
{
boost::mutex::scoped_lock lock(mWrite);
boost::mutex::scoped_lock lock2(mRead);
for(int a=0;a<thread1QueneLimit;a++)
{
if (thread1Quene[a].state!=NOTEXIST)
{
thread1Quene[a].z+=z;
thread1Quene[a].y+=z;
thread1Quene[a].x+=z;
// /!\ Checks only Z
if (thread1Quene[a].z>=CLIPDIST || thread1Quene[a].z<0 || thread1Quene[a].x>=CLIPDIST || thread1Quene[a].x<0 || thread1Quene[a].y>=CLIPDIST || thread1Quene[a].y<0)
{
thread1Quene[a].state = NOTEXIST;
}
}
if (thread1Done[a].state!=NOTEXIST)
{
thread1Done[a].z+=z;
thread1Done[a].y+=z;
thread1Done[a].x+=z;
// /!\ Checks only Z
if (thread1Done[a].z>=CLIPDIST || thread1Done[a].z<0 || thread1Done[a].x>=CLIPDIST || thread1Done[a].x<0 || thread1Done[a].y>=CLIPDIST || thread1Done[a].y<0)
{
thread1Done[a].state = NOTEXIST;
}
}
}
}
//Called by Thread1 - Loader
void world::thread1loop()
{
while (running)
{
boost::mutex::scoped_lock lock(mWrite);
bool changed=false;
for(int a=0;a<thread1QueneLimit;a++)
{
if (thread1Quene[a].state==NEW)
{
signed int xCur=thread1Quene[a].x+xOffset-HALFCLIPDIST;
signed int yCur=thread1Quene[a].y+yOffset-HALFCLIPDIST;
signed int zCur=thread1Quene[a].z+zOffset-HALFCLIPDIST;
//thread1Quene[a].chk = Writer->readChunk(xCur,yCur,zCur);
//thread1Quene[a].state = EXIST;
thread1addDone(thread1Quene[a].x,thread1Quene[a].y,thread1Quene[a].z,Writer->readChunk(xCur,yCur,zCur));
thread1Quene[a].state=NOTEXIST;
//cout << xCur << "\n" << yCur << "\n";
//Writer->readChunk(xCur,yCur,zCur,iChunkX,iChunkY,iChunkZ);
//Writer->writeChunk(xCur,yCur,zCur,iChunkX,iChunkY,iChunkZ);
changed=true;
}
}
if (changed)
{
//bufferInitAll();
cout << "-------------------------------------------------! New Chunks added by thread 2!-------------------------------------------------\n";
}
}
}
If this post was helpful please +1 or like it !

Webstrand

Hey man I have never worked with Quenes before so, I kinda want to stick to the array method.
I have changed the Mutex's and how it works. However the new code still gives a segmentation Fault.
(It has to be setting a ChunkExists to true when a chunk does not exist?

The main ~ (~0) creates the loader ~ (~1).
~0 adds tasks to thread1Quene[]
when ~1 sees a task it performs it and writes results in thread1Done[]
~0 checks the results array ( thread1Done[] ) if it sees a result it moves it to the game world (chunk* chunk[] and chunkExists=true)

Has to be a problem with how I am moving the data?


//Called by Thread0 - Main
void world::thread1add(int x, int y, int z)
{
boost::mutex::scoped_lock( mWrite );
for(int a=0;a<thread1QueneLimit;a++)
{
if (thread1Quene[a].state==NOTEXIST)
{
thread1Quene[a].x = x;
thread1Quene[a].y = y;
thread1Quene[a].z = z;
thread1Quene[a].state = NEW;
return;
}
}
cout << "/!\\ Thread1 Buffer Full!!!";
}
//Called by Thread1 - Loader
void world::thread1addDone(int x, int y, int z, chunk* chk)
{
boost::mutex::scoped_lock( mRead );
for(int a=0;a<thread1QueneLimit;a++)
{
if (thread1Done[a].state==NOTEXIST)
{
thread1Done[a].x = x;
thread1Done[a].y = y;
thread1Done[a].z = z;
thread1Done[a].chk = chk;
thread1Done[a].chk->bufferInit();
thread1Done[a].state = EXIST;
return;
}
}
cout << "/!\\ Thread1 Done Buffer Full!!!";
}
//Called by Thread0 - Main
void world::thread1recieve()
{
//boost::mutex::scoped_lock lock(mMain);
boost::mutex::scoped_lock lock(mRead);
//boost::scoped_lock( mMapLoading );
//loader_cv.wait( mMapLoading );
for(int a=0;a<thread1QueneLimit;a++)
{
if (thread1Done[a].state==EXIST)
{
Chunk[thread1Done[a].x][thread1Done[a].y][thread1Done[a].z] = thread1Done[a].chk;
chunkExists[thread1Done[a].x][thread1Done[a].y][thread1Done[a].z] = true;
//delete thread1Quene[a].chk;
thread1Done[a].state = NOTEXIST;
}
}
}
//Shift Thread 1
void world::thread1shift(signed int x, signed int y, signed int z)
{
boost::mutex::scoped_lock lock(mWrite);
boost::mutex::scoped_lock lock2(mRead);
for(int a=0;a<thread1QueneLimit;a++)
{
if (thread1Quene[a].state!=NOTEXIST)
{
thread1Quene[a].z+=z;
thread1Quene[a].y+=z;
thread1Quene[a].x+=z;
// /!\ Checks only Z
if (thread1Quene[a].z>=CLIPDIST || thread1Quene[a].z<0 || thread1Quene[a].x>=CLIPDIST || thread1Quene[a].x<0 || thread1Quene[a].y>=CLIPDIST || thread1Quene[a].y<0)
{
thread1Quene[a].state = NOTEXIST;
}
}
if (thread1Done[a].state!=NOTEXIST)
{
thread1Done[a].z+=z;
thread1Done[a].y+=z;
thread1Done[a].x+=z;
// /!\ Checks only Z
if (thread1Done[a].z>=CLIPDIST || thread1Done[a].z<0 || thread1Done[a].x>=CLIPDIST || thread1Done[a].x<0 || thread1Done[a].y>=CLIPDIST || thread1Done[a].y<0)
{
thread1Done[a].state = NOTEXIST;
}
}
}
}
//Called by Thread1 - Loader
void world::thread1loop()
{
while (running)
{
boost::mutex::scoped_lock lock(mWrite);
bool changed=false;
for(int a=0;a<thread1QueneLimit;a++)
{
if (thread1Quene[a].state==NEW)
{
signed int xCur=thread1Quene[a].x+xOffset-HALFCLIPDIST;
signed int yCur=thread1Quene[a].y+yOffset-HALFCLIPDIST;
signed int zCur=thread1Quene[a].z+zOffset-HALFCLIPDIST;
//thread1Quene[a].chk = Writer->readChunk(xCur,yCur,zCur);
//thread1Quene[a].state = EXIST;
thread1addDone(thread1Quene[a].x,thread1Quene[a].y,thread1Quene[a].z,Writer->readChunk(xCur,yCur,zCur));
thread1Quene[a].state=NOTEXIST;
//cout << xCur << "\n" << yCur << "\n";
//Writer->readChunk(xCur,yCur,zCur,iChunkX,iChunkY,iChunkZ);
//Writer->writeChunk(xCur,yCur,zCur,iChunkX,iChunkY,iChunkZ);
changed=true;
}
}
if (changed)
{
//bufferInitAll();
cout << "-------------------------------------------------! New Chunks added by thread 2!-------------------------------------------------\n";
}
}
}



I think I have located the problem.
If this post was helpful please +1 or like it !

Webstrand

This topic is closed to new replies.

Advertisement