(svn r10746) -Codechange: add a generic superclass for almost all pool items so we do not have to duplicate code for each of the pool item classes and use it for the station and roadstop classes.
authorrubidium
Thu, 02 Aug 2007 08:47:56 +0000
changeset 7873 b3bccdcf85ef
parent 7872 a0646ade9d4a
child 7874 c9fae1fb5d6c
(svn r10746) -Codechange: add a generic superclass for almost all pool items so we do not have to duplicate code for each of the pool item classes and use it for the station and roadstop classes.
src/oldpool.h
src/station.cpp
src/station.h
src/station_cmd.cpp
--- a/src/oldpool.h	Wed Aug 01 23:49:06 2007 +0000
+++ b/src/oldpool.h	Thu Aug 02 08:47:56 2007 +0000
@@ -29,14 +29,14 @@
 
 	const char* name;     ///< Name of the pool (just for debugging)
 
-	uint max_blocks;      ///< The max amount of blocks this pool can have
-	uint block_size_bits; ///< The size of each block in bits
-	uint item_size;       ///< How many bytes one block is
+	const uint max_blocks;      ///< The max amount of blocks this pool can have
+	const uint block_size_bits; ///< The size of each block in bits
+	const uint item_size;       ///< How many bytes one block is
 
 	/// Pointer to a function that is called after a new block is added
-	OldMemoryPoolNewBlock *new_block_proc;
+	const OldMemoryPoolNewBlock *new_block_proc;
 	/// Pointer to a function that is called to clean a block
-	OldMemoryPoolCleanBlock *clean_block_proc;
+	const OldMemoryPoolCleanBlock *clean_block_proc;
 
 	uint current_blocks;        ///< How many blocks we have in our pool
 	uint total_items;           ///< How many items we now have in this pool
@@ -44,20 +44,45 @@
 public:
 	byte **blocks;              ///< An array of blocks (one block hold all the items)
 
-	inline uint GetSize()
+	/**
+	 * Get the size of this pool, i.e. the total number of items you
+	 * can put into it at the current moment; the pool might still
+	 * be able to increase the size of the pool.
+	 * @return the size of the pool
+	 */
+	inline uint GetSize() const
 	{
 		return this->total_items;
 	}
 
-	inline bool CanAllocateMoreBlocks()
+	/**
+	 * Can this pool allocate more blocks, i.e. is the maximum amount
+	 * of allocated blocks not yet reached?
+	 * @return the if and only if the amount of allocable blocks is
+	 *         less than the amount of allocated blocks.
+	 */
+	inline bool CanAllocateMoreBlocks() const
 	{
 		return this->current_blocks < this->max_blocks;
 	}
 
-	inline uint GetBlockCount()
+	/**
+	 * Get the maximum number of allocable blocks.
+	 * @return the numebr of blocks
+	 */
+	inline uint GetBlockCount() const
 	{
 		return this->current_blocks;
 	}
+
+	/**
+	 * Get the name of this pool.
+	 * @return the name
+	 */
+	inline const char *GetName() const
+	{
+		return this->name;
+	}
 };
 
 template <typename T>
@@ -66,7 +91,13 @@
 				OldMemoryPoolNewBlock *new_block_proc, OldMemoryPoolCleanBlock *clean_block_proc) :
 		OldMemoryPoolBase(name, max_blocks, block_size_bits, item_size, new_block_proc, clean_block_proc) {}
 
