Index: src/simutrans/obj/baum.cc
===================================================================
--- src/simutrans/obj/baum.cc	(revision 10637)
+++ src/simutrans/obj/baum.cc	(working copy)
@@ -28,6 +28,7 @@
 
 FLAGGED_PIXVAL baum_t::outline_color = 0;
 
+freelist_tpl<baum_t> baum_t::fl;
 
 baum_t::baum_t(loadsave_t *file) :
 	obj_t(),
@@ -323,15 +324,3 @@
 {
 	return (welt->get_current_month() - (uint32)geburt) % (1<<12);
 }
-
-
-void *baum_t::operator new(size_t /*s*/)
-{
-	return freelist_t::gimme_node(sizeof(baum_t));
-}
-
-
-void baum_t::operator delete(void *p)
-{
-	freelist_t::putback_node(sizeof(baum_t),p);
-}
Index: src/simutrans/obj/baum.h
===================================================================
--- src/simutrans/obj/baum.h	(revision 10637)
+++ src/simutrans/obj/baum.h	(working copy)
@@ -13,6 +13,7 @@
 #include "../tpl/stringhashtable_tpl.h"
 #include "../tpl/vector_tpl.h"
 #include "../tpl/weighted_vector_tpl.h"
+#include "../tpl/freelist_tpl.h"
 #include "../descriptor/tree_desc.h"
 #include "../simcolor.h"
 #include "../dataobj/environment.h"
@@ -48,6 +49,8 @@
 
 	// one bit free ;)
 
+	static freelist_tpl<baum_t> fl;
+
 public:
 	/// Only the load save constructor should be called outside.
 	/// Otherwise I suggest use the plant tree function (@see tree_builder_t)
@@ -59,6 +62,9 @@
 
 	baum_t(koord3d pos, const tree_desc_t *desc);
 
+	void* operator new(size_t) { return fl.gimme_node(); }
+	void operator delete(void* p) { return fl.putback_node(p); }
+
 public:
 	/// @copydoc obj_t::get_name
 	const char *get_name() const OVERRIDE { return "Baum"; }
@@ -115,10 +121,6 @@
 	/// @returns age of the tree in months, between 0 and 4095
 	uint16 get_age() const;
 
-public:
-	void *operator new(size_t s);
-	void operator delete(void *p);
-
 private:
 	/// calculate offsets for new trees
 	void calc_off(slope_t::type slope, sint8 x=-128, sint8 y=-128);
Index: src/simutrans/obj/leitung2.cc
===================================================================
--- src/simutrans/obj/leitung2.cc	(revision 10637)
+++ src/simutrans/obj/leitung2.cc	(working copy)
@@ -438,23 +438,9 @@
 
 /************************************ from here on pump (source) stuff ********************************************/
 
-slist_tpl<pumpe_t *> pumpe_t::pumpe_list;
+freelist_iter_tpl<pumpe_t> pumpe_t::pl;
 
 
-void pumpe_t::new_world()
-{
-	pumpe_list.clear();
-}
-
-
-void pumpe_t::step_all(uint32 delta_t)
-{
-	for(pumpe_t* const p : pumpe_list) {
-		p->step(delta_t);
-	}
-}
-
-
 pumpe_t::pumpe_t(loadsave_t *file ) : leitung_t( koord3d::invalid, NULL )
 {
 	fab = NULL;
@@ -482,20 +468,17 @@
 	if(  net != NULL  ) {
 		net->sub_supply(power_supply);
 	}
-	pumpe_list.remove( this );
 }
 
-void pumpe_t::step(uint32 delta_t)
+sync_result pumpe_t::sync_step(uint32 delta_t)
 {
 	if(  fab == NULL  ) {
-		return;
+		return SYNC_REMOVE;
 	}
 	else if(  delta_t == 0  ) {
-		return;
+		return SYNC_OK;
 	}
 
-	// usage logic could go here
-
 	// resolve image
 	uint16 winter_offset = 0;
 	if(  skinverwaltung_t::senke->get_count() > 3  &&  (get_pos().z >= welt->get_snowline()  ||  welt->get_climate( get_pos().get_2d() ) == arctic_climate)  ) {
@@ -509,6 +492,7 @@
 		set_flag(obj_t::dirty);
 		set_image(new_image);
 	}
+	return SYNC_OK;
 }
 
 void pumpe_t::set_net(powernet_t * p)
@@ -578,16 +562,11 @@
 	}
 
 #ifdef MULTI_THREAD
-	pthread_mutex_lock( &pumpe_list_mutex );
-	pumpe_list.insert( this );
-	pthread_mutex_unlock( &pumpe_list_mutex );
-
 	pthread_mutex_lock( &calc_image_mutex );
 	set_image(skinverwaltung_t::pumpe->get_image_id(0));
 	is_crossing = false;
 	pthread_mutex_unlock( &calc_image_mutex );
 #else
-	pumpe_list.insert( this );
 	set_image(skinverwaltung_t::pumpe->get_image_id(0));
 	is_crossing = false;
 #endif
@@ -609,13 +588,14 @@
 
 /************************************ Distriubtion Transformer Code ********************************************/
 
-slist_tpl<senke_t *> senke_t::senke_list;
+freelist_iter_tpl<senke_t> senke_t::sl;
 uint32 senke_t::payment_timer = 0;
+bool senke_t::payout = false;
 
 void senke_t::new_world()
 {
-	senke_list.clear();
 	payment_timer = 0;
+	payout = false;
 }
 
 void senke_t::static_rdwr(loadsave_t *file)
@@ -625,7 +605,7 @@
 	}
 }
 
