diff --git a/projects/openttd_vs80.vcproj b/projects/openttd_vs80.vcproj index cf1b05dd8e..2ec5a57545 100644 --- a/projects/openttd_vs80.vcproj +++ b/projects/openttd_vs80.vcproj @@ -643,10 +643,6 @@ RelativePath=".\..\src\npf.cpp" > - - @@ -1251,14 +1247,6 @@ RelativePath=".\..\src\video\null_v.h" > - - - - @@ -1687,6 +1675,14 @@ RelativePath=".\..\src\core\overflowsafe_type.hpp" > + + + + diff --git a/projects/openttd_vs90.vcproj b/projects/openttd_vs90.vcproj index 41efc03dc5..be213cd284 100644 --- a/projects/openttd_vs90.vcproj +++ b/projects/openttd_vs90.vcproj @@ -640,10 +640,6 @@ RelativePath=".\..\src\npf.cpp" > - - @@ -1248,14 +1244,6 @@ RelativePath=".\..\src\video\null_v.h" > - - - - @@ -1684,6 +1672,14 @@ RelativePath=".\..\src\core\overflowsafe_type.hpp" > + + + + diff --git a/source.list b/source.list index cbd654e3f1..5a5af4ea7c 100644 --- a/source.list +++ b/source.list @@ -48,7 +48,6 @@ network/network_gamelist.cpp network/network_server.cpp network/network_udp.cpp npf.cpp -oldpool.cpp openttd.cpp os_timer.cpp #if WIN32 @@ -243,8 +242,6 @@ npf.h music/null_m.h sound/null_s.h video/null_v.h -oldpool.h -oldpool_func.h openttd.h order_base.h order_func.h @@ -367,6 +364,8 @@ core/math_func.cpp core/math_func.hpp core/mem_func.hpp core/overflowsafe_type.hpp +core/pool.hpp +core/pool_func.hpp core/random_func.cpp core/random_func.hpp core/smallmap_type.hpp diff --git a/src/aircraft_cmd.cpp b/src/aircraft_cmd.cpp index 25ba931b0d..287a99cb79 100644 --- a/src/aircraft_cmd.cpp +++ b/src/aircraft_cmd.cpp @@ -589,8 +589,11 @@ static void CheckIfAircraftNeedsService(Vehicle *v) } const Station *st = Station::Get(v->current_order.GetDestination()); + + assert(st != NULL); + /* only goto depot if the target airport has terminals (eg. it is airport) */ - if (st->IsValid() && st->airport_tile != INVALID_TILE && st->Airport()->terminals != NULL) { + if (st->airport_tile != INVALID_TILE && st->Airport()->terminals != NULL) { // printf("targetairport = %d, st->index = %d\n", v->u.air.targetairport, st->index); // v->u.air.targetairport = st->index; v->current_order.MakeGoToDepot(st->index, ODTFB_SERVICE); @@ -1535,7 +1538,7 @@ static void AircraftEventHandler_AtTerminal(Vehicle *v, const AirportFTAClass *a return; } - if (!v->current_order.IsValid()) return; + if (v->current_order.IsType(OT_NOTHING)) return; /* if the block of the next position is busy, stay put */ if (AirportHasBlock(v, &apc->layout[v->u.air.pos], apc)) return; @@ -2036,8 +2039,9 @@ bool Aircraft::Tick() for (uint i = 0; i != 2; i++) { /* stop if the aircraft was deleted */ + VehicleID index = this->index; if (!AircraftEventHandler(this, i)) return false; - assert(this->IsValid()); + assert(Vehicle::Get(index) == this); assert(IsNormalAircraft(this)); } diff --git a/src/articulated_vehicles.cpp b/src/articulated_vehicles.cpp index a271ee7ce5..43cb29c589 100644 --- a/src/articulated_vehicles.cpp +++ b/src/articulated_vehicles.cpp @@ -21,9 +21,9 @@ uint CountArticulatedParts(EngineID engine_type, bool purchase_window) * either, so it doesn't matter how many articulated parts there are. */ if (!Vehicle::CanAllocateItem()) return 0; - Vehicle *v = NULL;; + Vehicle *v = NULL; if (!purchase_window) { - v = new InvalidVehicle(); + v = new Vehicle(); v->engine_type = engine_type; } diff --git a/src/autoreplace.cpp b/src/autoreplace.cpp index f6a7144016..d2fa17ba97 100644 --- a/src/autoreplace.cpp +++ b/src/autoreplace.cpp @@ -6,9 +6,10 @@ #include "command_func.h" #include "group.h" #include "autoreplace_base.h" -#include "oldpool_func.h" +#include "core/pool_func.hpp" -DEFINE_OLD_POOL_GENERIC(EngineRenew, EngineRenew) +EngineRenewPool _enginerenew_pool("EngineRenew"); +INSTANTIATE_POOL_METHODS(EngineRenew) /** * Retrieves the EngineRenew that specifies the replacement of the given @@ -101,7 +102,5 @@ CommandCost RemoveEngineReplacement(EngineRenewList *erl, EngineID engine, Group void InitializeEngineRenews() { - /* Clean the engine renew pool and create 1 block in it */ - _EngineRenew_pool.CleanPool(); - _EngineRenew_pool.AddBlockToPool(); + _enginerenew_pool.CleanPool(); } diff --git a/src/autoreplace_base.h b/src/autoreplace_base.h index 5037c16f02..f37f686558 100644 --- a/src/autoreplace_base.h +++ b/src/autoreplace_base.h @@ -5,7 +5,7 @@ #ifndef AUTOREPLACE_BASE_H #define AUTOREPLACE_BASE_H -#include "oldpool.h" +#include "core/pool.hpp" #include "autoreplace_type.h" typedef uint16 EngineRenewID; @@ -15,23 +15,22 @@ typedef uint16 EngineRenewID; * placed here so the only exception to this rule, the saveload code, can use * it. */ -DECLARE_OLD_POOL(EngineRenew, EngineRenew, 3, 8000) +typedef Pool EngineRenewPool; +extern EngineRenewPool _enginerenew_pool; /** * Struct to store engine replacements. DO NOT USE outside of engine.c. Is * placed here so the only exception to this rule, the saveload code, can use * it. */ -struct EngineRenew : PoolItem { +struct EngineRenew : EngineRenewPool::PoolItem<&_enginerenew_pool> { EngineID from; EngineID to; EngineRenew *next; GroupID group_id; - EngineRenew(EngineID from = INVALID_ENGINE, EngineID to = INVALID_ENGINE) : from(from), to(to), next(NULL) {} - ~EngineRenew() { this->from = INVALID_ENGINE; } - - inline bool IsValid() const { return this->from != INVALID_ENGINE; } + EngineRenew(EngineID from = INVALID_ENGINE, EngineID to = INVALID_ENGINE) : from(from), to(to) {} + ~EngineRenew() {} }; #define FOR_ALL_ENGINE_RENEWS_FROM(var, start) FOR_ALL_ITEMS_FROM(EngineRenew, enginerenew_index, var, start) diff --git a/src/cargopacket.cpp b/src/cargopacket.cpp index cd5524c573..b2ce7ed3be 100644 --- a/src/cargopacket.cpp +++ b/src/cargopacket.cpp @@ -4,16 +4,15 @@ #include "stdafx.h" #include "station_base.h" -#include "oldpool_func.h" +#include "core/pool_func.hpp" /* Initialize the cargopacket-pool */ -DEFINE_OLD_POOL_GENERIC(CargoPacket, CargoPacket) +CargoPacketPool _cargopacket_pool("CargoPacket"); +INSTANTIATE_POOL_METHODS(CargoPacket) void InitializeCargoPackets() { - /* Clean the cargo packet pool and create 1 block in it */ - _CargoPacket_pool.CleanPool(); - _CargoPacket_pool.AddBlockToPool(); + _cargopacket_pool.CleanPool(); } CargoPacket::CargoPacket(StationID source, uint16 count) @@ -30,11 +29,6 @@ CargoPacket::CargoPacket(StationID source, uint16 count) this->paid_for = false; } -CargoPacket::~CargoPacket() -{ - this->count = 0; -} - bool CargoPacket::SameSource(const CargoPacket *cp) const { return this->source_xy == cp->source_xy && this->days_in_transit == cp->days_in_transit && this->paid_for == cp->paid_for; @@ -104,7 +98,6 @@ uint CargoList::DaysInTransit() const void CargoList::Append(CargoPacket *cp) { assert(cp != NULL); - assert(cp->IsValid()); for (List::iterator it = packets.begin(); it != packets.end(); it++) { if ((*it)->SameSource(cp) && (*it)->count + cp->count <= 65535) { diff --git a/src/cargopacket.h b/src/cargopacket.h index 739e7f3ede..26b38342c6 100644 --- a/src/cargopacket.h +++ b/src/cargopacket.h @@ -5,7 +5,7 @@ #ifndef CARGOPACKET_H #define CARGOPACKET_H -#include "oldpool.h" +#include "core/pool.hpp" #include "economy_type.h" #include "tile_type.h" #include "station_type.h" @@ -15,13 +15,13 @@ typedef uint32 CargoPacketID; struct CargoPacket; /** We want to use a pool */ -DECLARE_OLD_POOL(CargoPacket, CargoPacket, 10, 1000) - +typedef Pool CargoPacketPool; +extern CargoPacketPool _cargopacket_pool; /** * Container for cargo from the same location and time */ -struct CargoPacket : PoolItem { +struct CargoPacket : CargoPacketPool::PoolItem<&_cargopacket_pool> { Money feeder_share; ///< Value of feeder pickup to be paid for on delivery of cargo TileIndex source_xy; ///< The origin of the cargo (first station in feeder chain) TileIndex loaded_at_xy; ///< Location where this cargo has been loaded into the vehicle @@ -40,14 +40,7 @@ struct CargoPacket : PoolItem { CargoPacket(StationID source = INVALID_STATION, uint16 count = 0); /** Destroy the packet */ - virtual ~CargoPacket(); - - - /** - * Is this a valid cargo packet ? - * @return true if and only it is valid - */ - inline bool IsValid() const { return this->count != 0; } + ~CargoPacket() { } /** * Checks whether the cargo packet is from (exactly) the same source diff --git a/src/company_base.h b/src/company_base.h index bffe89b11e..192a8deba9 100644 --- a/src/company_base.h +++ b/src/company_base.h @@ -6,7 +6,7 @@ #define COMPANY_BASE_H #include "company_type.h" -#include "oldpool.h" +#include "core/pool.hpp" #include "road_type.h" #include "rail_type.h" #include "date_type.h" @@ -25,13 +25,11 @@ struct CompanyEconomyEntry { Money company_value; }; -/* The third parameter and the number after >> MUST be the same, - * otherwise more (or less) companies will be allowed to be - * created than what MAX_COMPANIES specifies! - */ -DECLARE_OLD_POOL(Company, Company, 1, (MAX_COMPANIES + 1) >> 1) +typedef Pool CompanyPool; +extern CompanyPool _company_pool; -struct Company : PoolItem { + +struct Company : CompanyPool::PoolItem<&_company_pool> { Company(uint16 name_1 = 0, bool is_ai = false); ~Company(); @@ -81,13 +79,6 @@ struct Company : PoolItem { EngineRenewList engine_renew_list; ///< Defined later CompanySettings settings; ///< settings specific for each company uint16 *num_engines; ///< caches the number of engines of each type the company owns (no need to save this) - - inline bool IsValid() const { return this->name_1 != 0; } - - static inline bool IsValidID(CompanyID company) - { - return company < MAX_COMPANIES && (uint)company < Company::GetPoolSize() && Company::Get(company)->IsValid(); - } }; #define FOR_ALL_COMPANIES_FROM(var, start) FOR_ALL_ITEMS_FROM(Company, company_index, var, start) @@ -95,12 +86,7 @@ struct Company : PoolItem { static inline byte ActiveCompanyCount() { - const Company *c; - byte count = 0; - - FOR_ALL_COMPANIES(c) count++; - - return count; + return (byte)Company::GetNumItems(); } Money CalculateCompanyValue(const Company *c); diff --git a/src/company_cmd.cpp b/src/company_cmd.cpp index ef694d8f2e..504ea38759 100644 --- a/src/company_cmd.cpp +++ b/src/company_cmd.cpp @@ -28,7 +28,7 @@ #include "road_func.h" #include "rail.h" #include "sprite.h" -#include "oldpool_func.h" +#include "core/pool_func.hpp" #include "table/strings.h" @@ -40,7 +40,8 @@ CompanyManagerFace _company_manager_face; ///< for company manager face storage uint _next_competitor_start; ///< the number of ticks before the next AI is started uint _cur_company_tick_index; ///< used to generate a name for one company that doesn't have a name yet per tick -DEFINE_OLD_POOL_GENERIC(Company, Company) +CompanyPool _company_pool("Company"); +INSTANTIATE_POOL_METHODS(Company) Company::Company(uint16 name_1, bool is_ai) : name_1(name_1), @@ -59,7 +60,6 @@ Company::~Company() if (CleaningPool()) return; DeleteCompanyWindows(this->index); - this->name_1 = 0; } /** @@ -421,7 +421,7 @@ void ResetCompanyLivery(Company *c) */ Company *DoStartupNewCompany(bool is_ai) { - if (ActiveCompanyCount() == MAX_COMPANIES || !Company::CanAllocateItem()) return NULL; + if (!Company::CanAllocateItem()) return NULL; /* we have to generate colour before this company is valid */ Colours colour = GenerateCompanyColour(); @@ -489,8 +489,7 @@ static void MaybeStartNewCompany() void InitializeCompanies() { - _Company_pool.CleanPool(); - _Company_pool.AddBlockToPool(); + _company_pool.CleanPool(); _cur_company_tick_index = 0; } diff --git a/src/core/pool.hpp b/src/core/pool.hpp new file mode 100644 index 0000000000..7c95803f7f --- /dev/null +++ b/src/core/pool.hpp @@ -0,0 +1,284 @@ +/* $Id$ */ + +/** @file pool.hpp Defintion of Pool, structure used to access PoolItems, and PoolItem, base structure for Vehicle, Town, and other indexed items. */ + +#ifndef POOL_HPP +#define POOL_HPP + +template +struct Pool { + static const size_t MAX_SIZE = Tmax_size; ///< Make template parameter accessible from outside + + const char * const name; ///< Name of this pool + + size_t size; ///< Current allocated size + size_t first_free; ///< No item with index lower than this is free (doesn't say anything about this one!) + size_t first_unused; ///< This and all higher indexes are free (doesn't say anything about first_unused-1 !) + size_t items; ///< Number of used indexes (non-NULL) + + bool cleaning; ///< True if cleaning pool (deleting all items) + + Titem **data; ///< Pointer to array of pointers to Titem + + /** Constructor */ + Pool(const char *name); + /** Destroys all items in the pool and resets all member variables */ + void CleanPool(); + + /** + * Returs Titem with given index + * @param index of item to get + * @return pointer to Titem + * @pre index < this->first_unused + */ + FORCEINLINE Titem *Get(size_t index) + { + assert(index < this->first_unused); + return this->data[index]; + } + + /** + * Tests whether given index can be used to get valid (non-NULL) Titem + * @param index index to examine + * @return true if PoolItem::Get(index) will return non-NULL pointer + */ + FORCEINLINE bool IsValidID(size_t index) + { + return index < this->first_unused && this->Get(index) != NULL; + } + + /** + * Tests whether we can allocate 'n' items + * @param n number of items we want to allocate + * @return true if 'n' items can be allocated + */ + FORCEINLINE bool CanAllocate(size_t n = 1) + { + return this->items <= Tmax_size - n; + } + + /** Base class for all PoolItems */ + template *Tpool> + struct PoolItem { + Tindex index; ///< Index of this pool item + + /** + * Allocates space for new Titem + * @param size size of Titem + * @return pointer to allocated memory + * @note can never fail (return NULL), use CanAllocate() to check first! + */ + FORCEINLINE void *operator new(size_t size) + { + return Tpool->GetNew(size); + } + + /** + * Marks Titem as free. Its memory is released + * @param p memory to free + * @note the item has to be allocated in the pool! + */ + FORCEINLINE void operator delete(void *p) + { + Titem *pn = (Titem *)p; + assert(pn == Tpool->Get(pn->index)); + Tpool->FreeItem(pn->index); + } + + /** + * Allocates space for new Titem with given index + * @param size size of Titem + * @param index index of item + * @return pointer to allocated memory + * @note can never fail (return NULL), use CanAllocate() to check first! + * @pre index has to be unused! Else it will crash + */ + FORCEINLINE void *operator new(size_t size, size_t index) + { + return Tpool->GetNew(size, index); + } + + /** + * Deletes item with given index. + * @param p Titem memory to release + * @param index index of item + * @note never use this! Only for internal use + * (called automatically when constructor of Titem uses throw()) + */ + FORCEINLINE void operator delete(void *p, size_t index) + { + assert(p == Tpool->Get(index)); + Tpool->FreeItem(index); + } + + + /** + * Allocates space for new Titem at given memory address + * @param size size of Titem + * @param ptr where are we allocating the item? + * @return pointer to allocated memory (== ptr) + * @note use of this is strongly discouraged + * @pre the memory must not be allocated in the Pool! + */ + FORCEINLINE void *operator new(size_t size, void *ptr) + { + for (size_t i = 0; i < Tpool->first_unused; i++) { + /* Don't allow creating new objects over existing. + * Even if we called the destructor and reused this memory, + * we don't know whether 'size' and size of currently allocated + * memory are the same (because of possible inheritance). + * Use { size_t index = item->index; delete item; new (index) item; } + * instead to make sure destructor is called and no memory leaks. */ + assert(ptr != Tpool->data[i]); + } + return ptr; + } + + /** + * Deletes item that was allocated by the function above + * @param p Titem memory to release + * @param ptr parameter given to operator new + * @note never use this! Only for internal use + * (called automatically when constructor of Titem uses throw()) + */ + FORCEINLINE void operator delete(void *p, void *ptr) + { + assert(p == ptr); + for (size_t i = 0; i < Tpool->first_unused; i++) { + assert(ptr != Tpool->data[i]); + } + } + + + /** Helper functions so we can use PoolItem::Function() instead of _poolitem_pool.Function() */ + + /** + * Tests whether we can allocate 'n' items + * @param n number of items we want to allocate + * @return true if 'n' items can be allocated + */ + static FORCEINLINE bool CanAllocateItem(size_t n = 1) + { + return Tpool->CanAllocate(n); + } + + /** + * Returns current state of pool cleaning - yes or no + * @return true iff we are cleaning the pool now + */ + static FORCEINLINE bool CleaningPool() + { + return Tpool->cleaning; + } + + /** + * Tests whether given index can be used to get valid (non-NULL) Titem + * @param index index to examine + * @return true if PoolItem::Get(index) will return non-NULL pointer + */ + static FORCEINLINE bool IsValidID(size_t index) + { + return Tpool->IsValidID(index); + } + + /** + * Returs Titem with given index + * @param index of item to get + * @return pointer to Titem + * @pre index < this->first_unused + */ + static FORCEINLINE Titem *Get(size_t index) + { + return Tpool->Get(index); + } + + /** + * Returs Titem with given index + * @param index of item to get + * @return pointer to Titem + * @note returns NULL for invalid index + */ + static FORCEINLINE Titem *GetIfValid(size_t index) + { + return index < Tpool->first_unused ? Tpool->Get(index) : NULL; + } + + /** + * Returns first unused index. Useful when iterating over + * all pool items. + * @return first unused index + */ + static FORCEINLINE size_t GetPoolSize() + { + return Tpool->first_unused; + } + + /** + * Returns number of valid items in the pool + * @return number of valid items in the pool + */ + static FORCEINLINE size_t GetNumItems() + { + return Tpool->items; + } + }; + +private: + static const size_t NO_FREE_ITEM = MAX_UVALUE(size_t); ///< Contant to indicate we can't allocate any more items + + /** + * Makes given index valid + * @param size size of item + * @param index index of item + * @pre index < this->size + * @pre this->Get(index) == NULL + */ + void *AllocateItem(size_t size, size_t index); + + /** + * Resizes the pool so 'index' can be addressed + * @param index index we will allocate later + * @pre index >= this->size + * @pre index < Tmax_size + */ + void ResizeFor(size_t index); + + /** + * Searches for first free index + * @return first free index, NO_FREE_ITEM on failure + */ + size_t FindFirstFree(); + + /** + * Allocates new item + * @param size size of item + * @return pointer to allocated item + * @note error() on failure! (no free item) + */ + void *GetNew(size_t size); + + /** + * Allocates new item with given index + * @param size size of item + * @param index index of item + * @return pointer to allocated item + * @note usererror() on failure! (index out of range or already used) + */ + void *GetNew(size_t size, size_t index); + + /** + * Deallocates memory used by this index and marks item as free + * @param index item to deallocate + * @pre unit is allocated (non-NULL) + * @note 'delete NULL' doesn't cause call of this function, so it is safe + */ + void FreeItem(size_t index); +}; + +#define FOR_ALL_ITEMS_FROM(type, iter, var, start) \ + for (size_t iter = start; var = NULL, iter < type::GetPoolSize(); iter++) \ + if ((var = type::Get(iter)) != NULL) + +#define FOR_ALL_ITEMS(type, iter, var) FOR_ALL_ITEMS_FROM(type, iter, var, 0) + +#endif /* POOL_HPP */ diff --git a/src/core/pool_func.hpp b/src/core/pool_func.hpp new file mode 100644 index 0000000000..df9e2692f0 --- /dev/null +++ b/src/core/pool_func.hpp @@ -0,0 +1,139 @@ +/* $Id$ */ + +/** @file pool_func.hpp Some methods of Pool are placed here in order to reduce compilation time and binary size. */ + +#ifndef POOL_FUNC_HPP +#define POOL_FUNC_HPP + +#include "alloc_func.hpp" +#include "mem_func.hpp" +#include "pool.hpp" + +#define DEFINE_POOL_METHOD(type) \ + template \ + type Pool + +DEFINE_POOL_METHOD(inline)::Pool(const char *name) : + name(name), + size(0), + first_free(0), + first_unused(0), + items(0), + cleaning(false), + data(NULL) +{ } + +DEFINE_POOL_METHOD(inline void)::ResizeFor(size_t index) +{ + assert(index >= this->size); + assert(index < Tmax_size); + + size_t new_size = min(Tmax_size, Align(index + 1, Tgrowth_step)); + + this->data = ReallocT(this->data, new_size); + MemSetT(this->data + this->size, 0, new_size - this->size); + + this->size = new_size; +} + +DEFINE_POOL_METHOD(inline size_t)::FindFirstFree() +{ + size_t index = this->first_free; + + for (; index < this->first_unused; index++) { + if (this->data[index] == NULL) return index; + } + + if (index < this->size) { + return index; + } + + assert(index == this->size); + assert(this->first_unused == this->size); + + if (index < Tmax_size) { + this->ResizeFor(index); + return index; + } + + assert(this->items == Tmax_size); + + return NO_FREE_ITEM; +} + +DEFINE_POOL_METHOD(inline void *)::AllocateItem(size_t size, size_t index) +{ + assert(this->data[index] == NULL); + + this->first_unused = max(this->first_unused, index + 1); + this->items++; + + Titem *item = this->data[index] = (Titem *)CallocT(size); + item->index = (uint)index; + return item; +} + +DEFINE_POOL_METHOD(void *)::GetNew(size_t size) +{ + size_t index = this->FindFirstFree(); + + if (index == NO_FREE_ITEM) { + error("%s: no more free items", this->name); + } + + this->first_free = index + 1; + return this->AllocateItem(size, index); +} + +DEFINE_POOL_METHOD(void *)::GetNew(size_t size, size_t index) +{ + if (index >= Tmax_size) { + usererror("failed loading savegame: %s index " PRINTF_SIZE " out of range (" PRINTF_SIZE ")", this->name, index, Tmax_size); + } + + if (index >= this->size) this->ResizeFor(index); + + if (this->data[index] != NULL) { + usererror("failed loading savegame: %s index " PRINTF_SIZE " already in use", this->name, index); + } + + return this->AllocateItem(size, index); +} + +DEFINE_POOL_METHOD(void)::FreeItem(size_t index) +{ + assert(index < this->size); + assert(this->data[index] != NULL); + free(this->data[index]); + this->data[index] = NULL; + this->first_free = min(this->first_free, index); + this->items--; +} + +DEFINE_POOL_METHOD(void)::CleanPool() +{ + this->cleaning = true; + for (size_t i = 0; i < this->first_unused; i++) { + delete this->Get(i); // 'delete NULL;' is very valid + } + assert(this->items == 0); + free(this->data); + this->first_unused = this->first_free = this->size = 0; + this->data = NULL; + this->cleaning = false; +} + +#undef DEFINE_POOL_METHOD + +/** + * Force instantiation of pool methods so we don't get linker errors. + * Only methods accessed from methods defined in pool.hpp need to be + * forcefully instantiated. + */ +#define INSTANTIATE_POOL_METHODS(name) \ + template void * name ## Pool::GetNew(size_t size); \ + template void * name ## Pool::GetNew(size_t size, size_t index); \ + template void name ## Pool::FreeItem(size_t index); \ + template void name ## Pool::CleanPool(); + +#endif /* POOL_FUNC_HPP */ diff --git a/src/core/random_func.cpp b/src/core/random_func.cpp index 6e9cb0a94c..4e2897625a 100644 --- a/src/core/random_func.cpp +++ b/src/core/random_func.cpp @@ -40,7 +40,7 @@ void SetRandomSeed(uint32 seed) uint32 DoRandom(int line, const char *file) { - if (_networking && (NetworkClientSocket::Get(0)->status != STATUS_INACTIVE || !_network_server)) { + if (_networking && (!_network_server || (NetworkClientSocket::IsValidID(0) && NetworkClientSocket::Get(0)->status != STATUS_INACTIVE))) { printf("Random [%d/%d] %s:%d\n", _frame_counter, (byte)_current_company, file, line); } diff --git a/src/date.cpp b/src/date.cpp index 858c65119c..2f297591d8 100644 --- a/src/date.cpp +++ b/src/date.cpp @@ -184,12 +184,10 @@ static const Month _autosave_months[] = { */ static void RunVehicleDayProc(uint daytick) { - uint total = Vehicle::GetPoolSize(); - - for (uint i = daytick; i < total; i += DAY_TICKS) { + for (size_t i = daytick; i < Vehicle::GetPoolSize(); i += DAY_TICKS) { Vehicle *v = Vehicle::Get(i); - if (v->IsValid()) { + if (v != NULL) { /* Call the 32-day callback if needed */ CheckVehicle32Day(v); v->OnNewDay(); diff --git a/src/depot.cpp b/src/depot.cpp index e73490071b..b034e85319 100644 --- a/src/depot.cpp +++ b/src/depot.cpp @@ -6,12 +6,13 @@ #include "depot_base.h" #include "order_func.h" #include "window_func.h" -#include "oldpool_func.h" #include "core/bitmath_func.hpp" #include "tile_map.h" #include "water_map.h" +#include "core/pool_func.hpp" -DEFINE_OLD_POOL_GENERIC(Depot, Depot) +DepotPool _depot_pool("Depot"); +INSTANTIATE_POOL_METHODS(Depot) /** * Gets a depot from a tile @@ -48,11 +49,9 @@ Depot::~Depot() /* Delete the depot-window */ DeleteWindowById(WC_VEHICLE_DEPOT, this->xy); - this->xy = INVALID_TILE; } void InitializeDepots() { - _Depot_pool.CleanPool(); - _Depot_pool.AddBlockToPool(); + _depot_pool.CleanPool(); } diff --git a/src/depot_base.h b/src/depot_base.h index 350eaee8fa..b4e47cb60a 100644 --- a/src/depot_base.h +++ b/src/depot_base.h @@ -7,19 +7,18 @@ #include "tile_type.h" #include "depot_type.h" -#include "oldpool.h" +#include "core/pool.hpp" #include "town_type.h" -DECLARE_OLD_POOL(Depot, Depot, 3, 8000) +typedef Pool DepotPool; +extern DepotPool _depot_pool; -struct Depot : PoolItem { +struct Depot : DepotPool::PoolItem<&_depot_pool> { TileIndex xy; TownID town_index; Depot(TileIndex xy = INVALID_TILE) : xy(xy) {} ~Depot(); - - inline bool IsValid() const { return this->xy != INVALID_TILE; } }; Depot *GetDepotByTile(TileIndex tile); diff --git a/src/engine.cpp b/src/engine.cpp index 24918c11c6..262729c199 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -18,15 +18,16 @@ #include "date_func.h" #include "autoreplace_gui.h" #include "string_func.h" -#include "oldpool_func.h" #include "ai/ai.hpp" #include "vehicle_func.h" #include "settings_type.h" +#include "core/pool_func.hpp" #include "table/strings.h" #include "table/engines.h" -DEFINE_OLD_POOL_GENERIC(Engine, Engine) +EnginePool _engine_pool("Engine"); +INSTANTIATE_POOL_METHODS(Engine) EngineOverrideManager _engine_mngr; @@ -356,7 +357,7 @@ EngineID EngineOverrideManager::GetID(VehicleType type, uint16 grf_local_id, uin */ void SetCachedEngineCounts() { - uint engines = Engine::GetPoolSize(); + size_t engines = Engine::GetPoolSize(); /* Set up the engine count for all companies */ Company *c; @@ -392,8 +393,7 @@ void SetCachedEngineCounts() void SetupEngines() { - _Engine_pool.CleanPool(); - _Engine_pool.AddBlockToPool(); + _engine_pool.CleanPool(); assert(_engine_mngr.Length() >= _engine_mngr.NUM_DEFAULT_ENGINES); const EngineIDMapping *end = _engine_mngr.End(); diff --git a/src/engine_base.h b/src/engine_base.h index e3e055164b..3e53564e47 100644 --- a/src/engine_base.h +++ b/src/engine_base.h @@ -7,12 +7,13 @@ #include "engine_type.h" #include "economy_type.h" -#include "oldpool.h" +#include "core/pool.hpp" #include "core/smallvec_type.hpp" -DECLARE_OLD_POOL(Engine, Engine, 6, 10000) +typedef Pool EnginePool; +extern EnginePool _engine_pool; -struct Engine : PoolItem { +struct Engine : EnginePool::PoolItem<&_engine_pool> { char *name; ///< Custom name of engine Date intro_date; Date age; @@ -49,8 +50,6 @@ struct Engine : PoolItem { Engine(VehicleType type, EngineID base); ~Engine(); - inline bool IsValid() const { return this->info.climates != 0; } - CargoID GetDefaultCargoType() const; bool CanCarryCargo() const; uint GetDisplayDefaultCapacity() const; diff --git a/src/group.h b/src/group.h index 193568ca07..e60f66c43b 100644 --- a/src/group.h +++ b/src/group.h @@ -6,14 +6,15 @@ #define GROUP_H #include "group_type.h" -#include "oldpool.h" +#include "core/pool.hpp" #include "company_type.h" #include "vehicle_type.h" #include "engine_type.h" -DECLARE_OLD_POOL(Group, Group, 5, 2047) +typedef Pool GroupPool; +extern GroupPool _group_pool; -struct Group : PoolItem { +struct Group : GroupPool::PoolItem<&_group_pool> { char *name; ///< Group Name uint16 num_vehicle; ///< Number of vehicles wich belong to the group @@ -24,9 +25,7 @@ struct Group : PoolItem { uint16 *num_engines; ///< Caches the number of engines of each type the company owns (no need to save this) Group(CompanyID owner = INVALID_COMPANY); - virtual ~Group(); - - bool IsValid() const; + ~Group(); }; diff --git a/src/group_cmd.cpp b/src/group_cmd.cpp index 030bf69187..1c1b78feef 100644 --- a/src/group_cmd.cpp +++ b/src/group_cmd.cpp @@ -14,13 +14,16 @@ #include "autoreplace_func.h" #include "string_func.h" #include "company_func.h" -#include "oldpool_func.h" #include "core/alloc_func.hpp" +#include "core/pool_func.hpp" #include "table/strings.h" GroupID _new_group_id; +GroupPool _group_pool("Group"); +INSTANTIATE_POOL_METHODS(Group) + /** * Update the num engines of a groupID. Decrease the old one and increase the new one * @note called in SetTrainGroupID and UpdateTrainGroupID @@ -40,32 +43,25 @@ static inline void UpdateNumEngineGroup(EngineID i, GroupID old_g, GroupID new_g } -DEFINE_OLD_POOL_GENERIC(Group, Group) - Group::Group(Owner owner) { this->owner = owner; - if (this->IsValid()) this->num_engines = CallocT(Engine::GetPoolSize()); + if (!Company::IsValidID(owner)) return; + + this->num_engines = CallocT(Engine::GetPoolSize()); } Group::~Group() { free(this->name); - this->owner = INVALID_OWNER; free(this->num_engines); } -bool Group::IsValid() const -{ - return this->owner != INVALID_OWNER; -} - void InitializeGroup() { - _Group_pool.CleanPool(); - _Group_pool.AddBlockToPool(); + _group_pool.CleanPool(); } @@ -334,7 +330,7 @@ CommandCost CmdSetGroupReplaceProtection(TileIndex tile, DoCommandFlag flags, ui */ void RemoveVehicleFromGroup(const Vehicle *v) { - if (!v->IsValid() || !v->IsPrimaryVehicle()) return; + if (!v->IsPrimaryVehicle()) return; if (!IsDefaultGroupID(v->group_id)) DecreaseGroupNumVehicle(v->group_id); } @@ -350,7 +346,7 @@ void SetTrainGroupID(Vehicle *v, GroupID new_g) { if (!Group::IsValidID(new_g) && !IsDefaultGroupID(new_g)) return; - assert(v->IsValid() && v->type == VEH_TRAIN && IsFrontEngine(v)); + assert(v->type == VEH_TRAIN && IsFrontEngine(v)); for (Vehicle *u = v; u != NULL; u = u->Next()) { if (IsEngineCountable(u)) UpdateNumEngineGroup(u->engine_type, u->group_id, new_g); @@ -372,7 +368,7 @@ void SetTrainGroupID(Vehicle *v, GroupID new_g) */ void UpdateTrainGroupID(Vehicle *v) { - assert(v->IsValid() && v->type == VEH_TRAIN && (IsFrontEngine(v) || IsFreeWagon(v))); + assert(v->type == VEH_TRAIN && (IsFrontEngine(v) || IsFreeWagon(v))); GroupID new_g = IsFrontEngine(v) ? v->group_id : (GroupID)DEFAULT_GROUP; for (Vehicle *u = v; u != NULL; u = u->Next()) { diff --git a/src/group_gui.cpp b/src/group_gui.cpp index 2480255634..bf262b2ab6 100644 --- a/src/group_gui.cpp +++ b/src/group_gui.cpp @@ -533,22 +533,18 @@ public: case GRP_WIDGET_LIST_VEHICLE: { // Matrix Vehicle uint32 id_v = (pt.y - PLY_WND_PRC__OFFSET_TOP_WIDGET) / (int)this->resize.step_height; - const Vehicle *v; - if (id_v >= this->vscroll.cap) return; // click out of bounds id_v += this->vscroll.pos; if (id_v >= this->vehicles.Length()) return; // click out of list bound - v = this->vehicles[id_v]; + const Vehicle *v = this->vehicles[id_v]; this->vehicle_sel = v->index; - if (v->IsValid()) { - SetObjectToPlaceWnd(v->GetImage(DIR_W), GetVehiclePalette(v), HT_DRAG, this); - _cursor.vehchain = true; - } + SetObjectToPlaceWnd(v->GetImage(DIR_W), GetVehiclePalette(v), HT_DRAG, this); + _cursor.vehchain = true; this->SetDirty(); break; diff --git a/src/industry.h b/src/industry.h index a99e8fc093..e3a4292e6b 100644 --- a/src/industry.h +++ b/src/industry.h @@ -5,7 +5,7 @@ #ifndef INDUSTRY_H #define INDUSTRY_H -#include "oldpool.h" +#include "core/pool.hpp" #include "core/random_func.hpp" #include "newgrf_storage.h" #include "cargo_type.h" @@ -90,12 +90,13 @@ enum IndustryBehaviour { DECLARE_ENUM_AS_BIT_SET(IndustryBehaviour); -DECLARE_OLD_POOL(Industry, Industry, 3, 8000) +typedef Pool IndustryPool; +extern IndustryPool _industry_pool; /** * Defines the internal data of a functionnal industry */ -struct Industry : PoolItem { +struct Industry : IndustryPool::PoolItem<&_industry_pool> { typedef PersistentStorageArray PersistentStorage; TileIndex xy; ///< coordinates of the primary tile the industry is built one @@ -134,8 +135,6 @@ struct Industry : PoolItem { Industry(TileIndex tile = INVALID_TILE) : xy(tile) {} ~Industry(); - - inline bool IsValid() const { return this->xy != INVALID_TILE; } }; struct IndustryTileTable { @@ -265,12 +264,11 @@ void BuildIndustriesLegend(); /* industry_cmd.cpp */ void SetIndustryDailyChanges(); -extern int _total_industries; // general counter extern uint16 _industry_counts[NUM_INDUSTRYTYPES]; // Number of industries per type ingame static inline uint GetNumIndustries() { - return _total_industries; + return (uint)Industry::GetNumItems(); } /** Increment the count of industries for this type @@ -280,7 +278,6 @@ static inline void IncIndustryTypeCount(IndustryType type) { assert(type < INVALID_INDUSTRYTYPE); _industry_counts[type]++; - _total_industries++; } /** Decrement the count of industries for this type @@ -290,7 +287,6 @@ static inline void DecIndustryTypeCount(IndustryType type) { assert(type < INVALID_INDUSTRYTYPE); _industry_counts[type]--; - _total_industries--; } /** get the count of industries for this type @@ -306,7 +302,6 @@ static inline uint8 GetIndustryTypeCount(IndustryType type) * This way, we centralize all counts activities */ static inline void ResetIndustryCounts() { - _total_industries = 0; memset(&_industry_counts, 0, sizeof(_industry_counts)); } diff --git a/src/industry_cmd.cpp b/src/industry_cmd.cpp index 23ff100461..754cee0fe4 100644 --- a/src/industry_cmd.cpp +++ b/src/industry_cmd.cpp @@ -30,22 +30,24 @@ #include "date_func.h" #include "vehicle_func.h" #include "sound_func.h" -#include "oldpool_func.h" #include "animated_tile_func.h" #include "effectvehicle_func.h" #include "ai/ai.hpp" +#include "core/pool_func.hpp" #include "table/strings.h" #include "table/industry_land.h" #include "table/build_industry.h" +IndustryPool _industry_pool("Industry"); +INSTANTIATE_POOL_METHODS(Industry) + void ShowIndustryViewWindow(int industry); void BuildOilRig(TileIndex tile); static byte _industry_sound_ctr; static TileIndex _industry_sound_tile; -int _total_industries; ///< General counter uint16 _industry_counts[NUM_INDUSTRYTYPES]; ///< Number of industries per type ingame IndustrySpec _industry_specs[NUM_INDUSTRYTYPES]; @@ -80,8 +82,6 @@ void ResetIndustryCreationProbility(IndustryType type) _industry_specs[type].appear_creation[_settings_game.game_creation.landscape] = 0; } -DEFINE_OLD_POOL_GENERIC(Industry, Industry) - /** * Retrieve the type for this industry. Although it is accessed by a tile, * it will return the general type of industry, and not the sprite index @@ -95,7 +95,8 @@ IndustryType GetIndustryType(TileIndex tile) assert(IsTileType(tile, MP_INDUSTRY)); const Industry *ind = GetIndustryByTile(tile); - return ind->IsValid() ? ind->type : (IndustryType)IT_INVALID; + assert(ind != NULL); + return ind->type; } /** @@ -132,10 +133,7 @@ Industry::~Industry() /* Industry can also be destroyed when not fully initialized. * This means that we do not have to clear tiles either. */ - if (this->width == 0) { - this->xy = INVALID_TILE; - return; - } + if (this->width == 0) return; BEGIN_TILE_LOOP(tile_cur, this->width, this->height, this->xy); if (IsTileType(tile_cur, MP_INDUSTRY)) { @@ -167,7 +165,6 @@ Industry::~Industry() DeleteSubsidyWithIndustry(this->index); DeleteWindowById(WC_INDUSTRY_VIEW, this->index); InvalidateWindowData(WC_INDUSTRY_DIRECTORY, 0, 0); - this->xy = INVALID_TILE; } static void IndustryDrawSugarMine(const TileInfo *ti) @@ -1624,7 +1621,7 @@ static Industry *CreateNewIndustryHelper(TileIndex tile, IndustryType type, DoCo /* We need to return a non-NULL pointer to tell we have created an industry. * However, we haven't created a real one (no DC_EXEC), so return a fake one. */ - return Industry::Get(0); + return (Industry *)-1; } /** Build/Fund an industry @@ -2011,7 +2008,7 @@ int WhoCanServiceIndustry(Industry *ind) if (o->IsType(OT_GOTO_STATION) && !(o->GetUnloadType() & OUFB_TRANSFER)) { /* Vehicle visits a station to load or unload */ Station *st = Station::Get(o->GetDestination()); - if (!st->IsValid()) continue; + assert(st != NULL); /* Same cargo produced by industry is dropped here => not serviced by vehicle v */ if ((o->GetUnloadType() & OUFB_UNLOAD) && !c_accepts) break; @@ -2323,8 +2320,7 @@ void IndustryMonthlyLoop() void InitializeIndustries() { - _Industry_pool.CleanPool(); - _Industry_pool.AddBlockToPool(); + _industry_pool.CleanPool(); ResetIndustryCounts(); _industry_sound_tile = 0; diff --git a/src/misc_gui.cpp b/src/misc_gui.cpp index e373373a62..643abfb671 100644 --- a/src/misc_gui.cpp +++ b/src/misc_gui.cpp @@ -184,7 +184,7 @@ public: /* Local authority */ SetDParam(0, STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE); - if (t != NULL && t->IsValid()) { + if (t != NULL) { SetDParam(0, STR_TOWN); SetDParam(1, t->index); } diff --git a/src/network/core/tcp_game.cpp b/src/network/core/tcp_game.cpp index d34ace4bf7..b4bb52190a 100644 --- a/src/network/core/tcp_game.cpp +++ b/src/network/core/tcp_game.cpp @@ -13,16 +13,16 @@ #include "../network_internal.h" #include "packet.h" #include "tcp_game.h" +#include "../../core/pool_func.hpp" #include "table/strings.h" -#include "../../oldpool_func.h" /** Make very sure the preconditions given in network_type.h are actually followed */ -assert_compile(MAX_CLIENT_SLOTS == (MAX_CLIENT_SLOTS >> NCI_BITS_PER_POOL_BLOCK) << NCI_BITS_PER_POOL_BLOCK); assert_compile(MAX_CLIENT_SLOTS > MAX_CLIENTS); +assert_compile(NetworkClientSocketPool::MAX_SIZE == MAX_CLIENT_SLOTS); -typedef ClientIndex NetworkClientSocketID; -DEFINE_OLD_POOL_GENERIC(NetworkClientSocket, NetworkClientSocket); +NetworkClientSocketPool _networkclientsocket_pool("NetworkClientSocket"); +INSTANTIATE_POOL_METHODS(NetworkClientSocket) NetworkClientSocket::NetworkClientSocket(ClientID client_id) { diff --git a/src/network/core/tcp_game.h b/src/network/core/tcp_game.h index bfc82f17f3..d01a3d9a8e 100644 --- a/src/network/core/tcp_game.h +++ b/src/network/core/tcp_game.h @@ -12,6 +12,7 @@ #include "os_abstraction.h" #include "tcp.h" #include "packet.h" +#include "../../core/pool.hpp" /** * Enum with all types of UDP packets. @@ -76,12 +77,12 @@ enum ClientStatus { STATUS_ACTIVE, ///< The client is active within in the game }; - class NetworkClientSocket; -DECLARE_OLD_POOL(NetworkClientSocket, NetworkClientSocket, NCI_BITS_PER_POOL_BLOCK, MAX_CLIENT_SLOTS >> NCI_BITS_PER_POOL_BLOCK); +typedef Pool NetworkClientSocketPool; +extern NetworkClientSocketPool _networkclientsocket_pool; /** Base socket handler for all TCP sockets */ -class NetworkClientSocket : public PoolItem, public NetworkTCPSocketHandler { +class NetworkClientSocket : public NetworkClientSocketPool::PoolItem<&_networkclientsocket_pool>, public NetworkTCPSocketHandler { /* TODO: rewrite into a proper class */ private: NetworkClientInfo *info; ///< Client info related to this socket @@ -100,7 +101,6 @@ public: NetworkClientSocket(ClientID client_id = INVALID_CLIENT_ID); ~NetworkClientSocket(); - inline bool IsValid() const { return this->IsConnected(); } inline void SetInfo(NetworkClientInfo *info) { assert(info != NULL && this->info == NULL); this->info = info; } inline NetworkClientInfo *GetInfo() const { return this->info; } diff --git a/src/network/network.cpp b/src/network/network.cpp index 4d407e2b0b..266ce506d6 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -32,16 +32,18 @@ #include "../landscape_type.h" #include "../rev.h" #include "../core/alloc_func.hpp" +#include "../core/pool_func.hpp" #ifdef DEBUG_DUMP_COMMANDS #include "../fileio_func.h" #endif /* DEBUG_DUMP_COMMANDS */ #include "table/strings.h" -#include "../oldpool_func.h" DECLARE_POSTFIX_INCREMENT(ClientID); -typedef ClientIndex NetworkClientInfoID; -DEFINE_OLD_POOL_GENERIC(NetworkClientInfo, NetworkClientInfo); +assert_compile(NetworkClientInfoPool::MAX_SIZE == NetworkClientSocketPool::MAX_SIZE); + +NetworkClientInfoPool _networkclientinfo_pool("NetworkClientInfo"); +INSTANTIATE_POOL_METHODS(NetworkClientInfo) bool _networking; ///< are we in networking mode? bool _network_server; ///< network-server is active @@ -557,10 +559,8 @@ static bool NetworkListen() /** Resets both pools used for network clients */ static void InitializeNetworkPools() { - _NetworkClientSocket_pool.CleanPool(); - _NetworkClientSocket_pool.AddBlockToPool(); - _NetworkClientInfo_pool.CleanPool(); - _NetworkClientInfo_pool.AddBlockToPool(); + _networkclientsocket_pool.CleanPool(); + _networkclientinfo_pool.CleanPool(); } /* Close all current connections */ diff --git a/src/network/network_base.h b/src/network/network_base.h index 700541b491..2714217cd9 100644 --- a/src/network/network_base.h +++ b/src/network/network_base.h @@ -8,11 +8,12 @@ #ifdef ENABLE_NETWORK #include "network_type.h" -#include "../oldpool.h" +#include "../core/pool.hpp" -DECLARE_OLD_POOL(NetworkClientInfo, NetworkClientInfo, NCI_BITS_PER_POOL_BLOCK, MAX_CLIENT_SLOTS >> NCI_BITS_PER_POOL_BLOCK); +typedef Pool NetworkClientInfoPool; +extern NetworkClientInfoPool _networkclientinfo_pool; -struct NetworkClientInfo : PoolItem { +struct NetworkClientInfo : NetworkClientInfoPool::PoolItem<&_networkclientinfo_pool> { ClientID client_id; ///< Client identifier (same as ClientState->client_id) char client_name[NETWORK_CLIENT_NAME_LENGTH]; ///< Name of the client byte client_lang; ///< The language of the client @@ -23,8 +24,6 @@ struct NetworkClientInfo : PoolItemindex; - return ci->client_name; - } + /* Skip inactive clients */ + NetworkClientInfo *ci; + FOR_ALL_CLIENT_INFOS_FROM(ci, *item) { + *item = ci->index; + return ci->client_name; } *item = MAX_CLIENT_SLOTS; } diff --git a/src/network/network_type.h b/src/network/network_type.h index 7e27d398c4..4bdb64429a 100644 --- a/src/network/network_type.h +++ b/src/network/network_type.h @@ -16,13 +16,10 @@ enum { /** How many clients can we have */ MAX_CLIENTS = 255, - /** The number of bits per pool client block */ - NCI_BITS_PER_POOL_BLOCK = 3, // => 8 items per block /** - * The number of slots; must be a multiple of (1 << NCI_BITS_PER_POOL_BLOCK) - * and be at least 1 more than MAX_CLIENTS. It must furthermore be less than - * or equal to 256 as client indices (sent over the network) are 8 bits. - * It needs 1 more for the dedicated server. + * The number of slots; must be at least 1 more than MAX_CLIENTS. It must + * furthermore be less than or equal to 256 as client indices (sent over + * the network) are 8 bits. It needs 1 more for the dedicated server. */ MAX_CLIENT_SLOTS = 256, diff --git a/src/newgrf.cpp b/src/newgrf.cpp index 06aafc09dd..d5ed0d69c0 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -378,7 +378,7 @@ static Engine *GetNewEngine(const GRFFile *file, VehicleType type, uint16 intern if (static_access) return NULL; - uint engine_pool_size = Engine::GetPoolSize(); + size_t engine_pool_size = Engine::GetPoolSize(); /* ... it's not, so create a new one based off an existing engine */ Engine *e = new Engine(type, internal_id); @@ -5623,8 +5623,7 @@ static void ResetNewGRFData() _grf_id_overrides.clear(); InitializeSoundPool(); - _SpriteGroup_pool.CleanPool(); - _SpriteGroup_pool.AddBlockToPool(); + _spritegroup_pool.CleanPool(); } static void BuildCargoTranslationMap() diff --git a/src/newgrf_spritegroup.cpp b/src/newgrf_spritegroup.cpp index c4b4002108..d29c193e3c 100644 --- a/src/newgrf_spritegroup.cpp +++ b/src/newgrf_spritegroup.cpp @@ -3,13 +3,13 @@ /** @file newgrf_spritegroup.cpp Handling of primarily NewGRF action 2. */ #include "stdafx.h" -#include "oldpool.h" #include "newgrf.h" #include "newgrf_spritegroup.h" #include "sprite.h" -#include "oldpool_func.h" +#include "core/pool_func.hpp" -DEFINE_OLD_POOL_GENERIC(SpriteGroup, SpriteGroup) +SpriteGroupPool _spritegroup_pool("SpriteGroup"); +INSTANTIATE_POOL_METHODS(SpriteGroup) SpriteGroup::~SpriteGroup() { @@ -37,8 +37,6 @@ SpriteGroup::~SpriteGroup() default: break; } - - this->type = SGT_INVALID; } TemporaryStorageArray _temp_store; diff --git a/src/newgrf_spritegroup.h b/src/newgrf_spritegroup.h index 1e745480b1..ebaa908eaf 100644 --- a/src/newgrf_spritegroup.h +++ b/src/newgrf_spritegroup.h @@ -11,7 +11,7 @@ #include "gfx_type.h" #include "engine_type.h" #include "tile_type.h" -#include "oldpool.h" +#include "core/pool.hpp" #include "newgrf_cargo.h" #include "newgrf_callbacks.h" @@ -184,10 +184,11 @@ enum SpriteGroupType { }; typedef uint32 SpriteGroupID; -DECLARE_OLD_POOL(SpriteGroup, SpriteGroup, 9, 250) +typedef Pool SpriteGroupPool; +extern SpriteGroupPool _spritegroup_pool; /* Common wrapper for all the different sprite group types */ -struct SpriteGroup : PoolItem { +struct SpriteGroup : SpriteGroupPool::PoolItem<&_spritegroup_pool> { SpriteGroup(SpriteGroupType type = SGT_INVALID) : type(type) { @@ -206,8 +207,6 @@ struct SpriteGroup : PoolItem { TileLayoutSpriteGroup layout; IndustryProductionSpriteGroup indprod; } g; - - inline bool IsValid() const { return this->type != SGT_INVALID; } }; diff --git a/src/oldpool.cpp b/src/oldpool.cpp deleted file mode 100644 index 7cec9d5977..0000000000 --- a/src/oldpool.cpp +++ /dev/null @@ -1,81 +0,0 @@ -/* $Id$ */ - -/** @file oldpool.cpp Implementation of the old pool. */ - -#include "stdafx.h" -#include "debug.h" -#include "oldpool.h" -#include "core/alloc_func.hpp" - -/** - * Clean a pool in a safe way (does free all blocks) - */ -void OldMemoryPoolBase::CleanPool() -{ - uint i; - - DEBUG(misc, 4, "[Pool] (%s) cleaning pool..", this->name); - - this->cleaning_pool = true; - /* Free all blocks */ - for (i = 0; i < this->current_blocks; i++) { - if (this->clean_block_proc != NULL) { - this->clean_block_proc(i * (1 << this->block_size_bits), (i + 1) * (1 << this->block_size_bits) - 1); - } - free(this->blocks[i]); - } - this->cleaning_pool = false; - - /* Free the block itself */ - free(this->blocks); - - /* Clear up some critical data */ - this->total_items = 0; - this->current_blocks = 0; - this->blocks = NULL; - this->first_free_index = 0; -} - -/** - * This function tries to increase the size of array by adding - * 1 block too it - * - * @return Returns false if the pool could not be increased - */ -bool OldMemoryPoolBase::AddBlockToPool() -{ - /* Is the pool at his max? */ - if (this->max_blocks == this->current_blocks) return false; - - this->total_items = (this->current_blocks + 1) * (1 << this->block_size_bits); - - DEBUG(misc, 4, "[Pool] (%s) increasing size of pool to %d items (%d bytes)", this->name, this->total_items, this->total_items * this->item_size); - - /* Increase the poolsize */ - this->blocks = ReallocT(this->blocks, this->current_blocks + 1); - - /* Allocate memory to the new block item */ - this->blocks[this->current_blocks] = CallocT(this->item_size * (1 << this->block_size_bits)); - - /* Call a custom function if defined (e.g. to fill indexes) */ - if (this->new_block_proc != NULL) this->new_block_proc(this->current_blocks * (1 << this->block_size_bits)); - - /* We have a new block */ - this->current_blocks++; - - return true; -} - -/** - * Adds blocks to the pool if needed (and possible) till index fits inside the pool - * - * @return Returns false if adding failed - */ -bool OldMemoryPoolBase::AddBlockIfNeeded(uint index) -{ - while (index >= this->total_items) { - if (!this->AddBlockToPool()) return false; - } - - return true; -} diff --git a/src/oldpool.h b/src/oldpool.h deleted file mode 100644 index 17b791ed7a..0000000000 --- a/src/oldpool.h +++ /dev/null @@ -1,385 +0,0 @@ -/* $Id$ */ - -/** @file oldpool.h Base for the old pool. */ - -#ifndef OLDPOOL_H -#define OLDPOOL_H - -#include "core/math_func.hpp" - -/* The function that is called after a new block is added - start_item is the first item of the new made block */ -typedef void OldMemoryPoolNewBlock(uint start_item); -/* The function that is called before a block is cleaned up */ -typedef void OldMemoryPoolCleanBlock(uint start_item, uint end_item); - -/** - * Stuff for dynamic vehicles. Use the wrappers to access the OldMemoryPool - * please try to avoid manual calls! - */ -struct OldMemoryPoolBase { - void CleanPool(); - bool AddBlockToPool(); - bool AddBlockIfNeeded(uint index); - -protected: - OldMemoryPoolBase(const char *name, uint max_blocks, uint block_size_bits, uint item_size, - OldMemoryPoolNewBlock *new_block_proc, OldMemoryPoolCleanBlock *clean_block_proc) : - name(name), max_blocks(max_blocks), block_size_bits(block_size_bits), - new_block_proc(new_block_proc), clean_block_proc(clean_block_proc), current_blocks(0), - total_items(0), cleaning_pool(false), item_size(item_size), first_free_index(0), blocks(NULL) {} - - const char *name; ///< Name of the pool (just for debugging) - - 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 - - /** Pointer to a function that is called after a new block is added */ - OldMemoryPoolNewBlock *new_block_proc; - /** Pointer to a function that is called to clean a block */ - 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 - - bool cleaning_pool; ///< Are we currently cleaning the pool? -public: - const uint item_size; ///< How many bytes one block is - uint first_free_index; ///< The index of the first free pool item in this pool - byte **blocks; ///< An array of blocks (one block hold all the items) - - /** - * Check if the index of pool item being deleted is lower than cached first_free_index - * @param index index of pool item - * @note usage of min() will result in better code on some architectures - */ - inline void UpdateFirstFreeIndex(uint index) - { - first_free_index = min(first_free_index, index); - } - - /** - * 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; - } - - /** - * 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; - } - - /** - * 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; - } - - /** - * Is the pool in the cleaning phase? - * @return true if it is - */ - inline bool CleaningPool() const - { - return this->cleaning_pool; - } -}; - -template -struct OldMemoryPool : public OldMemoryPoolBase { - OldMemoryPool(const char *name, uint max_blocks, uint block_size_bits, uint item_size, - OldMemoryPoolNewBlock *new_block_proc, OldMemoryPoolCleanBlock *clean_block_proc) : - OldMemoryPoolBase(name, max_blocks, block_size_bits, item_size, new_block_proc, clean_block_proc) {} - - /** - * 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] + - (index & ((1 << this->block_size_bits) - 1)) * this->item_size); - } -}; - -/** - * Generic function to initialize a new block in a pool. - * @param start_item the first item that needs to be initialized - */ -template *Tpool> -static void PoolNewBlock(uint start_item) -{ - 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++; - } -} - -/** - * Generic function to free a new block in a pool. - * @param start_item the first item that needs to be cleaned - * @param end_item the last item that needs to be cleaned - */ -template *Tpool> -static void PoolCleanBlock(uint start_item, uint end_item) -{ - for (uint i = start_item; i <= end_item; i++) { - T *t = Tpool->Get(i); - delete t; - } -} - -/** - * Template providing a predicate to allow STL containers of - * pointers to pool items to be sorted by index. - */ -template -struct PoolItemIndexLess { - /** - * The actual comparator. - * @param lhs the left hand side of the comparison. - * @param rhs the right hand side of the comparison. - * @return true if lhs' index is less than rhs' index. - */ - bool operator()(const T *lhs, const T *rhs) const - { - return lhs->index < rhs->index; - } -}; - -/** - * Generalization for all pool items that are saved in the savegame. - * It specifies all the mechanics to access the pool easily. - */ -template *Tpool> -struct PoolItem { - /** - * The pool-wide index of this object. - */ - Tid index; - - /** - * We like to have the correct class destructed. - * @warning It is called even for object allocated on stack, - * so it is not present in the TPool! - * Then, index is undefined, not associated with TPool in any way. - * @note The idea is to free up allocated memory etc. - */ - virtual ~PoolItem() - { - - } - - /** - * Constructor of given class. - * @warning It is called even for object allocated on stack, - * so it may not be present in TPool! - * Then, index is undefined, not associated with TPool in any way. - * @note The idea is to initialize variables (except index) - */ - PoolItem() - { - - } - - /** - * An overriden version of new that allocates memory on the pool. - * @param size the size of the variable (unused) - * @pre CanAllocateItem() - * @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' - * @note we only update Tpool->first_free_index - */ - void operator delete(void *p) - { - Tpool->UpdateFirstFreeIndex(((T*)p)->index); - } - - /** - * 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 - * @note we only update Tpool->first_free_index - */ - void operator delete(void *p, int index) - { - Tpool->UpdateFirstFreeIndex(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. - * @note we only update Tpool->first_free_index - */ - void operator delete(void *p, T *pn) - { - Tpool->UpdateFirstFreeIndex(pn->index); - } - - /** - * Get item with given index - * @param index item to get - */ - static FORCEINLINE T *Get(uint index) - { - return Tpool->Get(index); - } - - /** - * Get item with given index - * @param index item to get - * @return NULL for invalid items - */ - static FORCEINLINE T *GetIfValid(uint index) - { - if (index >= Tpool->GetSize()) return NULL; - T *item = Tpool->Get(index); - return item->IsValid() ? item : NULL; - } - - /** - * Returns size of the pool (in number of items) - * @return size of the pool - */ - static FORCEINLINE uint GetPoolSize() - { - return Tpool->GetSize(); - } - - /** - * Tests if given ID belongs to valid pool item - * @return is given ID valid? - */ - static FORCEINLINE bool IsValidID(uint index) - { - return index < Tpool->GetSize() && Tpool->Get(index)->IsValid(); - } - -private: - static T *AllocateSafeRaw(uint &first); - -protected: - /** - * Allocate a pool item; possibly allocate a new block in the pool. - * @pre CanAllocateItem() - * @return the allocated pool item. - */ - static inline T *AllocateRaw() - { - return AllocateSafeRaw(Tpool->first_free_index); - } - - /** - * Allocate a pool item; possibly allocate a new block in the pool. - * @param first the first pool item to start searching - * @pre CanAllocateItem() - * @return the allocated pool item. - */ - static inline T *AllocateRaw(uint &first) - { - if (first >= Tpool->GetSize() && !Tpool->AddBlockToPool()) return NULL; - - return AllocateSafeRaw(first); - } - - /** - * Are we cleaning this pool? - * @return true if we are - */ - static inline bool CleaningPool() - { - return Tpool->CleaningPool(); - } - -public: - static bool CanAllocateItem(uint count = 1); -}; - - -#define OLD_POOL_ENUM(name, type, block_size_bits, max_blocks) \ - enum { \ - name##_POOL_BLOCK_SIZE_BITS = block_size_bits, \ - name##_POOL_MAX_BLOCKS = max_blocks \ - }; - - -#define DECLARE_OLD_POOL(name, type, block_size_bits, max_blocks) \ - OLD_POOL_ENUM(name, type, block_size_bits, max_blocks) \ - extern OldMemoryPool _##name##_pool; - - -#define DEFINE_OLD_POOL_GENERIC(name, type) \ - OldMemoryPool _##name##_pool( \ - #name, name##_POOL_MAX_BLOCKS, name##_POOL_BLOCK_SIZE_BITS, sizeof(type), \ - PoolNewBlock, PoolCleanBlock); \ - template type *PoolItem::AllocateSafeRaw(uint &first); \ - template bool PoolItem::CanAllocateItem(uint count); - -#define FOR_ALL_ITEMS_FROM(type, iter, var, start) \ - for (size_t iter = start; var = NULL, iter < type::GetPoolSize(); iter++) \ - if ((var = type::Get(iter))->IsValid()) - -#define FOR_ALL_ITEMS(type, iter, var) FOR_ALL_ITEMS_FROM(type, iter, var, 0) - -#endif /* OLDPOOL_H */ diff --git a/src/oldpool_func.h b/src/oldpool_func.h deleted file mode 100644 index 82b451617d..0000000000 --- a/src/oldpool_func.h +++ /dev/null @@ -1,63 +0,0 @@ -/* $Id$ */ - -/** @file oldpool_func.h Functions related to the old pool. */ - -#ifndef OLDPOOL_FUNC_H -#define OLDPOOL_FUNC_H - -#include "oldpool.h" - -/** - * Allocate a pool item; possibly allocate a new block in the pool. - * @param first the first pool item to start searching - * @pre first <= Tpool->GetSize() - * @pre CanAllocateItem() - * @return the allocated pool item - */ -template *Tpool> T *PoolItem::AllocateSafeRaw(uint &first) -{ - uint last_minus_one = Tpool->GetSize() - 1; - - for (T *t = Tpool->Get(first); t != NULL; t = ((uint)t->index < last_minus_one) ? Tpool->Get(t->index + 1U) : NULL) { - if (!t->IsValid()) { - first = t->index; - Tid index = t->index; - - memset(t, 0, Tpool->item_size); - t->index = index; - return t; - } - } - - /* Check if we can add a block to the pool */ - if (Tpool->AddBlockToPool()) return AllocateRaw(first); - - /* One should *ALWAYS* be sure to have enough space before making vehicles! */ - NOT_REACHED(); -} - -/** - * Check whether we can allocate an item in this pool. This to prevent the - * need to actually construct the object and then destructing it again, - * which could be *very* costly. - * @param count the number of items to create - * @return true if and only if at least count items can be allocated. - */ -template *Tpool> bool PoolItem::CanAllocateItem(uint count) -{ - uint last_minus_one = Tpool->GetSize() - 1; - uint orig_count = count; - - for (T *t = Tpool->Get(Tpool->first_free_index); count > 0 && t != NULL; t = ((uint)t->index < last_minus_one) ? Tpool->Get(t->index + 1U) : NULL) { - if (!t->IsValid()) count--; - } - - if (count == 0) return true; - - /* Check if we can add a block to the pool */ - if (Tpool->AddBlockToPool()) return CanAllocateItem(orig_count); - - return false; -} - -#endif /* OLDPOOL_FUNC_H */ diff --git a/src/openttd.cpp b/src/openttd.cpp index cd2840664f..3b5ff715aa 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -291,7 +291,6 @@ static void InitializeDynamicVariables() _house_mngr.ResetMapping(); _industry_mngr.ResetMapping(); _industile_mngr.ResetMapping(); - _Company_pool.AddBlockToPool(); } @@ -316,16 +315,17 @@ static void ShutdownGame() /* Uninitialize variables that are allocated dynamically */ GamelogReset(); - _Town_pool.CleanPool(); - _Industry_pool.CleanPool(); - _Station_pool.CleanPool(); - _Vehicle_pool.CleanPool(); - _Sign_pool.CleanPool(); - _Order_pool.CleanPool(); - _Group_pool.CleanPool(); - _CargoPacket_pool.CleanPool(); - _Engine_pool.CleanPool(); - _Company_pool.CleanPool(); + _town_pool.CleanPool(); + _industry_pool.CleanPool(); + _station_pool.CleanPool(); + _roadstop_pool.CleanPool(); + _vehicle_pool.CleanPool(); + _sign_pool.CleanPool(); + _order_pool.CleanPool(); + _group_pool.CleanPool(); + _cargopacket_pool.CleanPool(); + _engine_pool.CleanPool(); + _company_pool.CleanPool(); free(_config_file); @@ -1034,6 +1034,55 @@ void SwitchToMode(SwitchMode new_mode) } +#include "depot_base.h" +#include "autoreplace_base.h" +#include "waypoint.h" +#include "network/core/tcp_game.h" +#include "network/network_base.h" +/** Make sure everything is valid. Will be removed in future. */ +static void CheckPools() +{ + const Depot *d; + FOR_ALL_DEPOTS(d) assert(IsRoadDepotTile(d->xy) || IsRailDepotTile(d->xy) || IsShipDepotTile(d->xy) || IsHangarTile(d->xy)); + const Industry *i; + FOR_ALL_INDUSTRIES(i) assert(IsValidTile(i->xy)); + const Engine *e; + FOR_ALL_ENGINES(e) assert(e->info.climates != 0); + const Order *o; + FOR_ALL_ORDERS(o) assert(!o->IsType(OT_NOTHING)); + const OrderList *ol; + FOR_ALL_ORDER_LISTS(ol) assert(ol->GetNumOrders() != INVALID_VEH_ORDER_ID && ol->GetNumVehicles() != 0); + const Town *t; + FOR_ALL_TOWNS(t) assert(IsValidTile(t->xy)); + const Group *g; + FOR_ALL_GROUPS(g) assert(g->owner != INVALID_OWNER); + const EngineRenew *er; + FOR_ALL_ENGINE_RENEWS(er) assert(er->from != INVALID_ENGINE); + const Waypoint *wp; + FOR_ALL_WAYPOINTS(wp) assert(IsValidTile(wp->xy)); + const Company *c; + FOR_ALL_COMPANIES(c) assert(c->name_1 != 0); + const CargoPacket *cp; + FOR_ALL_CARGOPACKETS(cp) assert(cp->count != 0); +#ifdef ENABLE_NETWORK + const NetworkClientSocket *ncs; + FOR_ALL_CLIENT_SOCKETS(ncs) assert(ncs->IsConnected()); + const NetworkClientInfo *nci; + FOR_ALL_CLIENT_INFOS(nci) assert(nci->client_id != INVALID_CLIENT_ID); +#endif + const Station *st; + FOR_ALL_STATIONS(st) assert(IsValidTile(st->xy)); + const RoadStop *rs; + FOR_ALL_ROADSTOPS(rs) assert(IsValidTile(rs->xy)); + const Sign *si; + FOR_ALL_SIGNS(si) assert(si->owner != INVALID_OWNER); + const Vehicle *v; + FOR_ALL_VEHICLES(v) assert(v->type != VEH_INVALID); + + FOR_ALL_ORDER_LISTS(ol) ol->DebugCheckSanity(); +} + + /** * State controlling game loop. * The state must not be changed from anywhere but here. @@ -1048,6 +1097,8 @@ void StateGameLoop() } if (IsGeneratingWorld()) return; + CheckPools(); + ClearStorageChanges(false); if (_game_mode == GM_EDITOR) { diff --git a/src/order_base.h b/src/order_base.h index 544c31b2d6..6630efe64b 100644 --- a/src/order_base.h +++ b/src/order_base.h @@ -6,7 +6,7 @@ #define ORDER_BASE_H #include "order_type.h" -#include "oldpool.h" +#include "core/pool.hpp" #include "core/bitmath_func.hpp" #include "cargo_type.h" #include "depot_type.h" @@ -14,15 +14,17 @@ #include "vehicle_type.h" #include "waypoint_type.h" -DECLARE_OLD_POOL(Order, Order, 6, 1000) -DECLARE_OLD_POOL(OrderList, OrderList, 4, 4000) +typedef Pool OrderPool; +typedef Pool OrderListPool; +extern OrderPool _order_pool; +extern OrderListPool _orderlist_pool; /* If you change this, keep in mind that it is saved on 3 places: * - Load_ORDR, all the global orders * - Vehicle -> current_order * - REF_ORDER (all REFs are currently limited to 16 bits!!) */ -struct Order : PoolItem { +struct Order : OrderPool::PoolItem<&_order_pool> { private: friend const struct SaveLoad *GetVehicleDescription(VehicleType vt); ///< Saving and loading the current order of vehicles. friend void Load_VEHS(); ///< Loading of ancient vehicles. @@ -42,7 +44,7 @@ public: uint16 travel_time; ///< How long in ticks the journey to this destination should take. Order() : refit_cargo(CT_NO_REFIT) {} - ~Order() { this->type = OT_NOTHING; } + ~Order() {} /** * Create an order based on a packed representation of that order. @@ -50,12 +52,6 @@ public: */ Order(uint32 packed); - /** - * Check if a Order really exists. - * @return true if the order is valid. - */ - inline bool IsValid() const { return this->type != OT_NOTHING; } - /** * Check whether this order is of the given type. * @param type the type to check against. @@ -246,7 +242,7 @@ public: /** Shared order list linking together the linked list of orders and the list * of vehicles sharing this order list. */ -struct OrderList : PoolItem { +struct OrderList : OrderListPool::PoolItem<&_orderlist_pool> { private: friend void AfterLoadVehicles(bool part_of_load); ///< For instantiating the shared vehicle chain friend const struct SaveLoad *GetOrderListDescription(); ///< Saving and loading of order lists. @@ -265,16 +261,20 @@ public: timetable_duration(0) { } /** Create an order list with the given order chain for the given vehicle. - * @param chain is the pointer to the first order of the order chain - * @param v is any vehicle of the shared order vehicle chain (does not need to be the first) + * @param chain pointer to the first order of the order chain + * @param v any vehicle using this orderlist */ - OrderList(Order *chain, Vehicle *v); + OrderList(Order *chain, Vehicle *v) { this->Initialize(chain, v); } /** Destructor. Invalidates OrderList for re-usage by the pool. */ - ~OrderList() { this->num_orders = INVALID_VEH_ORDER_ID; } + ~OrderList() {} - /** Checks, if this is a valid order list. */ - inline bool IsValid() const { return this->num_orders != INVALID_VEH_ORDER_ID; } + /** + * Recomputes everything. + * @param chain first order in the chain + * @param v one of vehicle that is using this orderlist + */ + void Initialize(Order *chain, Vehicle *v); /** * Get the first order of the order chain. diff --git a/src/order_cmd.cpp b/src/order_cmd.cpp index 230137efa9..c3bb1384f0 100644 --- a/src/order_cmd.cpp +++ b/src/order_cmd.cpp @@ -17,9 +17,9 @@ #include "newgrf_cargo.h" #include "timetable.h" #include "vehicle_func.h" -#include "oldpool_func.h" #include "depot_base.h" #include "settings_type.h" +#include "core/pool_func.hpp" #include "table/strings.h" @@ -33,8 +33,10 @@ assert_compile(sizeof(DestinationID) >= sizeof(StationID)); TileIndex _backup_orders_tile; BackuppedOrders _backup_orders_data; -DEFINE_OLD_POOL_GENERIC(Order, Order); -DEFINE_OLD_POOL_GENERIC(OrderList, OrderList); +OrderPool _order_pool("Order"); +INSTANTIATE_POOL_METHODS(Order) +OrderListPool _orderlist_pool("OrderList"); +INSTANTIATE_POOL_METHODS(OrderList) void Order::Free() { @@ -176,17 +178,21 @@ void Order::AssignOrder(const Order &other) this->travel_time = other.travel_time; } - -OrderList::OrderList(Order *chain, Vehicle *v) : - first(chain), num_orders(0), num_vehicles(1), first_shared(v), - timetable_duration(0) +void OrderList::Initialize(Order *chain, Vehicle *v) { + this->first = chain; + this->first_shared = v; + + this->num_orders = 0; + this->num_vehicles = 1; + this->timetable_duration = 0; + for (Order *o = this->first; o != NULL; o = o->next) { ++this->num_orders; this->timetable_duration += o->wait_time + o->travel_time; } - for (Vehicle *u = v->PreviousShared(); u != NULL; u = u->PreviousShared()) { + for (Vehicle *u = this->first_shared->PreviousShared(); u != NULL; u = u->PreviousShared()) { ++this->num_vehicles; this->first_shared = u; } @@ -197,7 +203,7 @@ OrderList::OrderList(Order *chain, Vehicle *v) : void OrderList::FreeChain(bool keep_orderlist) { Order *next; - for(Order *o = this->first; o != NULL; o = next) { + for (Order *o = this->first; o != NULL; o = next) { next = o->next; delete o; } @@ -1143,10 +1149,13 @@ CommandCost CmdCloneOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 (*order_dst)->AssignOrder(*order); order_dst = &(*order_dst)->next; } - if (dst->orders.list == NULL) dst->orders.list = new OrderList(first, dst); - else { + if (dst->orders.list == NULL) { + dst->orders.list = new OrderList(first, dst); + } else { assert(dst->orders.list->GetFirstOrder() == NULL); - new (dst->orders.list) OrderList(first, dst); + assert(!dst->orders.list->IsShared()); + delete dst->orders.list; + dst->orders.list = new OrderList(first, dst); } InvalidateVehicleOrder(dst, -1); @@ -1272,7 +1281,7 @@ void RestoreVehicleOrders(const Vehicle *v, const BackuppedOrders *bak) * order number is one more than the current amount of orders, and because * in network the commands are queued before send, the second insert always * fails in test mode. By bypassing the test-mode, that no longer is a problem. */ - for (uint i = 0; bak->order[i].IsValid(); i++) { + for (uint i = 0; !bak->order[i].IsType(OT_NOTHING); i++) { Order o = bak->order[i]; /* Conditional orders need to have their destination to be valid on insertion. */ if (o.IsType(OT_CONDITIONAL)) o.SetConditionSkipToOrder(0); @@ -1291,7 +1300,7 @@ void RestoreVehicleOrders(const Vehicle *v, const BackuppedOrders *bak) } /* Fix the conditional orders' destination. */ - for (uint i = 0; bak->order[i].IsValid(); i++) { + for (uint i = 0; !bak->order[i].IsType(OT_NOTHING); i++) { if (!bak->order[i].IsType(OT_CONDITIONAL)) continue; if (!DoCommandP(0, v->index + (i << 16), MOF_LOAD | (bak->order[i].GetConditionSkipToOrder() << 4), @@ -1776,11 +1785,9 @@ bool Order::ShouldStopAtStation(const Vehicle *v, StationID station) const void InitializeOrders() { - _Order_pool.CleanPool(); - _Order_pool.AddBlockToPool(); + _order_pool.CleanPool(); - _OrderList_pool.CleanPool(); - _OrderList_pool.AddBlockToPool(); + _orderlist_pool.CleanPool(); _backup_orders_tile = 0; } diff --git a/src/order_gui.cpp b/src/order_gui.cpp index 1f6958471a..e44c27f9af 100644 --- a/src/order_gui.cpp +++ b/src/order_gui.cpp @@ -1088,7 +1088,7 @@ public: if (v != NULL && this->HandleOrderVehClick(v)) return; const Order cmd = GetOrderCmdFromTile(this->vehicle, tile); - if (!cmd.IsValid()) return; + if (cmd.IsType(OT_NOTHING)) return; if (DoCommandP(this->vehicle->tile, this->vehicle->index + (this->OrderGetSel() << 16), cmd.Pack(), CMD_INSERT_ORDER | CMD_MSG(STR_ERROR_CAN_T_INSERT_NEW_ORDER))) { /* With quick goto the Go To button stays active */ diff --git a/src/road_cmd.cpp b/src/road_cmd.cpp index 356d1696e0..30b606bc36 100644 --- a/src/road_cmd.cpp +++ b/src/road_cmd.cpp @@ -1243,11 +1243,13 @@ void DrawRoadDepotSprite(int x, int y, DiagDirection dir, RoadType rt) } } -/** Updates cached nearest town for all road tiles +/** + * Updates cached nearest town for all road tiles * @param invalidate are we just invalidating cached data? + * @param ignore town that should be ignored (because we are deleting it now) * @pre invalidate == true implies _generating_world == true */ -void UpdateNearestTownForRoadTiles(bool invalidate) +void UpdateNearestTownForRoadTiles(bool invalidate, const Town *ignore) { assert(!invalidate || _generating_world); @@ -1255,7 +1257,7 @@ void UpdateNearestTownForRoadTiles(bool invalidate) if (IsTileType(t, MP_ROAD) && !HasTownOwnedRoad(t)) { TownID tid = (TownID)INVALID_TOWN; if (!invalidate) { - const Town *town = CalcClosestTownFromTile(t); + const Town *town = CalcClosestTownFromTile(t, UINT_MAX, ignore); if (town != NULL) tid = town->index; } SetTownIndex(t, tid); diff --git a/src/road_cmd.h b/src/road_cmd.h index 00235a3b3b..d1ff2b8d02 100644 --- a/src/road_cmd.h +++ b/src/road_cmd.h @@ -8,6 +8,6 @@ #include "direction_type.h" void DrawRoadDepotSprite(int x, int y, DiagDirection dir, RoadType rt); -void UpdateNearestTownForRoadTiles(bool invalidate); +void UpdateNearestTownForRoadTiles(bool invalidate, const struct Town *ignore = NULL); #endif /* ROAD_CMD_H */ diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index e350b343e1..f32af8537e 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -1457,7 +1457,7 @@ bool AfterLoadGame() Vehicle *v; FOR_ALL_VEHICLES(v) { - if (v->orders.list != NULL && v->orders.list->GetFirstOrder() != NULL && !v->orders.list->GetFirstOrder()->IsValid()) { + if (v->orders.list != NULL && v->orders.list->GetFirstOrder() != NULL && v->orders.list->GetFirstOrder()->IsType(OT_NOTHING)) { v->orders.list->FreeChain(); v->orders.list = NULL; } diff --git a/src/saveload/oldloader.cpp b/src/saveload/oldloader.cpp index 1feb3e4faf..25589a03ca 100644 --- a/src/saveload/oldloader.cpp +++ b/src/saveload/oldloader.cpp @@ -148,8 +148,8 @@ bool LoadChunk(LoadgameState *ls, void *base, const OldChunks *chunks) default: NOT_REACHED(); } - /* Sanity check */ - assert(base_ptr != NULL || chunk->ptr != NULL); + /* When both pointers are NULL, we are just skipping data */ + if (base_ptr == NULL && chunk->ptr == NULL) continue; /* Writing to the var: bits 8 to 15 have the VAR type */ if (chunk->ptr == NULL) ptr = base_ptr + chunk->offset; diff --git a/src/saveload/oldloader_sl.cpp b/src/saveload/oldloader_sl.cpp index ca63e7c1e2..5e6202401d 100644 --- a/src/saveload/oldloader_sl.cpp +++ b/src/saveload/oldloader_sl.cpp @@ -160,6 +160,8 @@ void FixOldVehicles() Vehicle *v; FOR_ALL_VEHICLES(v) { + if (v->next != NULL) v->next = Vehicle::Get((size_t)v->next); + /* For some reason we need to correct for this */ switch (v->spritenum) { case 0xfd: break; @@ -578,7 +580,7 @@ static bool LoadOldTown(LoadgameState *ls, int num) t->townnametype = t->townnametype == 0x10B6 ? 0x20C1 : t->townnametype + 0x2A00; } } else { - t->xy = INVALID_TILE; + delete t; } return true; @@ -594,12 +596,15 @@ static bool LoadOldOrder(LoadgameState *ls, int num) { if (!LoadChunk(ls, NULL, order_chunk)) return false; - new (num) Order(UnpackOldOrder(_old_order)); + Order *o = new (num) Order(UnpackOldOrder(_old_order)); - /* Relink the orders to eachother (in the orders for one vehicle are behind eachother, - * with an invalid order (OT_NOTHING) as indication that it is the last order */ - if (num > 0 && Order::Get(num)->IsValid()) { - Order::Get(num - 1)->next = Order::Get(num); + if (o->IsType(OT_NOTHING)) { + delete o; + } else { + /* Relink the orders to eachother (in the orders for one vehicle are behind eachother, + * with an invalid order (OT_NOTHING) as indication that it is the last order */ + Order *prev = Order::GetIfValid(num - 1); + if (prev != NULL) prev->next = o; } return true; @@ -642,7 +647,7 @@ static bool LoadOldDepot(LoadgameState *ls, int num) if (d->xy != 0) { d->town_index = RemapTownIndex(_old_town_index); } else { - d->xy = INVALID_TILE; + delete d; } return true; @@ -823,7 +828,7 @@ static bool LoadOldStation(LoadgameState *ls, int num) st->string_id = RemapOldStringID(_old_string_id); } } else { - st->xy = INVALID_TILE; + delete st; } return true; @@ -895,7 +900,7 @@ static bool LoadOldIndustry(LoadgameState *ls, int num) IncIndustryTypeCount(i->type); } else { - i->xy = INVALID_TILE; + delete i; } return true; @@ -1142,19 +1147,22 @@ static const OldChunks vehicle_empty_chunk[] = { static bool LoadOldVehicleUnion(LoadgameState *ls, int num) { - Vehicle *v = Vehicle::Get(_current_vehicle_id); + Vehicle *v = Vehicle::GetIfValid(_current_vehicle_id); uint temp = ls->total_read; bool res; - switch (v->type) { - default: NOT_REACHED(); - case VEH_INVALID : res = LoadChunk(ls, NULL, vehicle_empty_chunk); break; - case VEH_TRAIN : res = LoadChunk(ls, &v->u.rail, vehicle_train_chunk); break; - case VEH_ROAD : res = LoadChunk(ls, &v->u.road, vehicle_road_chunk); break; - case VEH_SHIP : res = LoadChunk(ls, &v->u.ship, vehicle_ship_chunk); break; - case VEH_AIRCRAFT: res = LoadChunk(ls, &v->u.air, vehicle_air_chunk); break; - case VEH_EFFECT : res = LoadChunk(ls, &v->u.effect, vehicle_effect_chunk); break; - case VEH_DISASTER: res = LoadChunk(ls, &v->u.disaster, vehicle_disaster_chunk); break; + if (v == NULL) { + res = LoadChunk(ls, NULL, vehicle_empty_chunk); + } else { + switch (v->type) { + default: NOT_REACHED(); + case VEH_TRAIN : res = LoadChunk(ls, &v->u.rail, vehicle_train_chunk); break; + case VEH_ROAD : res = LoadChunk(ls, &v->u.road, vehicle_road_chunk); break; + case VEH_SHIP : res = LoadChunk(ls, &v->u.ship, vehicle_ship_chunk); break; + case VEH_AIRCRAFT: res = LoadChunk(ls, &v->u.air, vehicle_air_chunk); break; + case VEH_EFFECT : res = LoadChunk(ls, &v->u.effect, vehicle_effect_chunk); break; + case VEH_DISASTER: res = LoadChunk(ls, &v->u.disaster, vehicle_disaster_chunk); break; + } } /* This chunk size should always be 10 bytes */ @@ -1271,7 +1279,7 @@ bool LoadOldVehicle(LoadgameState *ls, int num) uint type = ReadByte(ls); switch (type) { default: return false; - case 0x00 /* VEH_INVALID */: v = new (_current_vehicle_id) InvalidVehicle(); break; + case 0x00 /* VEH_INVALID */: v = NULL; break; case 0x25 /* MONORAIL */: case 0x20 /* VEH_TRAIN */: v = new (_current_vehicle_id) Train(); break; case 0x21 /* VEH_ROAD */: v = new (_current_vehicle_id) RoadVehicle(); break; @@ -1282,6 +1290,7 @@ bool LoadOldVehicle(LoadgameState *ls, int num) } if (!LoadChunk(ls, v, vehicle_chunk)) return false; + if (v == NULL) continue; SpriteID sprite = v->cur_image; /* no need to override other sprites */ @@ -1347,7 +1356,7 @@ bool LoadOldVehicle(LoadgameState *ls, int num) /* Read the vehicle type and allocate the right vehicle */ switch (ReadByte(ls)) { default: NOT_REACHED(); - case 0x00 /* VEH_INVALID */: v = new (_current_vehicle_id) InvalidVehicle(); break; + case 0x00 /* VEH_INVALID */: v = NULL; break; case 0x10 /* VEH_TRAIN */: v = new (_current_vehicle_id) Train(); break; case 0x11 /* VEH_ROAD */: v = new (_current_vehicle_id) RoadVehicle(); break; case 0x12 /* VEH_SHIP */: v = new (_current_vehicle_id) Ship(); break; @@ -1355,7 +1364,9 @@ bool LoadOldVehicle(LoadgameState *ls, int num) case 0x14 /* VEH_EFFECT */: v = new (_current_vehicle_id) EffectVehicle(); break; case 0x15 /* VEH_DISASTER*/: v = new (_current_vehicle_id) DisasterVehicle(); break; } + if (!LoadChunk(ls, v, vehicle_chunk)) return false; + if (v == NULL) continue; _old_vehicle_names[_current_vehicle_id] = RemapOldStringID(_old_string_id); @@ -1373,7 +1384,7 @@ bool LoadOldVehicle(LoadgameState *ls, int num) } v->current_order.AssignOrder(UnpackOldOrder(_old_order)); - if (_old_next_ptr != 0xFFFF) v->next = Vehicle::GetPoolSize() <= _old_next_ptr ? new (_old_next_ptr) InvalidVehicle() : Vehicle::Get(_old_next_ptr); + if (_old_next_ptr != 0xFFFF) v->next = (Vehicle *)_old_next_ptr; if (_cargo_count != 0) { CargoPacket *cp = new CargoPacket((_cargo_source == 0xFF) ? INVALID_STATION : _cargo_source, _cargo_count); diff --git a/src/saveload/order_sl.cpp b/src/saveload/order_sl.cpp index 6325b3cca6..d9283a2be3 100644 --- a/src/saveload/order_sl.cpp +++ b/src/saveload/order_sl.cpp @@ -81,7 +81,7 @@ Order UnpackOldOrder(uint16 packed) * Sanity check * TTD stores invalid orders as OT_NOTHING with non-zero flags/station */ - if (!order.IsValid() && packed != 0) order.MakeDummy(); + if (order.IsType(OT_NOTHING) && packed != 0) order.MakeDummy(); return order; } @@ -123,7 +123,6 @@ static void Load_ORDR() /* Version older than 5.2 did not have a ->next pointer. Convert them * (in the old days, the orderlist was 5000 items big) */ size_t len = SlGetFieldLength(); - uint i; if (CheckSavegameVersion(5)) { /* Pre-version 5 had an other layout for orders @@ -133,9 +132,9 @@ static void Load_ORDR() SlArray(orders, len, SLE_UINT16); - for (i = 0; i < len; ++i) { - Order *order = new (i) Order(); - order->AssignOrder(UnpackVersion4Order(orders[i])); + for (size_t i = 0; i < len; ++i) { + Order *o = new (i) Order(); + o->AssignOrder(UnpackVersion4Order(orders[i])); } free(orders); @@ -145,7 +144,7 @@ static void Load_ORDR() SlArray(orders, len, SLE_UINT32); - for (i = 0; i < len; ++i) { + for (size_t i = 0; i < len; ++i) { new (i) Order(orders[i]); } @@ -153,12 +152,17 @@ static void Load_ORDR() } /* Update all the next pointer */ - for (i = 1; i < len; ++i) { + Order *o; + FOR_ALL_ORDERS(o) { + /* Delete invalid orders */ + if (o->IsType(OT_NOTHING)) { + delete o; + continue; + } /* The orders were built like this: - * While the order is valid, set the previous will get it's next pointer set - * We start with index 1 because no order will have the first in it's next pointer */ - if (Order::Get(i)->IsValid()) - Order::Get(i - 1)->next = Order::Get(i); + * While the order is valid, set the previous will get its next pointer set */ + Order *prev = Order::GetIfValid(order_index - 1); + if (prev != NULL) prev->next = o; } } else { int index; @@ -172,6 +176,7 @@ static void Load_ORDR() static void Ptrs_ORDR() { + /* Orders from old savegames have pointers corrected in Load_ORDR */ if (CheckSavegameVersionOldStyle(5, 2)) return; Order *o; diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp index 9389bdab20..9735970d91 100644 --- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -739,8 +739,8 @@ void SlArray(void *array, size_t length, VarType conv) } -static uint ReferenceToInt(const void *obj, SLRefType rt); -static void *IntToReference(uint index, SLRefType rt); +static size_t ReferenceToInt(const void *obj, SLRefType rt); +static void *IntToReference(size_t index, SLRefType rt); /** @@ -782,15 +782,15 @@ void SlList(void *list, SLRefType conv) PtrList::iterator iter; for (iter = l->begin(); iter != l->end(); ++iter) { void *ptr = *iter; - SlWriteUint32(ReferenceToInt(ptr, conv)); + SlWriteUint32((uint32)ReferenceToInt(ptr, conv)); } break; } case SLA_LOAD: { - uint length = CheckSavegameVersion(69) ? SlReadUint16() : SlReadUint32(); + size_t length = CheckSavegameVersion(69) ? SlReadUint16() : SlReadUint32(); /* Load each reference and push to the end of the list */ - for (uint i = 0; i < length; i++) { + for (size_t i = 0; i < length; i++) { size_t data = CheckSavegameVersion(69) ? SlReadUint16() : SlReadUint32(); l->push_back((void *)data); } @@ -899,10 +899,10 @@ bool SlObjectMember(void *ptr, const SaveLoad *sld) case SL_REF: // Reference variable, translate switch (_sl.action) { case SLA_SAVE: - SlWriteUint32(ReferenceToInt(*(void **)ptr, (SLRefType)conv)); + SlWriteUint32((uint32)ReferenceToInt(*(void **)ptr, (SLRefType)conv)); break; case SLA_LOAD: - *(size_t *)ptr = (size_t)(CheckSavegameVersion(69) ? SlReadUint16() : SlReadUint32()); + *(size_t *)ptr = CheckSavegameVersion(69) ? SlReadUint16() : SlReadUint32(); break; case SLA_PTRS: *(void **)ptr = IntToReference(*(size_t *)ptr, (SLRefType)conv); @@ -1470,7 +1470,7 @@ static const ChunkHandler * const _chunk_handlers[] = { * @param rt SLRefType type of the object the index is being sought of * @return Return the pointer converted to an index of the type pointed to */ -static uint ReferenceToInt(const void *obj, SLRefType rt) +static size_t ReferenceToInt(const void *obj, SLRefType rt) { assert(_sl.action == SLA_SAVE); @@ -1505,7 +1505,7 @@ static uint ReferenceToInt(const void *obj, SLRefType rt) assert_compile(sizeof(size_t) <= sizeof(void *)); -static void *IntToReference(uint index, SLRefType rt) +static void *IntToReference(size_t index, SLRefType rt) { assert(_sl.action == SLA_PTRS); diff --git a/src/saveload/strings_sl.cpp b/src/saveload/strings_sl.cpp index 6813c2c06d..c39a036c9d 100644 --- a/src/saveload/strings_sl.cpp +++ b/src/saveload/strings_sl.cpp @@ -4,6 +4,7 @@ #include "../stdafx.h" #include "../core/alloc_func.hpp" +#include "../core/math_func.hpp" #include "../string_func.h" #include "saveload_internal.h" diff --git a/src/saveload/town_sl.cpp b/src/saveload/town_sl.cpp index 5847279181..2528be2a6d 100644 --- a/src/saveload/town_sl.cpp +++ b/src/saveload/town_sl.cpp @@ -10,8 +10,6 @@ #include "saveload.h" -extern uint _total_towns; - /** * Check and update town and house values. * @@ -181,13 +179,9 @@ static void Load_TOWN() { int index; - _total_towns = 0; - while ((index = SlIterateArray()) != -1) { Town *t = new (index) Town(); SlObject(t, _town_desc); - - _total_towns++; } } diff --git a/src/saveload/vehicle_sl.cpp b/src/saveload/vehicle_sl.cpp index ae904dbd54..a44bb6960e 100644 --- a/src/saveload/vehicle_sl.cpp +++ b/src/saveload/vehicle_sl.cpp @@ -208,7 +208,7 @@ void UpdateOldAircraft() */ static void CheckValidVehicles() { - uint total_engines = Engine::GetPoolSize(); + size_t total_engines = Engine::GetPoolSize(); EngineID first_engine[4] = { INVALID_ENGINE, INVALID_ENGINE, INVALID_ENGINE, INVALID_ENGINE }; Engine *e; @@ -282,7 +282,7 @@ void AfterLoadVehicles(bool part_of_load) } } else { // OrderList was saved as such, only recalculate not saved values if (v->PreviousShared() == NULL) { - new (v->orders.list) OrderList(v->orders.list->GetFirstOrder(), v); + v->orders.list->Initialize(v->orders.list->first, v); } } } diff --git a/src/signs.cpp b/src/signs.cpp index d1a3e74520..3da538a717 100644 --- a/src/signs.cpp +++ b/src/signs.cpp @@ -10,12 +10,13 @@ #include "viewport_func.h" #include "zoom_func.h" #include "functions.h" -#include "oldpool_func.h" +#include "core/pool_func.hpp" #include "table/strings.h" /* Initialize the sign-pool */ -DEFINE_OLD_POOL_GENERIC(Sign, Sign) +SignPool _sign_pool("Sign"); +INSTANTIATE_POOL_METHODS(Sign) Sign::Sign(Owner owner) { @@ -29,7 +30,6 @@ Sign::~Sign() if (CleaningPool()) return; DeleteRenameSignWindow(this->index); - this->owner = INVALID_OWNER; } /** @@ -80,6 +80,5 @@ void MarkSignDirty(Sign *si) */ void InitializeSigns() { - _Sign_pool.CleanPool(); - _Sign_pool.AddBlockToPool(); + _sign_pool.CleanPool(); } diff --git a/src/signs_base.h b/src/signs_base.h index e037fdc44d..e4fa3f9c42 100644 --- a/src/signs_base.h +++ b/src/signs_base.h @@ -8,11 +8,12 @@ #include "signs_type.h" #include "viewport_type.h" #include "tile_type.h" -#include "oldpool.h" +#include "core/pool.hpp" -DECLARE_OLD_POOL(Sign, Sign, 2, 16000) +typedef Pool SignPool; +extern SignPool _sign_pool; -struct Sign : PoolItem { +struct Sign : SignPool::PoolItem<&_sign_pool> { char *name; ViewportSign sign; int32 x; @@ -27,8 +28,6 @@ struct Sign : PoolItem { /** Destroy the sign */ ~Sign(); - - inline bool IsValid() const { return this->owner != INVALID_OWNER; } }; #define FOR_ALL_SIGNS_FROM(var, start) FOR_ALL_ITEMS_FROM(Sign, sign_index, var, start) diff --git a/src/station.cpp b/src/station.cpp index aff65dda67..03d7a9db80 100644 --- a/src/station.cpp +++ b/src/station.cpp @@ -20,9 +20,15 @@ #include "aircraft.h" #include "vehicle_gui.h" #include "settings_type.h" +#include "core/pool_func.hpp" #include "table/strings.h" +StationPool _station_pool("Station"); +INSTANTIATE_POOL_METHODS(Station) +RoadStopPool _roadstop_pool("RoadStop"); +INSTANTIATE_POOL_METHODS(RoadStop) + Station::Station(TileIndex tile) { DEBUG(station, cDebugCtorLevel, "I+%3d", index); @@ -88,8 +94,6 @@ Station::~Station() /* Remove all news items */ DeleteStationNews(this->index); - xy = INVALID_TILE; - InvalidateWindowData(WC_SELECT_STATION, 0, 0); for (CargoID c = 0; c < NUM_CARGO; c++) { @@ -460,8 +464,6 @@ RoadStop::~RoadStop() assert(num_vehicles == 0); DEBUG(ms, cDebugCtorLevel , "I- at %d[0x%x]", xy, xy); - - xy = INVALID_TILE; } /** Checks whether there is a free bay in this road stop */ @@ -546,3 +548,9 @@ RoadStop *RoadStop::GetNextRoadStop(const Vehicle *v) const return NULL; } + +void InitializeStations() +{ + _station_pool.CleanPool(); + _roadstop_pool.CleanPool(); +} diff --git a/src/station_base.h b/src/station_base.h index 218f1aa9e5..1b580db2b8 100644 --- a/src/station_base.h +++ b/src/station_base.h @@ -7,7 +7,7 @@ #include "station_type.h" #include "airport.h" -#include "oldpool.h" +#include "core/pool.hpp" #include "cargopacket.h" #include "cargo_type.h" #include "town_type.h" @@ -20,8 +20,10 @@ #include "viewport_type.h" #include -DECLARE_OLD_POOL(Station, Station, 6, 1000) -DECLARE_OLD_POOL(RoadStop, RoadStop, 5, 2000) +typedef Pool StationPool; +typedef Pool RoadStopPool; +extern StationPool _station_pool; +extern RoadStopPool _roadstop_pool; static const byte INITIAL_STATION_RATING = 175; @@ -48,7 +50,7 @@ struct GoodsEntry { }; /** A Stop for a Road Vehicle */ -struct RoadStop : PoolItem { +struct RoadStop : RoadStopPool::PoolItem<&_roadstop_pool> { static const int cDebugCtorLevel = 5; ///< Debug level on which Contructor / Destructor messages are printed static const uint LIMIT = 16; ///< The maximum amount of roadstops that are allowed at a single station static const uint MAX_BAY_COUNT = 2; ///< The maximum number of loading bays @@ -60,13 +62,7 @@ struct RoadStop : PoolItem { struct RoadStop *next; ///< Next stop of the given type at this station RoadStop(TileIndex tile = INVALID_TILE); - virtual ~RoadStop(); - - /** - * Determines whether a road stop exists - * @return true if and only is the road stop exists - */ - inline bool IsValid() const { return this->xy != INVALID_TILE; } + ~RoadStop(); /* For accessing status */ bool HasFreeBay() const; @@ -110,7 +106,7 @@ struct StationRect : public Rect { }; /** Station data structure */ -struct Station : PoolItem { +struct Station : StationPool::PoolItem<&_station_pool> { public: RoadStop *GetPrimaryRoadStop(RoadStopType type) const { @@ -173,7 +169,7 @@ public: static const int cDebugCtorLevel = 5; Station(TileIndex tile = INVALID_TILE); - virtual ~Station(); + ~Station(); void AddFacility(byte new_facility_bit, TileIndex facil_xy); @@ -195,12 +191,6 @@ public: uint GetPlatformLength(TileIndex tile) const; bool IsBuoy() const; - /** - * Determines whether a station exists - * @return true if and only is the station exists - */ - inline bool IsValid() const { return this->xy != INVALID_TILE; } - uint GetCatchmentRadius() const; }; diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp index 4334dfe8c7..fe2422c323 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -29,16 +29,11 @@ #include "date_func.h" #include "vehicle_func.h" #include "string_func.h" -#include "oldpool_func.h" #include "animated_tile_func.h" #include "elrail_func.h" #include "table/strings.h" -DEFINE_OLD_POOL_GENERIC(Station, Station) -DEFINE_OLD_POOL_GENERIC(RoadStop, RoadStop) - - /** * Check whether the given tile is a hangar. * @param t the tile to of whether it is a hangar. @@ -3200,17 +3195,6 @@ static CommandCost ClearTile_Station(TileIndex tile, DoCommandFlag flags) return CMD_ERROR; } -void InitializeStations() -{ - /* Clean the station pool and create 1 block in it */ - _Station_pool.CleanPool(); - _Station_pool.AddBlockToPool(); - - /* Clean the roadstop pool and create 1 block in it */ - _RoadStop_pool.CleanPool(); - _RoadStop_pool.AddBlockToPool(); -} - static CommandCost TerraformTile_Station(TileIndex tile, DoCommandFlag flags, uint z_new, Slope tileh_new) { if (_settings_game.construction.build_on_slopes && AutoslopeEnabled()) { diff --git a/src/station_func.h b/src/station_func.h index 7e548835ac..a8396a7ee3 100644 --- a/src/station_func.h +++ b/src/station_func.h @@ -7,7 +7,6 @@ #include "station_type.h" #include "sprite.h" -#include "oldpool.h" #include "rail_type.h" #include "road_type.h" #include "tile_type.h" diff --git a/src/strings.cpp b/src/strings.cpp index 2e04113b5a..8b2c4e3a31 100644 --- a/src/strings.cpp +++ b/src/strings.cpp @@ -669,7 +669,7 @@ static char *FormatString(char *buff, const char *str, const int64 *argv, uint c int64 args[2]; /* industry not valid anymore? */ - if (!i->IsValid()) break; + assert(i != NULL); /* First print the town name and the industry type name. */ args[0] = i->town->index; @@ -829,7 +829,7 @@ static char *FormatString(char *buff, const char *str, const int64 *argv, uint c case SCC_WAYPOINT_NAME: { // {WAYPOINT} Waypoint *wp = Waypoint::Get(GetInt32(&argv)); - assert(wp->IsValid()); + assert(wp != NULL); if (wp->name != NULL) { buff = strecpy(buff, wp->name, last); @@ -885,7 +885,7 @@ static char *FormatString(char *buff, const char *str, const int64 *argv, uint c const Town *t = Town::Get(GetInt32(&argv)); int64 temp[1]; - assert(t->IsValid()); + assert(t != NULL); temp[0] = t->townnameparts; uint32 grfid = t->townnamegrfid; @@ -911,7 +911,7 @@ static char *FormatString(char *buff, const char *str, const int64 *argv, uint c case SCC_GROUP_NAME: { // {GROUP} const Group *g = Group::Get(GetInt32(&argv)); - assert(g->IsValid()); + assert(g != NULL); if (g->name != NULL) { buff = strecpy(buff, g->name, last); @@ -928,6 +928,8 @@ static char *FormatString(char *buff, const char *str, const int64 *argv, uint c EngineID engine = (EngineID)GetInt32(&argv); const Engine *e = Engine::Get(engine); + assert(e != NULL); + if (e->name != NULL) { buff = strecpy(buff, e->name, last); } else { @@ -939,6 +941,8 @@ static char *FormatString(char *buff, const char *str, const int64 *argv, uint c case SCC_VEHICLE_NAME: { // {VEHICLE} const Vehicle *v = Vehicle::Get(GetInt32(&argv)); + assert(v != NULL); + if (v->name != NULL) { buff = strecpy(buff, v->name, last); } else { diff --git a/src/town.h b/src/town.h index ead399d0ce..0760378819 100644 --- a/src/town.h +++ b/src/town.h @@ -5,7 +5,7 @@ #ifndef TOWN_H #define TOWN_H -#include "oldpool.h" +#include "core/pool.hpp" #include "core/bitmath_func.hpp" #include "core/random_func.hpp" #include "cargo_type.h" @@ -100,9 +100,10 @@ struct BuildingCounts { static const uint CUSTOM_TOWN_NUMBER_DIFFICULTY = 4; ///< value for custom town number in difficulty settings static const uint CUSTOM_TOWN_MAX_NUMBER = 5000; ///< this is the maximum number of towns a user can specify in customisation -DECLARE_OLD_POOL(Town, Town, 3, 8000) +typedef Pool TownPool; +extern TownPool _town_pool; -struct Town : PoolItem { +struct Town : TownPool::PoolItem<&_town_pool> { TileIndex xy; /* Current population of people and amount of houses. */ @@ -183,13 +184,11 @@ struct Town : PoolItem { /** * Creates a new town */ - Town(TileIndex tile = INVALID_TILE); + Town(TileIndex tile = INVALID_TILE) : xy(tile) { } /** Destroy the town */ ~Town(); - inline bool IsValid() const { return this->xy != INVALID_TILE; } - void InitializeLayout(TownLayout layout); /** Calculate the max town noise @@ -297,9 +296,7 @@ TileIndexDiff GetHouseNorthPart(HouseID &house); static inline uint GetNumTowns() { - extern uint _total_towns; - - return _total_towns; + return (uint)Town::GetNumItems(); } /** @@ -324,7 +321,7 @@ static inline Town *GetRandomTown() return Town::Get(index); } -Town *CalcClosestTownFromTile(TileIndex tile, uint threshold = UINT_MAX); +Town *CalcClosestTownFromTile(TileIndex tile, uint threshold = UINT_MAX, const Town *ignore = NULL); #define FOR_ALL_TOWNS_FROM(var, start) FOR_ALL_ITEMS_FROM(Town, town_index, var, start) #define FOR_ALL_TOWNS(var) FOR_ALL_TOWNS_FROM(var, 0) diff --git a/src/town_cmd.cpp b/src/town_cmd.cpp index 2f5efb70d3..a93de76203 100644 --- a/src/town_cmd.cpp +++ b/src/town_cmd.cpp @@ -34,7 +34,6 @@ #include "window_func.h" #include "string_func.h" #include "newgrf_cargo.h" -#include "oldpool_func.h" #include "economy_func.h" #include "station_func.h" #include "cheat_type.h" @@ -42,11 +41,11 @@ #include "animated_tile_func.h" #include "date_func.h" #include "core/smallmap_type.hpp" +#include "core/pool_func.hpp" #include "table/strings.h" #include "table/town_land.h" -uint _total_towns; HouseSpec _house_specs[HOUSE_MAX]; Town *_cleared_town; @@ -56,13 +55,8 @@ uint32 _cur_town_ctr; ///< iterator through all towns in OnTick_Town uint32 _cur_town_iter; ///< frequency iterator at the same place /* Initialize the town-pool */ -DEFINE_OLD_POOL_GENERIC(Town, Town) - -Town::Town(TileIndex tile) -{ - if (tile != INVALID_TILE) _total_towns++; - this->xy = tile; -} +TownPool _town_pool("Town"); +INSTANTIATE_POOL_METHODS(Town) Town::~Town() { @@ -76,7 +70,6 @@ Town::~Town() * and remove from list of sorted towns */ DeleteWindowById(WC_TOWN_VIEW, this->index); InvalidateWindowData(WC_TOWN_DIRECTORY, 0, 0); - _total_towns--; /* Delete all industries belonging to the town */ FOR_ALL_INDUSTRIES(i) if (i->town == this) delete i; @@ -110,9 +103,7 @@ Town::~Town() MarkWholeScreenDirty(); - this->xy = INVALID_TILE; - - UpdateNearestTownForRoadTiles(false); + UpdateNearestTownForRoadTiles(false, this); } /** @@ -2689,13 +2680,14 @@ bool CheckIfAuthorityAllowsNewStation(TileIndex tile, DoCommandFlag flags) } -Town *CalcClosestTownFromTile(TileIndex tile, uint threshold) +Town *CalcClosestTownFromTile(TileIndex tile, uint threshold, const Town *ignore) { Town *t; uint best = threshold; Town *best_town = NULL; FOR_ALL_TOWNS(t) { + if (t == ignore) continue; uint dist = DistanceManhattan(tile, t->xy); if (dist < best) { best = dist; @@ -2713,6 +2705,7 @@ Town *ClosestTownFromTile(TileIndex tile, uint threshold) case MP_ROAD: if (!HasTownOwnedRoad(tile)) { TownID tid = GetTownIndex(tile); + if (tid == (TownID)INVALID_TOWN) { /* in the case we are generating "many random towns", this value may be INVALID_TOWN */ if (_generating_world) return CalcClosestTownFromTile(tile, threshold); @@ -2720,8 +2713,8 @@ Town *ClosestTownFromTile(TileIndex tile, uint threshold) return NULL; } + assert(Town::IsValidID(tid)); Town *town = Town::Get(tid); - assert(town->IsValid()); if (DistanceManhattan(tile, town->xy) >= threshold) town = NULL; @@ -2861,16 +2854,12 @@ void TownsYearlyLoop() void InitializeTowns() { - /* Clean the town pool and create 1 block in it */ - _Town_pool.CleanPool(); - _Town_pool.AddBlockToPool(); + _town_pool.CleanPool(); memset(_subsidies, 0, sizeof(_subsidies)); for (Subsidy *s = _subsidies; s != endof(_subsidies); s++) { s->cargo_type = CT_INVALID; } - - _total_towns = 0; } static CommandCost TerraformTile_Town(TileIndex tile, DoCommandFlag flags, uint z_new, Slope tileh_new) diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index e60df0daf3..a2e731c653 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -4282,7 +4282,7 @@ static bool TrainLocoHandler(Vehicle *v, bool mode) /* exit if train is stopped */ if (v->vehstatus & VS_STOPPED && v->cur_speed == 0) return true; - bool valid_order = v->current_order.IsValid() && v->current_order.GetType() != OT_CONDITIONAL; + bool valid_order = !v->current_order.IsType(OT_NOTHING) && v->current_order.GetType() != OT_CONDITIONAL; if (ProcessOrders(v) && CheckReverseTrain(v)) { v->load_unload_time_rem = 0; v->cur_speed = 0; @@ -4300,7 +4300,7 @@ static bool TrainLocoHandler(Vehicle *v, bool mode) if (!mode) HandleLocomotiveSmokeCloud(v); /* We had no order but have an order now, do look ahead. */ - if (!valid_order && v->current_order.IsValid()) { + if (!valid_order && !v->current_order.IsType(OT_NOTHING)) { CheckNextTrainTile(v); } @@ -4428,10 +4428,12 @@ bool Train::Tick() this->current_order_time++; + VehicleID index = this->index; + if (!TrainLocoHandler(this, false)) return false; /* make sure vehicle wasn't deleted. */ - assert(this->IsValid()); + assert(Vehicle::Get(index) == this); assert(IsFrontEngine(this)); return TrainLocoHandler(this, true); diff --git a/src/vehicle.cpp b/src/vehicle.cpp index 2127d6aecf..961e9ee4ba 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -31,12 +31,12 @@ #include "vehicle_func.h" #include "autoreplace_func.h" #include "autoreplace_gui.h" -#include "oldpool_func.h" #include "ai/ai.hpp" #include "core/smallmap_type.hpp" #include "depot_func.h" #include "settings_type.h" #include "network/network.h" +#include "core/pool_func.hpp" #include "table/sprites.h" #include "table/strings.h" @@ -50,7 +50,8 @@ uint16 _returned_refit_capacity; /* Initialize the vehicle-pool */ -DEFINE_OLD_POOL_GENERIC(Vehicle, Vehicle) +VehiclePool _vehicle_pool("Vehicle"); +INSTANTIATE_POOL_METHODS(Vehicle) /** Function to tell if a vehicle needs to be autorenewed * @param *c The vehicle owner @@ -462,8 +463,7 @@ static AutoreplaceMap _vehicles_to_autoreplace; void InitializeVehicles() { - _Vehicle_pool.CleanPool(); - _Vehicle_pool.AddBlockToPool(); + _vehicle_pool.CleanPool(); _vehicles_to_autoreplace.Reset(); ResetVehiclePosHash(); @@ -571,12 +571,7 @@ Vehicle::~Vehicle() delete v; UpdateVehiclePosHash(this, INVALID_COORD, 0); - this->next_hash = NULL; - this->next_new_hash = NULL; - DeleteVehicleNews(this->index, INVALID_STRING_ID); - - this->type = VEH_INVALID; } /** Adds a vehicle to the list of vehicles, that visited a depot this tick @@ -605,9 +600,12 @@ void CallVehicleTicks() Vehicle *v; FOR_ALL_VEHICLES(v) { /* Vehicle could be deleted in this tick */ - if (!v->Tick()) continue; + if (!v->Tick()) { + assert(Vehicle::Get(vehicle_index) == NULL); + continue; + } - assert(v->IsValid()); + assert(Vehicle::Get(vehicle_index) == v); switch (v->type) { default: break; diff --git a/src/vehicle_base.h b/src/vehicle_base.h index 087833cb65..955c4f3fe9 100644 --- a/src/vehicle_base.h +++ b/src/vehicle_base.h @@ -16,7 +16,7 @@ #include "date_type.h" #include "company_base.h" #include "company_type.h" -#include "oldpool.h" +#include "core/pool.hpp" #include "order_base.h" #include "cargopacket.h" #include "texteff.hpp" @@ -189,15 +189,18 @@ struct VehicleShip { TrackBitsByte state; }; -DECLARE_OLD_POOL(Vehicle, Vehicle, 9, 125) +typedef Pool VehiclePool; +extern VehiclePool _vehicle_pool; /* Some declarations of functions, so we can make them friendly */ struct SaveLoad; extern const SaveLoad *GetVehicleDescription(VehicleType vt); struct LoadgameState; extern bool LoadOldVehicle(LoadgameState *ls, int num); +extern bool AfterLoadGame(); +extern void FixOldVehicles(); -struct Vehicle : PoolItem, BaseVehicle { +struct Vehicle : VehiclePool::PoolItem<&_vehicle_pool>, BaseVehicle { private: Vehicle *next; ///< pointer to the next vehicle in the chain Vehicle *previous; ///< NOSAVE: pointer to the previous vehicle in the chain @@ -207,6 +210,8 @@ private: Vehicle *previous_shared; ///< NOSAVE: pointer to the previous vehicle in the shared order chain public: friend const SaveLoad *GetVehicleDescription(VehicleType vt); ///< So we can use private/protected variables in the saveload code + friend bool AfterLoadGame(); + friend void FixOldVehicles(); friend void AfterLoadVehicles(bool part_of_load); ///< So we can set the previous and first pointers while loading friend bool LoadOldVehicle(LoadgameState *ls, int num); ///< So we can set the proper next pointer while loading @@ -624,24 +629,6 @@ struct DisasterVehicle : public Vehicle { bool Tick(); }; -/** - * This class 'wraps' Vehicle; you do not actually instantiate this class. - * You create a Vehicle using AllocateVehicle, so it is added to the pool - * and you reinitialize that to a Train using: - * v = new (v) Train(); - * - * As side-effect the vehicle type is set correctly. - */ -struct InvalidVehicle : public Vehicle { - /** Initializes the Vehicle to a invalid vehicle */ - InvalidVehicle() { this->type = VEH_INVALID; } - - /** We want to 'destruct' the right class. */ - virtual ~InvalidVehicle() {} - - const char *GetTypeString() const { return "invalid vehicle"; } -}; - #define FOR_ALL_VEHICLES_FROM(var, start) FOR_ALL_ITEMS_FROM(Vehicle, vehicle_index, var, start) #define FOR_ALL_VEHICLES(var) FOR_ALL_VEHICLES_FROM(var, 0) diff --git a/src/vehicle_type.h b/src/vehicle_type.h index 76d552b3e2..d1152ace36 100644 --- a/src/vehicle_type.h +++ b/src/vehicle_type.h @@ -28,12 +28,6 @@ struct Vehicle; struct BaseVehicle { VehicleTypeByte type; ///< Type of vehicle - - /** - * Is this vehicle a valid vehicle? - * @return true if and only if the vehicle is valid. - */ - inline bool IsValid() const { return this->type != VEH_INVALID; } }; static const VehicleID INVALID_VEHICLE = 0xFFFF; diff --git a/src/water_map.h b/src/water_map.h index be6c22b909..3d2f77d993 100644 --- a/src/water_map.h +++ b/src/water_map.h @@ -5,6 +5,8 @@ #ifndef WATER_MAP_H #define WATER_MAP_H +#include "core/math_func.hpp" + enum WaterTileType { WATER_TILE_CLEAR, WATER_TILE_COAST, diff --git a/src/waypoint.cpp b/src/waypoint.cpp index f356284921..96a9e50259 100644 --- a/src/waypoint.cpp +++ b/src/waypoint.cpp @@ -11,10 +11,11 @@ #include "waypoint.h" #include "window_func.h" #include "newgrf_station.h" -#include "oldpool_func.h" #include "order_func.h" +#include "core/pool_func.hpp" -DEFINE_OLD_POOL_GENERIC(Waypoint, Waypoint) +WaypointPool _waypoint_pool("Waypoint"); +INSTANTIATE_POOL_METHODS(Waypoint) /** * Update all signs @@ -79,11 +80,6 @@ void DrawWaypointSprite(int x, int y, int stat_id, RailType railtype) } } -Waypoint::Waypoint(TileIndex tile) -{ - this->xy = tile; -} - Waypoint::~Waypoint() { free(this->name); @@ -93,11 +89,9 @@ Waypoint::~Waypoint() RemoveOrderFromAllVehicles(OT_GOTO_WAYPOINT, this->index); RedrawWaypointSign(this); - this->xy = INVALID_TILE; } void InitializeWaypoints() { - _Waypoint_pool.CleanPool(); - _Waypoint_pool.AddBlockToPool(); + _waypoint_pool.CleanPool(); } diff --git a/src/waypoint.h b/src/waypoint.h index 7e6f9f12a9..eb388e86d0 100644 --- a/src/waypoint.h +++ b/src/waypoint.h @@ -6,17 +6,18 @@ #define WAYPOINT_H #include "waypoint_type.h" -#include "oldpool.h" #include "rail_map.h" #include "command_type.h" #include "station_type.h" #include "town_type.h" #include "viewport_type.h" #include "date_type.h" +#include "core/pool.hpp" -DECLARE_OLD_POOL(Waypoint, Waypoint, 3, 8000) +typedef Pool WaypointPool; +extern WaypointPool _waypoint_pool; -struct Waypoint : PoolItem { +struct Waypoint : WaypointPool::PoolItem<&_waypoint_pool> { TileIndex xy; ///< Tile of waypoint TownID town_index; ///< Town associated with the waypoint @@ -34,10 +35,8 @@ struct Waypoint : PoolItem { byte deleted; ///< Delete counter. If greater than 0 then it is decremented until it reaches 0; the waypoint is then is deleted. - Waypoint(TileIndex tile = INVALID_TILE); + Waypoint(TileIndex tile = INVALID_TILE) : xy(tile) { } ~Waypoint(); - - inline bool IsValid() const { return this->xy != INVALID_TILE; } }; #define FOR_ALL_WAYPOINTS_FROM(var, start) FOR_ALL_ITEMS_FROM(Waypoint, waypoint_index, var, start) diff --git a/src/waypoint_cmd.cpp b/src/waypoint_cmd.cpp index 468d216cb0..ae3980edf8 100644 --- a/src/waypoint_cmd.cpp +++ b/src/waypoint_cmd.cpp @@ -74,7 +74,7 @@ static void MakeDefaultWaypointName(Waypoint *wp) Waypoint *lwp = Waypoint::Get(cid); /* check only valid waypoints... */ - if (lwp->IsValid() && wp != lwp) { + if (lwp != NULL && wp != lwp) { /* only waypoints with 'generic' name within the same city */ if (lwp->name == NULL && lwp->town_index == wp->town_index) { /* if lwp->town_cn < next, uint will overflow to '+inf' */ diff --git a/src/waypoint_gui.cpp b/src/waypoint_gui.cpp index 10f067677b..9d0ac71890 100644 --- a/src/waypoint_gui.cpp +++ b/src/waypoint_gui.cpp @@ -144,6 +144,5 @@ static const WindowDesc _waypoint_view_desc( void ShowWaypointWindow(const Waypoint *wp) { - if (!wp->IsValid()) return; // little safety AllocateWindowDescFront(&_waypoint_view_desc, wp->index); }