-	inline T *Get(uint index)
+	/**
+	 * Get the pool entry at the given index.
+	 * @param index the index into the pool
+	 * @pre index < this->GetSize()
+	 * @return the pool entry.
+	 */
+	inline T *Get(uint index) const
 	{
 		assert(index < this->GetSize());
 		return (T*)(this->blocks[index >> this->block_size_bits] +
@@ -99,11 +130,9 @@
 template <typename T, OldMemoryPool<T> *Tpool>
 static void PoolNewBlock(uint start_item)
 {
-	/* We don't use FOR_ALL here, because FOR_ALL skips invalid items.
-	 *  TODO - This is just a temporary stage, this will be removed. */
 	for (T *t = Tpool->Get(start_item); t != NULL; t = (t->index + 1U < Tpool->GetSize()) ? Tpool->Get(t->index + 1U) : NULL) {
+		t = new (t) T();
 		t->index = start_item++;
-		t->PreInit();
 	}
 }
 
@@ -125,6 +154,128 @@
 }
 
 
+/**
+ * Generalization for all pool items that are saved in the savegame.
+ * It specifies all the mechanics to access the pool easily.
+ */
+template <typename T, typename Tid, OldMemoryPool<T> *Tpool>
+struct PoolItem {
+	/**
+	 * The pool-wide index of this object.
+	 */
+	Tid index;
+
+	/**
+	 * We like to have the correct class destructed.
+	 */
+	virtual ~PoolItem()
+	{
+	}
+
+	/**
+	 * Called on each object when the pool is being destroyed, so one
+	 * can free allocated memory without the need for freeing for
+	 * example orders.
+	 */
+	virtual void QuickFree()
+	{
+	}
+
+	/**
+	 * An overriden version of new that allocates memory on the pool.
+	 * @param size the size of the variable (unused)
+	 * @return the memory that is 'allocated'
+	 */
+	void *operator new (size_t size)
+	{
+		return AllocateRaw();
+	}
+
+	/**
+	 * 'Free' the memory allocated by the overriden new.
+	 * @param p the memory to 'free'
+	 */
+	void operator delete(void *p)
+	{
+	}
+
+	/**
+	 * An overriden version of new, so you can directly allocate a new object with
+	 * the correct index when one is loading the savegame.
+	 * @param size  the size of the variable (unused)
+	 * @param index the index of the object
+	 * @return the memory that is 'allocated'
+	 */
+	void *operator new (size_t size, int index)
+	{
+		if (!Tpool->AddBlockIfNeeded(index)) error("%s: failed loading savegame: too many %s", Tpool->GetName(), Tpool->GetName());
+
+		return Tpool->Get(index);
+	}
+
+	/**
+	 * 'Free' the memory allocated by the overriden new.
+	 * @param p     the memory to 'free'
+	 * @param index the original parameter given to create the memory
+	 */
+	void operator delete(void *p, int index)
+	{
+	}
+
+	/**
+	 * An overriden version of new, so you can use the vehicle instance
+	 * instead of a newly allocated piece of memory.
+	 * @param size the size of the variable (unused)
+	 * @param pn   the already existing object to use as 'storage' backend
+	 * @return the memory that is 'allocated'
+	 */
+	void *operator new(size_t size, T *pn)
+	{
+		return pn;
+	}
+
+	/**
+	 * 'Free' the memory allocated by the overriden new.
+	 * @param p  the memory to 'free'
+	 * @param pn the pointer that was given to 'new' on creation.
+	 */
+	void operator delete(void *p, T *pn)
+	{
+	}
+
+	/**
+	 * Is this a valid object or not?
+	 * @return true if and only if it is valid
+	 */
+	virtual bool IsValid() const
+	{
+		return false;
+	}
+
+private:
+	/**
+	 * Allocate a pool item; possibly allocate a new block in the pool.
+	 * @return the allocated pool item (or NULL when the pool is full).
+	 */
+	static T *AllocateRaw()
+	{
+		for (T *t = Tpool->Get(0); t != NULL; t = (t->index + 1U < Tpool->GetSize()) ? Tpool->Get(t->index + 1U) : NULL) {
+			if (!t->IsValid()) {
+				Tid index = t->index;
+
+				memset(t, 0, sizeof(T));
+				t->index = index;
+				return t;
+			}
+		}
+
+		/* Check if we can add a block to the pool */
+		if (Tpool->AddBlockToPool()) return AllocateRaw();
+
+		return NULL;
+	}
+};
+
 
 #define OLD_POOL_ENUM(name, type, block_size_bits, max_blocks) \
 	enum { \
--- a/src/station.cpp	Wed Aug 01 23:49:06 2007 +0000
+++ b/src/station.cpp	Thu Aug 02 08:47:56 2007 +0000
@@ -91,29 +91,6 @@
 	free(this->speclist);
 }
 
-void *Station::operator new(size_t size)
-{
-	Station *st = AllocateRaw();
-	return st;
-}
-
-void *Station::operator new(size_t size, int st_idx)
-{
-	if (!AddBlockIfNeeded(&_Station_pool, st_idx))
-		error("Stations: failed loading savegame: too many stations");
-
-	Station *st = GetStation(st_idx);
-	return st;
-}
-
-void Station::operator delete(void *p)
-{
-}
-
-void Station::operator delete(void *p, int st_idx)
-{
-}
-
 /** Called when new facility is built on the station. If it is the first facility
  * it initializes also 'xy' and 'random_bits' members */
 void Station::AddFacility(byte new_facility_bit, TileIndex facil_xy)
@@ -176,30 +153,6 @@
 	return IsTileType(tile, MP_STATION) && GetStationIndex(tile) == index && IsRailwayStation(tile);
 }
 