-void senke_t::step_all(uint32 delta_t)
+void senke_t::sync_handler(uint32 delta_t)
 {
 	// payment period (could be tied to game setting)
 	const uint32 pay_period = PRODUCTION_DELTA_T * 10; // 10 seconds
@@ -632,16 +612,10 @@
 
 	// revenue payout timer
 	payment_timer += delta_t;
-	const bool payout = payment_timer >= pay_period;
+	payout = payment_timer >= pay_period;
 	payment_timer %= pay_period;
 
-	// step all distribution transformers
-	for(senke_t* const s : senke_list) {
-		s->step(delta_t);
-		if (payout) {
-			s->pay_revenue();
-		}
-	}
+	sl.sync_step(delta_t);
 }
 
 
@@ -655,8 +629,6 @@
 	is_transformer = true;
 
 	rdwr( file );
-
-	welt->sync.add(this);
 }
 
 
@@ -670,17 +642,13 @@
 	is_transformer = true;
 
 	player_t::book_construction_costs(player, welt->get_settings().cst_transformer, get_pos().get_2d(), powerline_wt);
-
-	welt->sync.add(this);
 }
 
-
 senke_t::~senke_t()
 {
 	// one last final income
 	pay_revenue();
 
-	welt->sync.remove( this );
 	if(fab!=NULL) {
 		fab->remove_transformer_connected(this);
 		fab = NULL;
@@ -688,22 +656,9 @@
 	if(  net != NULL  ) {
 		net->sub_demand(power_demand);
 	}
-	senke_list.remove( this );
 }
 
-void senke_t::step(uint32 delta_t)
-{
-	if(  fab == NULL  ) {
-		return;
-	}
-	else if(  delta_t == 0  ) {
-		return;
-	}
 
-	// energy metering logic
-	energy_acc += ((uint64)power_demand * (uint64)get_net()->get_normal_supply() * (uint64)delta_t) / ((uint64)PRODUCTION_DELTA_T << powernet_t::FRACTION_PRECISION);
-}
-
 void senke_t::pay_revenue()
 {
 	// megajoules (megawatt seconds) per cent
@@ -807,6 +762,14 @@
 			set_image( new_image );
 		}
 	}
+
+	// energy metering logic
+	energy_acc += ((uint64)power_demand * (uint64)get_net()->get_normal_supply() * (uint64)delta_t) / ((uint64)PRODUCTION_DELTA_T << powernet_t::FRACTION_PRECISION);
+
+	if (payout) {
+		pay_revenue();
+	}
+
 	return SYNC_OK;
 }
 
@@ -858,11 +821,6 @@
 	}
 
 #ifdef MULTI_THREAD
-	pthread_mutex_lock( &senke_list_mutex );
-#endif
-	senke_list.insert( this );
-#ifdef MULTI_THREAD
-	pthread_mutex_unlock( &senke_list_mutex );
 	pthread_mutex_lock( &calc_image_mutex );
 #endif
 	set_image(skinverwaltung_t::senke->get_image_id(0));
Index: src/simutrans/obj/leitung2.h
===================================================================
--- src/simutrans/obj/leitung2.h	(revision 10637)
+++ src/simutrans/obj/leitung2.h	(working copy)
@@ -13,6 +13,8 @@
 #include "simobj.h"
 #include "../tpl/slist_tpl.h"
 
+#include "../tpl/freelist_iter_tpl.h"
+
 // bitshift for converting internal power values to MW for display
 extern const uint32 POWER_TO_MW;
 
@@ -125,21 +127,15 @@
 
 
 
