changeset 11972:fd10870d74d4 draft

(svn r16378) -Codechange: replace OldPool with simpler Pool. Compilation time, binary size and run time (with asserts disabled) should be improved
author smatz <smatz@openttd.org>
date Fri, 22 May 2009 15:13:50 +0000
parents 9daf69237623
children e17a54c88806
files projects/openttd_vs80.vcproj projects/openttd_vs90.vcproj source.list src/aircraft_cmd.cpp src/articulated_vehicles.cpp src/autoreplace.cpp src/autoreplace_base.h src/cargopacket.cpp src/cargopacket.h src/company_base.h src/company_cmd.cpp src/core/pool.hpp src/core/pool_func.hpp src/core/random_func.cpp src/date.cpp src/depot.cpp src/depot_base.h src/engine.cpp src/engine_base.h src/group.h src/group_cmd.cpp src/group_gui.cpp src/industry.h src/industry_cmd.cpp src/misc_gui.cpp src/network/core/tcp_game.cpp src/network/core/tcp_game.h src/network/network.cpp src/network/network_base.h src/network/network_chat_gui.cpp src/network/network_type.h src/newgrf.cpp src/newgrf_spritegroup.cpp src/newgrf_spritegroup.h src/oldpool.cpp src/oldpool.h src/oldpool_func.h src/openttd.cpp src/order_base.h src/order_cmd.cpp src/order_gui.cpp src/road_cmd.cpp src/road_cmd.h src/saveload/afterload.cpp src/saveload/oldloader.cpp src/saveload/oldloader_sl.cpp src/saveload/order_sl.cpp src/saveload/saveload.cpp src/saveload/strings_sl.cpp src/saveload/town_sl.cpp src/saveload/vehicle_sl.cpp src/signs.cpp src/signs_base.h src/station.cpp src/station_base.h src/station_cmd.cpp src/station_func.h src/strings.cpp src/town.h src/town_cmd.cpp src/train_cmd.cpp src/vehicle.cpp src/vehicle_base.h src/vehicle_type.h src/water_map.h src/waypoint.cpp src/waypoint.h src/waypoint_cmd.cpp src/waypoint_gui.cpp
diffstat 69 files changed, 834 insertions(+), 995 deletions(-) [+]
line wrap: on
line diff
--- a/projects/openttd_vs80.vcproj
+++ b/projects/openttd_vs80.vcproj
@@ -644,10 +644,6 @@
 				>
 			</File>
 			<File
-				RelativePath=".\..\src\oldpool.cpp"
-				>
-			</File>
-			<File
 				RelativePath=".\..\src\openttd.cpp"
 				>
 			</File>
@@ -1252,14 +1248,6 @@
 				>
 			</File>
 			<File
-				RelativePath=".\..\src\oldpool.h"
-				>
-			</File>
-			<File
-				RelativePath=".\..\src\oldpool_func.h"
-				>
-			</File>
-			<File
 				RelativePath=".\..\src\openttd.h"
 				>
 			</File>
@@ -1688,6 +1676,14 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\core\pool.hpp"
+				>
+			</File>
+			<File
+				RelativePath=".\..\src\core\pool_func.hpp"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\core\random_func.cpp"
 				>
 			</File>
--- a/projects/openttd_vs90.vcproj
+++ b/projects/openttd_vs90.vcproj
@@ -641,10 +641,6 @@
 				>
 			</File>
 			<File
-				RelativePath=".\..\src\oldpool.cpp"
-				>
-			</File>
-			<File
 				RelativePath=".\..\src\openttd.cpp"
 				>
 			</File>
@@ -1249,14 +1245,6 @@
 				>
 			</File>
 			<File
-				RelativePath=".\..\src\oldpool.h"
-				>
-			</File>
-			<File
-				RelativePath=".\..\src\oldpool_func.h"
-				>
-			</File>
-			<File
 				RelativePath=".\..\src\openttd.h"
 				>
 			</File>
@@ -1685,6 +1673,14 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\core\pool.hpp"
+				>
+			</File>
+			<File
+				RelativePath=".\..\src\core\pool_func.hpp"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\core\random_func.cpp"
 				>
 			</File>