-/*static*/ Station *Station::AllocateRaw()
-{
-	Station *st = NULL;
-
-	/* We don't use FOR_ALL here, because FOR_ALL skips invalid items.
-	 * TODO - This is just a temporary stage, this will be removed. */
-	for (st = GetStation(0); st != NULL; st = (st->index + 1U < GetStationPoolSize()) ? GetStation(st->index + 1U) : NULL) {
-		if (!st->IsValid()) {
-			StationID index = st->index;
-
-			memset(st, 0, sizeof(Station));
-			st->index = index;
-			return st;
-		}
-	}
-
-	/* Check if we can add a block to the pool */
-	if (AddBlockToPool(&_Station_pool)) return AllocateRaw();
-
-	_error_message = STR_3008_TOO_MANY_STATIONS_LOADING;
-	return NULL;
-}
-
-
 /** Obtain the length of a platform
  * @pre tile must be a railway station tile
  * @param tile A tile that contains the platform in question
@@ -426,36 +379,6 @@
 /*                     RoadStop implementation                          */
 /************************************************************************/
 
-/** Allocates a new RoadStop onto the pool, or recycles an unsed one
- *  @return a pointer to the new roadstop
- */
-void *RoadStop::operator new(size_t size)
-{
-	RoadStop *rs = AllocateRaw();
-	return rs;
-}
-
-/** Gets a RoadStop with a given index and allocates it when needed
-  * @return a pointer to the roadstop
-  */
-void *RoadStop::operator new(size_t size, int index)
-{
-	if (!AddBlockIfNeeded(&_RoadStop_pool, index)) {
-		error("RoadStops: failed loading savegame: too many RoadStops");
-	}
-
-	RoadStop *rs = GetRoadStop(index);
-	return rs;
-}
-
-void RoadStop::operator delete(void *p)
-{
-}
-
-void RoadStop::operator delete(void *p, int index)
-{
-}
-
 /** Initializes a RoadStop */
 RoadStop::RoadStop(TileIndex tile) :
 	xy(tile),
@@ -483,37 +406,13 @@
 
 	DEBUG(ms, cDebugCtorLevel , "I- at %d[0x%x]", xy, xy);
 