-class pumpe_t : public leitung_t
+class pumpe_t : public leitung_t, public sync_steppable
 {
-public:
-	static void new_world();
-	static void step_all(uint32 delta_t);
-
 private:
-	static slist_tpl<pumpe_t *> pumpe_list;
-
 	fabrik_t *fab;
 
 	// The power supplied through the transformer.
 	uint32 power_supply;
 
-	void step(uint32 delta_t);
+	static freelist_iter_tpl<pumpe_t> pl; // if not declared static, it would consume 4 bytes due to empty class nonzero rules
 
 public:
 	pumpe_t(loadsave_t *file);
@@ -146,6 +142,13 @@
 	pumpe_t(koord3d pos, player_t *player);
 	~pumpe_t();
 
+	void* operator new(size_t) { return pl.gimme_node(); }
+	void operator delete(void* p) { return pl.putback_node(p); }
+
+	static void sync_handler(uint32 delta_t) { pl.sync_step(delta_t); }
+
+	sync_result sync_step(uint32 delta_t) OVERRIDE;
+
 	void set_net(powernet_t* p) OVERRIDE;
 
 	/**
@@ -185,20 +188,7 @@
  */
 class senke_t : public leitung_t, public sync_steppable
 {
-public:
-	static void new_world();
-	static void step_all(uint32 delta_t);
-
-	/**
-	 * Read and write static state.
-	 * This is used to make payments occur at the same time after load as after saving.
-	 */
-	static void static_rdwr(loadsave_t *file);
-
 private:
-	// List of all distribution transformers.
-	static slist_tpl<senke_t *> senke_list;
-
 	// Timer for global power payment.
 	static uint32 payment_timer;
 
@@ -221,11 +211,29 @@
 	// Pay out revenue for the energy metered.
 	void pay_revenue();
 
+	static freelist_iter_tpl<senke_t> sl; // if not declared static, it would consume 4 bytes due to empty class nonzero rules
+
+	// true, needs payout
+	static bool payout;
+
 public:
+	static void new_world();
+
+	/**
+	 * Read and write static state.
+	 * This is used to make payments occur at the same time after load as after saving.
+	 */
+	static void static_rdwr(loadsave_t* file);
+
 	senke_t(loadsave_t *file);
 	senke_t(koord3d pos, player_t *player);
 	~senke_t();
 
+	void* operator new(size_t) { return sl.gimme_node(); }
+	void operator delete(void* p) { return sl.putback_node(p); }
+
+	static void sync_handler(uint32 delta_t);
+
 	void set_net(powernet_t* p) OVERRIDE;
 
 	typ get_typ() const OVERRIDE { return senke; }
Index: src/simutrans/obj/wolke.cc
===================================================================
--- src/simutrans/obj/wolke.cc	(revision 10637)
+++ src/simutrans/obj/wolke.cc	(working copy)
@@ -11,7 +11,6 @@
 #include "../utils/simrandom.h"
 #include "wolke.h"
 
-#include "../dataobj/freelist.h"
 #include "../dataobj/loadsave.h"
 
 #include "../descriptor/factory_desc.h"
@@ -18,9 +17,10 @@
 
 #include "../tpl/vector_tpl.h"
 
-
 vector_tpl<const skin_desc_t *>wolke_t::all_clouds(0);
 
+freelist_iter_tpl<wolke_t> wolke_t::fl;
+
 bool wolke_t::register_desc(const skin_desc_t* desc)
 {
 	// avoid duplicates with same name
@@ -34,19 +34,6 @@
 }
 
 
-void *wolke_t::operator new(size_t /*s*/)
-{
-	return freelist_t::gimme_node(sizeof(wolke_t));
-}
-
-
-void wolke_t::operator delete(void *p)
-{
-	freelist_t::putback_node(sizeof(wolke_t),p);
-}
-
-
-
 wolke_t::wolke_t(koord3d pos, sint8 b_x_off, sint8 b_y_off, sint16 b_h_off, uint16 lt, uint16 ul, const skin_desc_t* desc ) :
 	obj_no_info_t(pos)
 {
@@ -63,9 +50,6 @@
 wolke_t::~wolke_t()
 {
 	mark_image_dirty( get_image(), calc_yoff() );
-	if(  insta_zeit != lifetime  ) {
-		welt->sync_way_eyecandy.remove( this );
-	}
 }
 
 
Index: src/simutrans/obj/wolke.h
===================================================================
--- src/simutrans/obj/wolke.h	(revision 10637)
+++ src/simutrans/obj/wolke.h	(working copy)
@@ -14,6 +14,7 @@
 #include "../tpl/vector_tpl.h"
 #include "../display/simimg.h"
 
+#include "../tpl/freelist_iter_tpl.h"
 
 class karte_t;
 
@@ -37,12 +38,11 @@
 
 	sint16 calc_yoff() const; // calculate the smoke height using uplift and insta_zeit
 
+	static freelist_iter_tpl<wolke_t> fl; // if not declared static, it would consume 4 bytes due to empty class nonzero rules
+
 public:
 	static bool register_desc(const skin_desc_t *desc);
 
-	void * operator new(size_t s);
-	void operator delete(void *p);
-
 	wolke_t(loadsave_t *file);
 	wolke_t(koord3d pos, sint8 xoff, sint8 yoff, sint16 hoff, uint16 lifetime, uint16 uplift, const skin_desc_t *cloud );
 	~wolke_t();
@@ -49,6 +49,11 @@
 
 	sync_result sync_step(uint32 delta_t) OVERRIDE;
 
+	void* operator new(size_t) { return fl.gimme_node(); }
+	void operator delete(void* p) { return fl.putback_node(p); }
+
+	static void sync_handler(uint32 delta_t) { fl.sync_step(delta_t); }
+
 	const char* get_name() const OVERRIDE { return "Wolke"; }
 	typ get_typ() const OVERRIDE { return sync_wolke; }
 
Index: src/simutrans/simfab.cc
===================================================================
--- src/simutrans/simfab.cc	(revision 10637)
+++ src/simutrans/simfab.cc	(working copy)
@@ -1592,7 +1592,7 @@
 		const koord offset = ( desc->get_smokeoffset(rot)*OBJECT_OFFSET_STEPS)/16;
 		wolke_t *smoke =  new wolke_t(gr->get_pos(), offset.x, 0, offset.y, desc->get_smokelifetime(), desc->get_smokeuplift(), rada->get_images() );
 		gr->obj_add(smoke);
-		welt->sync_way_eyecandy.add( smoke );
+//		welt->sync_way_eyecandy.add( smoke );
 	}
 
 	// maybe sound?
Index: src/simutrans/tpl/freelist_iter_tpl.h
===================================================================
--- src/simutrans/tpl/freelist_iter_tpl.h	(nonexistent)
+++ src/simutrans/tpl/freelist_iter_tpl.h	(working copy)
@@ -0,0 +1,229 @@
+/*
+ * This file is part of the Simutrans project under the Artistic License.
+ * (see LICENSE.txt)
+ */
+
+#ifndef TPL_FREELIST_ITER_TPL_H
+#define TPL_FREELIST_ITER_TPL_H
+
+#include <typeinfo>
+
+#include "../simmem.h"
+#include <bitset>
+
+#ifdef MULTI_THREADx
+#include "../utils/simthread.h"
+#endif
+
+#include "../obj/sync_steppable.h"
+
+/**
+  * A template class for const sized memory pool
+  * Must be a static member! Does not use exceptions
+  */
+template<class T> class freelist_iter_tpl
+{
+private:
+	struct nodelist_node_t
+	{
+#ifdef DEBUG_FREELIST
+		unsigned magic : 15;
+		unsigned free : 1;
+#endif
+		nodelist_node_t* next;
+	};
+
+
+#ifdef MULTI_THREADx
+	pthread_mutex_t freelist_mutex = PTHREAD_MUTEX_INITIALIZER;;
+#endif
+
+	// next free node (or NULL)
+	nodelist_node_t* freelist;
+
+	// number of currently allocated node
+	size_t nodecount;
+
+	// we aim for near 32 kB chunks, hoping that the system will allocate them on each page
+	// and they fit the L1 cache
+	const size_t new_chuck_size = (32250*8) / (sizeof(T)*8+1);
+
+	struct chunklist_node_t {
+		chunklist_node_t *chunk_next;
+		// marking empty and allocated tiles for fast interation
+		std::bitset<(32250 * 8) / (sizeof(T) * 8 + 1)> allocated_mask;
+	};
+
+	// list of all allocated memory
+	chunklist_node_t* chunk_list;
+
+	void change_obj(char *p,bool b)
+	{
+		char *c_list = (char *)chunk_list;
+		const size_t chunk_mem_size = sizeof(chunklist_node_t) + sizeof(T) * new_chuck_size;
+		while (c_list && (p<c_list || c_list+chunk_mem_size <p)) {
+			// not in this chunk => continue
+			c_list = (char *)((chunklist_node_t *)c_list)->chunk_next;
+		}
+		// we have found us (or we crash on error)
+		size_t index = ((p - c_list) - sizeof(chunklist_node_t)) / sizeof(T);
+		assert(index < new_chuck_size);
+		((chunklist_node_t*)c_list)->allocated_mask.set(index, b);
+	}
+
+	// clears all list memories
+	void free_all_nodes()
+	{
+		while (chunk_list) {
+			chunklist_node_t* p = chunk_list;
+			chunk_list = chunk_list->chunk_next;
+
+			// now release memory
+#ifdef USE_VALGRIND_MEMCHECK
+			VALGRIND_DESTROY_MEMPOOL(p);
+#endif
+			free(p);
+		}
+		freelist = 0;
+		chunk_list = 0;
+		nodecount = 0;
+	}
+
+public:
+	freelist_iter_tpl() : freelist(0), nodecount(0), chunk_list(0) {}
+
+	void sync_step(uint32 delta_t)
+	{
+		chunklist_node_t* c_list = chunk_list;
+		while (c_list) {
+			T  *p = (T *)(((char *)c_list)+sizeof(chunklist_node_t));
+			for (unsigned i = 0; i < new_chuck_size; i++) {
+				if (c_list->allocated_mask.test(i)) {
+					// is active object
+					if (sync_result result = p[i].sync_step(delta_t)) {
+						// remove from sync
+						c_list->allocated_mask.set(i, false);
+						// and maybe delete
+						if (result == SYNC_DELETE) {
+							delete (p+i);
+							if (nodecount == 0) {
+								return; // since even the main chunk list became invalid
+							}
+						}
+					}
+				}
+			}
+			c_list = c_list->chunk_next;
+		}
+	}
+
+	// switch on off sync handling
+	void add_sync(T* p) { change_obj((char*)p,true); };
+	void remove_sync(T* p) { change_obj((char*)p,false); };
+
+	size_t get_nodecout() const { return nodecount; }
+
+	void *gimme_node()
+	{
+#ifdef MULTI_THREADx
+		pthread_mutex_lock(&freelist_mutex);
+#endif
+		nodelist_node_t *tmp;
+		if (freelist == NULL) {
+			char* p = (char*)xmalloc(new_chuck_size *sizeof(T)+sizeof(chunklist_node_t));
+			memset(p, 0, sizeof(chunklist_node_t)); // clear allocation bits and next pointer
+
+#ifdef USE_VALGRIND_MEMCHECK
+			// tell valgrind that we still cannot access the pool p
+			VALGRIND_MAKE_MEM_NOACCESS(p, new_chuck_size * sizeof(T) + sizeof(chunklist_node_t));
+#endif
+			// put the memory into the chunklist for free it
+			chunklist_node_t* chunk = (chunklist_node_t *)p;
+
+#ifdef USE_VALGRIND_MEMCHECK
+			// tell valgrind that we reserved space for one nodelist_node_t
+			VALGRIND_CREATE_MEMPOOL(chunk, 0, false);
+			VALGRIND_MEMPOOL_ALLOC(chunk, chunk, sizeof(*chunk));
+			VALGRIND_MAKE_MEM_UNDEFINED(chunk, sizeof(*chunk));
+#endif
+			chunk->chunk_next = chunk_list;
+			chunk_list = chunk;
+			p += sizeof(chunklist_node_t);
+			// then enter nodes into nodelist
+			for (int i = 0; i < new_chuck_size; i++) {
+				nodelist_node_t* tmp = (nodelist_node_t*)(p + i * sizeof(T));
+#ifdef USE_VALGRIND_MEMCHECK
+				// tell valgrind that we reserved space for one nodelist_node_t
+				VALGRIND_CREATE_MEMPOOL(tmp, 0, false);
+				VALGRIND_MEMPOOL_ALLOC(tmp, tmp, sizeof(*tmp));
+				VALGRIND_MAKE_MEM_UNDEFINED(tmp, sizeof(*tmp));
+#endif
+				tmp->next = freelist;
+				freelist = tmp;
+			}
+		}
+
+		// return first node of list
+		tmp = freelist;
+		freelist = tmp->next;
+
+		change_obj((char *)(&(tmp->next)),true);
+
+#ifdef MULTI_THREADx
+		pthread_mutex_unlock(&freelist_mutex);
+#endif
+
+#ifdef USE_VALGRIND_MEMCHECK
+		// tell valgrind that we now have access to a chunk of size bytes
+		VALGRIND_MEMPOOL_CHANGE(tmp, tmp, tmp, sizeof(T));
+		VALGRIND_MAKE_MEM_UNDEFINED(tmp, sizeof(T));
+#endif
+
+#ifdef DEBUG_FREELIST
+		tmp->magic = 0x5555;
+		tmp->free = 0;
+#endif
+		nodecount++;
+
+		return (void *)(&(tmp->next));
+	}
+
+	void putback_node(void* p)
+	{
+#ifdef USE_VALGRIND_MEMCHECK
+		// tell valgrind that we keep access to a nodelist_node_t within the memory chunk
+		VALGRIND_MEMPOOL_CHANGE(p, p, p, sizeof(nodelist_node_t));
+		VALGRIND_MAKE_MEM_NOACCESS(p, size);
+		VALGRIND_MAKE_MEM_UNDEFINED(p, sizeof(nodelist_node_t));
+#endif
+
+#ifdef MULTI_THREADx
+		pthread_mutex_unlock(&freelist_mutex);
+#endif
+
+		// putback to first node
+		nodelist_node_t* tmp = (nodelist_node_t*)p;
+#ifdef DEBUG_FREELIST
+		tmp = (nodelist_node_t*)((char*)p - min_size);
+		assert(tmp->magic == 0x5555 && tmp->free == 0 && tmp->size == size / 4);
+		tmp->free = 1;
+#endif
+
+		tmp->next = freelist;
+		freelist = tmp;
+
+		change_obj((char *)p,0);
+		nodecount--;
+
+		if (nodecount == 0) {
+			free_all_nodes();
+		}
+
+#ifdef MULTI_THREADx
+		pthread_mutex_unlock(&freelist_mutex);
+#endif
+	}
+
+};
+
+#endif

Property changes on: src/simutrans/tpl/freelist_iter_tpl.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Author Date Id Rev URL
\ No newline at end of property
Index: src/simutrans/tpl/freelist_tpl.h
===================================================================
--- src/simutrans/tpl/freelist_tpl.h	(nonexistent)
+++ src/simutrans/tpl/freelist_tpl.h	(working copy)
@@ -0,0 +1,169 @@
+/*
+ * This file is part of the Simutrans project under the Artistic License.
+ * (see LICENSE.txt)
+ */
+
+#ifndef TPL_FREELIST_TPL_H
+#define TPL_FREELIST_TPL_H
+
+struct nodelist_node_t
+{
+#ifdef DEBUG_FREELIST
+	unsigned magic : 15;
+	unsigned free : 1;
+#endif
+	nodelist_node_t* next;
+};
+
+#include <typeinfo>
+
+#include "../simmem.h"
+
+#ifdef MULTI_THREADx
+#include "../utils/simthread.h"
+#endif
+
+
+/**
+  * A template class for const sized memory pool
+  * Must be a static member! Does not use exceptions
+  */
+template<class T> class freelist_tpl
+{
+private:
+	// next free node (or NULL)
+	nodelist_node_t* freelist;
+
+	// number of currently allocated node
+	size_t nodecount;
+
+	// list of all allocated memory
+	nodelist_node_t* chunk_list;
+
+	const size_t new_chuck_size = (32768 - sizeof(void*)) / sizeof(T);
+
+#ifdef MULTI_THREADx
+	pthread_mutex_t freelist_mutex = PTHREAD_MUTEX_INITIALIZER;;
+#endif
+
+public:
+	freelist_tpl() : freelist(0), nodecount(0), chunk_list(0) {}
+
+	freelist_tpl(size_t ncs) : freelist(0), nodecount(0), chunk_list(0), new_chuck_size(ncs) {}
+
+	void *gimme_node()
+	{
+#ifdef MULTI_THREADx
+		pthread_mutex_lock(&freelist_mutex);
+#endif
+		nodelist_node_t *tmp;
+		if (freelist == NULL) {
+			int chunksize = 0x1000;
+			char* p = (char*)xmalloc(chunksize *sizeof(T) + sizeof(nodelist_node_t));
+
+#ifdef USE_VALGRIND_MEMCHECK
+			// tell valgrind that we still cannot access the pool p
+			VALGRIND_MAKE_MEM_NOACCESS(p, chunksize *sizeof(T) + sizeof(nodelist_node_t));
+#endif
+			// put the memory into the chunklist for free it
+			nodelist_node_t* chunk = (nodelist_node_t *)p;
+
+#ifdef USE_VALGRIND_MEMCHECK
+			// tell valgrind that we reserved space for one nodelist_node_t
+			VALGRIND_CREATE_MEMPOOL(chunk, 0, false);
+			VALGRIND_MEMPOOL_ALLOC(chunk, chunk, sizeof(*chunk));
+			VALGRIND_MAKE_MEM_UNDEFINED(chunk, sizeof(*chunk));
+#endif
+			chunk->next = chunk_list;
+			chunk_list = chunk;
+			p += sizeof(nodelist_node_t);
+			// then enter nodes into nodelist
+			for (int i = 0; i < chunksize; i++) {
+				nodelist_node_t* tmp = (nodelist_node_t*)(p + i * sizeof(T));
+#ifdef USE_VALGRIND_MEMCHECK
+				// tell valgrind that we reserved space for one nodelist_node_t
+				VALGRIND_CREATE_MEMPOOL(tmp, 0, false);
+				VALGRIND_MEMPOOL_ALLOC(tmp, tmp, sizeof(*tmp));
+				VALGRIND_MAKE_MEM_UNDEFINED(tmp, sizeof(*tmp));
+#endif
+				tmp->next = freelist;
+				freelist = tmp;
+			}
+		}
+
+		// return first node of list
+		tmp = freelist;
+		freelist = tmp->next;
+
+#ifdef MULTI_THREADx
+		pthread_mutex_unlock(&freelist_mutex);
+#endif
+
+#ifdef USE_VALGRIND_MEMCHECK
+		// tell valgrind that we now have access to a chunk of size bytes
+		VALGRIND_MEMPOOL_CHANGE(tmp, tmp, tmp, sizeof(T));
+		VALGRIND_MAKE_MEM_UNDEFINED(tmp, sizeof(T));
+#endif
+
+#ifdef DEBUG_FREELIST
+		tmp->magic = 0x5555;
+		tmp->free = 0;
+#endif
+		nodecount++;
+
+		return (void *)(&(tmp->next));
+	}
+
+	// clears all list memories
+	void free_all_nodes()
+	{
+		while (chunk_list) {
+			nodelist_node_t* p = chunk_list;
+			chunk_list = chunk_list->next;
+
+			// now release memory
+#ifdef USE_VALGRIND_MEMCHECK
+			VALGRIND_DESTROY_MEMPOOL(p);
+#endif
+			free(p);
+		}
+		freelist = 0;
+		nodecount = 0;
+	}
+
+	void putback_node(void* p)
+	{
+#ifdef USE_VALGRIND_MEMCHECK
+		// tell valgrind that we keep access to a nodelist_node_t within the memory chunk
+		VALGRIND_MEMPOOL_CHANGE(p, p, p, sizeof(nodelist_node_t));
+		VALGRIND_MAKE_MEM_NOACCESS(p, size);
+		VALGRIND_MAKE_MEM_UNDEFINED(p, sizeof(nodelist_node_t));
+#endif
+
+#ifdef MULTI_THREADx
+		pthread_mutex_unlock(&freelist_mutex);
+#endif
+
+		// putback to first node
+		nodelist_node_t* tmp = (nodelist_node_t*)p;
+#ifdef DEBUG_FREELIST
+		tmp = (nodelist_node_t*)((char*)p - min_size);
+		assert(tmp->magic == 0x5555 && tmp->free == 0 && tmp->size == size / 4);
+		tmp->free = 1;
+#endif
+		tmp->next = freelist;
+		freelist = tmp;
+
+		nodecount--;
+
+		if (nodecount == 0) {
+			free_all_nodes();
+		}
+#ifdef MULTI_THREADx
+		pthread_mutex_unlock(&freelist_mutex);
+#endif
+	}
+
+};
+
+#endif

Property changes on: src/simutrans/tpl/freelist_tpl.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: src/simutrans/vehicle/movingobj.cc
===================================================================
--- src/simutrans/vehicle/movingobj.cc	(revision 10637)
+++ src/simutrans/vehicle/movingobj.cc	(working copy)
@@ -33,6 +33,8 @@
 
 /******************************** static stuff: desc management ****************************************************************/
 
+freelist_iter_tpl<movingobj_t> movingobj_t::fl;
+
 vector_tpl<const groundobj_desc_t *> movingobj_t::movingobj_typen(0);
 
 stringhashtable_tpl<groundobj_desc_t *> movingobj_t::desc_table;
@@ -152,9 +154,6 @@
 movingobj_t::movingobj_t(loadsave_t *file) : vehicle_base_t()
 {
 	rdwr(file);
-	if(get_desc()) {
-		welt->sync.add( this );
-	}
 }
 
 
@@ -165,16 +164,9 @@
 	timetochange = 0; // will do random direct change anyway during next step
 	direction = calc_set_direction( koord3d(0,0,0), koord3d(koord::west,0) );
 	calc_image();
-	welt->sync.add( this );
 }
 
 
-movingobj_t::~movingobj_t()
-{
-	welt->sync.remove( this );
-}
-
-
 bool movingobj_t::check_season(const bool)
 {
 	const image_id old_image = get_image();
@@ -417,17 +409,3 @@
 	// next position
 	pos_next = pos_next_next;
 }
-
-
-
-void *movingobj_t::operator new(size_t /*s*/)
-{
-	return freelist_t::gimme_node(sizeof(movingobj_t));
-}
-
-
-
-void movingobj_t::operator delete(void *p)
-{
-	freelist_t::putback_node(sizeof(movingobj_t),p);
-}
Index: src/simutrans/vehicle/movingobj.h
===================================================================
--- src/simutrans/vehicle/movingobj.h	(revision 10637)
+++ src/simutrans/vehicle/movingobj.h	(working copy)
@@ -9,6 +9,7 @@
 
 #include "../tpl/stringhashtable_tpl.h"
 #include "../tpl/vector_tpl.h"
+#include "../tpl/freelist_iter_tpl.h"
 #include "../descriptor/groundobj_desc.h"
 #include "../simcolor.h"
 #include "../obj/sync_steppable.h"
@@ -39,6 +40,8 @@
 	/// static vector for fast lookup of desc
 	static vector_tpl<const groundobj_desc_t *> movingobj_typen;
 
+	static freelist_iter_tpl<movingobj_t> fl; // if not declared static, it would consume 4 bytes due to empty class nonzero rules
+
 protected:
 	void rdwr(loadsave_t *file) OVERRIDE;
 
@@ -52,10 +55,14 @@
 
 	movingobj_t(loadsave_t *file);
 	movingobj_t(koord3d pos, const groundobj_desc_t *);
-	~movingobj_t();
 
 	sync_result sync_step(uint32 delta_t) OVERRIDE;
 
+	static void sync_handler(uint32 delta_t) { fl.sync_step(delta_t); }
+
+	void* operator new(size_t) { return fl.gimme_node(); }
+	void operator delete(void* p) { return fl.putback_node(p); }
+
 	// always free
 	virtual bool check_next_tile(const grund_t *) const;
 	grund_t* hop_check() OVERRIDE;
@@ -81,8 +88,6 @@
 
 	bool is_flying() const OVERRIDE { return get_desc()->get_waytype()==air_wt; }
 
-	void * operator new(size_t s);
-	void operator delete(void *p);
 };
 
 #endif