--- a/source.list
+++ b/source.list
@@ -48,7 +48,6 @@
 network/network_server.cpp
 network/network_udp.cpp
 npf.cpp
-oldpool.cpp
 openttd.cpp
 os_timer.cpp
 #if WIN32
@@ -243,8 +242,6 @@
 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.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
--- a/src/aircraft_cmd.cpp
+++ b/src/aircraft_cmd.cpp
@@ -589,8 +589,11 @@
 	}
 
 	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 @@
 		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 @@
 
 	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));
 	}
 
--- a/src/articulated_vehicles.cpp
+++ b/src/articulated_vehicles.cpp
@@ -21,9 +21,9 @@
 	 * 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;
 	}
 
--- 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 @@
 
 void InitializeEngineRenews()
 {
-	/* Clean the engine renew pool and create 1 block in it */
-	_EngineRenew_pool.CleanPool();
-	_EngineRenew_pool.AddBlockToPool();
+	_enginerenew_pool.CleanPool();
 }
--- 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 @@
  * placed here so the only exception to this rule, the saveload code, can use
  * it.
  */
-DECLARE_OLD_POOL(EngineRenew, EngineRenew, 3, 8000)
+typedef Pool<EngineRenew, EngineRenewID, 16, 64000> 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<EngineRenew, EngineRenewID, &_EngineRenew_pool> {
+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)
--- 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 @@
 	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 @@
 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) {
--- 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 @@
 struct CargoPacket;
 
 /** We want to use a pool */
-DECLARE_OLD_POOL(CargoPacket, CargoPacket, 10, 1000)
-
+typedef Pool<CargoPacket, CargoPacketID, 1024, 1048576> CargoPacketPool;
+extern CargoPacketPool _cargopacket_pool;
 
 /**
  * Container for cargo from the same location and time
  */
-struct CargoPacket : PoolItem<CargoPacket, CargoPacketID, &_CargoPacket_pool> {
+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 @@
 	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
--- 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 @@
 	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<Company, CompanyByte, 1, MAX_COMPANIES> CompanyPool;
+extern CompanyPool _company_pool;
 
-struct Company : PoolItem<Company, CompanyByte, &_Company_pool> {
+
+struct Company : CompanyPool::PoolItem<&_company_pool> {
 	Company(uint16 name_1 = 0, bool is_ai = false);
 	~Company();
 
@@ -81,13 +79,6 @@
 	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 @@
 
 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);
--- 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 @@
 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 @@
 	if (CleaningPool()) return;
 
 	DeleteCompanyWindows(this->index);
-	this->name_1 = 0;
 }
 
 /**
@@ -421,7 +421,7 @@
  */
 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 @@
 
 void InitializeCompanies()
 {
-	_Company_pool.CleanPool();
-	_Company_pool.AddBlockToPool();
+	_company_pool.CleanPool();
 	_cur_company_tick_index = 0;
 }
 
new file mode 100644
--- /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 <class Titem, typename Tindex, size_t Tgrowth_step, size_t Tmax_size>
+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 <struct Pool<Titem, Tindex, Tgrowth_step, Tmax_size> *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 */
new file mode 100644
--- /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 <class Titem, typename Tindex, size_t Tgrowth_step, size_t Tmax_size> \
+	type Pool<Titem, Tindex, Tgrowth_step, Tmax_size>
+
+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<byte>(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 */
--- a/src/core/random_func.cpp
+++ b/src/core/random_func.cpp
@@ -40,7 +40,7 @@
 
 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);
 	}
 
--- a/src/date.cpp
+++ b/src/date.cpp
@@ -184,12 +184,10 @@
  */
 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();
--- 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 @@
 
 	/* 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();
 }
--- 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<Depot, DepotID, 64, 64000> DepotPool;
+extern DepotPool _depot_pool;
 
-struct Depot : PoolItem<Depot, DepotID, &_Depot_pool> {
+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);
--- 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 @@
  */
 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 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();
--- 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<Engine, EngineID, 64, 64000> EnginePool;
+extern EnginePool _engine_pool;
 
-struct Engine : PoolItem<Engine, EngineID, &_Engine_pool> {
+struct Engine : EnginePool::PoolItem<&_engine_pool> {
 	char *name;         ///< Custom name of engine
 	Date intro_date;
 	Date age;
@@ -49,8 +50,6 @@
 	Engine(VehicleType type, EngineID base);
 	~Engine();
 
-	inline bool IsValid() const { return this->info.climates != 0; }
-
 	CargoID GetDefaultCargoType() const;
 	bool CanCarryCargo() const;
 	uint GetDisplayDefaultCapacity() const;
--- 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<Group, GroupID, 16, 64000> GroupPool;
+extern GroupPool _group_pool;
 
-struct Group : PoolItem<Group, GroupID, &_Group_pool> {
+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 @@
 	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();
 };
 
 
--- 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 @@
 }
 
 
-DEFINE_OLD_POOL_GENERIC(Group, Group)
-
 
 Group::Group(Owner owner)
 {
 	this->owner = owner;
 
-	if (this->IsValid()) this->num_engines = CallocT<uint16>(Engine::GetPoolSize());
+	if (!Company::IsValidID(owner)) return;
+
+	this->num_engines = CallocT<uint16>(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 @@
  */
 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 @@
 {
 	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 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()) {
--- a/src/group_gui.cpp
+++ b/src/group_gui.cpp
@@ -533,22 +533,18 @@
 
 			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;
--- 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 @@
 
 DECLARE_ENUM_AS_BIT_SET(IndustryBehaviour);
 
-DECLARE_OLD_POOL(Industry, Industry, 3, 8000)
+typedef Pool<Industry, IndustryID, 64, 64000> IndustryPool;
+extern IndustryPool _industry_pool;
 
 /**
  * Defines the internal data of a functionnal industry
  */
-struct Industry : PoolItem<Industry, IndustryID, &_Industry_pool> {
+struct Industry : IndustryPool::PoolItem<&_industry_pool> {
 	typedef PersistentStorageArray<uint32, 16> PersistentStorage;
 
 	TileIndex xy;                       ///< coordinates of the primary tile the industry is built one
@@ -134,8 +135,6 @@
 
 	Industry(TileIndex tile = INVALID_TILE) : xy(tile) {}
 	~Industry();
-
-	inline bool IsValid() const { return this->xy != INVALID_TILE; }
 };
 
 struct IndustryTileTable {
@@ -265,12 +264,11 @@
 /* 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 @@
 {
 	assert(type < INVALID_INDUSTRYTYPE);
 	_industry_counts[type]++;
-	_total_industries++;
 }
 
 /** Decrement the count of industries for this type
@@ -290,7 +287,6 @@
 {
 	assert(type < INVALID_INDUSTRYTYPE);
 	_industry_counts[type]--;
-	_total_industries--;
 }
 
 /** get the count of industries for this type
@@ -306,7 +302,6 @@
  * This way, we centralize all counts activities */
 static inline void ResetIndustryCounts()
 {
-	_total_industries = 0;
 	memset(&_industry_counts, 0, sizeof(_industry_counts));
 }
 
--- 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 @@
 	_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 @@
 	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 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 @@
 	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 @@
 
 	/* 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 @@
 			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 InitializeIndustries()
 {
-	_Industry_pool.CleanPool();
-	_Industry_pool.AddBlockToPool();
+	_industry_pool.CleanPool();
 
 	ResetIndustryCounts();
 	_industry_sound_tile = 0;
--- a/src/misc_gui.cpp
+++ b/src/misc_gui.cpp
@@ -184,7 +184,7 @@
 
 		/* 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);
 		}
--- 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)
 {
--- 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 @@
 	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<NetworkClientSocket, ClientIndex, 8, MAX_CLIENT_SLOTS> NetworkClientSocketPool;
+extern NetworkClientSocketPool _networkclientsocket_pool;
 
 /** Base socket handler for all TCP sockets */
-class NetworkClientSocket : public PoolItem<NetworkClientSocket, ClientIndex, &_NetworkClientSocket_pool>, 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 @@
 	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; }
 
--- 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 @@
 /** 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 */
--- 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<NetworkClientInfo, ClientIndex, 8, MAX_CLIENT_SLOTS> NetworkClientInfoPool;
+extern NetworkClientInfoPool _networkclientinfo_pool;
 
-struct NetworkClientInfo : PoolItem<NetworkClientInfo, ClientIndex, &_NetworkClientInfo_pool> {
+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 @@
 
 	NetworkClientInfo(ClientID client_id = INVALID_CLIENT_ID) : client_id(client_id) {}
 	~NetworkClientInfo() { client_id = INVALID_CLIENT_ID; }
-
-	inline bool IsValid() const { return client_id != INVALID_CLIENT_ID; }
 };
 
 #define FOR_ALL_CLIENT_INFOS_FROM(var, start) FOR_ALL_ITEMS_FROM(NetworkClientInfo, clientinfo_index, var, start)
--- a/src/network/network_chat_gui.cpp
+++ b/src/network/network_chat_gui.cpp
@@ -303,14 +303,11 @@
 
 		/* First, try clients */
 		if (*item < MAX_CLIENT_SLOTS) {
-			if (*item < NetworkClientInfo::GetPoolSize()) {
-				/* Skip inactive clients */
-				NetworkClientInfo *ci;
-				FOR_ALL_CLIENT_INFOS_FROM(ci, *item) break;
-				if (ci != NULL) {
-					*item = ci->index;
-					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;
 		}
--- a/src/network/network_type.h
+++ b/src/network/network_type.h
@@ -16,13 +16,10 @@
 	/** 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,
 
--- a/src/newgrf.cpp
+++ b/src/newgrf.cpp
@@ -378,7 +378,7 @@
 
 	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 @@
 	_grf_id_overrides.clear();
 
 	InitializeSoundPool();
-	_SpriteGroup_pool.CleanPool();
-	_SpriteGroup_pool.AddBlockToPool();
+	_spritegroup_pool.CleanPool();
 }
 
 static void BuildCargoTranslationMap()
--- 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 @@
 		default:
 			break;
 	}
-
-	this->type = SGT_INVALID;
 }
 
 TemporaryStorageArray<uint32, 0x110> _temp_store;
--- 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 @@
 };
 
 typedef uint32 SpriteGroupID;
-DECLARE_OLD_POOL(SpriteGroup, SpriteGroup, 9, 250)
+typedef Pool<SpriteGroup, SpriteGroupID, 512, 64000> SpriteGroupPool;
+extern SpriteGroupPool _spritegroup_pool;
 
 /* Common wrapper for all the different sprite group types */
-struct SpriteGroup : PoolItem<SpriteGroup, SpriteGroupID, &_SpriteGroup_pool> {
+struct SpriteGroup : SpriteGroupPool::PoolItem<&_spritegroup_pool> {
 	SpriteGroup(SpriteGroupType type = SGT_INVALID) :
 		type(type)
 	{
@@ -206,8 +207,6 @@
 		TileLayoutSpriteGroup layout;
 		IndustryProductionSpriteGroup indprod;
 	} g;
-
-	inline bool IsValid() const { return this->type != SGT_INVALID; }
 };
 
 
deleted file mode 100644
--- 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<byte>(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;
-}
deleted file mode 100644
--- 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 <typename T>
-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 <typename T, OldMemoryPool<T> *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 <typename T, OldMemoryPool<T> *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 <typename T>
-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 <typename T, typename Tid, OldMemoryPool<T> *Tpool>
-struct PoolItem {
-	/**
-	 * The pool-wide index of this object.
-	 */
-	Tid index;
-
-	/**
-	 * We like to have the correct class destructed.
-	 * @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<type> _##name##_pool;
-
-
-#define DEFINE_OLD_POOL_GENERIC(name, type) \
-	OldMemoryPool<type> _##name##_pool( \
-		#name, name##_POOL_MAX_BLOCKS, name##_POOL_BLOCK_SIZE_BITS, sizeof(type), \
-		PoolNewBlock<type, &_##name##_pool>, PoolCleanBlock<type, &_##name##_pool>); \
-		template type *PoolItem<type, type##ID, &_##name##_pool>::AllocateSafeRaw(uint &first); \
-		template bool PoolItem<type, type##ID, &_##name##_pool>::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 */
deleted file mode 100644
--- 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<typename T, typename Tid, OldMemoryPool<T> *Tpool> T *PoolItem<T, Tid, Tpool>::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<typename T, typename Tid, OldMemoryPool<T> *Tpool> bool PoolItem<T, Tid, Tpool>::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 */
--- a/src/openttd.cpp
+++ b/src/openttd.cpp
@@ -291,7 +291,6 @@
 	_house_mngr.ResetMapping();
 	_industry_mngr.ResetMapping();
 	_industile_mngr.ResetMapping();
-	_Company_pool.AddBlockToPool();
 }
 
 
@@ -316,16 +315,17 @@
 
 	/* 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 @@
 }
 
 
+#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 @@
 	}
 	if (IsGeneratingWorld()) return;
 
+	CheckPools();
+
 	ClearStorageChanges(false);
 
 	if (_game_mode == GM_EDITOR) {
--- 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<Order, OrderID, 256, 64000> OrderPool;
+typedef Pool<OrderList, OrderListID, 128, 64000> 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<Order, OrderID, &_Order_pool> {
+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 @@
 	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.
@@ -51,12 +53,6 @@
 	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.
 	 * @return true if the order matches.
@@ -246,7 +242,7 @@
 /** Shared order list linking together the linked list of orders and the list
  *  of vehicles sharing this order list.
  */
-struct OrderList : PoolItem<OrderList, OrderListID, &_OrderList_pool> {
+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 @@
 		  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.
--- 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 @@
 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 @@
 	this->travel_time = other.travel_time;
 }
 
+void OrderList::Initialize(Order *chain, Vehicle *v)
+{
+	this->first = chain;
+	this->first_shared = v;
 
-OrderList::OrderList(Order *chain, Vehicle *v) :
-		first(chain), num_orders(0), num_vehicles(1), first_shared(v),
-		timetable_duration(0)
-{
+	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 @@
 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 @@
 					(*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 @@
 		 *  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 @@
 		}
 
 			/* 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 @@
 
 void InitializeOrders()
 {
-	_Order_pool.CleanPool();
-	_Order_pool.AddBlockToPool();
+	_order_pool.CleanPool();
 
-	_OrderList_pool.CleanPool();
-	_OrderList_pool.AddBlockToPool();
+	_orderlist_pool.CleanPool();
 
 	_backup_orders_tile = 0;
 }
--- a/src/order_gui.cpp
+++ b/src/order_gui.cpp
@@ -1088,7 +1088,7 @@
 			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 */
--- a/src/road_cmd.cpp
+++ b/src/road_cmd.cpp
@@ -1243,11 +1243,13 @@
 	}
 }
 
-/** 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 @@
 		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);
--- 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 */
--- a/src/saveload/afterload.cpp
+++ b/src/saveload/afterload.cpp
@@ -1457,7 +1457,7 @@
 
 		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;
 			}
--- a/src/saveload/oldloader.cpp
+++ b/src/saveload/oldloader.cpp
@@ -148,8 +148,8 @@
 					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;
--- a/src/saveload/oldloader_sl.cpp
+++ b/src/saveload/oldloader_sl.cpp
@@ -160,6 +160,8 @@
 	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 @@
 			t->townnametype = t->townnametype == 0x10B6 ? 0x20C1 : t->townnametype + 0x2A00;
 		}
 	} else {
-		t->xy = INVALID_TILE;
+		delete t;
 	}
 
 	return true;
@@ -594,12 +596,15 @@
 {
 	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 @@
 	if (d->xy != 0) {
 		d->town_index = RemapTownIndex(_old_town_index);
 	} else {
-		d->xy = INVALID_TILE;
+		delete d;
 	}
 
 	return true;
@@ -823,7 +828,7 @@
 			st->string_id = RemapOldStringID(_old_string_id);
 		}
 	} else {
-		st->xy = INVALID_TILE;
+		delete st;
 	}
 
 	return true;
@@ -895,7 +900,7 @@
 
 		IncIndustryTypeCount(i->type);
 	} else {
-		i->xy = INVALID_TILE;
+		delete i;
 	}
 
 	return true;
@@ -1142,19 +1147,22 @@
 
 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 @@
 			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 @@
 			}
 
 			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 @@
 			/* 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 @@
 				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 @@
 		}
 		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);
--- a/src/saveload/order_sl.cpp
+++ b/src/saveload/order_sl.cpp
@@ -81,7 +81,7 @@
 	 * 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 @@
 		/* 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 @@
 
 			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 @@
 
 			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 @@
 		}
 
 		/* 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 Ptrs_ORDR()
 {
+	/* Orders from old savegames have pointers corrected in Load_ORDR */
 	if (CheckSavegameVersionOldStyle(5, 2)) return;
 
 	Order *o;
--- a/src/saveload/saveload.cpp
+++ b/src/saveload/saveload.cpp
@@ -739,8 +739,8 @@
 }
 
 
-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 @@
 			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 @@
 				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 @@
  * @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 @@
 
 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);
 
--- 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"
 
--- 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 @@
 {
 	int index;
 
-	_total_towns = 0;
-
 	while ((index = SlIterateArray()) != -1) {
 		Town *t = new (index) Town();
 		SlObject(t, _town_desc);
-
-		_total_towns++;
 	}
 }
 
--- a/src/saveload/vehicle_sl.cpp
+++ b/src/saveload/vehicle_sl.cpp
@@ -208,7 +208,7 @@
  */
 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 @@
 					}
 				} 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);
 					}
 				}
 			}
