Game Development Community

GServerContainer.castRay thread safe?

by Justin Mosiman · in Torque Game Engine Advanced · 12/25/2007 (10:18 pm) · 2 replies

I'm hoping somebody smarter than me can answer this question..

Here's what I am trying to do: I have used the A* pathfinding algorithm with atlas, and that works as expected. In order to determine if the node can be traversed, I am doing the following:
if(gServerContainer.castRay(Point3F(x,y,75),Point3F(x,y,-5), WaterObjectType | AtlasObjectType, &rInfo))

I initially call this function at statup after you choose the map. It takes a second or two to generate the pathfinding data and I'd like to reduce this. I have reduced the number of nodes that it checks but I was thinking that I could just use a separate thread and you wouldn't see the delay at all.

I have the additional thread being created correctly (using the class Thread from platformThread), but when I try to run the game I am always getting the memory reading error:
Quote:
First-chance exception at 0x00000000 in TGEA_DEBUG.exe: 0xC0000005: Access violation reading location 0x00000000.

In the debugger it always quits at:
if ((v = (uIntf*)ZALLOC(z, 19, sizeof(uInt))) == Z_NULL)
    return Z_MEM_ERROR;
in the file lib\zlib\inftrees.c (line 305-306).

If I switch over to the thread that I created for the pathfinding there isn't a constant value that appears when it fails. Sometimes it gets to an x value of 81 and other times 262. There also isn't a constant piece of code that is being called when it fails (on the pathfinding thread).

I don't have a great understanding of how Torque works as a whole, which is what I think it is going to take with this problem.. Based on the debugging I've done, I wonder if the gServerContainer.castRay is thread safe. If I change gServerContainer to gClientContainer everything works fine, except my pathfinding (it is generated on the server).

If anybody has any idea at all, any help would be greatly appreciated.

Thanks,
Justin

#1
12/31/2007 (8:45 pm)
I'm still getting this error... if it helps, it is stopping at about a third of the way through when it is loading the datablocks. I have been trying to debug this and I keep thinking I am getting closer to solving the problem but it's just not working... so any suggestions are welcomed.
#2
01/28/2008 (5:37 pm)
I thought maybe if I took a break from this and come back to it, it would help.. but no.

Let me post more of my code. I am casting a ray on the atlas terrain to see if it is traversable or not, and I am trying to use a separate thread to do that.

The following code creates the new thread
void AtlasPathfind::genPathfinding(int xMax, int yMax)
{
	mMaxX = xMax;
	mMaxY = yMax;

	// Create a new thread for generating the pathfinding
	if(!mGenPathfindingThreadActive){
      mGenPathfindingThreadActive = true;
      mGenPathfindingThread = new Thread(genPathfindingThunk, this);
   }
}

And then this actual does the ray casting
void AtlasPathfind::genPathfindingThunk(void *d)
{
   ((AtlasPathfind*)d)->genPathfindingThread();
}

void AtlasPathfind::genPathfindingThread()
{
	Mutex::lockMutex(mGenPathfindingMutex);
	// We don't want to take into account every position, so divide it by the space in between the nodes
	int xMax = ((mMaxX / NODE_SPACE) + 1);
	int yMax = ((mMaxY / NODE_SPACE) + 1);
	// Allocate memory for the arrays
	mPathfindData = Allocate2DArray<U8>(xMax,yMax);
	mCleanWhichList = Allocate2DArray<U8>(xMax,yMax);

	PROFILE_START(pathfinding_rayCast);
	for(int x = 0; x < mMaxX; x += NODE_SPACE){
		S32 xArray = getArrayPointFromNodePoint(x);
		for(int y = 0; y < mMaxY; y += NODE_SPACE){
			S32 yArray = getArrayPointFromNodePoint(y);
			mPathfindData[xArray][yArray] = TRAVERSABLE;
			RayInfo rInfo;
			if(gServerContainer.castRay(Point3F(x,y,75),Point3F(x,y,-5),
												 WaterObjectType | AtlasObjectType, &rInfo))
			{
				if(rInfo.object->getClassName() == "AtlasInstance2"){
					if(rInfo.normal.z > 0.94){
						mPathfindData[xArray][yArray] = TRAVERSABLE;
					}else{
						mPathfindData[xArray][yArray] = NONTRAVERSABLE;
					}
				}else if(rInfo.object->getClassName() == "WaterBlock"){
					mPathfindData[xArray][yArray] = NONTRAVERSABLE;
				}
				mCleanWhichList[xArray][yArray] = ON_NO_LIST;
			}
		}
	}
	PROFILE_END();

	Mutex::unlockMutex(mGenPathfindingMutex);
}

Anybody see anything that doesn't look thread friendly? I am creating the mutex in the constructor and destroying it in the destructor. It is still failing at that ZALLOC line from above.

Thank you