Index: src/simutrans/vehicle/pedestrian.cc
===================================================================
--- src/simutrans/vehicle/pedestrian.cc	(revision 10637)
+++ src/simutrans/vehicle/pedestrian.cc	(working copy)
@@ -21,6 +21,8 @@
 #include <cstdio>
 
 
+freelist_iter_tpl<pedestrian_t> pedestrian_t::fl;
+
 static uint32 const strecke[] = { 6000, 11000, 15000, 20000, 25000, 30000, 35000, 40000 };
 
 static weighted_vector_tpl<const pedestrian_desc_t*> list_timeline;
@@ -66,7 +68,6 @@
 	steps_offset = 0;
 	rdwr(file);
 	if(desc) {
-		welt->sync.add(this);
 		ped_offset = desc->get_offset();
 	}
 	calc_disp_lane();
@@ -121,14 +122,6 @@
 }
 
 
-pedestrian_t::~pedestrian_t()
-{
-	if(  time_to_life>0  ) {
-		welt->sync.remove( this );
-	}
-}
-
-
 void pedestrian_t::calc_image()
 {
 	set_image(desc->get_image_id(ribi_t::get_dir(get_direction())));
@@ -211,14 +204,12 @@
 			// we create maximal 4 pedestrians here for performance reasons
 			for (int i = 0; i < 4 && count > 0; i++) {
 				pedestrian_t* fg = new pedestrian_t(bd);
-				bool ok = bd->obj_add(fg) != 0; // 256 limit reached
-				if (ok) {
+				if (bd->obj_add(fg) != 0) {
 					fg->calc_height(bd);
 					if (i > 0) {
 						// walk a little
 						fg->sync_step( (i & 3) * 64 * 24);
 					}
-					welt->sync.add(fg);
 					count--;
 				}
 				else {
@@ -226,8 +217,7 @@
 					fg->set_flag(obj_t::not_on_map);
 					// do not try to delete it from sync-list
 					fg->time_to_life = 0;
-					delete fg;
-					return; // it is pointless to try again
+					return; // it is pointless to try for more here
 				}
 			}
 		}
@@ -382,15 +372,3 @@
 		buf.printf(translator::translate("Constructed by %s"), maker);
 	}
 }
