(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.

This commit is contained in:
rubidium 2007-08-02 08:47:56 +00:00
parent aa78685c99
commit 9378e5fd38
4 changed files with 181 additions and 155 deletions

View File

@ -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 OldMemoryPoolBase {
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(OldMemoryPoolBase *array, uint index) { retu
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_item, uint end_item)
}
/**
* 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 { \

View File

@ -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(TileIndex tile) const
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 = (Rect src)
/* 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 */

View File

@ -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,19 +157,10 @@ struct Station {
static const int cDebugCtorLevel = 3;
Station(TileIndex tile = 0);
~Station();
virtual ~Station();
void PreInit() {}
void QuickFree();
/* 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 AddFacility(byte new_facility_bit, TileIndex facil_xy);
void MarkDirty() const;
void MarkTilesDirty(bool cargo_change) 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(StationID index)
/* 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)

View File

@ -927,7 +927,7 @@ CommandCost CmdBuildRailroadStation(TileIndex tile_org, uint32 flags, uint32 p1,
} 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 tile, uint32 flags, uint32 p1, uint32 p2)
} 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 tile, uint32 flags, uint32 p1, uint32 p2)
/* 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, uint32 flags, uint32 p1, uint32 p2)
/* 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, uint32 flags, uint32 p1, uint32 p2)
} 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;