-	xy = INVALID_TILE;
-}
-
-/** Low-level function for allocating a RoadStop on the pool */
-RoadStop *RoadStop::AllocateRaw()
-{
-	RoadStop *rs;
-
-	/* We don't use FOR_ALL here, because FOR_ALL skips invalid items.
-	 * TODO - This is just a temporary stage, this will be removed. */
-	for (rs = GetRoadStop(0); rs != NULL; rs = (rs->index + 1U < GetRoadStopPoolSize()) ? GetRoadStop(rs->index + 1U) : NULL) {
-		if (!rs->IsValid()) {
-			RoadStopID index = rs->index;
-
-			memset(rs, 0, sizeof(*rs));
-			rs->index = index;
-
-			return rs;
-		}
-	}
-
-	/* Check if we can add a block to the pool */
-	if (AddBlockToPool(&_RoadStop_pool)) return AllocateRaw();
-
-	return NULL;
+	xy = 0;
 }
 
 /** Determines whether a RoadStop is a valid (i.e. existing) one */
 bool RoadStop::IsValid() const
 {
-	return xy != INVALID_TILE;
+	return xy != 0;
 }
 
 /** Checks whether there is a free bay in this road stop */
--- a/src/station.h	Wed Aug 01 23:49:06 2007 +0000
+++ b/src/station.h	Thu Aug 02 08:47:56 2007 +0000
@@ -15,6 +15,12 @@
 #include "cargopacket.h"
 #include <list>
 
+struct Station;
+struct RoadStop;
+
+DECLARE_OLD_POOL(Station, Station, 6, 1000)
+DECLARE_OLD_POOL(RoadStop, RoadStop, 5, 2000)
+
 static const byte INITIAL_STATION_RATING = 175;
 
 struct GoodsEntry {
@@ -35,7 +41,7 @@
 };
 
 /** A Stop for a Road Vehicle */