-
-
-void *pedestrian_t::operator new(size_t /*s*/)
-{
-	return freelist_t::gimme_node(sizeof(pedestrian_t));
-}
-
-
-void pedestrian_t::operator delete(void *p)
-{
-	freelist_t::putback_node(sizeof(pedestrian_t),p);
-}
Index: src/simutrans/vehicle/pedestrian.h
===================================================================
--- src/simutrans/vehicle/pedestrian.h	(revision 10637)
+++ src/simutrans/vehicle/pedestrian.h	(working copy)
@@ -8,6 +8,7 @@
 
 
 #include "simroadtraffic.h"
+#include "../tpl/freelist_iter_tpl.h"
 
 
 class pedestrian_desc_t;
@@ -32,6 +33,8 @@
 
 	bool list_empty();
 
+	static freelist_iter_tpl<pedestrian_t> fl; // if not declared static, it would consume 4 bytes due to empty class nonzero rules
+
 protected:
 	void rdwr(loadsave_t *file) OVERRIDE;
 
@@ -46,7 +49,7 @@
 public:
 	pedestrian_t(loadsave_t *file);
 
-	virtual ~pedestrian_t();
+	static void sync_handler(uint32 delta_t) { fl.sync_step(delta_t); }
 
 	const pedestrian_desc_t *get_desc() const { return desc; }
 
