r708 - trunk/game

lordhavoc at icculus.org lordhavoc at icculus.org
Fri May 5 17:50:55 EDT 2006


Author: lordhavoc
Date: 2006-05-05 17:50:55 -0400 (Fri, 05 May 2006)
New Revision: 708

Modified:
   trunk/game/g_entity.c
Log:
reworked G_Entity_New some more to fix a horrible crash and added more
comments


Modified: trunk/game/g_entity.c
===================================================================
--- trunk/game/g_entity.c	2006-05-05 21:32:26 UTC (rev 707)
+++ trunk/game/g_entity.c	2006-05-05 21:50:55 UTC (rev 708)
@@ -8,9 +8,8 @@
 G_Entity *G_Entity_New(G_Entity *parent, const G_Entity_Class *eclass, const G_Entity_Position *position)
 {
 	G_Entity *entity;
-	Nbool bestfound = false;
-	Nvec tbest = 0;
-	NUint32 childindex = 0, bestindex = 0;
+	Nvec tbest;
+	NUint32 childindex = 0, bestindex, index;
 	if (!eclass)
 		return NULL;
 	if (!eclass->codeclass->name)
@@ -36,35 +35,45 @@
 	if (!position)
 		position = &GS.identityposition;
 
-	for (entity = G.entities + G.allocentity;G.allocentity < G_MAX_ENTITIES;G.allocentity++, entity++)
+	// search for the first available entity slot in an optimized manner.
+	// G.allocentity tracks the first known gap in the G.entities array, it is
+	// incremented until a gap is found, and reset when an entity is freed
+	while (G.allocentity < G_MAX_ENTITIES && G.entities[G.allocentity].eclass)
+		G.allocentity++;
+	// if we couldn't find any at all, return NULL
+	if (G.allocentity >= G_MAX_ENTITIES)
 	{
+		Console_Printf("Ran out of entities (%i)\n", G_MAX_ENTITIES);
+		return NULL;
+	}
+	// now we know we're sitting at a valid free slot, but we want to choose
+	// one that hasn't been freed recently as there may still be references
+	// pointing to it (usually they will be cleared a moment later)
+	bestindex = G.allocentity;
+	tbest = G.entities[bestindex].freetime;
+	for (index = G.allocentity + 1, entity = G.entities + index;index < G_MAX_ENTITIES;index++, entity++)
+	{
 		if (!entity->eclass)
 		{
-			if (G.time - entity->freetime >= FREETIMEOUT)
+			if (entity->freetime == 0 || G.time - entity->freetime >= FREETIMEOUT)
 			{
 				// this entity has not been used recently, so anything
 				// referencing it has probably cleared its references already,
 				// so it is probably safe to reuse it now
-				bestfound = true;
-				bestindex = G.allocentity++;
+				bestindex = index;
+				tbest = entity->freetime;
 				break;
 			}
-			else if (!bestfound || (entity->freetime < tbest))
+			else if (entity->freetime < tbest)
 			{
 				// found a free slot that hasn't timed out yet, keep track of
-				// which one is oldest incase we can't find one
+				// which one is oldest incase we can't find any safe ones
 				// (this is a dangerous situation but it's even worse to fail)
-				bestfound = true;
-				bestindex = G.allocentity;
+				bestindex = index;
 				tbest = entity->freetime;
 			}
 		}
 	}
-	if (!bestfound)
-	{
-		Console_Printf("Ran out of entities (%i)\n", G_MAX_ENTITIES);
-		return NULL;
-	}
 	entity = G.entities + bestindex;
 	// update entity range to include this newly allocated entity
 	// (the entity range is used to avoid processing the entire array each




More information about the neither-commits mailing list