--- 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 @@
 	if (CleaningPool()) return;
 
 	DeleteRenameSignWindow(this->index);
-	this->owner = INVALID_OWNER;
 }
 
 /**
@@ -80,6 +80,5 @@
  */
 void InitializeSigns()
 {
-	_Sign_pool.CleanPool();
-	_Sign_pool.AddBlockToPool();
+	_sign_pool.CleanPool();
 }
--- 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<Sign, SignID, 16, 64000> SignPool;
+extern SignPool _sign_pool;
 
-struct Sign : PoolItem<Sign, SignID, &_Sign_pool> {
+struct Sign : SignPool::PoolItem<&_sign_pool> {
 	char *name;
 	ViewportSign sign;
 	int32        x;
@@ -27,8 +28,6 @@
 
 	/** 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)
--- 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 @@
 	/* 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 @@
 	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 @@
 
 	return NULL;
 }
+
+void InitializeStations()
+{
+	_station_pool.CleanPool();
+	_roadstop_pool.CleanPool();
+}
--- 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 <list>
 
-DECLARE_OLD_POOL(Station, Station, 6, 1000)
-DECLARE_OLD_POOL(RoadStop, RoadStop, 5, 2000)
+typedef Pool<Station, StationID, 32, 64000> StationPool;
+typedef Pool<RoadStop, RoadStopID, 32, 64000> RoadStopPool;
+extern StationPool _station_pool;
+extern RoadStopPool _roadstop_pool;
 
 static const byte INITIAL_STATION_RATING = 175;
 
@@ -48,7 +50,7 @@
 };
 
 /** A Stop for a Road Vehicle */
-struct RoadStop : PoolItem<RoadStop, RoadStopID, &_RoadStop_pool> {
+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  *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 @@
 };
 
 /** Station data structure */
-struct Station : PoolItem<Station, StationID, &_Station_pool> {
+struct Station : StationPool::PoolItem<&_station_pool> {
 public:
 	RoadStop *GetPrimaryRoadStop(RoadStopType type) const
 	{
@@ -173,7 +169,7 @@
 	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 @@
 	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;
 };
 
--- 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 @@
 	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()) {
--- 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"
--- a/src/strings.cpp
+++ b/src/strings.cpp
@@ -669,7 +669,7 @@
 				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 @@
 			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 @@
 				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 @@
 			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 @@
 				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 @@
 			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 {
--- 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 @@
 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<Town, TownID, 64, 64000> TownPool;
+extern TownPool _town_pool;
 
-struct Town : PoolItem<Town, TownID, &_Town_pool> {
+struct Town : TownPool::PoolItem<&_town_pool> {
 	TileIndex xy;
 
 	/* Current population of people and amount of houses. */
@@ -183,13 +184,11 @@
 	/**
 	 * 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 @@
 
 static inline uint GetNumTowns()
 {
-	extern uint _total_towns;
-
-	return _total_towns;
+	return (uint)Town::GetNumItems();
 }
 
 /**
@@ -324,7 +321,7 @@
 	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)
--- 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_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 @@
 	 * 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 @@
 
 	MarkWholeScreenDirty();
 
-	this->xy = INVALID_TILE;
-
-	UpdateNearestTownForRoadTiles(false);
+	UpdateNearestTownForRoadTiles(false, this);
 }
 
 /**
@@ -2689,13 +2680,14 @@
 }
 
 
-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 @@
 		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 @@
 					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 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)
--- a/src/train_cmd.cpp
+++ b/src/train_cmd.cpp
@@ -4282,7 +4282,7 @@
 	/* 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 @@
 	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 @@
 
 		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);
--- 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 @@
 
 
 /* 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 @@
 
 void InitializeVehicles()
 {
-	_Vehicle_pool.CleanPool();
-	_Vehicle_pool.AddBlockToPool();
+	_vehicle_pool.CleanPool();
 
 	_vehicles_to_autoreplace.Reset();
 	ResetVehiclePosHash();
@@ -571,12 +571,7 @@
 	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 @@
 	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;
--- 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 @@
 	TrackBitsByte state;
 };
 
-DECLARE_OLD_POOL(Vehicle, Vehicle, 9, 125)
+typedef Pool<Vehicle, VehicleID, 512, 64000> 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<Vehicle, VehicleID, &_Vehicle_pool>, 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 @@
 	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 @@
 	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)
 
--- a/src/vehicle_type.h
+++ b/src/vehicle_type.h
@@ -28,12 +28,6 @@
 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;
--- 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,
--- 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 @@
 	}
 }
 
-Waypoint::Waypoint(TileIndex tile)
-{
-	this->xy = tile;
-}
-
 Waypoint::~Waypoint()
 {
 	free(this->name);
@@ -93,11 +89,9 @@
 	RemoveOrderFromAllVehicles(OT_GOTO_WAYPOINT, this->index);
 
 	RedrawWaypointSign(this);
-	this->xy = INVALID_TILE;
 }
 
 void InitializeWaypoints()
 {
-	_Waypoint_pool.CleanPool();
-	_Waypoint_pool.AddBlockToPool();
+	_waypoint_pool.CleanPool();
 }
--- 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<Waypoint, WaypointID, 32, 64000> WaypointPool;
+extern WaypointPool _waypoint_pool;
 
-struct Waypoint : PoolItem<Waypoint, WaypointID, &_Waypoint_pool> {
+struct Waypoint : WaypointPool::PoolItem<&_waypoint_pool> {
 	TileIndex xy;      ///< Tile of waypoint
 
 	TownID town_index; ///< Town associated with the waypoint
@@ -34,10 +35,8 @@
 
 	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)
--- a/src/waypoint_cmd.cpp
+++ b/src/waypoint_cmd.cpp
@@ -74,7 +74,7 @@
 		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' */
--- a/src/waypoint_gui.cpp
+++ b/src/waypoint_gui.cpp
@@ -144,6 +144,5 @@
 
 void ShowWaypointWindow(const Waypoint *wp)
 {
-	if (!wp->IsValid()) return;  // little safety
 	AllocateWindowDescFront<WaypointWindow>(&_waypoint_view_desc, wp->index);
 }