@@ -72,8 +75,8 @@
 	grund_t* hop_check() OVERRIDE;
 	void hop(grund_t* gr) OVERRIDE;
 
-	void * operator new(size_t s);
-	void operator delete(void *p);
+	void* operator new(size_t) { return fl.gimme_node(); }
+	void operator delete(void* p) { return fl.putback_node(p); }
 
 	// class register functions
 	static bool register_desc(const pedestrian_desc_t *desc);
Index: src/simutrans/vehicle/simroadtraffic.cc
===================================================================
--- src/simutrans/vehicle/simroadtraffic.cc	(revision 10637)
+++ src/simutrans/vehicle/simroadtraffic.cc	(working copy)
@@ -231,6 +231,7 @@
 /**********************************************************************************************************************/
 /* statsauto_t (city cars) from here on */
 
+freelist_iter_tpl<private_car_t> private_car_t::fl;
 
 static weighted_vector_tpl<const citycar_desc_t*> liste_timeline;
 stringhashtable_tpl<const citycar_desc_t *> private_car_t::table;
@@ -312,11 +313,6 @@
 	if(gr  &&  gr->ist_uebergang()) {
 		gr->find<crossing_t>(2)->release_crossing(this);
 	}
-
-	// just to be sure we are removed from this list!
-	if(time_to_life>0) {
-		welt->sync.remove(this);
-	}
 	welt->buche( -1, karte_t::WORLD_CITYCARS );
 }
 
