(svn r3143) -Codechange: greatly increased speed when allocating vehicles
authorbjarni
Sat, 05 Nov 2005 19:58:16 +0000
changeset 2606 7ae924de184b
parent 2605 d9d7eecdd1f1
child 2607 08f42ae6fbfc
(svn r3143) -Codechange: greatly increased speed when allocating vehicles
This increases the speed greatly when allocating more than one at a time
(planes, artic engines, cloning...) and when adding another block of
vehicles to the vehicle pool (adding 512 vehicles each time)
vehicle.c
--- a/vehicle.c	Sat Nov 05 18:32:21 2005 +0000
+++ b/vehicle.c	Sat Nov 05 19:58:16 2005 +0000
@@ -297,49 +297,64 @@
 	return NULL;
 }
 
-Vehicle *AllocateVehicle(void)
+/*
+ * finds a free vehicle in the memory or allocates a new one
+ * returns a pointer to the first free vehicle or NULL if all vehicles are in use
+ * *skip_vehicles is an offset to where in the array we should begin looking
+ * this is to avoid looping though the same vehicles more than once after we learned that they are not free
+ * this feature is used by AllocateVehicles() since it need to allocate more than one and when
+ * another block is added to _vehicle_pool, since we only do that when we know it's already full
+ */
+static Vehicle *AllocateSingleVehicle(VehicleID *skip_vehicles)
 {
 	/* See note by ForceAllocateSpecialVehicle() why we skip the
 	 * first blocks */
 	Vehicle *v;
+	const int offset = (1 << VEHICLES_POOL_BLOCK_SIZE_BITS) * BLOCKS_FOR_SPECIAL_VEHICLES;
 
-	FOR_ALL_VEHICLES_FROM(v, (1 << _vehicle_pool.block_size_bits) * BLOCKS_FOR_SPECIAL_VEHICLES) {
-		if (v->type == 0)
-			return InitializeVehicle(v);
+	if (*skip_vehicles < (_vehicle_pool.total_items - offset)) {	// make sure the offset in the array is not larger than the array itself
+		FOR_ALL_VEHICLES_FROM(v, offset + *skip_vehicles) {
+			(*skip_vehicles)++;
+			if (v->type == 0)
+				return InitializeVehicle(v);
+		}
 	}
 
 	/* Check if we can add a block to the pool */
 	if (AddBlockToPool(&_vehicle_pool))
-		return AllocateVehicle();
+		return AllocateSingleVehicle(skip_vehicles);
 
 	return NULL;
 }
 
+Vehicle *AllocateVehicle(void)
+{
+	VehicleID counter = 0;
+	return AllocateSingleVehicle(&counter);
+}
+
 /** Allocates a lot of vehicles and frees them again
-* @param vl pointer to an array of vehicles that can store all the vehicles in the test
-* @param num number of vehicles to test for
+* @param vl pointer to an array of vehicles to get allocated. Can be NULL if the vehicles aren't needed (makes it test only)
+* @param num number of vehicles to allocate room for
 *	returns true if there is room to allocate all the vehicles
 */
 bool AllocateVehicles(Vehicle **vl, int num)
 {
 	int i;
 	Vehicle *v;
-	bool success = true;
+	VehicleID counter = 0;
 
 	for(i = 0; i != num; i++) {
-		vl[i] = v = AllocateVehicle();
+		v = AllocateSingleVehicle(&counter);
 		if (v == NULL) {
-			success = false;
-			break;
+			return false;
 		}
-		v->type = 1;
+		if (vl != NULL) {
+			vl[i] = v;
+		}
 	}
 
-	while (--i >= 0) {
-		vl[i]->type = 0;
-	}
-
-	return success;
+	return true;
 }
 
 
@@ -1550,13 +1565,8 @@
 			veh_counter++;
 		} while ((v = v->next) != NULL);
 
-		{
-			Vehicle **vl = malloc(sizeof(Vehicle*) * veh_counter);	// some platforms do not support Vehicle *vl[veh_counter]
-			bool can_allocate_vehicles = AllocateVehicles(vl, veh_counter);
-			free(vl);
-			if (!can_allocate_vehicles) {
-				return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME);
-			}
+		if (!AllocateVehicles(NULL, veh_counter)) {
+			return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME);
 		}
 	}