Changeset - r7377:722cd70012ed
[Not reviewed]
master
0 4 0
rubidium - 17 years ago 2007-08-02 08:47:56
rubidium@openttd.org
(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.
4 files changed with 182 insertions and 156 deletions:
0 comments (0 inline, 0 general)
src/oldpool.h
Show inline comments
 
@@ -29,14 +29,14 @@ protected:
 

	
 
	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 @@ protected:
 
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 @@ struct OldMemoryPool : public OldMemoryP
 
				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 @@ static inline bool AddBlockIfNeeded(OldM
 
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 @@ static void PoolCleanBlock(uint start_it
 
}
 

	
 

	
 
/**
 
 * 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 { \
src/station.cpp
Show inline comments
 
@@ -91,29 +91,6 @@ void Station::QuickFree()
 
	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 @@ bool Station::TileBelongsToRailStation(T
 
	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 @@ StationRect& StationRect::operator = (Re
 
/*                     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 @@ RoadStop::~RoadStop()
 

	
 
	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 */
src/station.h
Show inline comments
 
@@ -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 @@ struct GoodsEntry {
 
};
 

	
 
/** 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 @@ struct RoadStop {
 
	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 @@ struct RoadStop {
 
	void FreeBay(uint nr);
 
	bool IsEntranceBusy() const;
 
	void SetEntranceBusy(bool busy);
 
protected:
 
	static RoadStop *AllocateRaw();
 
};
 

	
 
struct StationSpecList {
 
@@ -108,7 +101,7 @@ struct StationRect : public Rect {
 
	StationRect& operator = (Rect src);
 
};
 

	
 
struct Station {
 
struct Station : PoolItem<Station, StationID, &_Station_pool> {
 
	public:
 
		RoadStop *GetPrimaryRoadStop(RoadStop::Type type) const
 
		{
 
@@ -151,7 +144,6 @@ struct Station {
 
	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 @@ struct Station {
 
	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 @@ struct Station {
 
	uint GetPlatformLength(TileIndex tile) const;
 
	bool IsBuoy() const;
 
	bool IsValid() const;
 

	
 
protected:
 
	static Station *AllocateRaw();
 
};
 

	
 
enum StationType {
 
@@ -238,8 +218,6 @@ void UpdateAllStationVirtCoord();
 
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 @@ static inline bool IsValidStationID(Stat
 

	
 
/* 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)
 

	
src/station_cmd.cpp
Show inline comments
 
@@ -927,7 +927,7 @@ CommandCost CmdBuildRailroadStation(Tile
 
	} 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 @@ CommandCost CmdBuildRoadStop(TileIndex t
 
	} 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 @@ CommandCost CmdBuildAirport(TileIndex ti
 

	
 
		/* 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 @@ CommandCost CmdBuildBuoy(TileIndex tile,
 

	
 
	/* 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 @@ CommandCost CmdBuildDock(TileIndex tile,
 
	} 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;
0 comments (0 inline, 0 general)