-struct RoadStop {
+struct RoadStop : PoolItem<RoadStop, RoadStopID, &_RoadStop_pool> {
 	/** Types of RoadStops */
 	enum Type {
 		BUS,                                ///< A standard stop for buses
@@ -47,23 +53,12 @@
 	static const uint MAX_BAY_COUNT   =  2;  ///< The maximum number of loading bays
 
 	TileIndex        xy;                    ///< Position on the map
-	RoadStopID       index;                 ///< Global (i.e. pool-wide) index
 	byte             status;                ///< Current status of the Stop. Like which spot is taken. Access using *Bay and *Busy functions.
 	byte             num_vehicles;          ///< Number of vehicles currently slotted to this stop
 	struct RoadStop  *next;                 ///< Next stop of the given type at this station
 
-	RoadStop(TileIndex tile);
-	~RoadStop();
-
-	void PreInit() { this->xy = INVALID_TILE; }
-	void QuickFree() {}
-
-	void *operator new (size_t size);
-	void operator delete(void *rs);
-
-	/* For loading games */
-	void *operator new (size_t size, int index);
-	void operator delete(void *rs, int index);
+	RoadStop(TileIndex tile = 0);
+	virtual ~RoadStop();
 
 	bool IsValid() const;
 
@@ -75,8 +70,6 @@
 	void FreeBay(uint nr);
 	bool IsEntranceBusy() const;
 	void SetEntranceBusy(bool busy);
-protected:
-	static RoadStop *AllocateRaw();
 };
 
 struct StationSpecList {
@@ -108,7 +101,7 @@
 	StationRect& operator = (Rect src);
 };
 
-struct Station {
+struct Station : PoolItem<Station, StationID, &_Station_pool> {
 	public:
 		RoadStop *GetPrimaryRoadStop(RoadStop::Type type) const
 		{
@@ -151,7 +144,6 @@
 	Date build_date;
 
 	uint64 airport_flags;   ///< stores which blocks on the airport are taken. was 16 bit earlier on, then 32
-	StationID index;
 
 	byte last_vehicle_type;
 	std::list<Vehicle *> loading_vehicles;
@@ -165,18 +157,9 @@
 	static const int cDebugCtorLevel = 3;
 
 	Station(TileIndex tile = 0);
-	~Station();
-
-	void PreInit() {}
-	void QuickFree();
+	virtual ~Station();
 
-	/* normal new/delete operators. Used when building/removing station */
-	void *operator new (size_t size);
-	void operator delete(void *p);
-
-	/* new/delete operators accepting station index. Used when loading station from savegame. */
-	void *operator new (size_t size, int st_idx);
-	void operator delete(void *p, int st_idx);
+	void QuickFree();
 
 	void AddFacility(byte new_facility_bit, TileIndex facil_xy);
 	void MarkDirty() const;
@@ -186,9 +169,6 @@
 	uint GetPlatformLength(TileIndex tile) const;
 	bool IsBuoy() const;
 	bool IsValid() const;
-
-protected:
-	static Station *AllocateRaw();
 };
 
 enum StationType {
@@ -238,8 +218,6 @@
 void RebuildStationLists();
 void ResortStationLists();
 
-DECLARE_OLD_POOL(Station, Station, 6, 1000)
-
 static inline StationID GetMaxStationIndex()
 {
 	/* TODO - This isn't the real content of the function, but
@@ -266,8 +244,6 @@
 
 /* Stuff for ROADSTOPS */
 
-DECLARE_OLD_POOL(RoadStop, RoadStop, 5, 2000)
-
 #define FOR_ALL_ROADSTOPS_FROM(rs, start) for (rs = GetRoadStop(start); rs != NULL; rs = (rs->index + 1U < GetRoadStopPoolSize()) ? GetRoadStop(rs->index + 1U) : NULL) if (rs->IsValid())
 #define FOR_ALL_ROADSTOPS(rs) FOR_ALL_ROADSTOPS_FROM(rs, 0)
 
--- a/src/station_cmd.cpp	Wed Aug 01 23:49:06 2007 +0000
+++ b/src/station_cmd.cpp	Thu Aug 02 08:47:56 2007 +0000
@@ -927,7 +927,7 @@
 	} else {
 		/* allocate and initialize new station */
 		st = new Station(tile_org);
-		if (st == NULL) return CMD_ERROR;
+		if (st == NULL) return_cmd_error(STR_3008_TOO_MANY_STATIONS_LOADING);
 
 		/* ensure that in case of error (or no DC_EXEC) the station gets deleted upon return */
 		st_auto_delete = st;
@@ -1358,7 +1358,7 @@
 	} else {
 		/* allocate and initialize new station */
 		st = new Station(tile);
-		if (st == NULL) return CMD_ERROR;
+		if (st == NULL) return_cmd_error(STR_3008_TOO_MANY_STATIONS_LOADING);
 
 		/* ensure that in case of error (or no DC_EXEC) the new station gets deleted upon return */
 		st_auto_delete = st;
@@ -1652,7 +1652,7 @@
 
 		/* allocate and initialize new station */
 		st = new Station(tile);
-		if (st == NULL) return CMD_ERROR;
+		if (st == NULL) return_cmd_error(STR_3008_TOO_MANY_STATIONS_LOADING);
 
 		/* ensure that in case of error (or no DC_EXEC) the station gets deleted upon return */
 		st_auto_delete = st;
@@ -1774,7 +1774,7 @@
 
 	/* allocate and initialize new station */
 	Station *st = new Station(tile);
-	if (st == NULL) return CMD_ERROR;
+	if (st == NULL) return_cmd_error(STR_3008_TOO_MANY_STATIONS_LOADING);
 
 	/* ensure that in case of error (or no DC_EXEC) the station gets deleted upon return */
 	AutoPtrT<Station> st_auto_delete(st);
@@ -1939,7 +1939,7 @@
 	} else {
 		/* allocate and initialize new station */
 		st = new Station(tile);
-		if (st == NULL) return CMD_ERROR;
+		if (st == NULL) return_cmd_error(STR_3008_TOO_MANY_STATIONS_LOADING);
 
 		/* ensure that in case of error (or no DC_EXEC) the station gets deleted upon return */
 		st_auto_delete = st;