Index: src/simutrans/obj/baum.cc
===================================================================
--- src/simutrans/obj/baum.cc	(revision 10635)
+++ 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 10635)
+++ 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/wolke.cc
===================================================================
--- src/simutrans/obj/wolke.cc	(revision 10635)
+++ 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 10635)
+++ 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,16 @@
 
 	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);
+	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); }
+
 	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();
Index: src/simutrans/simfab.cc
===================================================================
--- src/simutrans/simfab.cc	(revision 10635)
+++ 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,227 @@
+/*
+ * 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
+	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); };
+
+
+	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
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/pedestrian.cc
===================================================================
--- src/simutrans/vehicle/pedestrian.cc	(revision 10635)
+++ src/simutrans/vehicle/pedestrian.cc	(working copy)
@@ -21,6 +21,8 @@
 #include <cstdio>
 
 
+freelist_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;
@@ -382,15 +384,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 10635)
+++ src/simutrans/vehicle/pedestrian.h	(working copy)
@@ -8,6 +8,7 @@
 
 
 #include "simroadtraffic.h"
+#include "../tpl/freelist_tpl.h"
 
 
 class pedestrian_desc_t;
@@ -32,6 +33,8 @@
 
 	bool list_empty();
 
+	static freelist_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;
 
@@ -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/vehicle.cc
===================================================================
--- src/simutrans/vehicle/vehicle.cc	(revision 10635)
+++ 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 10635)
+++ 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"
@@ -2656,6 +2657,7 @@
 		* => 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!