@@ -327,9 +323,6 @@
 	rdwr(file);
 	ms_traffic_jam = 0;
 	calc_disp_lane();
-	if(desc) {
-		welt->sync.add(this);
-	}
 	welt->buche( +1, karte_t::WORLD_CITYCARS );
 }
 
Index: src/simutrans/vehicle/simroadtraffic.h
===================================================================
--- src/simutrans/vehicle/simroadtraffic.h	(revision 10637)
+++ src/simutrans/vehicle/simroadtraffic.h	(working copy)
@@ -12,6 +12,7 @@
 
 #include "../tpl/stringhashtable_tpl.h"
 #include "../obj/sync_steppable.h"
+#include "../tpl/freelist_iter_tpl.h"
 
 class citycar_desc_t;
 class karte_t;
@@ -93,6 +94,9 @@
 	void calc_disp_lane();
 
 	bool can_enter_tile(grund_t *gr);
+
+	static freelist_iter_tpl<private_car_t> fl; // if not declared static, it would consume 4 bytes due to empty class nonzero rules
+
 protected:
 	void rdwr(loadsave_t *file) OVERRIDE;
 
@@ -110,12 +114,17 @@
 
 	virtual ~private_car_t();
 
+	sync_result sync_step(uint32 delta_t) OVERRIDE;
+
+	void* operator new(size_t) { return fl.gimme_node(); }
+	void operator delete(void* p) { return fl.putback_node(p); }
+
+	static void sync_handler(uint32 delta_t) { fl.sync_step(delta_t); }
+
 	void rotate90() OVERRIDE;
 
-	const citycar_desc_t *get_desc() const { return desc; }
+	const citycar_desc_t* get_desc() const { return desc; }
 
-	sync_result sync_step(uint32 delta_t) OVERRIDE;
-
 	void hop(grund_t *gr) OVERRIDE;
 
 	void enter_tile(grund_t* gr) OVERRIDE;
Index: src/simutrans/vehicle/vehicle.cc
===================================================================
--- src/simutrans/vehicle/vehicle.cc	(revision 10637)
+++ src/simutrans/vehicle/vehicle.cc	(working copy)
@@ -660,7 +660,7 @@
 					delete abgas;
 				}
 				else {
-					welt->sync_way_eyecandy.add( abgas );
+//					welt->sync_way_eyecandy.add( abgas );
 				}
 			}
 		}
Index: src/simutrans/world/simworld.cc
===================================================================
--- src/simutrans/world/simworld.cc	(revision 10637)
+++ src/simutrans/world/simworld.cc	(working copy)
@@ -60,6 +60,7 @@
 #include "../obj/groundobj.h"
 #include "../obj/gebaeude.h"
 #include "../obj/leitung2.h"
+#include "../obj/wolke.h"
 
 #include "../gui/password_frame.h"
 #include "../gui/messagebox.h"
@@ -440,7 +441,6 @@
 	// removes all moving stuff from the sync_step
 	sync.clear();
 	sync_eyecandy.clear();
-	sync_way_eyecandy.clear();
 	old_progress += cached_size.x*cached_size.y;
 	ls.set_progress( old_progress );
 	DBG_MESSAGE("karte_t::destroy()", "sync list cleared");
@@ -2656,14 +2656,15 @@
 		* => they are now in a hastable!
 		*/
 	sync_eyecandy.sync_step( delta_t );
+	wolke_t::sync_handler(delta_t);
 
-	/* pedestrians do not require exact sync and are added/removed frequently
-		* => they are now in a hastable!
-		*/
-	sync_way_eyecandy.sync_step( delta_t );
-
 	clear_random_mode( INTERACTIVE_RANDOM );
 
+	pedestrian_t::sync_handler(delta_t);
+	movingobj_t::sync_handler(delta_t);
+	private_car_t::sync_handler(delta_t);
+	senke_t::sync_handler(delta_t);
+
 	sync.sync_step( delta_t );
 
 	ticker::update();
@@ -3263,8 +3264,8 @@
 	// step powerlines - required order: powernet, pumpe then senke
 	DBG_DEBUG4("karte_t::step", "step poweline stuff");
 	powernet_t::step_all(delta_t);
-	pumpe_t::step_all(delta_t);
-	senke_t::step_all(delta_t);
+	pumpe_t::sync_handler(delta_t);
+//	senke_t::step_all(delta_t); // not needed, handeld by sunc_step already
 
 	DBG_DEBUG4("karte_t::step", "step players");
 	// then step all players
@@ -4260,7 +4261,6 @@
 	if (file->is_loading()) {
 		// zum laden vorbereiten -> tabelle loeschen
 		powernet_t::new_world();
-		pumpe_t::new_world();
 		senke_t::new_world();
 		script_api::new_world();
 
Index: src/simutrans/world/simworld.h
===================================================================
--- src/simutrans/world/simworld.h	(revision 10637)
+++ src/simutrans/world/simworld.h	(working copy)
@@ -1034,7 +1034,6 @@
 
 	sync_list_t sync;              ///< vehicles, transformers, traffic lights
 	sync_list_t sync_eyecandy;     ///< animated buildings
-	sync_list_t sync_way_eyecandy; ///< smoke
 
 	/**
 	 * Synchronous stepping of objects like vehicles.
