import from yans
authorMathieu Lacage <mathieu.lacage@sophia.inria.fr>
Tue, 29 Aug 2006 17:42:13 +0200
changeset 9 2c31ae7c94db
parent 8 cb4ae01ba180
child 10 e409dc8cb135
import from yans
src/common/buffer.cc
src/common/buffer.h
src/common/callback-logger.h
src/common/chunk-constant-data.cc
src/common/chunk-constant-data.h
src/common/chunk-llc-snap.cc
src/common/chunk-llc-snap.h
src/common/chunk-utils.cc
src/common/chunk-utils.h
src/common/chunk.cc
src/common/chunk.h
src/common/count-ptr-holder.tcc
src/common/data-writer.cc
src/common/data-writer.h
src/common/f-traced-variable.tcc
src/common/ipv4-address.cc
src/common/ipv4-address.h
src/common/ipv4-network-interface.cc
src/common/ipv4-network-interface.h
src/common/llc-snap-encapsulation.cc
src/common/llc-snap-encapsulation.h
src/common/mac-address-factory.cc
src/common/mac-address-factory.h
src/common/mac-address.cc
src/common/mac-address.h
src/common/mac-network-interface.cc
src/common/mac-network-interface.h
src/common/packet-logger.cc
src/common/packet-logger.h
src/common/packet.cc
src/common/packet.h
src/common/pcap-writer.cc
src/common/pcap-writer.h
src/common/population-analysis.cc
src/common/population-analysis.h
src/common/position.cc
src/common/position.h
src/common/random-uniform-mrg32k3a.cc
src/common/random-uniform.h
src/common/ref-ptr.h
src/common/rng-mrg32k3a.cc
src/common/rng-mrg32k3a.h
src/common/seed-generator-mrg32k3a.cc
src/common/seed-generator.h
src/common/sgi-hashmap.h
src/common/si-traced-variable.tcc
src/common/static-position.cc
src/common/static-position.h
src/common/static-speed-position.cc
src/common/static-speed-position.h
src/common/tags.cc
src/common/tags.h
src/common/timeout.cc
src/common/timeout.h
src/common/trace-container.cc
src/common/trace-container.h
src/common/trace-stream-test.cc
src/common/trace-stream.h
src/common/traced-variable-test.cc
src/common/ui-traced-variable.tcc
src/common/utils.cc
src/common/utils.h
src/core/callback-test.cc
src/core/callback.h
src/core/exec-commands.h
src/core/reference-list-test.cc
src/core/reference-list.h
src/core/system-file.h
src/core/system-mutex.h
src/core/system-semaphore.h
src/core/system-thread.h
src/core/test.cc
src/core/test.h
src/core/unix-exec-commands.cc
src/core/unix-system-file.cc
src/core/unix-system-mutex.cc
src/core/unix-system-semaphore.cc
src/core/unix-system-thread.cc
src/core/unix-wall-clock-ms.cc
src/core/wall-clock-ms.h
src/core/win32-system-file.cc
src/core/win32-system-mutex.cc
src/core/win32-system-semaphore.cc
src/core/win32-system-thread.cc
src/core/win32-wall-clock-ms.cc
src/simulator/event-impl.cc
src/simulator/event-impl.h
src/simulator/event-tcc-test.cc
src/simulator/event-tcc.cc
src/simulator/event.h
src/simulator/event.tcc
src/simulator/scheduler-heap.cc
src/simulator/scheduler-heap.h
src/simulator/scheduler-list.cc
src/simulator/scheduler-list.h
src/simulator/scheduler-map.cc
src/simulator/scheduler-map.h
src/simulator/scheduler.cc
src/simulator/scheduler.h
src/simulator/simulator.cc
src/simulator/simulator.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/buffer.cc	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,595 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2005,2006 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#include "buffer.h"
+#include <cassert>
+
+#include <iostream>
+//#define TRACE(x) std::cout << x << std::endl;
+#define TRACE(x)
+
+namespace yans {
+
+Buffer::BufferDataList  Buffer::m_free_list;
+uint32_t Buffer::m_max_total_add_start = 0;
+uint32_t Buffer::m_max_total_add_end = 0;
+
+struct Buffer::BufferData *
+Buffer::allocate (uint32_t req_size, uint32_t req_start)
+{
+	if (req_size == 0) {
+		req_size = 1;
+	}
+	assert (req_size >= 1);
+	uint32_t size = req_size - 1 + sizeof (struct Buffer::BufferData);
+	uint8_t *b = new uint8_t [size];
+	struct BufferData *data = reinterpret_cast<struct Buffer::BufferData*>(b);
+	data->m_size = req_size;
+	data->m_initial_start = req_start;
+	data->m_dirty_start = req_start;
+	data->m_dirty_size = 0;
+	data->m_count = 1;
+	return data;
+}
+
+void
+Buffer::deallocate (struct Buffer::BufferData *data)
+{
+	uint8_t *buf = reinterpret_cast<uint8_t *> (data);
+	delete [] buf;
+}
+#ifdef USE_FREE_LIST
+void
+Buffer::recycle (struct Buffer::BufferData *data)
+{
+	assert (data->m_count == 0);
+	/* get rid of it if it is too small for later reuse. */
+	if (data->m_size < (Buffer::m_max_total_add_start + Buffer::m_max_total_add_end)) {
+		Buffer::deallocate (data);
+		return; 
+	}
+	/* feed into free list */
+	if (Buffer::m_free_list.size () > 1000) {
+		Buffer::deallocate (data);
+	} else {
+		Buffer::m_free_list.push_back (data);
+	}
+}
+
+Buffer::BufferData *
+Buffer::create (void)
+{
+	/* try to find a buffer correctly sized. */
+	while (!Buffer::m_free_list.empty ()) {
+		struct Buffer::BufferData *data = Buffer::m_free_list.back ();
+		Buffer::m_free_list.pop_back ();
+		if (data->m_size >= (m_max_total_add_start + m_max_total_add_end)) {
+			data->m_initial_start = m_max_total_add_start;
+			data->m_dirty_start = m_max_total_add_start;
+			data->m_dirty_size = 0;
+			data->m_count = 1;
+			return data;
+		}
+		Buffer::deallocate (data);
+	}
+	struct Buffer::BufferData *data = Buffer::allocate (m_max_total_add_start+m_max_total_add_end,
+							    m_max_total_add_start);
+	assert (data->m_count == 1);
+	return data;
+}
+#else
+void
+Buffer::recycle (struct Buffer::BufferData *data)
+{
+	Buffer::deallocate (data);
+}
+
+Buffer::BufferData *
+Buffer::create (void)
+{
+	return Buffer::allocate (m_max_total_add_start+m_max_total_add_end,
+				 m_max_total_add_start);
+}
+#endif
+
+}; // namespace yans
+
+
+#include <cassert>
+
+namespace yans {
+
+
+void 
+Buffer::add_at_start (uint32_t start)
+{
+	assert (m_start <= m_data->m_initial_start);
+	bool is_dirty = m_data->m_count > 1 && m_start > m_data->m_dirty_start;
+	if (m_start >= start && !is_dirty) {
+		/* enough space in the buffer and not dirty. */
+		m_start -= start;
+		m_size += start;
+	} else if (m_size + start <= m_data->m_size && !is_dirty) {
+		/* enough space but need to move data around to fit new data */
+                memmove (m_data->m_data + start, get_start (), m_size);
+		assert (start > m_start);
+		m_data->m_initial_start += start;
+                m_start = 0;
+                m_size += start;
+	} else if (m_start < start) {
+		/* not enough space in buffer */
+		uint32_t new_size = m_size + start;
+		struct Buffer::BufferData *new_data = Buffer::allocate (new_size, 0);
+		memcpy (new_data->m_data + start, get_start (), m_size);
+		new_data->m_initial_start = m_data->m_initial_start + start;
+		m_data->m_count--;
+		if (m_data->m_count == 0) {
+			Buffer::deallocate (m_data);
+		}
+		m_data = new_data;
+		m_start = 0;
+		m_size = new_size;
+	} else {
+		/* enough space in the buffer but it is dirty ! */
+		assert (is_dirty);
+		struct Buffer::BufferData *new_data = Buffer::create ();
+		memcpy (new_data->m_data + m_start, get_start (), m_size);
+		new_data->m_initial_start = m_data->m_initial_start;
+		m_data->m_count--;
+		if (m_data->m_count == 0) {
+			recycle (m_data);
+		}
+		m_data = new_data;
+		m_start -= start;
+		m_size += start;
+	} 
+	// update dirty area
+	m_data->m_dirty_start = m_start;
+	m_data->m_dirty_size = m_size;
+	// update m_max_total_add_start
+	uint32_t added_at_start;
+	if (m_data->m_initial_start > m_start) {
+		added_at_start = m_data->m_initial_start - m_start;
+	} else {
+		added_at_start = 0;
+	}
+	if (added_at_start > m_max_total_add_start) {
+		m_max_total_add_start = added_at_start;
+	}
+	TRACE ("start add="<<start<<", start="<<m_start<<", size="<<m_size<<", zero="<<m_zero_area_size<<
+	       ", real size="<<m_data->m_size<<", ini start="<<m_data->m_initial_start<<
+	       ", dirty start="<<m_data->m_dirty_start<<", dirty size="<<m_data->m_dirty_size); 
+}
+void 
+Buffer::add_at_end (uint32_t end)
+{
+	assert (m_start <= m_data->m_initial_start);
+	bool is_dirty = m_data->m_count > 1 &&
+		m_start + m_size < m_data->m_dirty_start + m_data->m_dirty_size;
+	if (m_start + m_size + end <= m_data->m_size && !is_dirty) {
+		/* enough space in buffer and not dirty */
+		m_size += end;
+	} else if (m_size + end <= m_data->m_size && !is_dirty) {
+		/* enough space but need to move data around to fit the extra data */
+                uint32_t new_start = m_data->m_size - (m_size + end);
+                memmove (m_data->m_data + new_start, get_start (), m_size);
+		assert (new_start < m_start);
+		m_data->m_initial_start -= m_start - new_start;
+                m_start = new_start;
+                m_size += end;
+	} else if (m_start + m_size + end > m_data->m_size) {
+		/* not enough space in buffer */
+		uint32_t new_size = m_size + end;
+		struct Buffer::BufferData *new_data = Buffer::allocate (new_size, 0);
+		memcpy (new_data->m_data, get_start (), m_size);
+		new_data->m_initial_start = m_data->m_initial_start;
+		m_data->m_count--;
+		if (m_data->m_count == 0) {
+			Buffer::deallocate (m_data);
+		}
+		m_data = new_data;
+		m_size = new_size;
+		m_start = 0;
+	} else {
+		/* enough space in the buffer but it is dirty ! */
+		assert (is_dirty);
+		struct Buffer::BufferData *new_data = Buffer::create ();
+		memcpy (new_data->m_data + m_start, get_start (), m_size);
+		new_data->m_initial_start = m_data->m_initial_start;
+		m_data->m_count--;
+		if (m_data->m_count == 0) {
+			recycle (m_data);
+		}
+		m_data = new_data;
+		m_size += end;
+	} 
+	// update dirty area
+	m_data->m_dirty_start = m_start;
+	m_data->m_dirty_size = m_size;
+	// update m_max_total_add_end
+	uint32_t end_loc = m_start + m_size;
+	uint32_t added_at_end;
+	if (m_data->m_initial_start < end_loc) {
+		added_at_end = end_loc - m_data->m_initial_start;
+	} else {
+		added_at_end = 0;
+	}
+	if (added_at_end > m_max_total_add_end) {
+		m_max_total_add_end = added_at_end;
+	}
+	TRACE ("end add="<<end<<", start="<<m_start<<", size="<<m_size<<", zero="<<m_zero_area_size<<
+	       ", real size="<<m_data->m_size<<", ini start="<<m_data->m_initial_start<<
+	       ", dirty start="<<m_data->m_dirty_start<<", dirty size="<<m_data->m_dirty_size); 
+}
+
+void 
+Buffer::remove_at_start (uint32_t start)
+{
+	if (m_zero_area_size == 0) {
+		if (m_size <= start) {
+			m_start += m_size;
+			m_size = 0;
+		} else {
+			m_start += start;
+			m_size -= start;
+		}
+	} else {
+		assert (m_data->m_initial_start >= m_start);
+		uint32_t zero_start = m_data->m_initial_start - m_start;
+		uint32_t zero_end = zero_start + m_zero_area_size;
+		uint32_t data_end = m_size + m_zero_area_size;
+		if (start <= zero_start) {
+			/* only remove start of buffer */
+			m_start += start;
+			m_size -= start;
+		} else if (start <= zero_end) {
+			/* remove start of buffer _and_ start of zero area */
+			m_start += zero_start;
+			uint32_t zero_delta = start - zero_start;
+			m_zero_area_size -= zero_delta;
+			assert (zero_delta <= start);
+			m_size -= zero_start;
+		} else if (start <= data_end) {
+			/* remove start of buffer, complete zero area, and part
+			 * of end of buffer */
+			m_start += start - m_zero_area_size;
+			m_size -= start - m_zero_area_size;
+			m_zero_area_size = 0;
+		} else {
+			/* remove all buffer */
+			m_start += m_size;
+			m_size = 0;
+			m_zero_area_size = 0;
+		}
+	}
+	TRACE ("start remove="<<start<<", start="<<m_start<<", size="<<m_size<<", zero="<<m_zero_area_size<<
+	       ", real size="<<m_data->m_size<<", ini start="<<m_data->m_initial_start<<
+	       ", dirty start="<<m_data->m_dirty_start<<", dirty size="<<m_data->m_dirty_size); 
+}
+void 
+Buffer::remove_at_end (uint32_t end)
+{
+	if (m_zero_area_size == 0) {
+		if (m_size <= end) {
+			m_size = 0;
+		} else {
+			m_size -= end;
+		} 
+	} else {
+		assert (m_data->m_initial_start >= m_start);
+		uint32_t zero_start = m_data->m_initial_start - m_start;
+		uint32_t zero_end = zero_start + m_zero_area_size;
+		uint32_t data_end = m_size + m_zero_area_size;
+		assert (zero_start <= m_size);
+		assert (zero_end <= m_size + m_zero_area_size);
+		if (data_end <= end) {
+			/* remove all buffer */
+			m_zero_area_size = 0;
+			m_start += m_size;
+			m_size = 0;
+		} else if (data_end - zero_start <= end) {
+			/* remove end of buffer, zero area, part of start of buffer */
+			assert (end >= m_zero_area_size);
+			m_size -= end - m_zero_area_size;
+			m_zero_area_size = 0;
+		} else if (data_end - zero_end <= end) {
+			/* remove end of buffer, part of zero area */
+			uint32_t zero_delta = end - (data_end - zero_end);
+			m_zero_area_size -= zero_delta;
+			m_size -= end - zero_delta;
+		} else {
+			/* remove part of end of buffer */
+			m_size -= end;
+		}
+	}
+	TRACE ("end remove="<<end<<", start="<<m_start<<", size="<<m_size<<", zero="<<m_zero_area_size<<
+	       ", real size="<<m_data->m_size<<", ini start="<<m_data->m_initial_start<<
+	       ", dirty start="<<m_data->m_dirty_start<<", dirty size="<<m_data->m_dirty_size); 
+}
+
+Buffer 
+Buffer::create_fragment (uint32_t start, uint32_t length) const
+{
+	uint32_t zero_start = m_data->m_initial_start - m_start;
+	uint32_t zero_end = zero_start + m_zero_area_size;
+	if (m_zero_area_size != 0 &&
+	    start + length > zero_start &&
+	    start <= zero_end) {
+		transform_into_real_buffer ();
+	}
+	Buffer tmp = *this;
+	tmp.remove_at_start (start);
+	tmp.remove_at_end (get_size () - (start + length));
+	return tmp;
+}
+
+void
+Buffer::transform_into_real_buffer (void) const
+{
+	if (m_zero_area_size != 0) {
+		assert (m_data->m_initial_start >= m_start);
+		assert (m_size >= (m_data->m_initial_start - m_start));
+		Buffer tmp;
+		tmp.add_at_start (m_zero_area_size);
+		tmp.begin ().write_u8 (0, m_zero_area_size);
+		uint32_t data_start = m_data->m_initial_start - m_start;
+		tmp.add_at_start (data_start);
+		tmp.begin ().write (m_data->m_data+m_start, data_start);
+		uint32_t data_end = m_size - (m_data->m_initial_start - m_start);
+		tmp.add_at_end (data_end);
+		Buffer::Iterator i = tmp.end ();
+		i.prev (data_end);
+		i.write (m_data->m_data+m_data->m_initial_start,data_end);
+		*const_cast<Buffer *> (this) = tmp;
+	}
+}
+
+
+uint8_t *
+Buffer::peek_data (void) const
+{
+	transform_into_real_buffer ();
+	return m_data->m_data + m_start;
+}
+
+
+
+
+}; // namespace yans
+
+
+#ifdef RUN_SELF_TESTS
+
+#include "yans/test.h"
+#include <iomanip>
+
+namespace yans {
+
+class BufferTest: public Test {
+private:
+  bool ensure_written_bytes (Buffer b, uint32_t n, uint8_t array[]);
+public:
+  virtual bool run_tests (void);
+  BufferTest ();
+};
+
+
+BufferTest::BufferTest ()
+	: Test ("Buffer") {}
+
+bool
+BufferTest::ensure_written_bytes (Buffer b, uint32_t n, uint8_t array[])
+{
+	bool success = true;
+	uint8_t *expected = array;
+	uint8_t *got;
+	got = b.peek_data ();
+	for (uint32_t j = 0; j < n; j++) {
+		if (got[j] != expected[j]) {
+			success = false;
+		}
+	}
+	if (!success) {
+		failure () << "Buffer -- ";
+		failure () << "expected: n=";
+		failure () << n << ", ";
+		failure ().setf (std::ios::hex, std::ios::basefield);
+		for (uint32_t j = 0; j < n; j++) {
+			failure () << (uint16_t)expected[j] << " ";
+		}
+		failure ().setf (std::ios::dec, std::ios::basefield);
+		failure () << "got: ";
+		failure ().setf (std::ios::hex, std::ios::basefield);
+		for (uint32_t j = 0; j < n; j++) {
+			failure () << (uint16_t)got[j] << " ";
+		}
+		failure () << std::endl;
+	}
+	return success;
+}
+
+/* Note: works only when variadic macros are
+ * available which is the case for gcc.
+ * XXX
+ */
+#define ENSURE_WRITTEN_BYTES(buffer, n, ...) \
+{ \
+	uint8_t bytes[] = {__VA_ARGS__}; \
+	if (!ensure_written_bytes (buffer, n , bytes)) { \
+		ok = false; \
+	} \
+}
+
+bool
+BufferTest::run_tests (void)
+{
+	bool ok = true;
+	Buffer buffer;
+	Buffer::Iterator i;
+	buffer.add_at_start (6);
+	i = buffer.begin ();
+	i.write_u8 (0x66);
+	ENSURE_WRITTEN_BYTES (buffer, 1, 0x66);
+	i = buffer.begin ();
+	i.write_u8 (0x67);
+	ENSURE_WRITTEN_BYTES (buffer, 1, 0x67);
+	i.write_hton_u16 (0x6568);
+	i = buffer.begin ();
+	ENSURE_WRITTEN_BYTES (buffer, 3, 0x67, 0x65, 0x68);
+	i.write_hton_u16 (0x6369);
+	ENSURE_WRITTEN_BYTES (buffer, 3, 0x63, 0x69, 0x68);
+	i.write_hton_u32 (0xdeadbeaf);
+	ENSURE_WRITTEN_BYTES (buffer, 6, 0x63, 0x69, 0xde, 0xad, 0xbe, 0xaf);
+	buffer.add_at_start (2);
+	i = buffer.begin ();
+	i.write_u16 (0);
+	ENSURE_WRITTEN_BYTES (buffer, 8, 0, 0, 0x63, 0x69, 0xde, 0xad, 0xbe, 0xaf);
+	buffer.add_at_end (2);
+	i = buffer.begin ();
+	i.next (8);
+	i.write_u16 (0);
+	ENSURE_WRITTEN_BYTES (buffer, 10, 0, 0, 0x63, 0x69, 0xde, 0xad, 0xbe, 0xaf, 0, 0);
+	buffer.remove_at_start (3);
+	i = buffer.begin ();
+	ENSURE_WRITTEN_BYTES (buffer, 7, 0x69, 0xde, 0xad, 0xbe, 0xaf, 0, 0);
+	buffer.remove_at_end (4);
+	i = buffer.begin ();
+	ENSURE_WRITTEN_BYTES (buffer, 3, 0x69, 0xde, 0xad);
+	buffer.add_at_start (1);
+	i = buffer.begin ();
+	i.write_u8 (0xff);
+	ENSURE_WRITTEN_BYTES (buffer, 4, 0xff, 0x69, 0xde, 0xad);
+	buffer.add_at_end (1);
+	i = buffer.begin ();
+	i.next (4);
+	i.write_u8 (0xff);
+	i.prev (2);
+	uint16_t saved = i.read_u16 ();
+	i.prev (2);
+	i.write_hton_u16 (0xff00);
+	i.prev (2);
+	if (i.read_ntoh_u16 () != 0xff00) {
+		ok = false;
+	}
+	i.prev (2);
+	i.write_u16 (saved);
+	ENSURE_WRITTEN_BYTES (buffer, 5, 0xff, 0x69, 0xde, 0xad, 0xff);
+	Buffer o = buffer;
+	ENSURE_WRITTEN_BYTES (o, 5, 0xff, 0x69, 0xde, 0xad, 0xff);
+	o.add_at_start (1);
+	i = o.begin ();
+	i.write_u8 (0xfe);
+	ENSURE_WRITTEN_BYTES (o, 6, 0xfe, 0xff, 0x69, 0xde, 0xad, 0xff);
+	buffer.add_at_start (2);
+	i = buffer.begin ();
+	i.write_u8 (0xfd);
+	i.write_u8 (0xfd);
+	ENSURE_WRITTEN_BYTES (o, 6, 0xfe, 0xff, 0x69, 0xde, 0xad, 0xff);
+	ENSURE_WRITTEN_BYTES (buffer, 7, 0xfd, 0xfd, 0xff, 0x69, 0xde, 0xad, 0xff);
+
+	// test self-assignment
+	{
+		Buffer a = o;
+		a = a;
+	}
+
+	// test remove start.
+	buffer = Buffer (5);
+	ENSURE_WRITTEN_BYTES (buffer, 5, 0, 0, 0, 0, 0);
+	buffer.remove_at_start (1);
+	ENSURE_WRITTEN_BYTES (buffer, 4, 0, 0, 0, 0);
+	buffer.add_at_start (1);
+	buffer.begin ().write_u8 (0xff);
+	ENSURE_WRITTEN_BYTES (buffer, 5, 0xff, 0, 0, 0, 0);
+	buffer.remove_at_start(3);
+	ENSURE_WRITTEN_BYTES (buffer, 2, 0, 0);
+	buffer.add_at_start (4);
+	buffer.begin ().write_hton_u32 (0xdeadbeaf);
+	ENSURE_WRITTEN_BYTES (buffer, 6,  0xde, 0xad, 0xbe, 0xaf, 0, 0);
+	buffer.remove_at_start (2);
+	ENSURE_WRITTEN_BYTES (buffer, 4,  0xbe, 0xaf, 0, 0);
+	buffer.add_at_end (4);
+	i = buffer.begin ();
+	i.next (4);
+	i.write_hton_u32 (0xdeadbeaf);
+	ENSURE_WRITTEN_BYTES (buffer, 8,  0xbe, 0xaf, 0, 0, 0xde, 0xad, 0xbe, 0xaf);
+	buffer.remove_at_start (5);
+	ENSURE_WRITTEN_BYTES (buffer, 3,  0xad, 0xbe, 0xaf);
+	// test remove end
+	buffer = Buffer (5);
+	ENSURE_WRITTEN_BYTES (buffer, 5, 0, 0, 0, 0, 0);
+	buffer.remove_at_end (1);
+	ENSURE_WRITTEN_BYTES (buffer, 4, 0, 0, 0, 0);
+	buffer.add_at_end (2);
+	i = buffer.begin ();
+	i.next (4);
+	i.write_u8 (0xab);
+	i.write_u8 (0xac);
+	ENSURE_WRITTEN_BYTES (buffer, 6, 0, 0, 0, 0, 0xab, 0xac);
+	buffer.remove_at_end (1);
+	ENSURE_WRITTEN_BYTES (buffer, 5, 0, 0, 0, 0, 0xab);
+	buffer.remove_at_end (3);
+	ENSURE_WRITTEN_BYTES (buffer, 2, 0, 0);
+	buffer.add_at_end (6);
+	i = buffer.begin ();
+	i.next (2);
+	i.write_u8 (0xac);
+	i.write_u8 (0xad);
+	i.write_u8 (0xae);
+	i.write_u8 (0xaf);
+	i.write_u8 (0xba);
+	i.write_u8 (0xbb);
+	ENSURE_WRITTEN_BYTES (buffer, 8, 0, 0, 0xac, 0xad, 0xae, 0xaf, 0xba, 0xbb);
+	buffer.add_at_start (3);
+	i = buffer.begin ();
+	i.write_u8 (0x30);
+	i.write_u8 (0x31);
+	i.write_u8 (0x32);
+	ENSURE_WRITTEN_BYTES (buffer, 11, 0x30, 0x31, 0x32, 0, 0, 0xac, 0xad, 0xae, 0xaf, 0xba, 0xbb);
+	buffer.remove_at_end (9);
+	ENSURE_WRITTEN_BYTES (buffer, 2, 0x30, 0x31);
+	buffer = Buffer (3);
+	buffer.add_at_end (2);
+	i = buffer.begin ();
+	i.next (3);
+	i.write_hton_u16 (0xabcd);
+	buffer.add_at_start (1);
+	buffer.begin ().write_u8 (0x21);
+	ENSURE_WRITTEN_BYTES (buffer, 6, 0x21, 0, 0, 0, 0xab, 0xcd);
+	buffer.remove_at_end (8);
+	if (buffer.get_size () != 0) {
+		ok = false;
+	}
+	
+	
+	
+
+	return ok;
+}
+
+
+
+static BufferTest g_buffer_test;
+
+}; // namespace yans
+
+#endif /* RUN_SELF_TESTS */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/buffer.h	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,690 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2005,2006 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#ifndef BUFFER_H
+#define BUFFER_H
+
+#include <stdint.h>
+#include <vector>
+
+namespace yans {
+
+/**
+ * \brief automatically resized byte buffer
+ *
+ * This represents a buffer of bytes. Its size is
+ * automatically adjusted to hold any data prepended
+ * or appended by the user. Its implementation is optimized
+ * to ensure that the number of buffer resizes is minimized,
+ * by creating new Buffers of the maximum size ever used.
+ * The correct maximum size is learned at runtime during use by 
+ * recording the maximum size of each packet.
+ */
+class Buffer {
+public:
+	/**
+	 * \brief iterator in a Buffer instance
+	 */
+	class Iterator {
+	public:
+		inline Iterator ();
+		/**
+		 * go forward by one byte
+		 */
+		inline void next (void);
+		/**
+		 * go backward by one byte
+		 */
+		inline void prev (void);
+		/**
+		 * \param delta number of bytes to go forward
+		 */
+		inline void next (uint32_t delta);
+		/**
+		 * \param delta number of bytes to go backward
+		 */
+		inline void prev (uint32_t delta);
+		/**
+		 * \param o the second iterator
+		 * \return number of bytes included between the two iterators
+		 *
+		 * This method works only if the two iterators point
+		 * to the same underlying buffer. Debug builds ensure
+		 * this with an assert.
+		 */
+		inline int32_t get_distance_from (Iterator const &o) const;
+		
+		/**
+		 * \return true if this iterator points to the end of the byte array.
+		 *         false otherwise.
+		 */
+		inline bool is_end (void) const;
+		/**
+		 * \return true if this iterator points to the start of the byte array.
+		 *         false otherwise.
+		 */
+		inline bool is_start (void) const;
+
+		/**
+		 * \param data data to write in buffer
+		 *
+		 * Write the data in buffer and avance the iterator position
+		 * by one byte.
+		 */
+		inline void write_u8 (uint8_t  data);
+		/**
+		 * \param data data to write in buffer
+		 * \param len number of times data must be written in buffer
+		 *
+		 * Write the data in buffer len times and avance the iterator position
+		 * by len byte.
+		 */
+		inline void write_u8 (uint8_t data, uint32_t len);
+		/**
+		 * \param data data to write in buffer
+		 *
+		 * Write the data in buffer and avance the iterator position
+		 * by two bytes. The format of the data written in the byte
+		 * buffer is non-portable. We only ensure that read_u16 will
+		 * return exactly what we wrote with write_u16 if the program
+		 * is run on the same machine.
+		 */
+		inline void write_u16 (uint16_t data);
+		/**
+		 * \param data data to write in buffer
+		 *
+		 * Write the data in buffer and avance the iterator position
+		 * by four bytes. The format of the data written in the byte
+		 * buffer is non-portable. We only ensure that read_u32 will
+		 * return exactly what we wrote with write_u32 if the program
+		 * is run on the same machine.
+		 */
+		inline void write_u32 (uint32_t data);
+		/**
+		 * \param data data to write in buffer
+		 *
+		 * Write the data in buffer and avance the iterator position
+		 * by eight bytes. The format of the data written in the byte
+		 * buffer is non-portable. We only ensure that read_u64 will
+		 * return exactly what we wrote with write_u64 if the program
+		 * is run on the same machine.
+		 */
+		inline void write_u64 (uint64_t data);
+		/**
+		 * \param data data to write in buffer
+		 *
+		 * Write the data in buffer and avance the iterator position
+		 * by two bytes. The data is written in network order and the
+		 * input data is expected to be in host order.
+		 */
+		inline void write_hton_u16 (uint16_t data);
+		/**
+		 * \param data data to write in buffer
+		 *
+		 * Write the data in buffer and avance the iterator position
+		 * by four bytes. The data is written in network order and the
+		 * input data is expected to be in host order.
+		 */
+		inline void write_hton_u32 (uint32_t data);
+		/**
+		 * \param data data to write in buffer
+		 *
+		 * Write the data in buffer and avance the iterator position
+		 * by eight bytes. The data is written in network order and the
+		 * input data is expected to be in host order.
+		 */
+		inline void write_hton_u64 (uint64_t data);
+		/**
+		 * \param buffer a byte buffer to copy in the internal buffer.
+		 * \param size number of bytes to copy.
+		 *
+		 * Write the data in buffer and avance the iterator position
+		 * by size bytes.
+		 */
+		inline void write (uint8_t const*buffer, uint16_t size);
+		/**
+		 * \param start the start of the data to copy
+		 * \param end the end of the data to copy
+		 *
+		 * Write the data delimited by start and end in internal buffer 
+		 * and avance the iterator position by the number of bytes
+		 * copied.
+		 * The input interators _must_ not point to the same Buffer as
+		 * we do to avoid overlapping copies. This is enforced 
+		 * in debug builds by asserts.
+		 */
+		inline void write (Iterator start, Iterator end);
+
+		/**
+		 * \return the byte read in the buffer.
+		 *
+		 * Read data and advance the Iterator by the number of bytes
+		 * read.
+		 */
+		inline uint8_t  read_u8 (void);
+		/**
+		 * \return the two bytes read in the buffer.
+		 *
+		 * Read data and advance the Iterator by the number of bytes
+		 * read.
+		 * The data is read in the format written by write_u16.
+		 */
+		inline uint16_t read_u16 (void);
+		/**
+		 * \return the four bytes read in the buffer.
+		 *
+		 * Read data and advance the Iterator by the number of bytes
+		 * read.
+		 * The data is read in the format written by write_u32.
+		 */
+		inline uint32_t read_u32 (void);
+		/**
+		 * \return the eight bytes read in the buffer.
+		 *
+		 * Read data and advance the Iterator by the number of bytes
+		 * read.
+		 * The data is read in the format written by write_u64.
+		 */
+		inline uint64_t read_u64 (void);
+		/**
+		 * \return the two bytes read in the buffer.
+		 *
+		 * Read data and advance the Iterator by the number of bytes
+		 * read.
+		 * The data is read in network format and return in host format.
+		 */
+		inline uint16_t read_ntoh_u16 (void);
+		/**
+		 * \return the four bytes read in the buffer.
+		 *
+		 * Read data and advance the Iterator by the number of bytes
+		 * read.
+		 * The data is read in network format and return in host format.
+		 */
+		inline uint32_t read_ntoh_u32 (void);
+		/**
+		 * \return the eight bytes read in the buffer.
+		 *
+		 * Read data and advance the Iterator by the number of bytes
+		 * read.
+		 * The data is read in network format and return in host format.
+		 */
+		inline uint64_t read_ntoh_u64 (void);
+		/**
+		 * \param buffer buffer to copy data into
+		 * \param size number of bytes to copy
+		 *
+		 * Copy size bytes of data from the internal buffer to the
+		 * input buffer and avance the Iterator by the number of
+		 * bytes read.
+		 */
+		inline void read (uint8_t *buffer, uint16_t size);
+	private:
+		friend class Buffer;
+		inline Iterator (Buffer const*buffer, uint32_t m_current);
+		inline uint32_t get_index (uint32_t n);
+		uint32_t m_zero_start;
+		uint32_t m_zero_end;
+		uint32_t m_data_end;
+		uint32_t m_current;
+		uint8_t *m_data;
+	};
+
+	/**
+	 * \return the number of bytes stored in this buffer.
+	 */
+	inline uint32_t get_size (void) const;
+
+	/**
+	 * \return a pointer to the start of the internal 
+	 * byte buffer.
+	 *
+	 * The returned pointer points to an area of
+	 * memory which is yans::Buffer::get_size () bytes big.
+	 * Please, try to never ever use this method. It is really
+	 * evil and is present only for a few specific uses.
+	 */
+	uint8_t *peek_data (void) const;
+
+	/**
+	 * \param start size to reserve
+	 *
+	 * Add bytes at the start of the Buffer. The
+	 * content of these bytes is undefined but debugging
+	 * builds initialize them to 0x33.
+	 * Any call to this method invalidates any Iterator
+	 * pointing to this Buffer.
+	 */
+	void add_at_start (uint32_t start);
+	/**
+	 * \param end size to reserve
+	 *
+	 * Add bytes at the end of the Buffer. The
+	 * content of these bytes is undefined but debugging
+	 * builds initialize them to 0x33.
+	 * Any call to this method invalidates any Iterator
+	 * pointing to this Buffer.
+	 */
+	void add_at_end (uint32_t end);
+	/**
+	 * \param start size to remove
+	 *
+	 * Remove bytes at the start of the Buffer.
+	 * Any call to this method invalidates any Iterator
+	 * pointing to this Buffer.
+	 */
+	void remove_at_start (uint32_t start);
+	/**
+	 * \param end size to remove
+	 *
+	 * Remove bytes at the end of the Buffer.
+	 * Any call to this method invalidates any Iterator
+	 * pointing to this Buffer.
+	 */
+	void remove_at_end (uint32_t end);
+
+	/**
+	 * \param start offset from start of packet
+	 * \param length
+	 *
+	 * \return a fragment of size length starting at offset
+	 * start.
+	 */
+	Buffer create_fragment (uint32_t start, uint32_t length) const;
+
+	/**
+	 * \return an Iterator which points to the
+	 * start of this Buffer.
+	 */
+	inline Buffer::Iterator begin (void) const;
+	/**
+	 * \return an Iterator which points to the
+	 * end of this Buffer.
+	 */
+	inline Buffer::Iterator end (void) const;
+
+	inline Buffer (Buffer const &o);
+	inline Buffer &operator = (Buffer const &o);
+	inline Buffer ();
+	inline Buffer (uint32_t data_size);
+	inline ~Buffer ();
+private:
+	struct BufferData {
+		uint32_t m_count;
+		uint32_t m_size;
+		uint32_t m_initial_start;
+		uint32_t m_dirty_start;
+		uint32_t m_dirty_size;
+		uint8_t m_data[1];
+	};
+	typedef std::vector<struct Buffer::BufferData*> BufferDataList;
+
+	inline uint8_t *get_start (void) const;
+	void transform_into_real_buffer (void) const;
+	static void recycle (struct Buffer::BufferData *data);
+	static struct Buffer::BufferData *create (void);
+	static struct Buffer::BufferData *allocate (uint32_t size, uint32_t start);
+	static void deallocate (struct Buffer::BufferData *data);
+
+	static BufferDataList m_free_list;
+	static uint32_t m_max_total_add_start;
+	static uint32_t m_max_total_add_end;
+
+	struct BufferData *m_data;
+	uint32_t m_zero_area_size;
+	uint32_t m_start;
+	uint32_t m_size;
+};
+
+}; // namespace yans
+
+#include <cassert>
+
+namespace yans {
+
+Buffer::Buffer ()
+	: m_data (Buffer::create ()),
+	  m_zero_area_size (0),
+	  m_start (m_max_total_add_start),
+	  m_size (0)
+{
+	if (m_start > m_data->m_size) {
+		m_start = 0;
+	}
+	assert (m_start <= m_data->m_size);
+}
+
+Buffer::Buffer (uint32_t data_size)
+	: m_data (Buffer::create ()),
+	  m_zero_area_size (data_size),
+	  m_start (m_max_total_add_start),
+	  m_size (0)
+{
+	if (m_start > m_data->m_size) {
+		m_start = 0;
+	}
+	assert (m_start <= m_data->m_size);
+}
+
+
+Buffer::Buffer (Buffer const&o)
+	: m_data (o.m_data),
+	  m_zero_area_size (o.m_zero_area_size),
+	  m_start (o.m_start),
+	  m_size (o.m_size)
+{
+	m_data->m_count++;
+	assert (m_start <= m_data->m_size);
+}
+
+Buffer &
+Buffer::operator = (Buffer const&o)
+{
+	if (m_data != o.m_data) {
+		// not assignment to self.
+		m_data->m_count--;
+		if (m_data->m_count == 0) {
+			recycle (m_data);
+		}
+		m_data = o.m_data;
+		m_data->m_count++;
+	}
+	m_zero_area_size = o.m_zero_area_size;
+	m_start = o.m_start;
+	m_size = o.m_size;
+	assert (m_start <= m_data->m_size);
+	return *this;
+}
+
+Buffer::~Buffer ()
+{
+	m_data->m_count--;
+	if (m_data->m_count == 0) {
+		recycle (m_data);
+	}
+}
+
+
+uint8_t *
+Buffer::get_start (void) const
+{
+	return m_data->m_data + m_start;
+}
+
+uint32_t 
+Buffer::get_size (void) const
+{
+	return m_size + m_zero_area_size;
+}
+
+Buffer::Iterator 
+Buffer::begin (void) const
+{
+	return Buffer::Iterator (this, 0);
+}
+Buffer::Iterator 
+Buffer::end (void) const
+{
+	return Buffer::Iterator (this, get_size ());
+}
+
+
+Buffer::Iterator::Iterator ()
+	: m_zero_start (0),
+	  m_zero_end (0),
+	  m_data_end (0),
+	  m_current (0),
+	  m_data (0)
+{}
+Buffer::Iterator::Iterator (Buffer const*buffer, uint32_t current)
+	: m_zero_start (buffer->m_data->m_initial_start-buffer->m_start),
+	  m_zero_end (m_zero_start+buffer->m_zero_area_size),
+	  m_data_end (buffer->get_size ()),
+	  m_current (current),
+	  m_data (buffer->m_data->m_data+buffer->m_start)
+{}
+
+void 
+Buffer::Iterator::next (void)
+{
+	assert (m_current + 1 <= m_data_end);
+	m_current++;
+}
+void 
+Buffer::Iterator::prev (void)
+{
+	assert (m_current >= 1);
+	m_current--;
+}
+void 
+Buffer::Iterator::next (uint32_t delta)
+{
+	assert (m_current + delta <= m_data_end);
+	m_current += delta;
+}
+void 
+Buffer::Iterator::prev (uint32_t delta)
+{
+	assert (m_current >= delta);
+	m_current -= delta;
+}
+int32_t
+Buffer::Iterator::get_distance_from (Iterator const &o) const
+{
+	assert (m_data == o.m_data);
+	int32_t start = m_current;
+	int32_t end = o.m_current;
+	return end - start;
+}
+
+bool 
+Buffer::Iterator::is_end (void) const
+{
+	return m_current == m_data_end;
+}
+bool 
+Buffer::Iterator::is_start (void) const
+{
+	return m_current == 0;
+}
+
+uint32_t
+Buffer::Iterator::get_index (uint32_t n)
+{
+	assert ( 
+		(m_current + n <= m_data_end) &&
+		((m_current + n <= m_zero_start) ||
+		 (m_current >= m_zero_end))
+		);
+	uint32_t index;
+	if (m_current < m_zero_start) {
+		index = m_current;
+	} else {
+		index = m_current - (m_zero_end-m_zero_start);
+	}
+	return index;
+}
+
+
+void 
+Buffer::Iterator::write (Iterator start, Iterator end)
+{
+	assert (start.m_data == end.m_data);
+	assert (start.m_current <= end.m_current);
+	assert (m_data != start.m_data);
+	uint32_t size = end.m_current - start.m_current;
+	uint8_t *src = start.m_data + start.get_index (size);
+	uint8_t *dest = m_data + get_index (size);
+	memcpy (dest, src, size);
+	m_current += size;
+}
+
+void 
+Buffer::Iterator::write_u8 (uint8_t  data, uint32_t len)
+{
+	uint8_t *current = m_data + get_index (len);
+	memset (current, data, len);
+	m_current += len;
+}
+void 
+Buffer::Iterator::write_u8  (uint8_t  data)
+{
+	m_data[get_index (1)] = data;
+	m_current++;
+}
+void 
+Buffer::Iterator::write_u16 (uint16_t data)
+{
+	uint16_t *buffer = (uint16_t *)(m_data + get_index (2));
+	*buffer = data;
+	m_current += 2;
+}
+void 
+Buffer::Iterator::write_u32 (uint32_t data)
+{
+	uint32_t *buffer = (uint32_t *)(m_data + get_index (4));
+	*buffer = data;
+	m_current += 4;
+}
+void 
+Buffer::Iterator::write_u64 (uint64_t data)
+{
+	uint64_t *buffer = (uint64_t *)(m_data + get_index (8));
+	*buffer = data;
+	m_current += 8;
+}
+void 
+Buffer::Iterator::write_hton_u16 (uint16_t data)
+{
+	uint8_t *current = m_data + get_index (2);
+	*(current+0) = (data >> 8) & 0xff;
+	*(current+1) = (data >> 0) & 0xff;
+	m_current += 2;
+}
+void 
+Buffer::Iterator::write_hton_u32 (uint32_t data)
+{
+	uint8_t *current = m_data + get_index (4);
+	*(current+0) = (data >> 24) & 0xff;
+	*(current+1) = (data >> 16) & 0xff;
+	*(current+2) = (data >> 8) & 0xff;
+	*(current+3) = (data >> 0) & 0xff;
+	m_current += 4;
+}
+void 
+Buffer::Iterator::write_hton_u64 (uint64_t data)
+{
+	uint8_t *current = m_data + get_index (8);
+	*(current+0) = (data >> 56) & 0xff;
+	*(current+1) = (data >> 48) & 0xff;
+	*(current+2) = (data >> 40) & 0xff;
+	*(current+3) = (data >> 32) & 0xff;
+	*(current+4) = (data >> 24) & 0xff;
+	*(current+5) = (data >> 16) & 0xff;
+	*(current+6) = (data >> 8) & 0xff;
+	*(current+7) = (data >> 0) & 0xff;
+	m_current += 8;
+}
+void 
+Buffer::Iterator::write (uint8_t const*buffer, uint16_t size)
+{
+	uint8_t *current = m_data + get_index (size);
+	memcpy (current, buffer, size);
+	m_current += size;
+}
+
+uint8_t  
+Buffer::Iterator::read_u8 (void)
+{
+	uint8_t data = m_data[get_index(1)];
+	m_current++;
+	return data;
+}
+uint16_t 
+Buffer::Iterator::read_u16 (void)
+{
+	uint16_t *buffer = reinterpret_cast<uint16_t *>(m_data + get_index (2));
+	m_current += 2;
+	return *buffer;
+}
+uint32_t 
+Buffer::Iterator::read_u32 (void)
+{
+	uint32_t *buffer = reinterpret_cast<uint32_t *>(m_data + get_index (4));
+	m_current += 4;
+	return *buffer;
+}
+uint64_t 
+Buffer::Iterator::read_u64 (void)
+{
+	uint64_t *buffer = reinterpret_cast<uint64_t *>(m_data + get_index (8));
+	m_current += 8;
+	return *buffer;
+}
+uint16_t 
+Buffer::Iterator::read_ntoh_u16 (void)
+{
+	uint8_t *current = m_data + get_index (2);
+	uint16_t retval = 0;
+	retval |= static_cast<uint16_t> (current[0]) << 8;
+	retval |= static_cast<uint16_t> (current[1]) << 0;
+	m_current += 2;
+	return retval;
+}
+uint32_t 
+Buffer::Iterator::read_ntoh_u32 (void)
+{
+	uint8_t *current = m_data + get_index (4);
+	uint32_t retval = 0;
+	retval |= static_cast<uint32_t> (current[0]) << 24;
+	retval |= static_cast<uint32_t> (current[1]) << 16;
+	retval |= static_cast<uint32_t> (current[2]) << 8;
+	retval |= static_cast<uint32_t> (current[3]) << 0;
+	m_current += 4;
+	return retval;
+}
+uint64_t 
+Buffer::Iterator::read_ntoh_u64 (void)
+{
+	uint8_t *current = m_data + get_index (8);
+	uint64_t retval = 0;
+	retval |= static_cast<uint64_t> (current[0]) << 56;
+	retval |= static_cast<uint64_t> (current[1]) << 48;
+	retval |= static_cast<uint64_t> (current[2]) << 40;
+	retval |= static_cast<uint64_t> (current[3]) << 32;
+	retval |= static_cast<uint64_t> (current[4]) << 24;
+	retval |= static_cast<uint64_t> (current[5]) << 16;
+	retval |= static_cast<uint64_t> (current[6]) << 8;
+	retval |= static_cast<uint64_t> (current[7]) << 0;
+	m_current += 8;
+	return retval;
+}
+void 
+Buffer::Iterator::read (uint8_t *buffer, uint16_t size)
+{
+	uint8_t *current = m_data + get_index (size);
+	memcpy (buffer, current, size);
+	m_current += size;
+}
+
+}; // namespace yans
+
+
+#endif /* BUFFER_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/callback-logger.h	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,84 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2005,2006 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#ifndef CALLBACK_LOGGER_H
+#define CALLBACK_LOGGER_H
+
+#include "yans/callback.h"
+
+namespace yans {
+
+class CallbackLoggerBase {};
+
+/**
+ * \brief log arbitrary number of parameters to a matching yans:Callback
+ *
+ * Whenever operator () is invoked on this class, the call and its arguments
+ * are forwarded to the internal matching yans::Callback.
+ */
+template<typename T1 = empty, typename T2 = empty, 
+	 typename T3 = empty, typename T4 = empty,
+	 typename T5 = empty>
+class CallbackLogger : public CallbackLoggerBase{
+public:
+	CallbackLogger ()
+		: m_callback () {}
+	void set_callback (Callback<void,T1,T2,T3,T4,T5> callback) {
+		m_callback = callback;
+	}
+	void operator() (void) {
+		if (!m_callback.is_null ()) {
+			m_callback ();
+		}
+	}
+	void operator() (T1 a1) {
+		if (!m_callback.is_null ()) {
+			m_callback (a1);
+		}
+	}
+	void operator() (T1 a1, T2 a2) {
+		if (!m_callback.is_null ()) {
+			m_callback (a1,a2);
+		}
+	}
+	void operator() (T1 a1, T2 a2, T3 a3) {
+		if (!m_callback.is_null ()) {
+			m_callback (a1,a2,a3);
+		}
+	}
+	void operator() (T1 a1, T2 a2, T3 a3, T4 a4) {
+		if (!m_callback.is_null ()) {
+			m_callback (a1,a2,a3,a4);
+		}
+	}
+	void operator() (T1 a1, T2 a2, T3 a3, T4 a4,T5 a5) {
+		if (!m_callback.is_null ()) {
+			m_callback (a1,a2,a3,a4,a5);
+		}
+	}
+
+private:
+	Callback<void,T1,T2,T3,T4,T5> m_callback;
+};
+
+}; // namespace yans
+
+#endif /* CALLBACK_LOGGER_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/chunk-constant-data.cc	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,63 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2005 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#include "chunk-constant-data.h"
+
+namespace yans {
+
+ChunkConstantData::ChunkConstantData (uint32_t len, uint8_t data)
+	: m_len (len), m_data (data)
+{}
+
+ChunkConstantData::~ChunkConstantData ()
+{}
+
+
+void 
+ChunkConstantData::print (std::ostream *os) const
+{
+	*os << "(constant data)"
+	    << " len=" << m_len
+	    << ", data=" << m_data;
+}
+
+void 
+ChunkConstantData::add_to (Buffer *buffer) const
+{
+	buffer->add_at_start (m_len);
+#ifndef NDEBUG
+	buffer->begin ().write_u8 (m_data, m_len);
+#endif
+}
+void 
+ChunkConstantData::peek_from (Buffer const *buffer)
+{
+	m_len = buffer->get_size ();
+	m_data = buffer->begin ().read_u8 ();
+}
+void 
+ChunkConstantData::remove_from (Buffer *buffer)
+{
+	buffer->remove_at_start (m_len);
+}
+
+
+}; // namespace yans
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/chunk-constant-data.h	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,47 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2005 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#ifndef CHUNK_CONSTANT_DATA_H
+#define CHUNK_CONSTANT_DATA_H
+
+#include "chunk.h"
+#include <stdint.h>
+
+namespace yans {
+
+
+class ChunkConstantData : public Chunk {
+public:
+	ChunkConstantData (uint32_t len, uint8_t data);
+	~ChunkConstantData ();
+
+private:
+	virtual void print (std::ostream *os) const;
+	virtual void add_to (Buffer *buffer) const;
+	virtual void peek_from (Buffer const *buffer);
+	virtual void remove_from (Buffer *buffer);
+	uint32_t m_len;
+	uint8_t m_data;
+};
+
+}; // namespace yans
+
+#endif /* CHUNK_CONSTANT_DATA_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/chunk-llc-snap.cc	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,94 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2005 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#include "chunk-llc-snap.h"
+#include <cassert>
+
+#define noTRACE_CHUNK_LLC_SNAP 1
+
+#ifdef TRACE_CHUNK_LLC_SNAP
+#include <iostream>
+#include "simulator.h"
+# define TRACE(x) \
+std::cout << "CHUNK LLCSNAP TRACE " << Simulator::now_s () << " " << x << std::endl;
+#else /* TRACE_CHUNK_LLC_SNAP */
+# define TRACE(format,...)
+#endif /* TRACE_CHUNK_LLC_SNAP */
+
+
+namespace yans {
+
+ChunkLlcSnap::ChunkLlcSnap ()
+{}
+
+ChunkLlcSnap::~ChunkLlcSnap ()
+{}
+void 
+ChunkLlcSnap::set_type (enum Type type)
+{
+	m_ether_type = type;
+}
+enum ChunkLlcSnap::Type
+ChunkLlcSnap::get_type (void)
+{
+	return (enum ChunkLlcSnap::Type) m_ether_type;
+}
+
+uint32_t 
+ChunkLlcSnap::get_size (void) const
+{
+	return 1 + 1 + 1 + 3 + 2;
+}
+void 
+ChunkLlcSnap::print (std::ostream *os) const
+{
+	*os << "(mac)"
+	    << " EtherType: ";
+	os->setf (std::ios::hex, std::ios::basefield);
+	*os << m_ether_type;
+	os->setf (std::ios::dec, std::ios::basefield);
+}
+
+void 
+ChunkLlcSnap::add_to (Buffer *buffer) const
+{
+	buffer->add_at_start (get_size ());
+	Buffer::Iterator i = buffer->begin ();
+	uint8_t buf[] = {0xaa, 0xaa, 0x03, 0, 0, 0};
+	i.write (buf, 6);
+	i.write_hton_u16 (m_ether_type);
+}
+void 
+ChunkLlcSnap::peek_from (Buffer const *buffer)
+{
+	Buffer::Iterator i = buffer->begin ();
+	i.next (5+1);
+	m_ether_type = i.read_ntoh_u16 ();
+}
+void 
+ChunkLlcSnap::remove_from (Buffer *buffer)
+{
+	buffer->remove_at_start (get_size ());
+}
+
+
+
+}; // namespace yans
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/chunk-llc-snap.h	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,55 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2005 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#ifndef CHUNK_LLC_SNAP_H
+#define CHUNK_LLC_SNAP_H
+
+#include "chunk.h"
+#include <stdint.h>
+
+namespace yans {
+
+class ChunkLlcSnap : public Chunk {
+ public:
+	ChunkLlcSnap ();
+	virtual ~ChunkLlcSnap ();
+
+	enum Type {
+		TYPE_IPV4 = 0x0800,
+		TYPE_ARP  = 0x0806
+	};
+
+	void set_type (enum Type type);
+	enum Type get_type (void);
+
+	uint32_t get_size (void) const;
+
+private:
+	virtual void print (std::ostream *os) const;
+	virtual void add_to (Buffer *buffer) const;
+	virtual void peek_from (Buffer const *buffer);
+	virtual void remove_from (Buffer *buffer);
+	uint16_t m_ether_type;
+};
+
+}; // namespace yans
+
+#endif /* CHUNK_LLC_SNAP_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/chunk-utils.cc	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,49 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2006 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#include "chunk-utils.h"
+
+namespace yans {
+
+void write_to (Buffer::Iterator &i, Ipv4Address ad)
+{
+	i.write_hton_u32 (ad.get_host_order ());
+}
+void write_to (Buffer::Iterator &i, MacAddress ad)
+{
+	uint8_t mac[6];
+	ad.peek (mac);
+	i.write (mac, 6);
+}
+
+void read_from (Buffer::Iterator &i, Ipv4Address &ad)
+{
+	ad.set_host_order (i.read_ntoh_u32 ());
+}
+void read_from (Buffer::Iterator &i, MacAddress &ad)
+{
+	uint8_t mac[6];
+	i.read (mac, 6);
+	ad.set (mac);
+}
+
+
+
+}; // namespace yans
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/chunk-utils.h	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,38 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2006 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#ifndef CHUNK_UTILS_H
+#define CHUNK_UTILS_H
+
+#include "buffer.h"
+#include "ipv4-address.h"
+#include "mac-address.h"
+
+namespace yans {
+
+void write_to (Buffer::Iterator &i, Ipv4Address ad);
+void write_to (Buffer::Iterator &i, MacAddress ad);
+
+void read_from (Buffer::Iterator &i, Ipv4Address &ad);
+void read_from (Buffer::Iterator &i, MacAddress &ad);
+
+};
+
+#endif /* CHUNK_UTILS_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/chunk.cc	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,65 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2005 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#include "chunk.h"
+#include <cassert>
+
+namespace yans {
+
+Chunk::Chunk ()
+	: m_must_peek_before_remove (false) {}
+
+void 
+Chunk::print (std::ostream &os) const
+{
+	print (&os);
+}
+void 
+Chunk::add (Buffer *buffer) const
+{
+	add_to (buffer);
+}
+void 
+Chunk::peek (Buffer const *buffer)
+{
+	peek_from (buffer);
+	m_must_peek_before_remove = true;
+}
+void 
+Chunk::remove (Buffer *buffer)
+{
+	assert (m_must_peek_before_remove);
+	remove_from (buffer);
+	m_must_peek_before_remove = false;
+}
+
+
+
+Chunk::~Chunk ()
+{}
+
+std::ostream& operator<< (std::ostream& os, Chunk const& chunk)
+{
+	chunk.print (os);
+	return os;
+}
+
+}; // namespace yans
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/chunk.h	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,89 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2005 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#ifndef CHUNK_H
+#define CHUNK_H
+
+#include <stdint.h>
+#include <ostream>
+#include "buffer.h"
+
+namespace yans {
+
+/**
+ * \brief Protocol header serialization and deserialization.
+ *
+ * Every Protocol header which needs to be inserted and removed
+ * from a Packet instance must derive from this abstract base class
+ * and implement the private pure virtual methods defined here.
+ */
+class Chunk {
+public:
+	Chunk ();
+	/**
+	 * Derived classes must provided an explicit virtual destructor
+	 */
+	virtual ~Chunk () = 0;
+
+	void print (std::ostream &os) const;
+
+	void add (Buffer *buffer) const;
+	void peek (Buffer const *buffer);
+	void remove (Buffer *buffer);
+private:
+	bool m_must_peek_before_remove;
+	/**
+	 * \param os the std output stream in which this 
+	 *           protocol header must print itself.
+	 */
+	virtual void print (std::ostream *os) const = 0;
+
+	/**
+	 * \param buffer the buffer in which the protocol header
+	 *        must serialize itself.
+	 *
+	 * This method must:
+	 *   - reserve room for its serialized representation in the input buffer
+	 *   - serialize itself in this reserved room
+	 */
+	virtual void add_to (Buffer *buffer) const = 0;
+	/**
+	 * \param buffer the buffer from which the protocol header must
+	 *        deserialize itself.
+	 *
+	 */
+	virtual void peek_from (Buffer const *buffer) = 0;
+	/**
+	 * \param buffer the buffer from which the protocol header
+	 *        must remove itself.
+	 *
+	 * This method must remove its serialized representation 
+	 * from the input buffer. This method does not need to deserialize
+	 * the data itself.
+	 */
+	virtual void remove_from (Buffer *buffer) = 0;
+};
+
+std::ostream& operator<< (std::ostream& os, Chunk const& chunk);
+
+}; // namespace yans
+
+#endif /* CHUNK_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/count-ptr-holder.tcc	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,70 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2006 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#ifndef COUNT_PTR_HOLDER_TCC
+#define COUNT_PTR_HOLDER_TCC
+
+namespace yans {
+
+template <typename T>
+class CountPtrHolder {
+public:
+	typedef T *real_type;
+
+	CountPtrHolder (T *env) 
+		: m_env (env) {
+		m_env->ref ();
+	}
+	~CountPtrHolder () {
+		if (m_env != 0) {
+			m_env->unref ();
+		}
+	}
+	CountPtrHolder (CountPtrHolder const&o) {
+		m_env = o.m_env;
+		m_env->ref ();
+	}
+	T *remove (void) {
+		T *env = m_env;
+		m_env = 0;
+		return env;
+	}
+private:
+	CountPtrHolder ();
+	CountPtrHolder &operator = (CountPtrHolder const& o);
+	T *m_env;
+};
+
+template<typename T>
+CountPtrHolder<T>
+make_count_ptr_holder (T *t) {
+	return CountPtrHolder<T> (t);
+}
+
+template<typename T>
+CountPtrHolder<T const>
+make_const_count_ptr_holder (T *t) {
+	return CountPtrHolder<T const> (t);
+}
+
+}; // namespace yans
+
+#endif /* REF_HOLDER_TCC */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/data-writer.cc	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,119 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2005 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#include "data-writer.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/poll.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <cassert>
+#include <string.h>
+#include <list>
+
+#define noTRACE_DATA_WRITER 1
+
+#ifdef TRACE_DATA_WRITER
+#include <iostream>
+# define TRACE(x) \
+std::cout << "DATA WRITER TRACE " << this << " " << x << std::endl;
+#else /* TRACE_DATA_WRITER */
+# define TRACE(format,...)
+#endif /* TRACE_DATA_WRITER */
+
+#define BUFFER_SIZE (4096)
+
+
+namespace yans {
+
+class DataWriterPrivate {
+public:
+	DataWriterPrivate ();
+	~DataWriterPrivate ();
+
+	void open (char const *filename);
+	void write (uint8_t *buffer, uint32_t size);
+private:
+	uint8_t m_data[BUFFER_SIZE];
+	uint32_t m_current;
+	int m_fd;
+};
+
+DataWriterPrivate::DataWriterPrivate ()
+	: m_current (0)
+{}
+DataWriterPrivate::~DataWriterPrivate ()
+{
+	::write (m_fd, m_data, m_current);
+	::close (m_fd);
+}
+
+
+void
+DataWriterPrivate::open (char const *filename)
+{
+	m_fd = ::open (filename, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
+	assert (m_fd != -1);
+}
+
+#ifndef min
+#define min(a,b) ((a)<(b)?(a):(b))
+#endif /* min */
+
+void
+DataWriterPrivate::write (uint8_t *buffer, uint32_t size)
+{
+	while (size > 0) {
+		uint32_t to_copy = min (BUFFER_SIZE - m_current, size);
+		memcpy (m_data + m_current, buffer, to_copy);
+		size -= to_copy;
+		m_current += to_copy;
+		buffer += to_copy;
+		if (m_current == BUFFER_SIZE) {
+			ssize_t written = 0;
+			written = ::write (m_fd, m_data, BUFFER_SIZE);
+			assert (written == BUFFER_SIZE);
+			m_current = 0;
+		}
+	}
+}
+
+DataWriter::DataWriter ()
+	: m_priv (new DataWriterPrivate ())
+{}
+DataWriter::~DataWriter ()
+{
+	delete m_priv;
+	m_priv = 0;
+}
+
+void 
+DataWriter::open (char const *filename)
+{
+	m_priv->open (filename);
+}
+void 
+DataWriter::write (uint8_t *buffer, uint32_t size)
+{
+	m_priv->write (buffer, size);
+}
+
+}; // namespace
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/data-writer.h	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,44 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2005 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#ifndef DATA_WRITER_H
+#define DATA_WRITER_H
+
+#include <stdint.h>
+
+namespace yans {
+
+class DataWriterPrivate;
+
+class DataWriter {
+public:
+	DataWriter ();
+	~DataWriter ();
+
+	void open (char const *filename);
+	void write (uint8_t *buffer, uint32_t size);
+private:
+	DataWriterPrivate *m_priv;
+};
+
+}; //namespace yans
+
+#endif /* DATA_WRITER_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/f-traced-variable.tcc	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,58 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2006 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#ifndef F_TRACED_VARIABLE_TCC
+#define F_TRACED_VARIABLE_TCC
+
+#include "yans/callback.h"
+#include <stdint.h>
+
+namespace yans {
+
+class FTracedVariableBase {
+public:
+	typedef Callback<void,double, double> ChangeNotifyCallback;
+
+	FTracedVariableBase () {}
+	FTracedVariableBase (FTracedVariableBase const &o) {}
+	FTracedVariableBase &operator = (FTracedVariableBase const &o) {
+		return *this;
+	}
+
+	~FTracedVariableBase () {}
+
+	void set_callback(ChangeNotifyCallback callback) {
+		m_callback = callback;
+	}
+protected:
+	void notify (double old_val, double new_val) {
+		if (old_val != new_val && !m_callback.is_null ()) {
+			m_callback (old_val, new_val);
+		}
+	}
+private:
+	ChangeNotifyCallback m_callback;
+};
+
+
+}; // namespace yans
+
+#endif /* F_TRACED_VARIABLE_TCC */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/ipv4-address.cc	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,203 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2005 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#include "utils.h"
+#include "ipv4-address.h"
+
+namespace yans {
+
+Ipv4Mask::Ipv4Mask ()
+	: m_mask (0x66666666)
+{}
+
+Ipv4Mask::Ipv4Mask (uint32_t mask)
+	: m_mask (mask)
+{}
+Ipv4Mask::Ipv4Mask (char const *mask)
+{
+	m_mask = ascii_to_ipv4_host (mask);
+}
+
+bool 
+Ipv4Mask::is_equal (Ipv4Mask other) const
+{
+	if (other.m_mask == m_mask) {
+		return true;
+	} else {
+		return false;
+	}
+}
+
+
+bool 
+Ipv4Mask::is_match (Ipv4Address a, Ipv4Address b) const
+{
+	if ((a.get_host_order () & m_mask) == (b.get_host_order () & m_mask)) {
+		return true;
+	} else {
+		return false;
+	}
+}
+
+uint32_t 
+Ipv4Mask::get_host_order (void) const
+{
+	return m_mask;
+}
+void 
+Ipv4Mask::set_host_order (uint32_t value)
+{
+	m_mask = value;
+}
+
+void 
+Ipv4Mask::print (std::ostream *os) const
+{
+	*os << ((m_mask >> 24) & 0xff) << "."
+	    << ((m_mask >> 16) & 0xff) << "."
+	    << ((m_mask >> 8) & 0xff) << "."
+	    << ((m_mask >> 0) & 0xff);
+}
+
+
+Ipv4Mask
+Ipv4Mask::get_loopback (void)
+{
+	static Ipv4Mask loopback = Ipv4Mask ("255.0.0.0");
+	return loopback;
+}
+Ipv4Mask
+Ipv4Mask::get_zero (void)
+{
+	static Ipv4Mask zero = Ipv4Mask ("0.0.0.0");
+	return zero;
+}
+
+Ipv4Address::Ipv4Address ()
+	: m_address (0x66666666)
+{}
+Ipv4Address::Ipv4Address (uint32_t address)
+{
+	m_address = address;
+}
+Ipv4Address::Ipv4Address (char const *address)
+{
+	m_address = ascii_to_ipv4_host (address);
+}
+
+bool 
+Ipv4Address::is_equal (Ipv4Address other) const
+{
+	if (other.m_address == m_address) {
+		return true;
+	} else {
+		return false;
+	}
+}
+
+bool 
+Ipv4Address::is_multicast (void)
+{
+	// XXX
+	return false;
+}
+
+uint32_t
+Ipv4Address::get_host_order (void) const
+{
+	return m_address;
+}
+void 
+Ipv4Address::set_host_order (uint32_t ip)
+{
+	m_address = ip;
+}
+void
+Ipv4Address::serialize (uint8_t buf[4]) const
+{
+	buf[0] = (m_address >> 24) & 0xff;
+	buf[1] = (m_address >> 16) & 0xff;
+	buf[2] = (m_address >> 8) & 0xff;
+	buf[3] = (m_address >> 0) & 0xff;
+}
+
+void 
+Ipv4Address::print (std::ostream *os) const
+{
+	*os << ((m_address >> 24) & 0xff) << "."
+	    << ((m_address >> 16) & 0xff) << "."
+	    << ((m_address >> 8) & 0xff) << "."
+	    << ((m_address >> 0) & 0xff);
+}
+
+
+
+Ipv4Address 
+Ipv4Address::get_zero (void)
+{
+	static Ipv4Address zero ("0.0.0.0");
+	return zero;
+}
+Ipv4Address 
+Ipv4Address::get_any (void)
+{
+	static Ipv4Address any ("0.0.0.0");
+	return any;
+}
+Ipv4Address 
+Ipv4Address::get_broadcast (void)
+{
+	static Ipv4Address broadcast ("255.255.255.255");
+	return broadcast;
+}
+Ipv4Address 
+Ipv4Address::get_loopback (void)
+{
+	Ipv4Address loopback ("127.0.0.1");
+	return loopback;
+}
+
+bool operator == (Ipv4Address const &a, Ipv4Address const &b)
+{
+	return a.is_equal (b);
+}
+bool operator != (Ipv4Address const &a, Ipv4Address const &b)
+{
+	return !a.is_equal (b);
+}
+size_t Ipv4AddressHash::operator()(Ipv4Address const &x) const 
+{ 
+	return x.get_host_order ();
+}
+
+std::ostream& operator<< (std::ostream& os, Ipv4Address const& address)
+{
+	address.print (&os);
+	return os;
+}
+std::ostream& operator<< (std::ostream& os, Ipv4Mask const& mask)
+{
+	mask.print (&os);
+	return os;
+}
+
+
+}; // namespace yans
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/ipv4-address.h	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,107 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2005 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#ifndef IPV4_ADDRESS_H
+#define IPV4_ADDRESS_H
+
+#include <stdint.h>
+#include <ostream>
+
+namespace yans {
+
+/* Ipv4 addresses are stored in host order in
+ * this class.
+ */
+class Ipv4Address {
+public:
+	Ipv4Address ();
+	/* input address is in host order. */
+	Ipv4Address (uint32_t address);
+	/* input address is in format:
+	 * hhh.xxx.xxx.lll
+	 * where h is the high byte and l the
+	 * low byte
+	 */
+	Ipv4Address (char const *address);
+
+	bool is_equal (Ipv4Address other) const;
+
+	/* Using this method is frowned upon.
+	 * Please, do _not_ use this method.
+	 * It is there only for chunk-ipv4.
+	 */
+	uint32_t get_host_order (void) const;
+	void set_host_order (uint32_t ip);
+	void serialize (uint8_t buf[4]) const;
+
+	void print (std::ostream *os) const;
+
+	bool is_broadcast (void);
+	bool is_multicast (void);
+
+	static Ipv4Address get_zero (void);
+	static Ipv4Address get_any (void);
+	static Ipv4Address get_broadcast (void);
+	static Ipv4Address get_loopback (void);
+private:
+	uint32_t m_address;
+};
+
+
+class Ipv4Mask {
+public:
+	Ipv4Mask ();
+	Ipv4Mask (uint32_t mask);
+	Ipv4Mask (char const *mask);
+
+	bool is_match (Ipv4Address a, Ipv4Address b) const;
+
+	bool is_equal (Ipv4Mask other) const;
+
+
+	/* Using this method is frowned upon.
+	 * Please, do _not_ use this method.
+	 */
+	uint32_t get_host_order (void) const;
+	void set_host_order (uint32_t value);
+
+	void print (std::ostream *os) const;
+
+	static Ipv4Mask get_loopback (void);
+	static Ipv4Mask get_zero (void);
+private:
+	uint32_t m_mask;
+};
+
+std::ostream& operator<< (std::ostream& os, Ipv4Address const& address);
+std::ostream& operator<< (std::ostream& os, Ipv4Mask const& mask);
+
+bool operator == (Ipv4Address const &a, Ipv4Address const &b);
+bool operator != (Ipv4Address const &a, Ipv4Address const &b);
+class Ipv4AddressHash : public std::unary_function<Ipv4Address, size_t> {
+public:
+	size_t operator()(Ipv4Address const &x) const;
+};
+bool operator != (Ipv4Address const &a, Ipv4Address const &b);
+
+}; // namespace yans
+
+#endif /* IPV4_ADDRESS_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/ipv4-network-interface.cc	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,82 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2006 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#include "ipv4-network-interface.h"
+
+namespace yans {
+
+Ipv4NetworkInterface::~Ipv4NetworkInterface ()
+{}
+
+void 
+Ipv4NetworkInterface::set_address (Ipv4Address ad)
+{
+	m_address = ad;
+}
+void 
+Ipv4NetworkInterface::set_mask (Ipv4Mask mask)
+{
+	m_mask = mask;
+}
+uint16_t
+Ipv4NetworkInterface::get_mtu (void) const
+{
+	return real_get_mtu ();
+}	
+Ipv4Mask 
+Ipv4NetworkInterface::get_mask (void) const
+{
+	return m_mask;
+}
+Ipv4Address 
+Ipv4NetworkInterface::get_address (void) const
+{
+	return m_address;
+}
+Ipv4Address 
+Ipv4NetworkInterface::get_broadcast (void) const
+{
+	uint32_t mask = m_mask.get_host_order ();
+	uint32_t address = m_address.get_host_order ();
+	Ipv4Address broadcast = Ipv4Address (address | (~mask));
+	return broadcast;
+}
+
+void 
+Ipv4NetworkInterface::send (Packet packet, Ipv4Address to)
+{
+	real_send (packet, to);
+}
+
+void 
+Ipv4NetworkInterface::set_rx_callback (RxCallback callback)
+{
+	m_rx_callback = callback;
+}
+
+void 
+Ipv4NetworkInterface::forward_up (Packet packet)
+{
+	m_rx_callback (packet, this);
+}
+
+
+
+}; // namespace yans
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/ipv4-network-interface.h	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,59 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2006 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#ifndef IPV4_NETWORK_INTERFACE
+#define IPV4_NETWORK_INTERFACE
+
+#include "ipv4-address.h"
+#include "yans/callback.h"
+#include "packet.h"
+
+namespace yans {
+
+class Packet;
+
+class Ipv4NetworkInterface {
+public:
+	typedef Callback<void, Packet , Ipv4NetworkInterface *>  RxCallback;
+	virtual ~Ipv4NetworkInterface () = 0;
+
+	void set_address (Ipv4Address ad);
+	void set_mask (Ipv4Mask mask);
+	
+	uint16_t get_mtu (void) const;
+	Ipv4Mask get_mask (void) const;
+	Ipv4Address get_address (void) const;
+	Ipv4Address get_broadcast (void) const;
+
+	void send (Packet packet, Ipv4Address to);
+	void set_rx_callback (RxCallback callback);
+protected:
+	void forward_up (Packet packet);
+private:
+	virtual uint16_t real_get_mtu (void) const = 0;
+	virtual void real_send (Packet packet, Ipv4Address to) = 0;
+	RxCallback m_rx_callback;
+	Ipv4Address m_address;
+	Ipv4Mask m_mask;
+};
+
+}; // namespace yans
+
+#endif /* IPV4_NETWORK_INTERFACE */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/llc-snap-encapsulation.cc	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,89 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2006 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#include "llc-snap-encapsulation.h"
+#include "chunk-llc-snap.h"
+#include "packet.h"
+#include "chunk.h"
+#include "mac-network-interface.h"
+#include <cassert>
+
+namespace yans {
+
+uint32_t
+LlcSnapEncapsulation::get_overhead (void) const
+{
+	ChunkLlcSnap llc;
+	return llc.get_size ();
+}
+void 
+LlcSnapEncapsulation::set_ipv4_callback (RxCallback callback)
+{
+	m_ipv4_callback = callback;
+}
+void 
+LlcSnapEncapsulation::set_arp_callback (RxCallback callback)
+{
+	m_arp_callback = callback;
+}
+void 
+LlcSnapEncapsulation::set_mac_interface (MacNetworkInterface *interface)
+{
+	m_interface = interface;
+}
+void 
+LlcSnapEncapsulation::send_ipv4 (Packet packet, MacAddress to)
+{
+	ChunkLlcSnap llc;
+	llc.set_type (ChunkLlcSnap::TYPE_IPV4);
+	packet.add (&llc);
+	m_interface->send (packet, to);
+}
+void 
+LlcSnapEncapsulation::send_arp (Packet packet, MacAddress to)
+{
+	ChunkLlcSnap llc;
+	llc.set_type (ChunkLlcSnap::TYPE_ARP);
+	packet.add (&llc);
+	m_interface->send (packet, to);
+}
+
+void
+LlcSnapEncapsulation::receive (Packet packet, MacNetworkInterface *interface)
+{
+	assert (interface == m_interface);
+	ChunkLlcSnap llc;
+	packet.peek (&llc);
+	packet.remove (&llc);
+	switch (llc.get_type ()) {
+	case ChunkLlcSnap::TYPE_IPV4:
+		m_ipv4_callback (packet);
+		break;
+	case ChunkLlcSnap::TYPE_ARP:
+		m_arp_callback (packet);
+		break;
+	default:
+		assert (false);
+		//NOT REACHED
+		break;
+	}
+}
+
+}; // namespace yans
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/llc-snap-encapsulation.h	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,52 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2006 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#ifndef LLC_SNAP_ENCAPSULATION
+#define LLC_SNAP_ENCAPSULATION
+
+#include <stdint.h>
+#include "yans/callback.h"
+#include "mac-address.h"
+#include "packet.h"
+
+namespace yans {
+
+class MacNetworkInterface;
+
+class LlcSnapEncapsulation {
+public:	
+	typedef Callback<void, Packet > RxCallback;
+
+	uint32_t get_overhead (void) const;
+	void set_ipv4_callback (RxCallback callback);
+	void set_arp_callback (RxCallback callback);
+	void set_mac_interface (MacNetworkInterface *interface);
+	void send_ipv4 (Packet packet, MacAddress to);
+	void send_arp (Packet packet, MacAddress to);
+	void receive (Packet packet, MacNetworkInterface *interface);
+private:
+	RxCallback m_ipv4_callback;
+	RxCallback m_arp_callback;
+	MacNetworkInterface *m_interface;
+};
+
+}; // namespace yans
+
+#endif /* LLC_SNAP_ENCAPSULATION */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/mac-address-factory.cc	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,46 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2006 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#include "mac-address-factory.h"
+
+namespace yans {
+
+MacAddressFactory::MacAddressFactory ()
+{
+	m_addr[0] = 0;
+	m_addr[1] = 0;
+	m_addr[2] = 0;
+	m_addr[3] = 0;
+	m_addr[4] = 0;
+	m_addr[5] = 0;
+	m_index = 0;
+}
+
+MacAddress 
+MacAddressFactory::get_next (void)
+{
+	m_addr[m_index]++;
+	if (m_addr[m_index] == 0) {
+		m_index++;
+	}
+	return MacAddress (m_addr);
+}
+
+}; // namespace yans
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/mac-address-factory.h	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,40 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2006 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#ifndef MAC_ADDRESS_FACTORY_H
+#define MAC_ADDRESS_FACTORY_H
+
+#include "mac-address.h"
+
+namespace yans {
+
+class MacAddressFactory {
+public:
+	MacAddressFactory ();
+	MacAddress get_next (void);
+private:
+	uint8_t m_addr[6];
+	uint8_t m_cur;
+	uint8_t m_index;
+};
+
+}; // namespace yans
+
+#endif /* MAC_ADDRESS_FACTORY_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/mac-address.cc	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,187 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2005 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#include "mac-address.h"
+#include "utils.h"
+
+namespace yans {
+
+MacAddress::MacAddress ()
+{
+	m_address[0] = 0;
+	m_address[1] = 0;
+	m_address[2] = 0;
+	m_address[3] = 0;
+	m_address[4] = 0;
+	m_address[5] = 0;
+}
+
+MacAddress::MacAddress (uint8_t const address[6])
+{
+	m_address[0] = address[0];
+	m_address[1] = address[1];
+	m_address[2] = address[2];
+	m_address[3] = address[3];
+	m_address[4] = address[4];
+	m_address[5] = address[5];
+}
+MacAddress::MacAddress (char const *address)
+{
+	ascii_to_mac_network (address, m_address);
+}
+MacAddress::MacAddress (uint32_t ip_multicast_address)
+{
+	m_address[0] = 1 | ((ip_multicast_address & 0x7f) << 1);
+	m_address[1] = (ip_multicast_address >> 7) & 0xff;
+	m_address[2] = (ip_multicast_address >> 16) & 0xff;
+	m_address[3] = 0x5e;
+	m_address[4] = 0;
+	m_address[5] = 0;
+}
+MacAddress::~MacAddress ()
+{}
+
+bool 
+MacAddress::is_equal (MacAddress other) const
+{
+	if (m_address[0] == other.m_address[0] &&
+	    m_address[1] == other.m_address[1] &&
+	    m_address[2] == other.m_address[2] &&
+	    m_address[3] == other.m_address[3] &&
+	    m_address[4] == other.m_address[4] &&
+	    m_address[5] == other.m_address[5]) {
+		return true;
+	} else {
+		return false;
+	}
+}
+bool 
+MacAddress::is_broadcast (void) const
+{
+	if (m_address[0] == 0xff &&
+	    m_address[1] == 0xff &&
+	    m_address[2] == 0xff &&
+	    m_address[3] == 0xff &&
+	    m_address[4] == 0xff &&
+	    m_address[5] == 0xff) {
+		return true;
+	} else {
+		return false;
+	}
+}
+bool 
+MacAddress::is_multicast (void) const
+{
+	if (m_address[0] & 0x1) {
+		return true;
+	} else {
+		return false;
+	}
+}
+bool 
+MacAddress::is_multicast_equal (MacAddress other) const
+{
+	if (get_multicast_part () == other.get_multicast_part ()) {
+		return true;
+	} else {
+		return false;
+	}
+}
+
+uint32_t
+MacAddress::get_multicast_part (void) const
+{
+	uint32_t part = 0;
+	part |= m_address[0] >> 1;
+	part |= m_address[1] << 7;
+	part |= (m_address[1] << 15);
+	return part;
+}
+
+
+void
+MacAddress::peek (uint8_t ad[6]) const
+{
+	memcpy (ad, m_address, 6);
+}
+void
+MacAddress::set (uint8_t const ad[6])
+{
+	memcpy (m_address, ad, 6);
+}
+
+void
+MacAddress::print (std::ostream *os) const
+{
+	os->setf (std::ios::hex, std::ios::basefield);
+	*os << (uint32_t)m_address[0] << ":"
+	    << (uint32_t)m_address[1] << ":"
+	    << (uint32_t)m_address[2] << ":"
+	    << (uint32_t)m_address[3] << ":"
+	    << (uint32_t)m_address[4] << ":"
+	    << (uint32_t)m_address[5];
+	os->setf (std::ios::dec, std::ios::basefield);
+}
+
+
+
+
+MacAddress
+MacAddress::get_broadcast (void)
+{
+	static MacAddress broadcast = MacAddress ("ff:ff:ff:ff:ff:ff");
+	return broadcast;
+}
+
+bool operator == (MacAddress const&a, MacAddress const&b)
+{
+	return a.is_equal (b);
+}
+
+bool operator != (MacAddress const&a, MacAddress const&b)
+{
+	return !a.is_equal (b);
+}
+
+bool operator < (MacAddress const&a, MacAddress const&b)
+{
+	uint8_t a_p[6];
+	uint8_t b_p[6];
+	a.peek (a_p);
+	b.peek (b_p);
+	for (uint8_t i = 0; i < 6; i++) {
+		if (a_p[i] < b_p[i]) {
+			return true;
+		} else if (a_p[i] > b_p[i]) {
+			return false;
+		}
+	}
+	return false;
+}
+
+std::ostream& operator<< (std::ostream& os, MacAddress const& address)
+{
+	address.print (&os);
+	return os;
+}
+
+
+}; // namespace yans
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/mac-address.h	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,72 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2005 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#ifndef MAC_ADDRESS_H
+#define MAC_ADDRESS_H
+
+#include <stdint.h>
+#include <ostream>
+
+namespace yans {
+
+class MacAddress {
+public:
+	MacAddress (void);
+	/* low byte should be first.
+	 */
+	MacAddress (uint8_t const address[6]);
+	/* The string should look like this:
+	 * hh-xx-xx-xx-xx-ll
+	 * where hh is the high byte and ll is
+	 * the low byte.
+	 */
+	MacAddress (char const *address);
+	/* create the mac address associated to 
+	 * this multicast ip address. 
+	 */
+	MacAddress (uint32_t multicast_ip_address);
+	~MacAddress ();
+
+	bool is_equal (MacAddress other) const;
+	bool is_broadcast (void) const;
+	bool is_multicast (void) const;
+	bool is_multicast_equal (MacAddress other) const;
+
+	void print (std::ostream *os) const;
+
+	void peek (uint8_t ad[6]) const;
+	void set (uint8_t const ad[6]);
+
+	static MacAddress get_broadcast (void);
+private:
+	uint32_t get_multicast_part (void) const;
+	uint8_t m_address[6];
+};
+
+bool operator == (MacAddress const&a, MacAddress const&b);
+bool operator != (MacAddress const&a, MacAddress const&b);
+bool operator < (MacAddress const&a, MacAddress const&b);
+
+std::ostream& operator<< (std::ostream& os, MacAddress const& address);
+
+}; // namespace yans
+
+#endif /* MAC_ADDRESS_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/mac-network-interface.cc	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,96 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2006 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#include "mac-network-interface.h"
+
+namespace yans {
+
+MacNetworkInterface::MacNetworkInterface (MacAddress self, uint16_t max_mtu)
+	: m_self (self), m_max_mtu (max_mtu), m_mtu (max_mtu)
+{}
+MacNetworkInterface::~MacNetworkInterface ()
+{}
+
+MacAddress 
+MacNetworkInterface::get_mac_address (void) const
+{
+	return m_self;
+}
+void
+MacNetworkInterface::set_mtu (uint16_t mtu)
+{
+	if (mtu > m_max_mtu ) {
+		m_mtu = m_max_mtu;
+	} else {
+		m_mtu = mtu;
+	}
+}
+uint16_t 
+MacNetworkInterface::get_mtu (void) const
+{
+	return m_mtu;
+}
+bool 
+MacNetworkInterface::is_down (void) const
+{
+	return m_is_down;
+}
+void 
+MacNetworkInterface::set_up   (void)
+{
+	m_is_down = false;
+	notify_up ();
+}
+void 
+MacNetworkInterface::set_down (void)
+{
+	m_is_down = true;
+	notify_down ();
+}
+
+void 
+MacNetworkInterface::set_status_change_callback (StatusChangeCallback callback)
+{
+	m_status_change_callback = callback;
+}
+
+void 
+MacNetworkInterface::set_rx_callback (RxCallback callback)
+{
+	m_rx_callback = callback;
+}
+void 
+MacNetworkInterface::send (Packet packet, MacAddress to)
+{
+	real_send (packet, to);
+}
+void 
+MacNetworkInterface::forward_up (Packet packet)
+{
+	m_rx_callback (packet, this);
+}
+
+void 
+MacNetworkInterface::notify_status_change (void)
+{
+	m_status_change_callback (this);
+}
+
+}; // namespace yans
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/mac-network-interface.h	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,68 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2006 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#ifndef MAC_NETWORK_INTERFACE_H
+#define MAC_NETWORK_INTERFACE_H
+
+#include <stdint.h>
+#include "yans/callback.h"
+#include "mac-address.h"
+#include "packet.h"
+
+namespace yans {
+
+class MacNetworkInterface {
+public:
+	typedef Callback<void, Packet , MacNetworkInterface *> RxCallback;
+	typedef Callback<void,MacNetworkInterface *> StatusChangeCallback; 
+
+	MacNetworkInterface (MacAddress self, uint16_t max_mtu);
+	virtual ~MacNetworkInterface () = 0;
+
+	MacAddress get_mac_address (void) const;
+	void set_mtu (uint16_t mtu);
+	uint16_t get_mtu (void) const;
+
+	bool is_down (void) const;
+	void set_up   (void);
+	void set_down (void);
+
+	void set_status_change_callback (StatusChangeCallback callback);
+	void set_rx_callback (RxCallback callback);
+	void send (Packet packet, MacAddress to);
+protected:
+	void forward_up (Packet packet);
+	void notify_status_change (void);
+private:
+	virtual void notify_up (void) = 0;
+	virtual void notify_down (void) = 0;
+	virtual void real_send (Packet packet, MacAddress to) = 0;
+
+	StatusChangeCallback m_status_change_callback;
+	RxCallback m_rx_callback;
+	MacAddress m_self;
+	uint16_t m_max_mtu;
+	uint16_t m_mtu;
+	bool m_is_down;
+};
+
+}; // namespace yans
+
+#endif /* MAC_NETWORK_INTERFACE_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/packet-logger.cc	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,42 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2006 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#include "packet-logger.h"
+
+namespace yans {
+
+PacketLogger::PacketLogger ()
+{}
+void 
+PacketLogger::log (Packet const packet)
+{
+	if (!m_callback.is_null ()) {
+		m_callback (packet);
+	}
+}
+void 
+PacketLogger::set_callback (PacketLoggerCallback callback)
+{
+	m_callback = callback;
+}
+
+}; // namespace yans
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/packet-logger.h	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,53 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2006 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#ifndef PACKET_LOGGER_H
+#define PACKET_LOGGER_H
+
+#include "yans/callback.h"
+#include "packet.h"
+
+namespace yans {
+
+/**
+ * \brief log packets
+ */
+class PacketLogger {
+public:
+	typedef Callback<void,Packet const> PacketLoggerCallback;
+	PacketLogger ();
+	/**
+	 * \param packet to log
+	 * If a non-null callback was set, the packet
+	 * is forwarded to that callback.
+	 */
+	void log (Packet const packet);
+	/**
+	 * \param callback callback to store
+	 */
+	void set_callback (PacketLoggerCallback callback);
+private:
+	PacketLoggerCallback m_callback;
+};
+
+}; // namespace yans
+
+#endif /* PACKET_LOGGER_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/packet.cc	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,127 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2005,2006 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#include "packet.h"
+#include <cassert>
+
+namespace yans {
+
+Packet::Packet ()
+	: m_buffer () {}
+
+Packet::Packet (uint32_t size)
+	: m_buffer (size)
+{}
+Packet::Packet (Buffer buffer, Tags tags)
+	: m_buffer (buffer),
+	  m_tags (tags)
+{}
+
+
+Packet 
+Packet::create_fragment (uint32_t start, uint32_t length) const
+{
+	Buffer tmp = m_buffer.create_fragment (start, length);
+	return Packet (tmp, m_tags);
+}
+
+uint32_t 
+Packet::get_size (void) const
+{
+	return m_buffer.get_size ();
+}
+
+void 
+Packet::add (Chunk *chunk)
+{
+	chunk->add (&m_buffer);
+}
+
+void 
+Packet::peek (Chunk *chunk) const
+{
+	chunk->peek (&m_buffer);
+}
+
+void 
+Packet::remove (Chunk *chunk)
+{
+	chunk->remove (&m_buffer);
+}
+
+
+void 
+Packet::write (PacketReadWriteCallback callback) const
+{
+	uint8_t *data = m_buffer.peek_data ();
+	uint32_t to_write = get_size ();
+	callback (data, to_write);
+}
+
+
+void 
+Packet::add_at_end (Packet packet)
+{
+	Buffer src = packet.m_buffer;
+	m_buffer.add_at_end (src.get_size ());
+	Buffer::Iterator dest_start = m_buffer.end ();
+	dest_start.prev (src.get_size ());
+	dest_start.write (src.begin (), src.end ());
+	/**
+	 * XXX: we might need to merge the tag list of the
+	 * other packet into the current packet.
+	 */
+}
+void 
+Packet::add_at_end (Packet packet, uint32_t start, uint32_t size)
+{
+	assert (packet.get_size () <= start + size);
+	Buffer src = packet.m_buffer;
+	m_buffer.add_at_end (src.get_size ());
+	Buffer::Iterator dest_start = m_buffer.end ();
+	dest_start.prev (size);
+	Buffer::Iterator src_start = src.begin ();
+	src_start.next (start);
+	Buffer::Iterator src_end = src_start;
+	src_end.next (size);
+	dest_start.write (src_start, src_end);
+	/**
+	 * XXX: we might need to merge the tag list of the
+	 * other packet into the current packet.
+	 */
+}
+void 
+Packet::remove_at_end (uint32_t size)
+{
+	m_buffer.remove_at_end (size);
+}
+void 
+Packet::remove_at_start (uint32_t size)
+{
+	m_buffer.remove_at_start (size);
+}
+
+void 
+Packet::remove_all_tags (void)
+{
+	m_tags.remove_all ();
+}
+
+}; // namespace yans
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/packet.h	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,90 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2005,2006 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#ifndef PACKET_H
+#define PACKET_H
+
+#include <stdint.h>
+#include "buffer.h"
+#include "chunk.h"
+#include "tags.h"
+#include "yans/callback.h"
+
+namespace yans {
+
+class Packet {
+public:
+	typedef Callback<void,uint8_t *,uint32_t> PacketReadWriteCallback;
+	Packet ();
+	Packet (uint32_t size);
+	Packet create_fragment (uint32_t start, uint32_t length) const;
+	uint32_t get_size (void) const;
+	void add (Chunk *chunk);
+	void peek (Chunk *chunk) const;
+	void remove (Chunk *chunk);
+	template <typename T>
+	void add_tag (T const *tag);
+	template <typename T>
+	bool remove_tag (T *tag);
+	template <typename T>
+	bool peek_tag (T *tag) const;
+	template <typename T>
+	bool update_tag (T const*tag);
+	void remove_all_tags (void);
+	void write (PacketReadWriteCallback callback) const;
+	void add_at_end (Packet packet);
+	void add_at_end (Packet packet, uint32_t offset, uint32_t size);
+	void remove_at_end (uint32_t size);
+	void remove_at_start (uint32_t size);
+
+private:
+	Packet (Buffer buffer, Tags tags);
+	Buffer m_buffer;
+	Tags m_tags;
+};
+
+}; // namespace yans
+
+namespace yans {
+
+template <typename T>
+void Packet::add_tag (T const*tag)
+{
+	m_tags.add (tag);
+}
+template <typename T>
+bool Packet::remove_tag (T *tag)
+{
+	return m_tags.remove (tag);
+}
+template <typename T>
+bool Packet::peek_tag (T *tag) const
+{
+	return m_tags.peek (tag);
+}
+template <typename T>
+bool Packet::update_tag (T const*tag)
+{
+	return m_tags.update (tag);
+}
+
+}; // namespace yans
+
+#endif /* PACKET_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/pcap-writer.cc	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,99 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2005,2006 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+/*
+ * Documentation kindly pointed out by Tom Henderson:
+ * http://wiki.ethereal.com/Development/LibpcapFileFormat
+ */
+
+#include "yans/simulator.h"
+#include "yans/system-file.h"
+#include "pcap-writer.h"
+#include "packet.h"
+
+
+namespace yans {
+
+enum {
+	PCAP_ETHERNET = 1
+};
+
+PcapWriter::PcapWriter ()
+{
+	m_writer = 0;
+	m_write_callback = make_callback (&PcapWriter::write_data, this);
+}
+PcapWriter::~PcapWriter ()
+{
+	delete m_writer;
+}
+
+void
+PcapWriter::open (char const *name)
+{
+	m_writer = new SystemFile ();
+	m_writer->open (name);
+}
+
+void 
+PcapWriter::write_header_ethernet (void)
+{
+	write_32 (0xa1b2c3d4);
+	write_16 (2);
+	write_16 (4);
+	write_32 (0);
+	write_32 (0);
+	write_32 (0xffff);
+	write_32 (PCAP_ETHERNET);
+}
+
+void 
+PcapWriter::write_packet (Packet const packet)
+{
+	if (m_writer != 0) {
+		uint64_t current = Simulator::now_us ();
+		uint64_t s = current / 1000000;
+		uint64_t us = current % 1000000;
+		write_32 (s & 0xffffffff);
+		write_32 (us & 0xffffffff);
+		write_32 (packet.get_size ());
+		write_32 (packet.get_size ());
+		packet.write (m_write_callback);
+	}
+}
+
+void
+PcapWriter::write_data (uint8_t *buffer, uint32_t size)
+{
+	m_writer->write (buffer, size);
+}
+void
+PcapWriter::write_32 (uint32_t data)
+{
+	m_writer->write ((uint8_t*)&data, 4);
+}
+void
+PcapWriter::write_16 (uint16_t data)
+{
+	m_writer->write ((uint8_t*)&data, 2);
+}
+
+}; // namespace yans
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/pcap-writer.h	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,73 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2005,2006 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#ifndef PCAP_WRITER_H
+#define PCAP_WRITER_H
+
+#include "yans/callback.h"
+#include <stdint.h>
+#include "packet.h"
+
+namespace yans {
+
+class SystemFile;
+
+/**
+ * \brief Pcap output for Packet logger
+ *
+ * Log Packets to a file in pcap format which can be
+ * read by pcap readers.
+ */
+class PcapWriter {
+public:
+	PcapWriter ();
+	~PcapWriter ();
+
+	/**
+	 * \param name the name of the file to store packet log into.
+	 * This method creates the file if it does not exist. If it
+	 * exists, the file is emptied.
+	 */
+	void open (char const *name);
+
+	/**
+	 * Write a pcap header in the output file which specifies
+	 * that the content of the file will Packets with
+	 * Ethernet/LLC/SNAP encapsulation.
+	 */
+	void write_header_ethernet (void);
+
+	/**
+	 * \param packet packet to write to output file
+	 */
+	void write_packet (Packet const packet);
+
+private:
+	void write_data (uint8_t *buffer, uint32_t size);
+	void write_32 (uint32_t data);
+	void write_16 (uint16_t data);
+	SystemFile *m_writer;
+	Callback<void,uint8_t *,uint32_t> m_write_callback;
+};
+
+}; // namespace yans
+
+#endif /* PCAP_WRITER_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/population-analysis.cc	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,94 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2005 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#include <cassert>
+#include <math.h>
+
+#include "population-analysis.h"
+
+/* This code is a C++ translation of Java code released under the GPLv2
+   copyright Mathieu Lacage in treegrowth-stable:
+   http://cutebugs.net/code/treegrowth-stable.
+ */
+
+namespace yans {
+
+PopulationAnalysis::PopulationAnalysis ()
+{
+	reset ();
+}
+PopulationAnalysis::~PopulationAnalysis ()
+{}
+
+void 
+PopulationAnalysis::reset (void)
+{
+	m_n = 0;
+	m_square_sum = 0.0;
+	m_mean = 0.0;
+	m_sum = 0.0;
+}
+
+void 
+PopulationAnalysis::add_term (double term)
+{
+	double d = (term - m_mean);
+        m_n++;
+        m_mean += d / m_n;
+        m_square_sum += d * (term - m_mean);
+	m_sum += term;
+}
+
+uint32_t
+PopulationAnalysis::get_n (void)
+{
+	return m_n;
+}
+double 
+PopulationAnalysis::get_total (void)
+{
+	return m_sum;
+}
+double 
+PopulationAnalysis::get_mean (void)
+{
+	return m_mean;
+}
+double 
+PopulationAnalysis::get_standard_deviation (void)
+{
+	if (m_n == 0) {
+		return 0.0;
+	}
+	assert (get_unbiased_variance () >= 0);
+        double deviation = sqrt (get_unbiased_variance ());
+        return deviation;
+}
+double 
+PopulationAnalysis::get_unbiased_variance (void)
+{
+        if (m_n == 1 || m_n == 0) {
+		return 0.0;
+        }
+        return m_square_sum / (m_n - 1);
+}
+
+}; // namespace yans
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/population-analysis.h	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,55 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2005 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+
+#ifndef POPULATION_ANALYSIS_H
+#define POPULATION_ANALYSIS_H
+
+#include <stdint.h>
+
+namespace yans {
+
+class PopulationAnalysis {
+public:
+	PopulationAnalysis ();
+	~PopulationAnalysis ();
+
+	void reset (void);
+
+	void add_term (double term);
+
+	uint32_t get_n (void);
+	double get_total (void);
+	double get_mean (void);
+	double get_standard_deviation (void);
+	double get_unbiased_variance (void);
+
+private:
+	double m_mean;
+	double m_square_sum;
+	double m_sum;
+	uint32_t m_n;
+};
+
+}; // namespace yans
+
+
+#endif /* POPULATION_ANALYSIS_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/position.cc	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,47 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2006 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#include "position.h"
+#include <math.h>
+
+namespace yans {
+
+Position::~Position ()
+{}
+
+void
+Position::get (double &x, double &y, double &z) const
+{
+	real_get (x,y,z);
+}
+double 
+Position::get_distance_from (Position const*position) const
+{
+	double ox,oy,oz;
+	double x,y,z;
+	position->real_get (ox,oy,oz);
+	real_get (x,y,z);
+	double dx = ox - x;
+	double dy = oy - y;
+	double dz = oz - z;
+	return sqrt (dx*dx+dy*dy+dz*dz);
+}
+
+}; // namespace yans
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/position.h	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,38 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2006 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#ifndef POSITION_H
+#define POSITION_H
+
+namespace yans {
+
+class Position {
+public:
+	virtual ~Position () = 0;
+
+	void get (double &x, double &y, double &z) const;
+	double get_distance_from (Position const*position) const;
+private:
+	virtual void real_get (double &x, double &y, double &z) const = 0;
+};
+
+}; // namespace yans
+
+#endif /* POSITION_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/random-uniform-mrg32k3a.cc	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,137 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2006 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#include "random-uniform.h"
+#include "seed-generator.h"
+#include "rng-mrg32k3a.h"
+
+namespace yans {
+
+class RandomUniformPrivate {
+public:
+	RandomUniformPrivate ();
+	~RandomUniformPrivate ();
+
+	void reset (uint32_t seed);
+
+	uint32_t get_max (void) const;
+	uint32_t get_min (void) const;
+
+	uint32_t get_uint (void);
+	uint32_t get_uint (uint32_t n);
+	uint32_t get_uint (uint32_t a, uint32_t b);
+	double get_double (void);
+private:
+	RngMrg32k3a m_rng;
+};
+
+RandomUniformPrivate::RandomUniformPrivate ()
+	: m_rng ()
+{
+	m_rng.reset (SeedGenerator::get ());
+}
+RandomUniformPrivate::~RandomUniformPrivate ()
+{}
+
+void 
+RandomUniformPrivate::reset (uint32_t seed)
+{
+	m_rng.reset (seed);
+}
+uint32_t 
+RandomUniformPrivate::get_max (void) const
+{
+	return m_rng.get_max ();
+}
+uint32_t 
+RandomUniformPrivate::get_min (void) const
+{
+	return m_rng.get_min ();
+}
+uint32_t 
+RandomUniformPrivate::get_uint (void)
+{
+	return m_rng.get_uint ();
+}
+uint32_t 
+RandomUniformPrivate::get_uint (uint32_t n)
+{
+	return m_rng.get_uint (n);
+}
+uint32_t 
+RandomUniformPrivate::get_uint (uint32_t a, uint32_t b)
+{
+	return m_rng.get_uint (a, b);
+}
+double
+RandomUniformPrivate::get_double (void)
+{
+	return m_rng.get_double ();
+}
+
+
+
+RandomUniform::RandomUniform ()
+	: m_priv (new RandomUniformPrivate ())
+{}
+RandomUniform::~RandomUniform ()
+{
+	delete m_priv;
+	m_priv = reinterpret_cast<RandomUniformPrivate *> (0xdeadbeaf);
+}
+
+void 
+RandomUniform::reset (uint32_t seed)
+{
+	m_priv->reset (seed);
+}
+uint32_t 
+RandomUniform::get_max (void) const
+{
+	return m_priv->get_max ();
+}
+uint32_t 
+RandomUniform::get_min (void) const
+{
+	return m_priv->get_min ();
+}
+uint32_t 
+RandomUniform::get_uint (void)
+{
+	return m_priv->get_uint ();
+}
+uint32_t 
+RandomUniform::get_uint (uint32_t n)
+{
+	return m_priv->get_uint (n);
+}
+uint32_t 
+RandomUniform::get_uint (uint32_t a, uint32_t b)
+{
+	return m_priv->get_uint (a, b);
+}
+double 
+RandomUniform::get_double (void)
+{
+	return m_priv->get_double ();
+}
+
+}; // namespace yans
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/random-uniform.h	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,57 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2006 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#ifndef RANDOM_UNIFORM_H
+#define RANDOM_UNIFORM_H
+
+#include <stdint.h>
+
+namespace yans {
+
+class RandomUniformPrivate;
+
+class RandomUniform {
+public:
+	RandomUniform ();
+	~RandomUniform ();
+
+	void reset (uint32_t seed);
+
+	uint32_t get_max (void) const;
+	uint32_t get_min (void) const;
+
+	/* return an integer in the range [min,max] */
+	uint32_t get_uint (void);
+	/* return an integer in the range [0,n] */
+	uint32_t get_uint (uint32_t n);
+	/* return an integer in the range [a,b] */
+	uint32_t get_uint (uint32_t a, uint32_t b);
+	/* return a floating-point number in the 
+	 * range [0,1)
+	 */
+	double get_double (void);
+private:
+	RandomUniformPrivate *m_priv;
+};
+
+}; // namespace yans
+
+
+#endif /* RANDOM_UNIFORM_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/ref-ptr.h	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,139 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2005,2006 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#ifndef REF_PTR_H
+#define REF_PTR_H
+
+namespace yans {
+
+template <typename T>
+class RefPtr {
+private:
+	T *m_env;
+public:
+	RefPtr () 
+		: m_env (0) 
+	{}
+
+	RefPtr (T *env) 
+		: m_env (env) 
+	{}
+	RefPtr (RefPtr const&o) 
+		: m_env (o.m_env)
+	{
+		if (m_env != 0) {
+			m_env->m_count++;
+		}
+	}
+	// allow conversions from T to T const.
+	template <typename U>
+	RefPtr (RefPtr<U> const &o)
+		: m_env (o.peek ())
+	{
+		if (m_env != 0) {
+			m_env->m_count++;
+		}
+	}
+	~RefPtr () 
+	{
+		if (m_env != 0) {
+			m_env->m_count--;
+			if (m_env->m_count == 0) {
+				m_env->destroy ();
+			}
+		}
+	}
+	RefPtr &operator = (RefPtr const& o) 
+	{
+		if (o.m_env != 0) {
+			o.m_env->m_count++;
+		}
+		if (m_env != 0) {
+			m_env->m_count--;
+			if (m_env->m_count == 0) {
+				m_env->destroy ();
+			}
+		}
+		m_env = o.m_env;
+		return *this;
+	}
+	T *operator -> () 
+	{
+		return m_env;
+	}
+	T *operator -> () const
+	{
+		return m_env;
+	}
+	// allow if (!sp)
+	bool operator! () 
+	{
+		return m_env == 0;
+	}
+private:
+	class Tester {
+	private:
+		void operator delete (void *);
+	};
+public:
+	// allow if (sp)
+	operator Tester * () const
+	{
+		if (m_env == 0) {
+			return 0;
+		}
+		static Tester test;
+		return &test;
+	}
+	// allow if (sp == 0)
+	inline friend bool operator == (RefPtr const &lhs, T const *rhs)
+	{
+		return lhs.m_env == rhs;
+	}
+	// allow if (0 == sp)
+	inline friend bool operator == (T const *lhs, RefPtr &rhs)
+	{
+		return lhs == rhs.m_env;
+	}
+	// allow if (sp != 0)
+	inline friend bool operator != (RefPtr const &lhs, T const *rhs)
+	{
+		return lhs.m_env != rhs;
+	}
+	// allow if (0 != sp)
+	inline friend bool operator != (T const *lhs, RefPtr &rhs)
+	{
+		return lhs != rhs.m_env;
+	}
+	
+	T *peek (void) 
+	{
+		return m_env;
+	}
+	T *peek (void) const
+	{
+		return m_env;
+	}
+};
+
+}; // namespace yans
+
+#endif /* REF_PTR_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/rng-mrg32k3a.cc	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,336 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ *  Copyright (C) 2001  Pierre L'Ecuyer (lecuyer@iro.umontreal.ca)
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ *  02110-1301 USA
+ */
+
+#include "rng-mrg32k3a.h"
+#include "seed-generator.h"
+#include <iostream>
+
+#ifndef MAXINT
+#define	MAXINT	2147483647	// XX [for now]
+#endif
+
+
+using namespace std; 
+namespace 
+{ 
+	const double m1 = 4294967087.0; 
+	const double m2 = 4294944443.0; 
+	const double norm = 1.0 / (m1 + 1.0); 
+	const double a12 = 1403580.0; 
+	const double a13n = 810728.0; 
+	const double a21 = 527612.0; 
+	const double a23n = 1370589.0; 
+	const double two17 = 131072.0; 
+	const double two53 = 9007199254740992.0; 
+	const double fact = 5.9604644775390625e-8; /* 1 / 2^24 */ 
+
+	// The following are the transition matrices of the two MRG 
+	// components (in matrix form), raised to the powers -1, 1, 
+	// 2^76, and 2^127, resp. 
+
+	const double InvA1[3][3] = { // Inverse of A1p0 
+		{ 184888585.0, 0.0, 1945170933.0 }, 
+		{ 1.0, 0.0, 0.0 }, 
+		{ 0.0, 1.0, 0.0 } 
+	}; 
+
+	const double InvA2[3][3] = { // Inverse of A2p0 
+		{ 0.0, 360363334.0, 4225571728.0 }, 
+		{ 1.0, 0.0, 0.0 }, 
+		{ 0.0, 1.0, 0.0 } 
+	}; 
+
+	const double A1p0[3][3] = { 
+		{ 0.0, 1.0, 0.0 }, 
+		{ 0.0, 0.0, 1.0 }, 
+		{ -810728.0, 1403580.0, 0.0 } 
+	}; 
+
+	const double A2p0[3][3] = { 
+		{ 0.0, 1.0, 0.0 }, 
+		{ 0.0, 0.0, 1.0 }, 
+		{ -1370589.0, 0.0, 527612.0 } 
+	}; 
+
+	const double A1p76[3][3] = { 
+		{ 82758667.0, 1871391091.0, 4127413238.0 }, 
+		{ 3672831523.0, 69195019.0, 1871391091.0 }, 
+		{ 3672091415.0, 3528743235.0, 69195019.0 } 
+	}; 
+
+	const double A2p76[3][3] = { 
+		{ 1511326704.0, 3759209742.0, 1610795712.0 }, 
+		{ 4292754251.0, 1511326704.0, 3889917532.0 }, 
+		{ 3859662829.0, 4292754251.0, 3708466080.0 } 
+	}; 
+
+	const double A1p127[3][3] = { 
+		{ 2427906178.0, 3580155704.0, 949770784.0 }, 
+		{ 226153695.0, 1230515664.0, 3580155704.0 }, 
+		{ 1988835001.0, 986791581.0, 1230515664.0 } 
+	}; 
+
+	const double A2p127[3][3] = { 
+		{ 1464411153.0, 277697599.0, 1610723613.0 }, 
+		{ 32183930.0, 1464411153.0, 1022607788.0 }, 
+		{ 2824425944.0, 32183930.0, 2093834863.0 } 
+	}; 
+
+} // end of anonymous namespace 
+
+//------------------------------------------------------------------- 
+// Return (a*s + c) MOD m; a, s, c and m must be < 2^35 
+// 
+
+double 
+RngMrg32k3a::MultModM (double a, double s, double c, double m) 
+{ 
+	double v; 
+	long a1; 
+	v=a*s+c; 
+	
+	if (v >= two53 || v <= -two53) { 
+		a1 = static_cast<long> (a / two17); a -= a1 * two17; 
+		v =a1*s; 
+		a1 = static_cast<long> (v / m); v -= a1 * m; 
+		v = v * two17 + a * s + c; 
+	} 
+	a1 = static_cast<long> (v / m); 
+	/* in case v < 0)*/ 
+	if ((v -= a1 * m) < 0.0) return v += m; else return v; 
+} 
+
+//------------------------------------------------------------------- 
+// Compute the vector v = A*s MOD m. Assume that -m < s[i] < m. 
+// Works also when v = s. 
+// 
+void
+RngMrg32k3a::MatVecModM (const double A[3][3], const double s[3], double v[3], 
+			 double m) 
+{ 
+	int i; 
+	double x[3]; // Necessary if v = s 
+	for (i = 0; i < 3; ++i) { 
+		x[i] = MultModM (A[i][0], s[0], 0.0, m); 
+		x[i] = MultModM (A[i][1], s[1], x[i], m); 
+		x[i] = MultModM (A[i][2], s[2], x[i], m); 
+	} 
+	for (i = 0; i < 3; ++i) 
+		v[i] = x[i]; 
+} 
+
+//------------------------------------------------------------------- 
+// Compute the matrix C = A*B MOD m. Assume that -m < s[i] < m. 
+// Note: works also if A = C or B = C or A = B = C. 
+// 
+void 
+RngMrg32k3a::MatMatModM (const double A[3][3], const double B[3][3], 
+			 double C[3][3], double m) 
+{ 
+	int i, j; 
+	double V[3], W[3][3]; 
+	for (i = 0; i < 3; ++i) { 
+		for (j = 0; j < 3; ++j) 
+			V[j] = B[j][i]; 
+		MatVecModM (A, V, V, m); 
+		for (j = 0; j < 3; ++j) 
+			
+			W[j][i] = V[j]; 
+		} 
+	for (i = 0; i < 3; ++i) 
+		for (j = 0; j < 3; ++j) 
+			C[i][j] = W[i][j]; 
+} 
+
+//------------------------------------------------------------------- 
+// Compute the matrix B = (A^(2^e) Mod m); works also if A = B. 
+// 
+void 
+RngMrg32k3a::MatTwoPowModM (const double A[3][3], double B[3][3], double m, 
+			    long e) 
+{ 
+	int i, j; 
+	/* initialize: B = A */ 
+	if (A != B) { 
+		for (i = 0; i < 3; ++i) 
+			for (j = 0; j < 3; ++j) 
+				B[i][j] = A[i][j]; 
+	} 
+	/* Compute B = A^(2^e) mod m */ 
+	for (i = 0; i < e; i++) 
+		MatMatModM (B, B, B, m); 
+} 
+
+//------------------------------------------------------------------- 
+// Compute the matrix B = (A^n Mod m); works even if A = B. 
+// 
+void 
+RngMrg32k3a::MatPowModM (const double A[3][3], double B[3][3], double m, 
+			 long n) 
+{ 
+	int i, j; 
+	double W[3][3]; 
+	/* initialize: W = A; B = I */ 
+	for (i = 0; i < 3; ++i) 
+		for (j = 0; j < 3; ++j) { 
+			W[i][j] = A[i][j]; 
+			B[i][j] = 0.0; 
+		} 
+	for (j = 0; j < 3; ++j) 
+		B[j][j] = 1.0; 
+	/* Compute B = A^n mod m using the binary decomposition of n */
+	while (n > 0) { 
+		if (n % 2) MatMatModM (W, B, B, m); 
+		MatMatModM (W, W, W, m); 
+		
+		n/=2; 
+	} 
+} 
+
+//-------------------------------------------------------------------- 
+// Check that the seeds are legitimate values. Returns 0 if legal 
+// seeds, -1 otherwise. 
+// 
+int 
+RngMrg32k3a::CheckSeed (const unsigned long seed[6]) 
+{ 
+	int i; 
+	for (i = 0; i < 3; ++i) { 
+		if (seed[i] >= m1) { 
+			std::cerr << "****************************************" << std::endl
+				  << "ERROR: Seed["<<i<<"] >= 4294967087, Seed is not set." << std::endl
+				  << "****************************************" << std::endl;
+			return (-1); 
+		} 
+	} 
+	for (i = 3; i < 6; ++i) { 
+		if (seed[i] >= m2) { 
+			std::cerr << "****************************************" << std::endl
+				  << "ERROR: Seed["<<i<<"] >= 429444443, Seed is not set."<<std::endl
+				  << "****************************************" <<std::endl;
+			return (-1); 
+		} 
+	} 
+	if (seed[0] == 0 && seed[1] == 0 && seed[2] == 0) { 
+		std::cerr<< "****************************************" << std::endl
+			 << "ERROR: First 3 seeds = 0." << std::endl 
+			 << "****************************************" << std::endl;
+		return (-1); 
+	} 
+	if (seed[3] == 0 && seed[4] == 0 && seed[5] == 0) { 
+		std::cerr << "****************************************" <<std::endl
+			  << "ERROR: Last 3 seeds = 0." << std::endl
+			  << "****************************************" << std::endl;
+		return (-1); 
+	} 
+	return 0; 
+} 
+
+
+//------------------------------------------------------------------------- 
+// Generate the next random number. 
+// 
+double RngMrg32k3a::U01 () 
+{ 
+	long k; 
+	double p1, p2, u; 
+	/* Component 1 */ 
+	p1 = a12 * Cg_[1] - a13n * Cg_[0]; 
+	k = static_cast<long> (p1 / m1); 
+	p1 -= k * m1; 
+	if (p1 < 0.0) p1 += m1; 
+	Cg_[0] = Cg_[1]; Cg_[1] = Cg_[2]; Cg_[2] = p1; 
+	/* Component 2 */ 
+	p2 = a21 * Cg_[5] - a23n * Cg_[3]; 
+	k = static_cast<long> (p2 / m2); 
+	p2 -= k * m2; 
+	if (p2 < 0.0) p2 += m2; 
+	Cg_[3] = Cg_[4]; Cg_[4] = Cg_[5]; Cg_[5] = p2; 
+	/* Combination */ 
+	u = ((p1 > p2) ? (p1 - p2) * norm : (p1 - p2 + m1) * norm); 
+	return u;
+} 
+
+//------------------------------------------------------------------------- 
+// Generate the next random number with extended (53 bits) precision. 
+// 
+double RngMrg32k3a::U01d () 
+{ 
+	double u; 
+	u = U01(); 
+	u += (U01() - 1.0) * fact; 
+	return (u < 0.0) ? u + 1.0 : u; 
+} 
+
+//************************************************************************* 
+// Public members of the class start here 
+//------------------------------------------------------------------------- 
+
+RngMrg32k3a::RngMrg32k3a ()
+{}
+
+void RngMrg32k3a::reset (long seed) 
+{
+	for (int i = 0; i < 6; ++i) { 
+		Bg_[i] = Cg_[i] = Ig_[i] = seed; 
+	} 
+}
+
+
+//------------------------------------------------------------------------- 
+// Generate the next random number. 
+// 
+
+uint32_t 
+RngMrg32k3a::get_max (void) const
+{
+	return MAXINT;
+}
+uint32_t 
+RngMrg32k3a::get_min (void) const
+{
+	return 0;
+}
+
+uint32_t 
+RngMrg32k3a::get_uint (void)
+{  
+	return get_uint (0, MAXINT);
+}
+
+uint32_t
+RngMrg32k3a::get_uint (uint32_t n) 
+{
+	return get_uint (0, n);
+}
+
+uint32_t
+RngMrg32k3a::get_uint (uint32_t low, uint32_t high) 
+{ 
+	return ((uint32_t) (low + (uint32_t) (((uint32_t) 
+					       (high-low+1)) * U01())));
+}
+
+double 
+RngMrg32k3a::get_double (void)
+{
+	
+	return U01d ();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/rng-mrg32k3a.h	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,65 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ *  Copyright (C) 2001  Pierre L'Ecuyer (lecuyer@iro.umontreal.ca)
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ *  02110-1301 USA
+ *
+ */
+#ifndef RNG_MRG32k3A_H
+#define RNG_MRG32k3A_H
+
+#include <stdint.h>
+
+
+/*
+ * Use class RNG in real programs.
+ */
+class RngMrg32k3a {
+public:
+	RngMrg32k3a ();
+
+	void reset (long seed);
+
+
+	uint32_t get_max (void) const;
+	uint32_t get_min (void) const;
+	uint32_t get_uint (void);
+	uint32_t get_uint (uint32_t n);
+	uint32_t get_uint (uint32_t low, uint32_t high);
+	double get_double (void);
+
+private:
+	double U01 (); 
+	double U01d (); 
+	double MultModM (double a, double s, double c, double m);
+	void MatVecModM (const double A[3][3], const double s[3], double v[3], 
+			 double m);
+	void MatMatModM (const double A[3][3], const double B[3][3], 
+			 double C[3][3], double m) ;
+	void MatTwoPowModM (const double A[3][3], double B[3][3], double m, 
+			    long e);
+	void MatPowModM (const double A[3][3], double B[3][3], double m, 
+			 long n);
+	int CheckSeed (const unsigned long seed[6]);
+
+	/*
+	  Vectors to store the current seed, the beginning of the current block
+	  (substream) and the beginning of the current stream.
+	*/
+	double Cg_[6], Bg_[6], Ig_[6]; 
+}; 
+
+#endif /* RNG_MRG32k3A_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/seed-generator-mrg32k3a.cc	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,61 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2006 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#include "seed-generator.h"
+#include "rng-mrg32k3a.h"
+
+namespace yans {
+
+class SeedGeneratorPrivate {
+public:
+	static void destroy (void);
+	static void reset (uint32_t seed);
+	static uint32_t get (void);
+private:
+	static RngMrg32k3a m_generator;
+};
+
+RngMrg32k3a SeedGeneratorPrivate::m_generator;
+
+void 
+SeedGeneratorPrivate::reset (uint32_t seed)
+{
+	m_generator.reset (seed);
+}
+uint32_t 
+SeedGeneratorPrivate::get (void)
+{
+	return m_generator.get_uint ();
+}
+
+
+
+void 
+SeedGenerator::reset (uint32_t seed)
+{
+	SeedGeneratorPrivate::reset (seed);
+}
+uint32_t 
+SeedGenerator::get (void)
+{
+	return SeedGeneratorPrivate::get ();
+}
+
+}; // namespace yans
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/seed-generator.h	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,40 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2006 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#ifndef SEED_GENERATOR_H
+#define SEED_GENERATOR_H
+
+#include <stdint.h>
+
+namespace yans {
+
+class SeedGeneratorPrivate;
+
+class SeedGenerator {
+public:
+	static void reset (uint32_t seed);
+	static uint32_t get (void);
+private:
+	SeedGenerator ();
+};
+
+}; // namespace yans
+
+#endif /* SEED_GENERATOR_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/sgi-hashmap.h	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,32 @@
+/* This code snippet was ripped out of the gcc 
+ * documentation and slightly modified to work
+ * with gcc 4.x
+ */
+#ifndef SGI_HASHMAP_H
+#define SGI_HASHMAP_H
+
+/* To use gcc extensions.
+ */
+#ifdef __GNUC__
+  #if __GNUC__ < 3
+     #include <hash_map.h>
+namespace Sgi { using ::hash_map; }; // inherit globals
+  #else 
+     #if __GNUC__ < 4
+       #include <ext/hash_map>
+       #if __GNUC_MINOR__ == 0
+namespace Sgi = std;               // GCC 3.0
+       #else
+namespace Sgi = ::__gnu_cxx;       // GCC 3.1 and later
+       #endif
+     #else  // gcc 4.x and later
+       #include <ext/hash_map>
+       namespace Sgi = ::__gnu_cxx;
+     #endif
+  #endif
+#else      // ...  there are other compilers, right?
+namespace Sgi = std;
+#endif
+
+
+#endif /* SGI_HASHMAP_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/si-traced-variable.tcc	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,237 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2006 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#ifndef SI_TRACED_VARIABLE_TCC
+#define SI_TRACED_VARIABLE_TCC
+
+#include "yans/callback.h"
+#include <stdint.h>
+
+namespace yans {
+
+class SiTracedVariableBase {
+public:
+	typedef Callback<void,int64_t, int64_t> ChangeNotifyCallback;
+
+	SiTracedVariableBase () {}
+	SiTracedVariableBase (SiTracedVariableBase const &o) {}
+	SiTracedVariableBase &operator = (SiTracedVariableBase const &o) {
+		return *this;
+	}
+
+	~SiTracedVariableBase () {}
+
+	void set_callback(ChangeNotifyCallback callback) {
+		m_callback = callback;
+	}
+protected:
+	void notify (int64_t old_val, int64_t new_val) {
+		if (old_val != new_val && !m_callback.is_null ()) {
+			m_callback (old_val, new_val);
+		}
+	}
+private:
+	ChangeNotifyCallback m_callback;
+};
+
+template <typename T>
+class UiTracedVariable;
+
+
+/**
+ * \brief trace variables of type "signed integer"
+ *
+ * This template class implements a POD type: it
+ * behaves like any other variable of type "signed integer"
+ * except that it also reports any changes to its
+ * value with its internal callback.
+ *
+ * To instantiate a 32-bit signed variable (to store
+ * a TCP counter for example), you would create a variable of type
+ * yans::UiTracedVariable<int32_t> :
+ \code
+ #include <stdint.h>
+ #include "yans/si-traced-variable.tcc"
+
+ yans::SiTracedVariable<uint16_t> var;
+ \endcode
+ * and you would use it like any other variable of type int32_t:
+ \code
+ var += 12;
+ var = 10;
+ var = -10;
+ \endcode
+ */
+template <typename T>
+class SiTracedVariable : public SiTracedVariableBase {
+public:
+	SiTracedVariable ()
+		: m_var (0)
+	{}
+	SiTracedVariable (T const &var) 
+		: m_var (var)
+	{}
+
+	SiTracedVariable &operator = (SiTracedVariable const &o) {
+		assign (o.get ());
+		return *this;
+	}
+	template <typename TT>
+	SiTracedVariable &operator = (SiTracedVariable<TT> const &o) {
+		assign (o.get ());
+		return *this;
+	}
+	template <typename TT>
+	SiTracedVariable &operator = (UiTracedVariable<TT> const &o) {
+		assign (o.get ());
+		return *this;
+	}
+	SiTracedVariable &operator++ () {
+		assign (get () + 1);
+		return *this;
+	}
+	SiTracedVariable &operator-- () {
+		assign (get () - 1);
+		return *this;
+	}
+	SiTracedVariable operator++ (int) {
+		SiTracedVariable old (*this);
+		++*this;
+		return old;
+	}
+	SiTracedVariable operator-- (int) {
+		SiTracedVariable old (*this);
+		--*this;
+		return old;
+	}
+	operator T () const {
+		return get ();
+	}
+
+
+	void assign (T var) {
+		notify (m_var, var);
+		m_var = var;
+	}
+        T get (void) const {
+		return m_var;
+	}
+
+private:
+	T m_var;
+};
+
+template <typename T>
+SiTracedVariable<T> &operator += (SiTracedVariable<T> &lhs, SiTracedVariable<T> const &rhs) {
+	lhs.assign (lhs.get () + rhs.get ());
+	return lhs;
+}
+template <typename T>
+SiTracedVariable<T> &operator -= (SiTracedVariable<T> &lhs, SiTracedVariable<T> const &rhs) {
+	lhs.assign (lhs.get () - rhs.get ());
+	return lhs;
+}
+template <typename T>
+SiTracedVariable<T> &operator *= (SiTracedVariable<T> &lhs, SiTracedVariable<T> const &rhs) {
+	lhs.assign (lhs.get () * rhs.get ());
+	return lhs;
+}
+template <typename T>
+SiTracedVariable<T> &operator /= (SiTracedVariable<T> &lhs, SiTracedVariable<T> const &rhs) {
+	lhs.assign (lhs.get () / rhs.get ());
+	return lhs;
+}
+template <typename T>
+SiTracedVariable<T> &operator <<= (SiTracedVariable<T> &lhs, SiTracedVariable<T> const &rhs) {
+	lhs.assign (lhs.get () << rhs.get ());
+	return lhs;
+}
+template <typename T>
+SiTracedVariable<T> &operator >>= (SiTracedVariable<T> &lhs, SiTracedVariable<T> const &rhs) {
+	lhs.assign (lhs.get () >> rhs.get ());
+	return lhs;
+}
+template <typename T>
+SiTracedVariable<T> &operator &= (SiTracedVariable<T> &lhs, SiTracedVariable<T> const &rhs) {
+	lhs.assign (lhs.get () & rhs.get ());
+	return lhs;
+}
+template <typename T>
+SiTracedVariable<T> &operator |= (SiTracedVariable<T> &lhs, SiTracedVariable<T> const &rhs) {
+	lhs.assign (lhs.get () | rhs.get ());
+	return lhs;
+}
+template <typename T>
+SiTracedVariable<T> &operator ^= (SiTracedVariable<T> &lhs, SiTracedVariable<T> const &rhs) {
+	lhs.assign (lhs.get () ^ rhs.get ());
+	return lhs;
+}
+
+
+template <typename T, typename U>
+SiTracedVariable<T> &operator += (SiTracedVariable<T> &lhs, U const &rhs) {
+	lhs.assign (lhs.get () + rhs);
+	return lhs;
+}
+template <typename T, typename U>
+SiTracedVariable<T> &operator -= (SiTracedVariable<T> &lhs, U const &rhs) {
+	lhs.assign (lhs.get () - rhs);
+	return lhs;
+}
+template <typename T, typename U>
+SiTracedVariable<T> &operator *= (SiTracedVariable<T> &lhs, U const &rhs) {
+	lhs.assign (lhs.get () * rhs);
+	return lhs;
+}
+template <typename T, typename U>
+SiTracedVariable<T> &operator /= (SiTracedVariable<T> &lhs, U const &rhs) {
+	lhs.assign (lhs.get () / rhs);
+	return lhs;
+}
+template <typename T, typename U>
+SiTracedVariable<T> &operator <<= (SiTracedVariable<T> &lhs, U const &rhs) {
+	lhs.assign (lhs.get () << rhs);
+	return lhs;
+}
+template <typename T, typename U>
+SiTracedVariable<T> &operator >>= (SiTracedVariable<T> &lhs, U const &rhs) {
+	lhs.assign (lhs.get () >> rhs);
+	return lhs;
+}
+template <typename T, typename U>
+SiTracedVariable<T> &operator &= (SiTracedVariable<T> &lhs, U const &rhs) {
+	lhs.assign (lhs.get () & rhs);
+	return lhs;
+}
+template <typename T, typename U>
+SiTracedVariable<T> &operator |= (SiTracedVariable<T> &lhs, U const &rhs) {
+	lhs.assign (lhs.get () | rhs);
+	return lhs;
+}
+template <typename T, typename U>
+SiTracedVariable<T> &operator ^= (SiTracedVariable<T> &lhs, U const &rhs) {
+	lhs.assign (lhs.get () ^ rhs);
+	return lhs;
+}
+
+}; // namespace yans
+
+#endif /* TRACED_VARIABLE_TCC */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/static-position.cc	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,46 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2006 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#include "static-position.h"
+
+namespace yans {
+
+StaticPosition::StaticPosition ()
+	: m_x (0.0), m_y (0.0), m_z (0.0)
+{}
+StaticPosition::~StaticPosition ()
+{}
+
+void 
+StaticPosition::set (double x, double y, double z)
+{
+	m_x = x;
+	m_y = y;
+	m_z = z;
+}
+void 
+StaticPosition::real_get (double &x, double &y, double &z) const
+{
+	x = m_x;
+	y = m_y;
+	z = m_z;
+}
+
+}; // namespace yans
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/static-position.h	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,43 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2006 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#ifndef STATIC_POSITION_H
+#define STATIC_POSITION_H
+
+#include "position.h"
+
+namespace yans {
+
+class StaticPosition : public Position {
+public:
+	StaticPosition ();
+	virtual ~StaticPosition ();
+
+	void set (double x, double y, double z);
+private:
+	virtual void real_get (double &x, double &y, double &z) const;
+	double m_x;
+	double m_y;
+	double m_z;
+};
+
+}; // namespace yans
+
+#endif /* STATIC_POSITION_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/static-speed-position.cc	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,68 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2006 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#include "static-speed-position.h"
+#include "yans/simulator.h"
+
+namespace yans {
+
+StaticSpeedPosition::StaticSpeedPosition ()
+	: m_x (0.0),
+	  m_y (0.0),
+	  m_z (0.0),
+	  m_dx (0.0),
+	  m_dy (0.0),
+	  m_dz (0.0),
+	  m_prev_us (0)
+{}
+StaticSpeedPosition::~StaticSpeedPosition ()
+{}
+
+void 
+StaticSpeedPosition::set (double x, double y, double z)
+{
+	m_x = x;
+	m_y = y;
+	m_z = z;
+}
+
+void 
+StaticSpeedPosition::set_delta (double dx, double dy, double dz)
+{
+	m_dx = dx / 1000000;
+	m_dy = dy / 1000000;
+	m_dz = dz / 1000000;
+}
+
+void 
+StaticSpeedPosition::real_get (double &x, double &y, double &z) const
+{
+	uint64_t now_us = Simulator::now_us ();
+	uint64_t delta_us = now_us - m_prev_us;
+	m_x += m_dx * delta_us;
+	m_y += m_dy * delta_us;
+	m_z += m_dz * delta_us;
+	m_prev_us = now_us;
+	x = m_x;
+	y = m_y;
+	z = m_z;
+}
+
+}; // namespace yans
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/static-speed-position.h	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,51 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2006 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#ifndef STATIC_SPEED_POSITION_H
+#define STATIC_SPEED_POSITION_H
+
+#include <stdint.h>
+#include "position.h"
+
+namespace yans {
+
+class StaticSpeedPosition : public Position {
+public:
+	StaticSpeedPosition ();
+	virtual ~StaticSpeedPosition ();
+
+	// m
+	void set (double x, double y, double z);
+	// m/s
+	void set_delta (double dx, double dy, double dz);
+private:
+	virtual void real_get (double &x, double &y, double &z) const;
+	mutable double m_x;
+	mutable double m_y;
+	mutable double m_z;
+	double m_dx;
+	double m_dy;
+	double m_dz;
+	mutable uint64_t m_prev_us;
+};
+
+}; // namespace yans
+
+#endif /* STATIC_SPEED_POSITION */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/tags.cc	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,322 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2006 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#include "tags.h"
+#include <string.h>
+
+namespace yans {
+
+TagsPrettyPrinterRegistry::PrettyPrinters TagsPrettyPrinterRegistry::g_pretty_printers;
+
+void 
+TagsPrettyPrinterRegistry::record (uint32_t uid, void (*cb) (uint8_t [Tags::SIZE], std::ostream &))
+{
+	for (PrettyPrintersI i = g_pretty_printers.begin (); 
+	     i != g_pretty_printers.end (); i++) {
+		if (i->first == uid) {
+			i->second = cb;
+			return;
+		}
+	}
+	g_pretty_printers.push_back (std::make_pair (uid, cb));
+}
+void 
+TagsPrettyPrinterRegistry::pretty_print (uint32_t uid, uint8_t buf[Tags::SIZE], std::ostream &os)
+{
+	for (PrettyPrintersI i = g_pretty_printers.begin (); 
+	     i != g_pretty_printers.end (); i++) {
+		if (i->first == uid) {
+			if (i->second == 0) {
+				os << "tag uid="<<uid<<" null pretty printer."<<std::endl;
+			} else {
+				(*(i->second)) (buf, os);
+			}
+			return;
+		}
+	}
+	os << "tag uid="<<uid<<" no pretty printer registered."<< std::endl;
+}
+
+
+
+uint32_t
+Tags::UidFactory::create (void)
+{
+	static uint32_t uid = 0;
+	uid++;
+	return uid;
+}
+
+
+#ifdef USE_FREE_LIST
+
+struct Tags::TagData *Tags::g_free = 0;
+uint32_t Tags::g_n_free = 0;
+
+struct Tags::TagData *
+Tags::alloc_data (void)
+{
+	struct Tags::TagData *retval;
+	if (g_free != 0) {
+		retval = g_free;
+		g_free = g_free->m_next;
+		g_n_free--;
+	} else {
+		retval = new struct Tags::TagData ();
+	}
+	return retval;
+}
+
+void
+Tags::free_data (struct TagData *data)
+{
+	if (g_n_free > 1000) {
+		delete data;
+		return;
+	}
+	g_n_free++;
+	data->m_next = g_free;
+	g_free = data;
+}
+#else
+struct Tags::TagData *
+Tags::alloc_data (void)
+{
+	struct Tags::TagData *retval;
+	retval = new struct Tags::TagData ();
+	return retval;
+}
+
+void
+Tags::free_data (struct TagData *data)
+{
+	delete data;
+}
+#endif
+
+bool
+Tags::remove (uint32_t id)
+{
+	bool found = false;
+	for (struct TagData *cur = m_next; cur != 0; cur = cur->m_next) {
+		if (cur->m_id == id) {
+			found = true;
+		}
+	}
+	if (!found) {
+		return false;
+	}
+	struct TagData *start = 0;
+	struct TagData **prev_next = &start;
+	for (struct TagData *cur = m_next; cur != 0; cur = cur->m_next) {
+		if (cur->m_id == id) {
+			/**
+			 * XXX
+			 * Note: I believe that we could optimize this to
+			 * avoid copying each TagData located after the target id
+			 * and just link the already-copied list to the next tag.
+			 */
+			continue;
+		}
+		struct TagData *copy = alloc_data ();
+		copy->m_id = cur->m_id;
+		copy->m_count = 1;
+		copy->m_next = 0;
+		memcpy (copy->m_data, cur->m_data, Tags::SIZE);
+		*prev_next = copy;
+		prev_next = &copy->m_next;
+	}
+	*prev_next = 0;
+	remove_all ();
+	m_next = start;
+	return true;
+}
+
+bool
+Tags::update (uint8_t const*buffer, uint32_t id)
+{
+	if (!remove (id)) {
+		return false;
+	}
+	struct TagData *new_start = alloc_data ();
+	new_start->m_count = 1;
+	new_start->m_next = 0;
+	new_start->m_id = id;
+	memcpy (new_start->m_data, buffer, Tags::SIZE);
+	new_start->m_next = m_next;
+	m_next = new_start;
+	return true;
+}
+
+void 
+Tags::pretty_print (std::ostream &os)
+{
+	for (struct TagData *cur = m_next; cur != 0; cur = cur->m_next) {
+		TagsPrettyPrinterRegistry::pretty_print (cur->m_id, cur->m_data, os);
+	}
+}
+
+
+}; // namespace yans
+
+#ifdef RUN_SELF_TESTS
+
+#include "yans/test.h"
+#include <iomanip>
+#include <iostream>
+
+namespace yans {
+
+class TagsTest : Test {
+public:
+	TagsTest ();
+	virtual ~TagsTest ();
+	virtual bool run_tests (void);
+};
+
+struct my_tag_a {
+	uint8_t a;
+};
+struct my_tag_b {
+	uint32_t b;
+};
+struct my_tag_c {
+	uint8_t c [Tags::SIZE];
+};
+struct my_invalid_tag {
+	uint8_t invalid [Tags::SIZE+1];
+};
+
+static void 
+my_tag_a_pretty_printer_cb (struct my_tag_a *a, std::ostream &os)
+{
+	os << "struct my_tag_a, a="<<(uint32_t)a->a<<std::endl;
+}
+static void 
+my_tag_b_pretty_printer_cb (struct my_tag_b *b, std::ostream &os)
+{
+	os << "struct my_tag_b, b="<<b->b<<std::endl;
+}
+static void 
+my_tag_c_pretty_printer_cb (struct my_tag_c *c, std::ostream &os)
+{
+	os << "struct my_tag_c, c="<<(uint32_t)c->c[0]<<std::endl;
+}
+
+
+static TagPrettyPrinter<struct my_tag_a> g_my_tag_a_pretty_printer (&my_tag_a_pretty_printer_cb);
+static TagPrettyPrinter<struct my_tag_b> g_my_tag_b_pretty_printer (&my_tag_b_pretty_printer_cb);
+static TagPrettyPrinter<struct my_tag_c> g_my_tag_c_pretty_printer (&my_tag_c_pretty_printer_cb);
+
+
+TagsTest::TagsTest ()
+	: Test ("Tags")
+{}
+TagsTest::~TagsTest ()
+{}
+
+bool 
+TagsTest::run_tests (void)
+{
+	bool ok = true;
+
+	// build initial tag.
+	Tags tags;
+	struct my_tag_a a;
+	a.a = 10;
+	tags.add (&a);
+	a.a = 0;
+	tags.peek (&a);
+	if (a.a != 10) {
+		ok = false;
+	}
+	//tags.pretty_print (std::cout);
+	struct my_tag_b b;
+	b.b = 0xff;
+	tags.add (&b);
+	b.b = 0;
+	tags.peek (&b);
+	if (b.b != 0xff) {
+		ok = false;
+	}
+	//tags.pretty_print (std::cout);
+
+	// make sure copy contains copy.
+	Tags other = tags;
+	//other.pretty_print (std::cout);
+	//tags.pretty_print (std::cout);
+	struct my_tag_a o_a;
+	o_a.a = 0;
+	other.peek (&o_a);
+	if (o_a.a != 10) {
+		ok = false;
+	}
+	struct my_tag_b o_b;
+	other.peek (&o_b);
+	if (o_b.b != 0xff) {
+		ok = false;
+	}
+	// remove data.
+	other.remove (&o_a);
+	if (other.peek (&o_a)) {
+		ok = false;
+	}
+	//other.pretty_print (std::cout);
+	if (!tags.peek (&o_a)) {
+		ok = false;
+	}
+	other.remove (&o_b);
+	if (other.peek (&o_b)) {
+		ok = false;
+	}
+	if (!tags.peek (&o_b)) {
+		ok = false;
+	}
+
+	other = tags;
+	Tags another = other;
+	struct my_tag_c c;
+	c.c[0] = 0x66;
+	another.add (&c);
+	c.c[0] = 0;
+	another.peek (&c);
+	if (!another.peek (&c)) {
+		ok = false;
+	}
+	if (tags.peek (&c)) {
+		ok = false;
+	}
+
+	other = other;
+	//other.pretty_print (std::cout);
+
+	//struct my_invalid_tag invalid;
+	//tags.add (&invalid);
+
+	return ok;
+}
+
+static TagsTest g_tags_test;
+
+
+}; // namespace yans
+
+#endif /* RUN_SELF_TESTS */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/tags.h	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,292 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2006 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#ifndef TAGS_H
+#define TAGS_H
+
+#include <stdint.h>
+#include <ostream>
+#include <vector>
+
+namespace yans {
+
+template <typename T>
+class TagPrettyPrinter;
+
+class Tags {
+public:
+	inline Tags ();
+	inline Tags (Tags const &o);
+	inline Tags &operator = (Tags const &o);
+	inline ~Tags ();
+
+	template <typename T>
+	void add (T const*tag);
+
+	template <typename T>
+	bool remove (T *tag);
+
+	template <typename T>
+	bool peek (T *tag) const;
+
+	template <typename T>
+	bool update (T const*tag);
+
+	void pretty_print (std::ostream &os);
+
+	inline void remove_all (void);
+
+	enum {
+		SIZE = 16
+	};
+private:
+	struct TagData {
+		struct TagData *m_next;
+		uint32_t m_id;
+		uint32_t m_count;
+		uint8_t m_data[Tags::SIZE];
+	};
+	class UidFactory {
+	public:
+		static uint32_t create (void);
+	};
+
+	bool remove (uint32_t id);
+	bool update (uint8_t const*buffer, uint32_t id);
+	struct Tags::TagData *alloc_data (void);
+	void free_data (struct TagData *data);
+
+	static struct Tags::TagData *g_free;
+	static uint32_t g_n_free;
+
+	struct TagData *m_next;
+};
+
+/**
+ * This class is used to register a pretty-printer
+ * callback function to print in a nice user-friendly
+ * way the content of the target type. To register
+ * such a type, all you need to do is instantiate
+ * an instance of this type any number of times (at
+ * least once). Typical users will create static global
+ * variable of this type and construct it with
+ * the proper function pointer.
+ */
+template <typename T>
+class TagPrettyPrinter {
+public:
+	TagPrettyPrinter<T> (void(*) (T *, std::ostream &));
+private:
+	TagPrettyPrinter<T> ();
+	static void pretty_print_cb (uint8_t *buf, std::ostream &os);
+	static void(*g_pretty_printer) (T *, std::ostream &);
+};
+
+class TagsPrettyPrinterRegistry {
+public:
+	static void record (uint32_t uid, void (*cb) (uint8_t buf[Tags::SIZE], std::ostream &os));
+	static void pretty_print (uint32_t uid, uint8_t buf[Tags::SIZE], std::ostream &os);
+private:
+	typedef std::vector<std::pair<uint32_t, void (*) (uint8_t [Tags::SIZE], std::ostream &)> > PrettyPrinters;
+	typedef std::vector<std::pair<uint32_t, void (*) (uint8_t [Tags::SIZE], std::ostream &)> >::iterator PrettyPrintersI;
+	static PrettyPrinters g_pretty_printers;
+};
+
+
+}; // namespace yans
+
+
+#include <cassert>
+#include <string.h>
+
+namespace yans {
+
+/**
+ * The TypeUid class is used to create a mapping Type --> uid
+ * Of course, this class is not perfect: the value of the uid
+ * associated to a given type could change accross multiple 
+ * runs of the same program on the same platform or accross
+ * multiple platforms. There exist no generic portable
+ * workaround/solution to this problem also known as 
+ * "type id management". The only other reliable solution 
+ * is to ask programmers to assign themselves a uid to each 
+ * type but this is painful from a management perspective.
+ *
+ * So, for now, this class is good enough provided you do
+ * not try to serialize to permanent storage the type uids
+ * generated by this class. Just don't try to do it. It might
+ * seem to work but it will fail spectacularily in certain
+ * use-cases and you will cry from debugging this. Hear me ?
+ */
+template <typename T>
+class TypeUid {
+public:
+	static const uint32_t get_uid (void);
+private:
+	T real_type;
+};
+
+template <typename T>
+const uint32_t TypeUid<T>::get_uid (void)
+{
+	static const uint32_t uid = Tags::UidFactory::create ();
+	return uid;
+}
+
+
+
+/**
+ * Implementation of the TagPrettyPrinter registration class.
+ * It records a callback with the TagPrettyPrinterRegistry.
+ * This callback performs type conversion before forwarding
+ * the call to the user-provided function.
+ */
+template <typename T>
+TagPrettyPrinter<T>::TagPrettyPrinter (void(*pretty_printer) (T *, std::ostream &))
+{
+	g_pretty_printer  = pretty_printer;
+	TagsPrettyPrinterRegistry::record (TypeUid<T>::get_uid (),
+					  &TagPrettyPrinter<T>::pretty_print_cb);
+}
+template <typename T>
+void 
+TagPrettyPrinter<T>::pretty_print_cb (uint8_t buf[Tags::SIZE], std::ostream &os)
+{
+	assert (sizeof (T) <= Tags::SIZE);
+	T *tag = reinterpret_cast<T *> (buf);
+	(*g_pretty_printer) (tag, os);
+}
+
+template <typename T>
+void (*TagPrettyPrinter<T>::g_pretty_printer) (T *, std::ostream &) = 0;
+
+
+
+
+template <typename T>
+void 
+Tags::add (T const*tag)
+{
+	assert (sizeof (T) <= Tags::SIZE);
+	uint8_t const*buf = reinterpret_cast<uint8_t const*> (tag);
+	// ensure this id was not yet added
+	for (struct TagData *cur = m_next; cur != 0; cur = cur->m_next) {
+		assert (cur->m_id != TypeUid<T>::get_uid ());
+	}
+	struct TagData *new_start = alloc_data ();
+	new_start->m_count = 1;
+	new_start->m_next = 0;
+	new_start->m_id = TypeUid<T>::get_uid ();
+	memcpy (new_start->m_data, buf, sizeof (T));
+	new_start->m_next = m_next;
+	m_next = new_start;
+}
+
+template <typename T>
+bool
+Tags::remove (T *tag)
+{
+	assert (sizeof (T) <= Tags::SIZE);
+	return remove (TypeUid<T>::get_uid ());
+}
+
+template <typename T>
+bool
+Tags::peek (T *tag) const
+{
+	assert (sizeof (T) <= Tags::SIZE);
+	uint8_t *buf = reinterpret_cast<uint8_t *> (tag);
+	for (struct TagData *cur = m_next; cur != 0; cur = cur->m_next) {
+		if (cur->m_id == TypeUid<T>::get_uid ()) {
+			/* found tag */
+			memcpy (buf, cur->m_data, sizeof (T));
+			return true;
+		}
+	}
+	/* no tag found */
+	return false;
+}
+
+template <typename T>
+bool
+Tags::update (T const*tag)
+{
+	assert (sizeof (T) <= Tags::SIZE);
+	uint8_t const*buf = reinterpret_cast<uint8_t const*> (tag);
+	return update (buf, TypeUid<T>::get_uid ());
+}
+
+
+Tags::Tags ()
+	: m_next ()
+{}
+
+Tags::Tags (Tags const &o)
+	: m_next (o.m_next)
+{
+	if (m_next != 0) {
+		m_next->m_count++;
+	}
+}
+
+Tags &
+Tags::operator = (Tags const &o)
+{
+	// self assignment
+	if (m_next == o.m_next) {
+		return *this;
+	}
+	remove_all ();
+	m_next = o.m_next;
+	if (m_next != 0) {
+		m_next->m_count++;
+	}
+	return *this;
+}
+
+Tags::~Tags ()
+{
+	remove_all ();
+}
+
+void
+Tags::remove_all (void)
+{
+	struct TagData *prev = 0;
+	for (struct TagData *cur = m_next; cur != 0; cur = cur->m_next) {
+		cur->m_count--;
+		if (cur->m_count > 0) {
+			break;
+		}
+		if (prev != 0) {
+			free_data (prev);
+		}
+		prev = cur;
+	}
+	if (prev != 0) {
+		free_data (prev);
+	}
+	m_next = 0;
+}
+
+
+}; // namespace yans
+
+#endif /* TAGS_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/timeout.cc	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,77 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2005 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#include "timeout.h"
+#include "yans/simulator.h"
+#include "yans/event.tcc"
+
+namespace yans {
+
+Timeout::Timeout (ExpireCallback callback)
+	: m_interval_us (0),
+	  m_count (0),
+	  m_current_count (0),
+	  m_stop (false),
+	  m_callback (callback)
+{}
+Timeout::~Timeout ()
+{}
+void 
+Timeout::set_interval (uint64_t us)
+{
+	m_interval_us = us;
+}
+void 
+Timeout::set_count (uint32_t count)
+{
+	m_count = count;
+}
+
+
+void Timeout::start (void)
+{
+	Simulator::schedule_rel_us (m_interval_us,
+				 make_event (&Timeout::expire, this));
+}
+void Timeout::stop (void)
+{
+	m_stop = true;
+}
+void Timeout::restart (void)
+{
+	m_current_count = m_count;
+}
+void
+Timeout::expire (void)
+{
+	if (m_stop) {
+		return;
+	}
+	m_current_count--;
+	if (m_current_count == 0) {
+		m_callback ();
+		return;
+	}
+	Simulator::schedule_rel_us (m_interval_us,
+				 make_event (&Timeout::expire, this));
+}
+
+
+}; // namespace yans
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/timeout.h	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,52 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2005 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#ifndef TIMEOUT_H
+#define TIMEOUT_H
+
+#include <stdint.h>
+#include "yans/callback.h"
+
+namespace yans {
+
+class Timeout {
+public:
+	typedef Callback<void> ExpireCallback;
+	Timeout (ExpireCallback callback);
+	~Timeout ();
+	void set_interval (uint64_t us);
+	void set_count (uint32_t count);
+	void start (void);
+	void stop (void);
+	void restart (void);
+private:
+	Timeout ();
+	void expire (void);
+	uint64_t m_interval_us;
+	uint32_t m_count;
+	uint32_t m_current_count;
+	bool m_stop;
+	ExpireCallback m_callback;
+};
+
+}; // namespace yans
+
+#endif /* TIMEOUT_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/trace-container.cc	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,197 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2006 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#include "trace-container.h"
+#include "packet-logger.h"
+#include "trace-stream.h"
+#include <utility>
+#include <cassert>
+
+namespace yans {
+
+TraceContainer::TraceContainer ()
+{}
+TraceContainer::~TraceContainer ()
+{
+	m_ui_list.erase (m_ui_list.begin (), m_ui_list.end ());
+	m_si_list.erase (m_si_list.begin (), m_si_list.end ());
+	m_f_list.erase (m_f_list.begin (), m_f_list.end ());
+}
+
+void 
+TraceContainer::set_ui_variable_callback (char const *name, Callback<void,uint64_t, uint64_t> callback)
+{
+	for (UiListI i = m_ui_list.begin (); i != m_ui_list.end (); i++) {
+		if ((*i).second == name) {
+			(*i).first->set_callback (callback);
+			return;
+		}
+	}
+	assert (false);
+}
+void 
+TraceContainer::set_si_variable_callback (char const *name, Callback<void,int64_t, int64_t> callback)
+{
+	for (SiListI i = m_si_list.begin (); i != m_si_list.end (); i++) {
+		if ((*i).second == name) {
+			(*i).first->set_callback (callback);
+			return;
+		}
+	}
+	assert (false);
+}
+void 
+TraceContainer::set_f_variable_callback (char const *name, Callback<void,double, double> callback)
+{
+	assert (false);
+}
+void 
+TraceContainer::set_packet_logger_callback (char const *name, Callback<void,Packet const> callback)
+{
+	for (PacketLoggerListI i = m_packet_logger_list.begin (); i != m_packet_logger_list.end (); i++) {
+		if ((*i).second == name) {
+			(*i).first->set_callback (callback);
+			return;
+		}
+	}
+	assert (false);	
+}
+void 
+TraceContainer::set_stream (char const *name, std::ostream *os)
+{
+	for (TraceStreamListI i = m_trace_stream_list.begin (); i != m_trace_stream_list.end (); i++) {
+		if ((*i).second == name) {
+			(*i).first->set_stream (os);
+			return;
+		}
+	}
+	assert (false);
+}
+
+void 
+TraceContainer::register_ui_variable (char const *name, UiTracedVariableBase *var)
+{
+	// ensure unicity
+	for (UiListI i = m_ui_list.begin (); i != m_ui_list.end (); i++) {
+		if (i->second == name) {
+			m_ui_list.erase (i);
+			break;
+		}
+	}
+	m_ui_list.push_back (std::make_pair (var, name));
+}
+void 
+TraceContainer::register_si_variable (char const *name, SiTracedVariableBase *var)
+{
+	// ensure unicity
+	for (SiListI i = m_si_list.begin (); i != m_si_list.end (); i++) {
+		if (i->second == name) {
+			m_si_list.erase (i);
+			break;
+		}
+	}
+	m_si_list.push_back (std::make_pair (var, name));
+}
+void 
+TraceContainer::register_f_variable (char const *name, FTracedVariableBase *var)
+{
+	assert (false);
+}
+
+void 
+TraceContainer::register_packet_logger (char const *name, PacketLogger *logger)
+{
+	// ensure unicity
+	for (PacketLoggerListI i = m_packet_logger_list.begin (); i != m_packet_logger_list.end (); i++) {
+		if (i->second == name) {
+			m_packet_logger_list.erase (i);
+			break;
+		}
+	}
+	m_packet_logger_list.push_back (std::make_pair (logger, name));
+}
+
+void 
+TraceContainer::register_stream (char const *name, TraceStream *stream)
+{
+	// ensure unicity
+	for (TraceStreamListI i = m_trace_stream_list.begin (); i != m_trace_stream_list.end (); i++) {
+		if (i->second == name) {
+			m_trace_stream_list.erase (i);
+			break;
+		}
+	}
+	m_trace_stream_list.push_back (std::make_pair (stream,name));
+
+}
+
+void 
+TraceContainer::register_callback (char const *name, CallbackLoggerBase *logger)
+{
+	for (CallbackListI i = m_callback_list.begin (); i != m_callback_list.end (); i++) {
+		if (i->second == name) {
+			m_callback_list.erase (i);
+			break;
+		}
+	}
+	m_callback_list.push_back (std::make_pair (logger, name));
+}
+
+
+
+
+}; // namespace yans
+
+#include <iostream>
+void 
+yans::TraceContainer::print_debug (void)
+{
+	if (!m_ui_list.empty ()) {
+		std::cout << "ui var: " << std::endl;
+		for (UiListI i = m_ui_list.begin (); i != m_ui_list.end (); i++) {
+			std::cout << "    \"" << (*i).second << "\""<<std::endl;
+		}
+	}
+	if (!m_si_list.empty ()) {
+		std::cout << "si var: " << std::endl;
+		for (SiListI i = m_si_list.begin (); i != m_si_list.end (); i++) {
+			std::cout << "    \"" << (*i).second << "\""<<std::endl;
+		}
+	}
+	if (!m_f_list.empty ()) {
+		std::cout << "f var: " << std::endl;
+		for (FListI i = m_f_list.begin (); i != m_f_list.end (); i++) {
+			std::cout << "    \"" << (*i).second << "\""<<std::endl;
+		}
+	}
+	if (!m_packet_logger_list.empty ()) {		
+		std::cout << "packet logger: " << std::endl;
+		for (PacketLoggerListI i = m_packet_logger_list.begin (); i != m_packet_logger_list.end (); i++) {
+			std::cout << "    \"" << (*i).second << "\""<<std::endl;
+		}
+	}
+	if (!m_callback_list.empty ()) {
+		std::cout << "callback list: "<<std::endl;
+		for (CallbackListI i = m_callback_list.begin (); i != m_callback_list.end (); i++) {
+			std::cout << "    \"" << i->second << "\""<<std::endl;
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/trace-container.h	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,299 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2006 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#ifndef TRACE_CONTAINER_H
+#define TRACE_CONTAINER_H
+
+#include "ui-traced-variable.tcc"
+#include "si-traced-variable.tcc"
+#include "f-traced-variable.tcc"
+#include "callback-logger.h"
+#include "yans/callback.h"
+#include "packet.h"
+#include <list>
+#include <string>
+
+namespace yans {
+
+class PacketLogger;
+class TraceStream;
+
+/**
+ * \brief register every source of trace events
+ *
+ * Model authors use the TraceContainer class to register
+ * their trace event sources. Model users use the TraceContainer
+ * class to connect their trace event listeners to the
+ * model trace event sources.
+ *
+ * TraceContainer can be used to register the following event sources:
+ *   - yans::PacketLogger : can be connected to yans::PcapWriter
+ *   - yans::TraceStream : can be connected to any std::ostream
+ *   - yans::CallbackLogger: can be connected to yans::Callback
+ *   - yans::UiTracedVariable
+ *   - yans::SiTracedVariable
+ *   - yans::FTracedVariable
+ *
+ * The following sample code shows how you can:
+ *   - create trace event sources
+ *   - register the trace event sources in a trace container
+ *   - set event sinks to each event source
+ *  
+ * \include samples/main-trace.cc
+ */
+class TraceContainer {
+public:
+	TraceContainer ();
+	~TraceContainer ();
+
+	/**
+	 * \param name the name of the target event source
+	 * \param callback the callback being connected to the target event source
+	 *
+	 * This method targets only event sources which are variables of any unsigned
+	 * integer type.
+	 */
+	void set_ui_variable_callback (char const *name, 
+				       Callback<void,uint64_t, uint64_t> callback);
+	/**
+	 * \param name the name of the target event source
+	 * \param callback the callback being connected to the target event source
+	 *
+	 * This method targets only event sources which are variables of any signed
+	 * integer type.
+	 */
+	void set_si_variable_callback (char const *name, Callback<void,int64_t, int64_t> callback);
+	/**
+	 * \param name the name of the target event source
+	 * \param callback the callback being connected to the target event source
+	 *
+	 * This method targets only event sources which are variables of any double type.
+	 */
+	void set_f_variable_callback (char const *name, Callback<void,double, double> callback);
+	/**
+	 * \param name the name of the target event source
+	 * \param callback the callback being connected to the target event source
+	 *
+	 * This method targets only event sources which are of type PacketLogger.
+	 */
+	void set_packet_logger_callback (char const *name, Callback<void,Packet const> callback);
+	/**
+	 * \param name the name of the target event source
+	 * \param os the output stream being connected to the source trace stream
+	 *
+	 * This method targets only event sources which are of type TraceStream.
+	 */
+	void set_stream (char const *name, std::ostream *os);
+
+	/**
+	 * \param name the name of the target event source
+	 * \param callback the callback being connected to the target event source.
+	 *
+	 * This method targets only event sources which are of type CallbackLogger<T1>
+	 */
+	template <typename T1>
+	void set_callback (char const *name, Callback<void,T1> callback);
+	/**
+	 * \param name the name of the target event source
+	 * \param callback the callback being connected to the target event source.
+	 *
+	 * This method targets only event sources which are of type CallbackLogger<T1,T2>
+	 */
+	template <typename T1, typename T2>
+	void set_callback (char const *name, Callback<void,T1,T2> callback);
+	/**
+	 * \param name the name of the target event source
+	 * \param callback the callback being connected to the target event source.
+	 *
+	 * This method targets only event sources which are of type CallbackLogger<T1,T2,T3>
+	 */
+	template <typename T1, typename T2, typename T3>
+	void set_callback (char const *name, Callback<void,T1,T2,T3> callback);
+	/**
+	 * \param name the name of the target event source
+	 * \param callback the callback being connected to the target event source.
+	 *
+	 * This method targets only event sources which are of type CallbackLogger<T1,T2,T3,T4>
+	 */
+	template <typename T1, typename T2, typename T3, typename T4>
+	void set_callback (char const *name, Callback<void,T1,T2,T3,T4> callback);
+	/**
+	 * \param name the name of the target event source
+	 * \param callback the callback being connected to the target event source.
+	 *
+	 * This method targets only event sources which are of type CallbackLogger<T1,T2,T3,T4,T5>
+	 */
+	template <typename T1, typename T2, typename T3, typename T4, typename T5>
+	void set_callback (char const *name, Callback<void,T1,T2,T3,T4,T5> callback);
+
+	/**
+	 * \param name the name of the registered event source
+	 * \param var the event source being registered
+	 *
+	 * This method registers only event sources of type "unsigned integer".
+	 */
+	void register_ui_variable (char const *name, UiTracedVariableBase *var);
+	/**
+	 * \param name the name of the registered event source
+	 * \param var the event source being registered
+	 *
+	 * This method registers only event sources of type "signed integer".
+	 */
+	void register_si_variable (char const *name, SiTracedVariableBase *var);
+	/**
+	 * \param name the name of the registered event source
+	 * \param var the event source being registered
+	 *
+	 * This method registers only event sources of type "double".
+	 */
+	void register_f_variable (char const *name, FTracedVariableBase *var);
+	/**
+	 * \param name the name of the registered event source
+	 * \param logger the event source being registered
+	 *
+	 * This method registers only event sources of type PacketLogger.
+	 */
+	void register_packet_logger (char const *name, PacketLogger *logger);
+	/**
+	 * \param name the name of the registered event source
+	 * \param stream the event source being registered
+	 *
+	 * This method registers only event sources of type TraceStream.
+	 */
+	void register_stream (char const *name, TraceStream *stream);
+
+	/**
+	 * \param name the name of the registeref event source
+	 * \param logger the callback logger being registered.
+	 *
+	 * This method registers only event sources of type CallbackLogger
+	 */
+	void register_callback (char const *name, CallbackLoggerBase*logger);
+
+	/**
+	 * Print the list of registered event sources in this container only.
+	 */
+	void print_debug (void);
+private:
+	typedef std::list<std::pair<UiTracedVariableBase *, std::string> > UiList;
+	typedef std::list<std::pair<UiTracedVariableBase *, std::string> >::iterator UiListI;
+	typedef std::list<std::pair<SiTracedVariableBase *, std::string> > SiList;
+	typedef std::list<std::pair<SiTracedVariableBase *, std::string> >::iterator SiListI;
+	typedef std::list<std::pair<FTracedVariableBase *, std::string> > FList;
+	typedef std::list<std::pair<FTracedVariableBase *, std::string> >::iterator FListI;
+	typedef std::list<std::pair<PacketLogger *, std::string> > PacketLoggerList;
+	typedef std::list<std::pair<PacketLogger *, std::string> >::iterator PacketLoggerListI;
+	typedef std::list<std::pair<TraceStream *, std::string> > TraceStreamList;
+	typedef std::list<std::pair<TraceStream *, std::string> >::iterator TraceStreamListI;
+	typedef std::list<std::pair<CallbackLoggerBase *, std::string> > CallbackList;
+	typedef std::list<std::pair<CallbackLoggerBase *, std::string> >::iterator CallbackListI;
+
+	UiList m_ui_list;
+	SiList m_si_list;
+	FList m_f_list;
+	PacketLoggerList m_packet_logger_list;
+	TraceStreamList m_trace_stream_list;
+	CallbackList m_callback_list;
+};
+
+}; // namespace yans
+
+#ifndef NDEBUG
+#include <cassert>
+#endif
+
+namespace yans {
+
+template <typename T1>
+void 
+TraceContainer::set_callback (char const *name, Callback<void,T1> callback)
+{
+	for (CallbackListI i = m_callback_list.begin (); i != m_callback_list.end (); i++) {
+		if (i->second == name) {
+			static_cast<CallbackLogger<T1> *> (i->first)->set_callback (callback);
+			return;
+		}
+	}
+#ifndef NDEBUG
+	assert (false);
+#endif
+}
+template <typename T1, typename T2>
+void 
+TraceContainer::set_callback (char const *name, Callback<void,T1,T2> callback)
+{
+	for (CallbackListI i = m_callback_list.begin (); i != m_callback_list.end (); i++) {
+		if (i->second == name) {
+			static_cast<CallbackLogger<T1,T2> *> (i->first)->set_callback (callback);
+			return;
+		}
+	}
+#ifndef NDEBUG
+	assert (false);
+#endif
+}
+template <typename T1, typename T2, typename T3>
+void 
+TraceContainer::set_callback (char const *name, Callback<void,T1,T2,T3> callback)
+{
+	for (CallbackListI i = m_callback_list.begin (); i != m_callback_list.end (); i++) {
+		if (i->second == name) {
+			static_cast<CallbackLogger<T1,T2,T3> *> (i->first)->set_callback (callback);
+			return;
+		}
+	}
+#ifndef NDEBUG
+	assert (false);
+#endif
+}
+template <typename T1, typename T2, typename T3, typename T4>
+void 
+TraceContainer::set_callback (char const *name, Callback<void,T1,T2,T3,T4> callback)
+{
+	for (CallbackListI i = m_callback_list.begin (); i != m_callback_list.end (); i++) {
+		if (i->second == name) {
+			static_cast<CallbackLogger<T1,T2,T3,T4> *> (i->first)->set_callback (callback);
+			return;
+		}
+	}
+#ifndef NDEBUG
+	assert (false);
+#endif
+}
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+void 
+TraceContainer::set_callback (char const *name, Callback<void,T1,T2,T3,T4,T5> callback)
+{
+	for (CallbackListI i = m_callback_list.begin (); i != m_callback_list.end (); i++) {
+		if (i->second == name) {
+			static_cast<CallbackLogger<T1,T2,T3,T4,T5> *> (i->first)->set_callback (callback);
+			return;
+		}
+	}
+#ifndef NDEBUG
+	assert (false);
+#endif
+}
+
+
+}; // namespace yans
+
+#endif /* TRACED_VARIABLE_CONTAINER_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/trace-stream-test.cc	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,68 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2006 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#include "trace-stream.h"
+#include "yans/test.h"
+#include <iostream>
+
+#ifdef RUN_SELF_TESTS
+
+namespace {
+
+class TestTraceStream : public yans::Test {
+public:
+	TestTraceStream ();
+	virtual bool run_tests (void);
+};
+
+static TestTraceStream g_test_stream;
+
+TestTraceStream::TestTraceStream ()
+	: Test ("TraceStream")
+{}
+
+bool
+TestTraceStream::run_tests (void)
+{
+	bool ok = true;
+	yans::TraceStream trace;
+	//trace.set_stream (&std::cout);
+	trace << 1;
+	trace << " X ";
+	trace << 1.0;
+	trace << std::endl;
+	trace << "test ";
+	trace << 1 << " test";
+	trace << "test "
+	      << 1.0 << " "
+	      << 0xdeadbead
+	      << std::endl;
+	trace << "0x" << std::hex 
+	      << 0xdeadbeaf 
+	      << std::dec << " "
+	      << 0xdeadbeaf
+	      << std::endl;
+	return ok;
+}
+
+
+}; // namespace yans
+
+#endif /* RUN_SELF_TESTS */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/trace-stream.h	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,73 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2006 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#ifndef TRACE_STREAM_H
+#define TRACE_STREAM_H
+
+#include <ostream>
+
+namespace yans {
+
+/**
+ * \brief log arbitrary data to std::ostreams
+ * 
+ * Whenever operator << is invoked on this class,
+ * it is forwarded to the stored std::ostream output
+ * stream (if there is one).
+ */
+class TraceStream {
+public:
+	TraceStream ()
+		: m_os (0) {}
+	template <typename T>
+	TraceStream &operator << (T const&v) {
+		if (m_os != 0) {
+			(*m_os) << v;
+		}
+		return *this;
+	}
+	template <typename T>
+	TraceStream &operator << (T &v) {
+		if (m_os != 0) {
+			(*m_os) << v;
+		}
+		return *this;
+	}
+	TraceStream &operator << (std::ostream &(*v) (std::ostream &)) {
+		if (m_os != 0) {
+			(*m_os) << v;
+		}
+		return *this;
+	}
+
+	/**
+	 * \param os the output stream to store
+	 */
+	void set_stream (std::ostream * os) {
+		m_os = os;
+	}
+private:
+	std::ostream *m_os;
+};
+
+}; // namespace yans
+
+
+#endif /* TRACE_STREAM_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/traced-variable-test.cc	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,252 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2006 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#include "ui-traced-variable.tcc"
+#include "si-traced-variable.tcc"
+#include "yans/test.h"
+#include "yans/callback.h"
+
+
+namespace yans {
+
+class Foo {
+public:
+	void notify (uint64_t old_val, uint64_t new_val) {}
+};
+
+class TracedVariableTest: public Test {
+public:
+	TracedVariableTest ();
+	void run_unsigned_tests (void);
+	void run_signed_unsigned_tests (void);
+	virtual bool run_tests (void);
+};
+void
+TracedVariableTest::run_unsigned_tests (void)
+{
+	UiTracedVariable<uint32_t> var, ovar, tmp;
+	uint32_t utmp;
+	Foo *foo = new Foo ();
+	
+	var.set_callback (make_callback (&Foo::notify, foo));
+
+	var = 10;
+	ovar = var;
+
+	if (var == ovar) {
+	}
+	if (var != ovar) {
+	}
+	if (var > ovar) {
+	}
+	if (var >= ovar) {
+	}
+	if (var < ovar) {
+	}
+	if (var <= ovar) {
+	}
+
+	if (var == 1) {
+	}
+	if (var != 1) {
+	}
+	if (var > 1) {
+	}
+	if (var >= 1) {
+	}
+	if (var < 1) {
+	}
+	if (var <= 1) {
+	}
+
+	if (1 == ovar) {
+	}
+	if (1 != ovar) {
+	}
+	if (1 > ovar) {
+	}
+	if (1 >= ovar) {
+	}
+	if (1 < ovar) {
+	}
+	if (1 <= ovar) {
+	}
+
+	var++;
+	++var;
+	var--;
+	--var;
+
+	tmp = var + ovar;
+	tmp = var - ovar;
+	tmp = var / ovar;
+	tmp = var * ovar;
+	tmp = var << ovar;
+	tmp = var >> ovar;
+	tmp = var & ovar;
+	tmp = var | ovar;
+	tmp = var ^ ovar;
+
+	tmp = var + 1;
+	tmp = var - 1;
+	tmp = var / 1;
+	tmp = var * 1;
+	tmp = var << 1;
+	tmp = var >> 1;
+	tmp = var & 1;
+	tmp = var | 1;
+	tmp = var ^ 1;
+
+	tmp = 1 + ovar;
+	tmp = 1 - ovar;
+	tmp = 1 / ovar;
+	tmp = 1 * ovar;
+	tmp = 1 << ovar;
+	tmp = 1 >> ovar;
+	tmp = 1 & ovar;
+	tmp = 1 | ovar;
+	tmp = 1 ^ ovar;
+
+	tmp += var;
+	tmp -= var;
+	tmp /= var;
+	tmp *= var;
+	tmp <<= var;
+	tmp >>= var;
+	tmp &= var;
+	tmp |= var;
+	tmp ^= var;
+
+	tmp += 1;
+	tmp -= 1;
+	tmp /= 1;
+	tmp *= 1;
+	tmp <<= 1;
+	tmp >>= 1;
+	tmp &= 1;
+	tmp |= 1;
+	tmp ^= 1;
+
+
+	utmp = var + ovar;
+	utmp = var - ovar;
+	utmp = var / ovar;
+	utmp = var * ovar;
+	utmp = var << ovar;
+	utmp = var >> ovar;
+	utmp = var & ovar;
+	utmp = var | ovar;
+	utmp = var ^ ovar;
+
+	utmp = var + 1;
+	utmp = var - 1;
+	utmp = var / 1;
+	utmp = var * 1;
+	utmp = var << 1;
+	utmp = var >> 1;
+	utmp = var & 1;
+	utmp = var | 1;
+	utmp = var ^ 1;
+
+	utmp = 1 + ovar;
+	utmp = 1 - ovar;
+	utmp = 1 / ovar;
+	utmp = 1 * ovar;
+	utmp = 1 << ovar;
+	utmp = 1 >> ovar;
+	utmp = 1 & ovar;
+	utmp = 1 | ovar;
+	utmp = 1 ^ ovar;
+
+	utmp += var;
+	utmp -= var;
+	utmp /= var;
+	utmp *= var;
+	utmp <<= var;
+	utmp >>= var;
+	utmp &= var;
+	utmp |= var;
+	utmp ^= var;
+
+	utmp += 1;
+	utmp -= 1;
+	utmp /= 1;
+	utmp *= 1;
+	utmp <<= 1;
+	utmp >>= 1;
+	utmp &= 1;
+	utmp |= 1;
+	utmp ^= 1;
+}
+
+void
+TracedVariableTest::run_signed_unsigned_tests (void)
+{
+	unsigned short utmp = 10;
+	unsigned int uitmp = 7;
+	short stmp = 5;
+	utmp = stmp;
+	utmp += stmp;
+	uitmp = utmp;
+	utmp = uitmp;
+
+	UiTracedVariable<unsigned short> uvar = 10;
+	UiTracedVariable<unsigned int> uivar = 5;
+	SiTracedVariable<short> svar = 5;
+	SiTracedVariable<int> sivar = 5;
+	uvar = svar;
+	svar = uvar;
+	uvar += svar;
+	svar += uvar;
+
+	uvar = sivar;
+	sivar = uvar;
+	uvar += sivar;
+	sivar += uvar;
+
+	uivar = uvar;
+	uvar = uivar;
+	uivar += uvar;
+	uvar += uivar;
+
+	sivar = svar;
+	svar = sivar;
+	sivar += svar;
+	svar += sivar;
+}
+
+bool 
+TracedVariableTest::run_tests (void)
+{
+	run_unsigned_tests ();
+	run_signed_unsigned_tests ();
+
+	return true;
+}
+
+TracedVariableTest::TracedVariableTest ()
+	: Test ("TracedVariable") {}
+
+static TracedVariableTest g_traced_variable_test;
+
+}; // namespace yans
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/ui-traced-variable.tcc	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,239 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2006 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#ifndef UI_TRACED_VARIABLE_TCC
+#define UI_TRACED_VARIABLE_TCC
+
+#include "yans/callback.h"
+#include <stdint.h>
+
+namespace yans {
+
+class UiTracedVariableBase {
+public:
+	typedef Callback<void, uint64_t, uint64_t> ChangeNotifyCallback;
+
+	UiTracedVariableBase ()
+		: m_callback () {}
+	/* We don't want to copy the base callback. Only set_callback on
+	 * a specific instance will do something to it. */
+	UiTracedVariableBase (UiTracedVariableBase const &o) 
+		: m_callback () {}
+	UiTracedVariableBase &operator = (UiTracedVariableBase const &o) {
+		return *this;
+	}
+	~UiTracedVariableBase () {}
+
+	void set_callback(ChangeNotifyCallback callback) {
+		m_callback = callback;
+	}
+protected:
+	void notify (uint64_t old_val, uint64_t new_val) {
+		if (old_val != new_val && !m_callback.is_null ()) {
+			m_callback (old_val, new_val);
+		}
+	}
+private:
+	ChangeNotifyCallback m_callback;
+};
+
+template <typename T>
+class SiTracedVariable;
+
+
+/**
+ * \brief trace variables of type "unsigned integer"
+ *
+ * This template class implements a POD type: it
+ * behaves like any other variable of type "unsigned integer"
+ * except that it also reports any changes to its
+ * value with its internal callback.
+ *
+ * To instantiate a 32-bit unsigned variable (to store
+ * a TCP counter for example), you would create a variable of type
+ * yans::UiTracedVariable<uint32_t> :
+ \code
+ #include <stdint.h>
+ #include "yans/ui-traced-variable.tcc"
+
+ yans::UiTracedVariable<uint32_t> var;
+ \endcode
+ * and you would use it like any other variable of type uint32_t:
+ \code
+ var += 12;
+ var = 10;
+ \endcode
+ */
+template <typename T>
+class UiTracedVariable : public UiTracedVariableBase {
+public:
+	UiTracedVariable ()
+		: m_var ()
+	{}
+	UiTracedVariable (T const &var) 
+		: m_var (var)
+	{}
+
+	UiTracedVariable &operator = (UiTracedVariable const &o) {
+		assign (o.get ());
+		return *this;
+	}
+	template <typename TT>
+	UiTracedVariable &operator = (UiTracedVariable<TT> const &o) {
+		assign (o.get ());
+		return *this;
+	}
+	template <typename TT>
+	UiTracedVariable &operator = (SiTracedVariable<TT> const &o) {
+		assign (o.get ());
+		return *this;
+	}
+	UiTracedVariable &operator++ () {
+		assign (get () + 1);
+		return *this;
+	}
+	UiTracedVariable &operator-- () {
+		assign (get () - 1);
+		return *this;
+	}
+	UiTracedVariable operator++ (int) {
+		UiTracedVariable old (*this);
+		++*this;
+		return old;
+	}
+	UiTracedVariable operator-- (int) {
+		UiTracedVariable old (*this);
+		--*this;
+		return old;
+	}
+	operator T () const {
+		return get ();
+	}
+
+
+	void assign (T var) {
+		notify (m_var, var);
+		m_var = var;
+	}
+        T get (void) const {
+		return m_var;
+	}
+
+private:
+	T m_var;
+};
+
+template <typename T>
+UiTracedVariable<T> &operator += (UiTracedVariable<T> &lhs, UiTracedVariable<T> const &rhs) {
+	lhs.assign (lhs.get () + rhs.get ());
+	return lhs;
+}
+template <typename T>
+UiTracedVariable<T> &operator -= (UiTracedVariable<T> &lhs, UiTracedVariable<T> const &rhs) {
+	lhs.assign (lhs.get () - rhs.get ());
+	return lhs;
+}
+template <typename T>
+UiTracedVariable<T> &operator *= (UiTracedVariable<T> &lhs, UiTracedVariable<T> const &rhs) {
+	lhs.assign (lhs.get () * rhs.get ());
+	return lhs;
+}
+template <typename T>
+UiTracedVariable<T> &operator /= (UiTracedVariable<T> &lhs, UiTracedVariable<T> const &rhs) {
+	lhs.assign (lhs.get () / rhs.get ());
+	return lhs;
+}
+template <typename T>
+UiTracedVariable<T> &operator <<= (UiTracedVariable<T> &lhs, UiTracedVariable<T> const &rhs) {
+	lhs.assign (lhs.get () << rhs.get ());
+	return lhs;
+}
+template <typename T>
+UiTracedVariable<T> &operator >>= (UiTracedVariable<T> &lhs, UiTracedVariable<T> const &rhs) {
+	lhs.assign (lhs.get () >> rhs.get ());
+	return lhs;
+}
+template <typename T>
+UiTracedVariable<T> &operator &= (UiTracedVariable<T> &lhs, UiTracedVariable<T> const &rhs) {
+	lhs.assign (lhs.get () & rhs.get ());
+	return lhs;
+}
+template <typename T>
+UiTracedVariable<T> &operator |= (UiTracedVariable<T> &lhs, UiTracedVariable<T> const &rhs) {
+	lhs.assign (lhs.get () | rhs.get ());
+	return lhs;
+}
+template <typename T>
+UiTracedVariable<T> &operator ^= (UiTracedVariable<T> &lhs, UiTracedVariable<T> const &rhs) {
+	lhs.assign (lhs.get () ^ rhs.get ());
+	return lhs;
+}
+
+
+template <typename T, typename U>
+UiTracedVariable<T> &operator += (UiTracedVariable<T> &lhs, U const &rhs) {
+	lhs.assign (lhs.get () + rhs);
+	return lhs;
+}
+template <typename T, typename U>
+UiTracedVariable<T> &operator -= (UiTracedVariable<T> &lhs, U const &rhs) {
+	lhs.assign (lhs.get () - rhs);
+	return lhs;
+}
+template <typename T, typename U>
+UiTracedVariable<T> &operator *= (UiTracedVariable<T> &lhs, U const &rhs) {
+	lhs.assign (lhs.get () * rhs);
+	return lhs;
+}
+template <typename T, typename U>
+UiTracedVariable<T> &operator /= (UiTracedVariable<T> &lhs, U const &rhs) {
+	lhs.assign (lhs.get () / rhs);
+	return lhs;
+}
+template <typename T, typename U>
+UiTracedVariable<T> &operator <<= (UiTracedVariable<T> &lhs, U const &rhs) {
+	lhs.assign (lhs.get () << rhs);
+	return lhs;
+}
+template <typename T, typename U>
+UiTracedVariable<T> &operator >>= (UiTracedVariable<T> &lhs, U const &rhs) {
+	lhs.assign (lhs.get () >> rhs);
+	return lhs;
+}
+template <typename T, typename U>
+UiTracedVariable<T> &operator &= (UiTracedVariable<T> &lhs, U const &rhs) {
+	lhs.assign (lhs.get () & rhs);
+	return lhs;
+}
+template <typename T, typename U>
+UiTracedVariable<T> &operator |= (UiTracedVariable<T> &lhs, U const &rhs) {
+	lhs.assign (lhs.get () | rhs);
+	return lhs;
+}
+template <typename T, typename U>
+UiTracedVariable<T> &operator ^= (UiTracedVariable<T> &lhs, U const &rhs) {
+	lhs.assign (lhs.get () ^ rhs);
+	return lhs;
+}
+
+}; // namespace yans
+
+#endif /* UI_TRACED_VARIABLE_TCC */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/utils.cc	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,293 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2005 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#include "utils.h"
+
+namespace yans {
+
+uint16_t 
+utils_hton_16 (uint16_t v)
+{
+	uint8_t array[2];
+	array[0] = (v >> 8) & 0xff;
+	array[1] = (v >> 0) & 0xff;
+	return *((uint16_t *)array);
+}
+uint32_t 
+utils_hton_32 (uint32_t v)
+{
+	uint8_t array[4];
+	array[0] = (v >> 24) & 0xff;
+	array[1] = (v >> 16) & 0xff;
+	array[2] = (v >>  8) & 0xff;
+	array[3] = (v >>  0) & 0xff;
+	return *((uint32_t *)array);
+}
+uint16_t 
+utils_ntoh_16 (uint16_t v)
+{
+	uint16_t val;
+	uint8_t *array;
+	array = (uint8_t *)&v;
+	val = (array[0] << 8) | (array[1] << 0);
+	return val;
+}
+uint32_t 
+utils_ntoh_32 (uint32_t v)
+{
+	uint32_t val = 0;
+	uint8_t *array = (uint8_t *)&v;
+	val |= array[0] << 24;
+	val |= array[1] << 16;
+	val |= array[2] << 8;
+	val |= array[3] << 0;
+	return val;
+}
+
+#define ASCII_DOT (0x2e)
+#define ASCII_ZERO (0x30)
+#define ASCII_A (0x41)
+#define ASCII_Z (0x5a)
+#define ASCII_a (0x61)
+#define ASCII_z (0x7a)
+#define ASCII_COLON (0x3a)
+
+
+uint32_t 
+ascii_to_ipv4_host (char const *address)
+{
+	uint32_t host = 0;
+	while (true) {
+		uint8_t byte = 0;
+		while (*address != ASCII_DOT &&
+		       *address != 0) {
+			byte *= 10;
+			byte += *address - ASCII_ZERO;
+			address++;
+		}
+		host <<= 8;
+		host |= byte;
+		if (*address == 0) {
+			break;
+		}
+		address++;
+	}
+	return host;
+}
+
+
+char
+ascii_to_low_case (char c)
+{
+	if (c >= ASCII_a && c <= ASCII_z) {
+		return c;
+	} else if (c >= ASCII_A && c <= ASCII_Z) {
+		return c + (ASCII_a - ASCII_A);
+	} else {
+		return c;
+	}
+}
+void 
+ascii_to_mac_network (char const *str, uint8_t address[6])
+{
+	uint8_t i = 0;
+	while (*str != 0 && i < 6) {
+		uint8_t byte = 0;
+		while (*str != ASCII_COLON && *str != 0) {
+			byte <<= 4;
+			char low = ascii_to_low_case (*str);
+			if (low >= ASCII_a) {
+				byte |= low - ASCII_a + 10;
+			} else {
+				byte |= low - ASCII_ZERO;
+			}
+			str++;
+		}
+		address[i] = byte;
+		str++;
+		i++;
+	}
+}
+
+uint16_t 
+utils_checksum_calculate (uint16_t checksum, uint8_t *buffer, uint16_t size)
+{
+	/* see RFC 1071 to understand this code. */
+	uint32_t sum = checksum;
+	uint16_t *data = (uint16_t *) buffer;
+	for (uint16_t i = 0; i < (size/2); i++) {
+		sum += data[i];
+	}
+	if ((size % 2) != 0) {
+		uint8_t tmp_buf[2];
+		tmp_buf[0] = buffer[size-1];
+		tmp_buf[1] = 0;
+		data = (uint16_t *)tmp_buf;
+		sum += *data;
+	}
+	while (sum >> 16) {
+		sum = (sum & 0xffff) + (sum >> 16);
+	}
+	return sum;
+}
+
+uint16_t 
+utils_checksum_complete (uint16_t checksum)
+{
+	return ~checksum;
+}
+
+
+}; // namespace yans
+
+
+#ifdef RUN_SELF_TESTS
+#include "yans/test.h"
+namespace yans {
+
+class UtilsTest : public Test {
+public:
+	UtilsTest ();
+	virtual bool run_tests (void);
+private:
+	bool test_ipv4_ascii_to_host (char const *str, uint32_t expected);
+	bool test_mac_ascii (char const *str, uint8_t expected[6]);
+	bool test_hton_16 (uint16_t v, uint8_t expected[2]);
+};
+bool
+UtilsTest::test_ipv4_ascii_to_host (char const *str, uint32_t expected)
+{
+	if (ascii_to_ipv4_host (str) != expected) {
+		failure () << "Utils ascii to host --"
+			   << " for: \"" << str << "\""
+			   << " expected: " << expected
+			   << " got: " << ascii_to_ipv4_host (str)
+			   << std::endl;
+		return false;
+	}
+	return true;
+}
+
+bool
+UtilsTest::test_mac_ascii (char const *str, uint8_t expected[6])
+{
+	uint8_t got[6];
+	ascii_to_mac_network (str, got);
+	for (uint8_t i = 0; i < 6; i++) {
+		if (got[i] != expected[i]) {
+			failure () << "Utils ascii to mac --"
+				   << " for: \"" << str << "\""
+				   << " expected: ";
+			failure ().setf (std::ios::hex, std::ios::basefield);
+			failure () << (uint32_t)expected[0] << ":"
+				   << (uint32_t)expected[1] << ":"
+				   << (uint32_t)expected[2] << ":"
+				   << (uint32_t)expected[3] << ":"
+				   << (uint32_t)expected[4] << ":"
+				   << (uint32_t)expected[5];
+			failure ().setf (std::ios::dec, std::ios::basefield);
+			failure () << " got: ";
+			failure ().setf (std::ios::hex, std::ios::basefield);
+			failure () << (uint32_t)got[0] << ":"
+				   << (uint32_t)got[1] << ":"
+				   << (uint32_t)got[2] << ":"
+				   << (uint32_t)got[3] << ":"
+				   << (uint32_t)got[4] << ":"
+				   << (uint32_t)got[5];
+			failure ().setf (std::ios::dec, std::ios::basefield);
+			failure () << std::endl;
+			return false;
+		}
+	}
+	return true;
+}
+
+bool
+UtilsTest::test_hton_16 (uint16_t v, uint8_t expected[2])
+{
+	uint16_t result = utils_hton_16 (v);
+	uint8_t *got = (uint8_t *)&result;
+	if (got[0] != expected[0] ||
+	    got[1] != expected[1]) {
+		failure () << "Utils hton 16 --"
+			   << " for: \"" << v << "\""
+			   << " expected: ";
+		failure ().setf (std::ios::hex, std::ios::basefield);
+		failure () << (uint32_t)expected[0] << ":"
+			   << (uint32_t)expected[1];
+		failure () << " got: ";
+		failure () << (uint32_t)got[0] << ":"
+			   << (uint32_t)got[1];
+		failure ().setf (std::ios::dec, std::ios::basefield);
+		failure () << std::endl;
+		return false;
+	}
+	return true;
+}
+
+#define TEST_IPV4_ASCII_TO_HOST(a,b)  \
+if (!test_ipv4_ascii_to_host (a,b)) { \
+	ok = false;                   \
+}
+
+#define TEST_MAC_ASCII(ad, a, b, c, d, e, f)       \
+{                                                  \
+	uint8_t expected[6] = {a, b, c, d, e, f};  \
+	if (!test_mac_ascii (ad, expected)) {      \
+		ok = false;                        \
+	}                                          \
+}
+
+#define TEST_HTON_16(v, a, b)               \
+{                                           \
+	uint8_t expected[2] = {a, b};       \
+	if (!test_hton_16 (v, expected)) {  \
+		ok = false;                 \
+	}                                   \
+}
+
+
+UtilsTest::UtilsTest ()
+	: Test ("Utils") {}
+
+bool 
+UtilsTest::run_tests (void)
+{
+	bool ok = true;
+	TEST_IPV4_ASCII_TO_HOST ("255.255.255.255", 0xffffffff);
+	TEST_IPV4_ASCII_TO_HOST ("255.255.255.0", 0xffffff00);
+	TEST_IPV4_ASCII_TO_HOST ("255.255.255.00", 0xffffff00);
+	TEST_IPV4_ASCII_TO_HOST ("255.255.255.000", 0xffffff00);
+	TEST_IPV4_ASCII_TO_HOST ("255.255.255.0000", 0xffffff00);
+	TEST_IPV4_ASCII_TO_HOST ("255.255.0.255", 0xffff00ff);
+	TEST_IPV4_ASCII_TO_HOST ("192.168.0.1", 0xc0a80001);
+	TEST_IPV4_ASCII_TO_HOST ("0.168.0.1", 0x00a80001);
+	TEST_MAC_ASCII ("00:00:00:00:00:00", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
+	TEST_MAC_ASCII ("00:00:00:00:00:01", 0x00, 0x00, 0x00, 0x00, 0x00, 0x01);
+	TEST_MAC_ASCII ("01:00:00:00:00:01", 0x01, 0x00, 0x00, 0x00, 0x00, 0x01);
+	TEST_MAC_ASCII ("ff:00:00:ff:00:01", 0xff, 0x00, 0x00, 0xff, 0x00, 0x01);
+	TEST_MAC_ASCII ("f0:00:00:00:5d:01", 0xf0, 0x00, 0x00, 0x00, 0x5d, 0x01);
+	TEST_HTON_16 (0xf00f, 0xf0, 0x0f);
+	return ok;
+}
+static UtilsTest g_utils_test;
+}; //namespace yans
+#endif /* RUN_SELF_TESTS */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/utils.h	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,43 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2005 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#ifndef UTILS_H
+#define UTILS_H
+
+#include <stdint.h>
+
+namespace yans {
+
+uint16_t utils_hton_16 (uint16_t v);
+uint32_t utils_hton_32 (uint32_t v);
+uint16_t utils_ntoh_16 (uint16_t v);
+uint32_t utils_ntoh_32 (uint32_t v);
+
+uint32_t ascii_to_ipv4_host (char const *address);
+void ascii_to_mac_network (char const *str, uint8_t address[6]);
+
+/* call with checksum = 0 the first time. */
+uint16_t utils_checksum_calculate (uint16_t checksum, uint8_t *buffer, uint16_t size);
+uint16_t utils_checksum_complete (uint16_t checksum);
+
+}; // namespace yans
+
+#endif /* UTILS_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/callback-test.cc	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,197 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2005,2006 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#include "test.h"
+#include "callback.h"
+#include <stdint.h>
+
+#ifdef RUN_SELF_TESTS
+
+namespace yans {
+
+static bool g_test5 = false;
+static bool g_test6 = false;
+static bool g_test7 = false;
+
+void test5 (void)
+{
+	g_test5 = true;
+}
+
+void test6 (int)
+{
+	g_test6 = true;
+}
+
+int test7 (int a)
+{
+	g_test7 = true;
+	return a;
+}
+
+class CallbackTest : public yans::Test {
+private:
+	bool m_test1;
+	bool m_test2;
+	bool m_test3;
+	bool m_test4;
+public:
+	CallbackTest ();
+	virtual bool run_tests (void);
+	void reset (void);
+	bool is_wrong (void);
+	void test1 (void);
+	int test2 (void);
+	void test3 (double a);
+	int test4 (double a, int b);
+	void test8 (Callback<void, int> callback);
+};
+
+CallbackTest::CallbackTest ()
+	: yans::Test ("Callback"),
+	  m_test1 (false),
+	  m_test2 (false),
+	  m_test3 (false),
+	  m_test4 (false)
+{}
+
+void 
+CallbackTest::test1 (void)
+{
+	m_test1 = true;
+}
+int 
+CallbackTest::test2 (void)
+{
+	m_test2 = true;
+	return 2;
+}
+void 
+CallbackTest::test3 (double a)
+{
+	m_test3 = true;
+}
+int 
+CallbackTest::test4 (double a, int b)
+{
+	m_test4 = true;
+	return 4;
+}
+void
+CallbackTest::test8 (Callback<void,int> callback)
+{
+	callback (3);
+}
+bool
+CallbackTest::is_wrong (void)
+{
+	if (!m_test1 ||
+	    !m_test2 ||
+	    !m_test3 ||
+	    !m_test4 ||
+	    !g_test5 ||
+	    !g_test6 ||
+	    !g_test7) {
+		return true;
+	}
+	return false;
+}
+
+void
+CallbackTest::reset (void)
+{
+	m_test1 = false;
+	m_test2 = false;
+	m_test3 = false;
+	m_test4 = false;
+	g_test5 = false;
+	g_test6 = false;
+	g_test7 = false;
+}
+
+  
+bool 
+CallbackTest::run_tests (void)
+{
+	bool ok = true;
+
+	typedef yans::Callback<void> A;
+	typedef yans::Callback<int> B;
+	typedef yans::Callback<void, double> C;
+	typedef yans::Callback<int, double, int> D;
+	typedef yans::Callback<void> E;
+	typedef yans::Callback<void,int> F;
+	typedef yans::Callback<int,int> G;
+	
+	A a0 (this, &CallbackTest::test1);
+	B b0;
+	b0 = B (this, &CallbackTest::test2);
+	C c0 = C (this, &CallbackTest::test3);
+	D d0 = D (this, &CallbackTest::test4);
+	E e0 = E (&test5);
+	F f0 = F (&test6);
+	G g0 = G (&test7);
+
+	a0 ();
+	b0 ();
+	c0 (0.0);
+	d0 (0.0, 1);
+	e0 ();
+	f0 (1);
+	g0 (1);
+
+	if (is_wrong ()) {
+		ok = false;
+	}
+
+	reset ();
+
+	A a1 = yans::make_callback (&CallbackTest::test1, this);
+	B b1 = yans::make_callback (&CallbackTest::test2, this);
+	C c1 = yans::make_callback (&CallbackTest::test3, this);
+	D d1 = yans::make_callback (&CallbackTest::test4, this);
+	E e1 = yans::make_callback (&test5);
+	F f1 = yans::make_callback (&test6);
+	G g1 = yans::make_callback (&test7);
+	
+	a1 ();
+	b1 ();
+	c1 (0.0);
+	d1 (0.0, 1);
+	e1 ();
+	f1 (1);
+	g1 (2);
+
+	test8 (f1);
+
+	Callback<void, int64_t,int64_t> a2;
+
+	if (is_wrong ()) {
+		ok = false;
+	}
+	return ok;
+}
+
+static CallbackTest g_callback_test;
+
+}; // namespace
+
+#endif /* RUN_SELF_TESTS */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/callback.h	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,518 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2005,2006 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#ifndef CALLBACK_H
+#define CALLBACK_H
+
+#include "reference-list.h"
+
+namespace yans {
+
+/***
+ * \internal
+ * This code was originally written based on the techniques 
+ * described in http://www.codeproject.com/cpp/TTLFunction.asp
+ * It was subsequently rewritten to follow the architecture
+ * outlined in "Modern C++ Design" by Andrei Alexandrescu in 
+ * chapter 5, "Generalized Functors".
+ *
+ * This code uses:
+ *   - default template parameters to saves users from having to
+ *     specify empty parameters when the number of parameters
+ *     is smaller than the maximum supported number
+ *   - the pimpl idiom: the Callback class is passed around by 
+ *     value and delegates the crux of the work to its pimpl
+ *     pointer.
+ *   - two pimpl implementations which derive from CallbackImpl
+ *     FunctorCallbackImpl can be used with any functor-type
+ *     while MemPtrCallbackImpl can be used with pointers to
+ *     member functions.
+ *   - a reference list implementation to implement the Callback's
+ *     value semantics.
+ *
+ * This code most notably departs from the alexandrescu 
+ * implementation in that it does not use type lists to specify
+ * and pass around the types of the callback arguments.
+ * Of course, it also does not use copy-destruction semantics
+ * and relies on a reference list rather than auto_ptr to hold
+ * the pointer.
+ */
+class empty {};
+
+// declare the CallbackImpl class
+template <typename R, typename T1, typename T2, typename T3, typename T4, typename T5>
+class CallbackImpl;
+// define CallbackImpl for 0 params
+template <typename R>
+class CallbackImpl<R,empty,empty,empty,empty,empty> {
+public:
+	virtual ~CallbackImpl () {}
+	virtual R operator() (void) = 0;
+};
+// define CallbackImpl for 1 params
+template <typename R, typename T1>
+class CallbackImpl<R,T1,empty,empty,empty,empty> {
+public:
+	virtual ~CallbackImpl () {}
+	virtual R operator() (T1) = 0;
+};
+// define CallbackImpl for 2 params
+template <typename R, typename T1, typename T2>
+class CallbackImpl<R,T1,T2,empty,empty,empty> {
+public:
+	virtual ~CallbackImpl () {}
+	virtual R operator() (T1, T2) = 0;
+};
+// define CallbackImpl for 3 params
+template <typename R, typename T1, typename T2, typename T3>
+class CallbackImpl<R,T1,T2,T3,empty,empty> {
+public:
+	virtual ~CallbackImpl () {}
+	virtual R operator() (T1, T2, T3) = 0;
+};
+// define CallbackImpl for 4 params
+template <typename R, typename T1, typename T2, typename T3, typename T4>
+class CallbackImpl<R,T1,T2,T3,T4,empty> {
+public:
+	virtual ~CallbackImpl () {}
+	virtual R operator() (T1, T2, T3, T4) = 0;
+};
+// define CallbackImpl for 5 params
+template <typename R, typename T1, typename T2, typename T3, typename T4, typename T5>
+class CallbackImpl {
+public:
+	virtual ~CallbackImpl () {}
+	virtual R operator() (T1, T2, T3, T4, T5) = 0;
+};
+
+
+// an impl for Functors:
+template <typename T, typename R, typename T1, typename T2, typename T3, typename T4,typename T5>
+class FunctorCallbackImpl : public CallbackImpl<R,T1,T2,T3,T4,T5> {
+public:
+	FunctorCallbackImpl (T const &functor)
+		: m_functor (functor) {}
+	virtual ~FunctorCallbackImpl () {}
+	R operator() (void) {
+		return m_functor ();
+	}
+	R operator() (T1 a1) {
+		return m_functor (a1);
+	}
+	R operator() (T1 a1,T2 a2) {
+		return m_functor (a1,a2);
+	}
+	R operator() (T1 a1,T2 a2,T3 a3) {
+		return m_functor (a1,a2,a3);
+	}
+	R operator() (T1 a1,T2 a2,T3 a3,T4 a4) {
+		return m_functor (a1,a2,a3,a4);
+	}
+	R operator() (T1 a1,T2 a2,T3 a3,T4 a4,T5 a5) {
+		return m_functor (a1,a2,a3,a4,a5);
+	}
+private:
+	T m_functor;
+};
+
+// an impl for Bound Functors:
+template <typename T, typename R, typename TX, typename T1, typename T2, typename T3, typename T4,typename T5>
+class BoundFunctorCallbackImpl : public CallbackImpl<R,T1,T2,T3,T4,T5> {
+public:
+	BoundFunctorCallbackImpl (T const &functor, TX a)
+		: m_functor (functor), m_a (a) {}
+	virtual ~BoundFunctorCallbackImpl () {}
+	R operator() (void) {
+		return m_functor (m_a);
+	}
+	R operator() (T1 a1) {
+		return m_functor (m_a,a1);
+	}
+	R operator() (T1 a1,T2 a2) {
+		return m_functor (m_a,a1,a2);
+	}
+	R operator() (T1 a1,T2 a2,T3 a3) {
+		return m_functor (m_a,a1,a2,a3);
+	}
+	R operator() (T1 a1,T2 a2,T3 a3,T4 a4) {
+		return m_functor (m_a,a1,a2,a3,a4);
+	}
+	R operator() (T1 a1,T2 a2,T3 a3,T4 a4,T5 a5) {
+		return m_functor (m_a,a1,a2,a3,a4,a5);
+	}
+private:
+	T m_functor;
+	TX m_a;
+};
+
+
+// an impl for pointer to member functions
+template <typename OBJ_PTR, typename MEM_PTR, typename R, typename T1, typename T2, typename T3, typename T4, typename T5>
+class MemPtrCallbackImpl : public CallbackImpl<R,T1,T2,T3,T4,T5> {
+public:
+	MemPtrCallbackImpl (OBJ_PTR const&obj_ptr, MEM_PTR mem_ptr)
+		: m_obj_ptr (obj_ptr), m_mem_ptr (mem_ptr) {}
+	virtual ~MemPtrCallbackImpl () {}
+	R operator() (void) {
+		return ((*m_obj_ptr).*m_mem_ptr) ();
+	}
+	R operator() (T1 a1) {
+		return ((*m_obj_ptr).*m_mem_ptr) (a1);
+	}
+	R operator() (T1 a1,T2 a2) {
+		return ((*m_obj_ptr).*m_mem_ptr) (a1,a2);
+	}
+	R operator() (T1 a1,T2 a2,T3 a3) {
+		return ((*m_obj_ptr).*m_mem_ptr) (a1,a2,a3);
+	}
+	R operator() (T1 a1,T2 a2,T3 a3,T4 a4) {
+		return ((*m_obj_ptr).*m_mem_ptr) (a1,a2,a3,a4);
+	}
+	R operator() (T1 a1,T2 a2,T3 a3,T4 a4,T5 a5) {
+		return ((*m_obj_ptr).*m_mem_ptr) (a1,a2,a3,a4,a5);
+	}
+private:
+	OBJ_PTR const m_obj_ptr;
+	MEM_PTR m_mem_ptr;
+};
+
+/**
+ * \brief Callback template class
+ *
+ * This class template implements the Functor Design Pattern.
+ * It is used to declare the type of a Callback:
+ *  - the first non-optional template argument represents
+ *    the return type of the callback.
+ *  - the second optional template argument represents
+ *    the type of the first argument to the callback.
+ *  - the third optional template argument represents
+ *    the type of the second argument to the callback.
+ *  - the fourth optional template argument represents
+ *    the type of the third argument to the callback.
+ *  - the fifth optional template argument represents
+ *    the type of the fourth argument to the callback.
+ *  - the sixth optional template argument represents
+ *    the type of the fifth argument to the callback.
+ *
+ * Callback instances are built with the \ref make_callback
+ * template functions. Callback instances have POD semantics:
+ * the memory they allocate is managed automatically, without
+ * user intervention which allows you to pass around Callback
+ * instances by value.
+ *
+ * Sample code which shows how to use this class template 
+ * as well as the function templates \ref make_callback :
+ * \include samples/main-callback.cc
+ */
+template<typename R, 
+	 typename T1 = empty, typename T2 = empty, 
+	 typename T3 = empty, typename T4 = empty,
+	 typename T5 = empty>
+class Callback {
+public:
+	template <typename FUNCTOR>
+	Callback (FUNCTOR const &functor) 
+		: m_impl (new FunctorCallbackImpl<FUNCTOR,R,T1,T2,T3,T4,T5> (functor))
+	{}
+
+	template <typename OBJ_PTR, typename MEM_PTR>
+	Callback (OBJ_PTR const &obj_ptr, MEM_PTR mem_ptr)
+		: m_impl (new MemPtrCallbackImpl<OBJ_PTR,MEM_PTR,R,T1,T2,T3,T4,T5> (obj_ptr, mem_ptr))
+	{}
+
+	Callback (ReferenceList<CallbackImpl<R,T1,T2,T3,T4,T5> *> const &impl)
+		: m_impl (impl)
+	{}
+
+	bool is_null (void) {
+		return (m_impl.get () == 0)?true:false;
+	}
+
+	Callback () : m_impl () {}
+	R operator() (void) {
+		return (*(m_impl.get ())) ();
+	}
+	R operator() (T1 a1) {
+		return (*(m_impl.get ())) (a1);
+	}
+	R operator() (T1 a1, T2 a2) {
+		return (*(m_impl).get ()) (a1,a2);
+	}
+	R operator() (T1 a1, T2 a2, T3 a3) {
+		return (*(m_impl).get ()) (a1,a2,a3);
+	}
+	R operator() (T1 a1, T2 a2, T3 a3, T4 a4) {
+		return (*(m_impl).get ()) (a1,a2,a3,a4);
+	}
+	R operator() (T1 a1, T2 a2, T3 a3, T4 a4,T5 a5) {
+		return (*(m_impl).get ()) (a1,a2,a3,a4,a5);
+	}
+private:
+	ReferenceList<CallbackImpl<R,T1,T2,T3,T4,T5>*> m_impl;
+};
+
+/**
+ * \defgroup make_callback make_callback
+ *
+ */
+
+/**
+ * \ingroup make_callback
+ * \param mem_ptr class method member pointer
+ * \param obj_ptr class instance
+ * \return a wrapper Callback
+ * Build Callbacks for class method members which takes no arguments
+ * and potentially return a value.
+ */
+template <typename OBJ, typename R>
+Callback<R> make_callback (R (OBJ::*mem_ptr) (), OBJ *const obj_ptr) {
+	return Callback<R> (obj_ptr, mem_ptr);
+}
+/**
+ * \ingroup make_callback
+ * \param mem_ptr class method member pointer
+ * \param obj_ptr class instance
+ * \return a wrapper Callback
+ * Build Callbacks for class method members which takes one argument
+ * and potentially return a value.
+ */
+template <typename OBJ, typename R, typename T1>
+Callback<R,T1> make_callback (R (OBJ::*mem_ptr) (T1), OBJ *const obj_ptr) {
+	return Callback<R,T1> (obj_ptr, mem_ptr);
+}
+/**
+ * \ingroup make_callback
+ * \param mem_ptr class method member pointer
+ * \param obj_ptr class instance
+ * \return a wrapper Callback
+ * Build Callbacks for class method members which takes two arguments
+ * and potentially return a value.
+ */
+template <typename OBJ, typename R, typename T1, typename T2>
+Callback<R,T1,T2> make_callback (R (OBJ::*mem_ptr) (T1,T2), OBJ *const obj_ptr) {
+	return Callback<R,T1,T2> (obj_ptr, mem_ptr);
+}
+/**
+ * \ingroup make_callback
+ * \param mem_ptr class method member pointer
+ * \param obj_ptr class instance
+ * \return a wrapper Callback
+ * Build Callbacks for class method members which takes three arguments
+ * and potentially return a value.
+ */
+template <typename OBJ, typename R, typename T1,typename T2, typename T3>
+Callback<R,T1,T2,T3> make_callback (R (OBJ::*mem_ptr) (T1,T2,T3), OBJ *const obj_ptr) {
+	return Callback<R,T1,T2,T3> (obj_ptr, mem_ptr);
+}
+/**
+ * \ingroup make_callback
+ * \param mem_ptr class method member pointer
+ * \param obj_ptr class instance
+ * \return a wrapper Callback
+ * Build Callbacks for class method members which takes four arguments
+ * and potentially return a value.
+ */
+template <typename OBJ, typename R, typename T1, typename T2, typename T3, typename T4>
+Callback<R,T1,T2,T3,T4> make_callback (R (OBJ::*mem_ptr) (T1,T2,T3,T4), OBJ *const obj_ptr) {
+	return Callback<R,T1,T2,T3,T4> (obj_ptr, mem_ptr);
+}
+/**
+ * \ingroup make_callback
+ * \param mem_ptr class method member pointer
+ * \param obj_ptr class instance
+ * \return a wrapper Callback
+ * Build Callbacks for class method members which takes five arguments
+ * and potentially return a value.
+ */
+template <typename OBJ, typename R, typename T1, typename T2, typename T3, typename T4,typename T5>
+Callback<R,T1,T2,T3,T4,T5> make_callback (R (OBJ::*mem_ptr) (T1,T2,T3,T4,T5), OBJ *const obj_ptr) {
+	return Callback<R,T1,T2,T3,T4,T5> (obj_ptr, mem_ptr);
+}
+
+/**
+ * \ingroup make_callback
+ * \param fn_ptr function pointer
+ * \return a wrapper Callback
+ * Build Callbacks for functions which takes no arguments
+ * and potentially return a value.
+ */
+template <typename R>
+Callback<R> make_callback (R (*fn_ptr) ()) {
+	return Callback<R> (fn_ptr);
+}
+/**
+ * \ingroup make_callback
+ * \param fn_ptr function pointer
+ * \return a wrapper Callback
+ * Build Callbacks for functions which takes one argument
+ * and potentially return a value.
+ */
+template <typename R, typename T1>
+Callback<R,T1> make_callback (R (*fn_ptr) (T1)) {
+	return Callback<R,T1> (fn_ptr);
+}
+/**
+ * \ingroup make_callback
+ * \param fn_ptr function pointer
+ * \return a wrapper Callback
+ * Build Callbacks for functions which takes two arguments
+ * and potentially return a value.
+ */
+template <typename R, typename T1, typename T2>
+Callback<R,T1,T2> make_callback (R (*fn_ptr) (T1,T2)) {
+	return Callback<R,T1,T2> (fn_ptr);
+}
+/**
+ * \ingroup make_callback
+ * \param fn_ptr function pointer
+ * \return a wrapper Callback
+ * Build Callbacks for functions which takes three arguments
+ * and potentially return a value.
+ */
+template <typename R, typename T1, typename T2,typename T3>
+Callback<R,T1,T2,T3> make_callback (R (*fn_ptr) (T1,T2,T3)) {
+	return Callback<R,T1,T2,T3> (fn_ptr);
+}
+/**
+ * \ingroup make_callback
+ * \param fn_ptr function pointer
+ * \return a wrapper Callback
+ * Build Callbacks for functions which takes four arguments
+ * and potentially return a value.
+ */
+template <typename R, typename T1, typename T2,typename T3,typename T4>
+Callback<R,T1,T2,T3,T4> make_callback (R (*fn_ptr) (T1,T2,T3,T4)) {
+	return Callback<R,T1,T2,T3,T4> (fn_ptr);
+}
+/**
+ * \ingroup make_callback
+ * \param fn_ptr function pointer
+ * \return a wrapper Callback
+ * Build Callbacks for functions which takes five arguments
+ * and potentially return a value.
+ */
+template <typename R, typename T1, typename T2,typename T3,typename T4,typename T5>
+Callback<R,T1,T2,T3,T4,T5> make_callback (R (*fn_ptr) (T1,T2,T3,T4,T5)) {
+	return Callback<R,T1,T2,T3,T4,T5> (fn_ptr);
+}
+
+
+
+/**
+ * \ingroup make_callback
+ * \return a wrapper Callback
+ * Build a null callback which takes no arguments
+ * and potentially return a value.
+ */
+template <typename R>
+Callback<R> make_null_callback (void) {
+	return Callback<R> ();
+}
+/**
+ * \ingroup make_callback
+ * \return a wrapper Callback
+ * Build a null callback which takes one argument
+ * and potentially return a value.
+ */
+template <typename R, typename T1>
+Callback<R,T1> make_null_callback (void) {
+	return Callback<R,T1> ();
+}
+/**
+ * \ingroup make_callback
+ * \return a wrapper Callback
+ * Build a null callback which takes two arguments
+ * and potentially return a value.
+ */
+template <typename R, typename T1, typename T2>
+Callback<R,T1,T2> make_null_callback (void) {
+	return Callback<R,T1,T2> ();
+}
+/**
+ * \ingroup make_callback
+ * \return a wrapper Callback
+ * Build a null callback which takes three arguments
+ * and potentially return a value.
+ */
+template <typename R, typename T1, typename T2,typename T3>
+Callback<R,T1,T2,T3> make_null_callback (void) {
+	return Callback<R,T1,T2,T3> ();
+}
+/**
+ * \ingroup make_callback
+ * \return a wrapper Callback
+ * Build a null callback which takes four arguments
+ * and potentially return a value.
+ */
+template <typename R, typename T1, typename T2,typename T3,typename T4>
+Callback<R,T1,T2,T3,T4> make_null_callback (void) {
+	return Callback<R,T1,T2,T3,T4> ();
+}
+/**
+ * \ingroup make_callback
+ * \return a wrapper Callback
+ * Build a null callback which takes five arguments
+ * and potentially return a value.
+ */
+template <typename R, typename T1, typename T2,typename T3,typename T4,typename T5>
+Callback<R,T1,T2,T3,T4,T5> make_null_callback (void) {
+	return Callback<R,T1,T2,T3,T4,T5> ();
+}
+
+template <typename R, typename TX, typename T1>
+Callback<R,T1> make_bound_callback (R (*fn_ptr) (TX,T1), TX a) {
+	ReferenceList<CallbackImpl<R,T1,empty,empty,empty,empty>*> impl =
+	ReferenceList<CallbackImpl<R,T1,empty,empty,empty,empty>*> (
+	new BoundFunctorCallbackImpl<R (*) (TX,T1),R,TX,T1,empty,empty,empty,empty> (fn_ptr, a)
+	);
+	return Callback<R,T1> (impl);
+}
+template <typename R, typename TX, typename T1, typename T2>
+Callback<R,T1,T2> make_bound_callback (R (*fn_ptr) (TX,T1,T2), TX a) {
+	ReferenceList<CallbackImpl<R,T1,T2,empty,empty,empty>*> impl =
+	ReferenceList<CallbackImpl<R,T1,T2,empty,empty,empty>*> (
+	new BoundFunctorCallbackImpl<R (*) (TX,T1,T2),R,TX,T1,T2,empty,empty,empty> (fn_ptr, a)
+	);
+	return Callback<R,T1,T2> (impl);
+}
+template <typename R, typename TX, typename T1, typename T2,typename T3,typename T4>
+Callback<R,T1,T2,T3,T4> make_bound_callback (R (*fn_ptr) (TX,T1,T2,T3,T4), TX a) {
+	ReferenceList<CallbackImpl<R,T1,T2,T3,T4,empty>*> impl =
+	ReferenceList<CallbackImpl<R,T1,T2,T3,T4,empty>*> (
+	new BoundFunctorCallbackImpl<R (*) (TX,T1,T2,T3,T4),R,TX,T1,T2,T3,T4,empty> (fn_ptr, a)
+	);
+	return Callback<R,T1,T2,T3,T4> (impl);
+}
+
+template <typename R, typename TX, typename T1, typename T2,typename T3,typename T4,typename T5>
+Callback<R,T1,T2,T3,T4,T5> make_bound_callback (R (*fn_ptr) (TX,T1,T2,T3,T4,T5), TX a) {
+	ReferenceList<CallbackImpl<R,T1,T2,T3,T4,T5>*> impl =
+	ReferenceList<CallbackImpl<R,T1,T2,T3,T4,T5>*> (
+	new BoundFunctorCallbackImpl<R (*) (TX,T1,T2,T3,T4,T5),R,TX,T1,T2,T3,T4,T5> (fn_ptr, a)
+	);
+	return Callback<R,T1,T2,T3,T4,T5> (impl);
+}
+
+
+}; // namespace yans
+
+
+#endif /* CALLBACK_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/exec-commands.h	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,58 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2006 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#ifndef EXEC_COMMANDS_H
+#define EXEC_COMMANDS_H
+
+#include <stdint.h>
+#include <string>
+#include <vector>
+#include "callback.h"
+
+namespace yans {
+
+class ExecCommandsPrivate;
+
+class Command {
+public:
+	void reset (void);
+	void append (std::string arg);
+	uint32_t get_n (void);
+	char const *get (uint32_t i);
+private:
+	typedef std::vector<std::string> Args;
+	Args m_args;
+};
+
+class ExecCommands {
+public:
+	typedef Callback<void,char const *,uint32_t> CommandCallback;
+	ExecCommands (uint32_t pool_size);
+	void enable_log (char const *main_log);
+	void add (Command command, char const *id);
+	void start (void);
+	uint32_t get_size (void);
+private:
+	ExecCommandsPrivate *m_priv;
+};
+
+};
+
+#endif /* EXEC_COMMANDS_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/reference-list-test.cc	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,120 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2006 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#include "reference-list.h"
+#include "test.h"
+
+#ifdef RUN_SELF_TESTS
+
+#define noREFTEST_DEBUG 1
+
+#ifdef REFTEST_DEBUG 
+#include <iostream>
+#define TRACE(x) \
+	std::cout << x << std::endl;
+#else
+#define TRACE(x)
+#endif
+
+namespace {
+
+class A {
+public:
+	A () {
+		TRACE ("constructor");
+	}
+	~A () {
+		TRACE ("destructor");
+	}
+	void trace (void) {
+		TRACE ("trace");
+	}
+};
+
+class RefTest : public yans::Test {
+public:
+	RefTest ();
+	virtual bool run_tests (void);
+private:
+	void test (yans::ReferenceList<A *>);
+};
+
+RefTest::RefTest ()
+	: yans::Test ("ReferenceList")
+{}
+
+void
+RefTest::test (yans::ReferenceList<A *> a) 
+{
+	a->trace ();
+}
+
+bool 
+RefTest::run_tests (void)
+{
+	bool ok = true;
+
+	{
+		yans::ReferenceList<A *> tmp;
+		{
+			yans::ReferenceList<A *> a (new A ());
+			
+			test (a);
+			tmp = a;
+			test (tmp);
+			a = tmp;
+			test (a);
+			TRACE ("leave inner scope");
+		}
+		test (tmp);
+		TRACE ("leave outer scope");
+	}
+
+	{
+		yans::ReferenceList<A *> tmp;
+	}
+
+	{
+		yans::ReferenceList<A *> tmp (new A ());
+	}
+
+	{
+		yans::ReferenceList<A *> tmp;
+		tmp.set (new A ());
+	}
+
+	{
+		TRACE ("test assignement");
+		yans::ReferenceList<A *> a0 (new A ());
+		yans::ReferenceList<A *> a1 (new A ());
+		a0 = a1;
+	}
+
+
+
+	return ok;
+}
+
+
+static RefTest g_ref_test = RefTest ();
+
+}; // namespace
+
+#endif /* RUN_SELF_TESTS */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/reference-list.h	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,117 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2006 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#ifndef REFERENCE_LIST_H
+#define REFERENCE_LIST_H
+
+/* This is a reference list implementation. The technique underlying
+ * this code was first described in 1995 by Risto Lankinen on Usenet
+ * but I have never been able to find his original posting. Instead,
+ * this code is based on the description of the technique found in
+ * "Modern C++ design" by Andrei Alexandrescu in chapter 7.
+ */
+
+
+namespace yans {
+
+template <typename OBJ_PTR>
+class ReferenceList;
+
+template <typename OBJ_PTR>
+class ReferenceList {
+public:
+	ReferenceList () 
+		:  m_obj_ptr (),
+		   m_prev (), 
+		   m_next () 
+	{
+		m_prev = this;
+		m_next = this;
+	}
+	ReferenceList (ReferenceList &o) 
+		: m_obj_ptr (),
+		  m_prev (), 
+		  m_next ()
+	{
+		m_prev = this;
+		m_next = this;
+		insert_self_in_other (o);
+	}
+	ReferenceList (ReferenceList const&o) 
+		: m_obj_ptr (),
+		  m_prev (), 
+		  m_next ()
+	{
+		m_prev = this;
+		m_next = this;
+		insert_self_in_other (o);
+	}
+	ReferenceList (OBJ_PTR const &obj_ptr)
+		: m_obj_ptr (obj_ptr), 
+		  m_prev (), 
+		  m_next ()
+	{
+		m_prev = this;
+		m_next = this;
+	}
+	~ReferenceList () {
+		remove_from_list ();
+	}
+	ReferenceList & operator= (ReferenceList const&o) {
+		remove_from_list ();
+		insert_self_in_other (o);
+		return *this;
+	}
+	OBJ_PTR operator-> () {
+		return m_obj_ptr;
+	}
+	void set (OBJ_PTR obj_ptr) {
+		remove_from_list ();
+		m_obj_ptr = obj_ptr;
+	}
+	OBJ_PTR get (void) {
+		// explicit conversion to raw pointer type.
+		return m_obj_ptr;
+	}
+private:
+	void insert_self_in_other (ReferenceList const&o) {
+		m_prev = &o;
+		m_next = o.m_next;
+		m_next->m_prev = this;
+		o.m_next = this;
+		m_obj_ptr = o.m_obj_ptr;
+	}
+	void remove_from_list (void) {
+		if (m_prev == this) {
+			//assert (m_next == this);
+			delete m_obj_ptr;
+			m_obj_ptr = OBJ_PTR ();
+		}
+		m_prev->m_next = m_next;
+		m_next->m_prev = m_prev;
+	}
+	OBJ_PTR m_obj_ptr;
+	mutable ReferenceList const*m_prev;
+	mutable ReferenceList const*m_next;
+};
+
+}; // namespace yans
+
+#endif /* REFERENCE_LIST_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/system-file.h	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,44 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2005 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#ifndef SYSTEM_FILE_H
+#define SYSTEM_FILE_H
+
+#include <stdint.h>
+
+namespace yans {
+
+class SystemFilePrivate;
+
+class SystemFile {
+public:
+	SystemFile ();
+	~SystemFile ();
+
+	void open (char const *filename);
+	void write (uint8_t *buffer, uint32_t size);
+private:
+	SystemFilePrivate *m_priv;
+};
+
+}; //namespace yans
+
+#endif /* SYSTEM_FILE_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/system-mutex.h	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,42 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2006 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#ifndef SYSTEM_MUTEX_H
+#define SYSTEM_MUTEX_H
+
+#include <stdint.h>
+
+namespace yans {
+
+class SystemMutexPrivate;
+
+class SystemMutex {
+public:
+	SystemMutex ();
+	~SystemMutex ();
+	void lock (void);
+	void unlock (void);
+ private:
+	SystemMutexPrivate *m_priv;
+};
+
+}; // namespace yans
+
+#endif /* SYSTEM_MUTEX_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/system-semaphore.h	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,44 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2006 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#ifndef SYSTEM_SEMAPHORE_H
+#define SYSTEM_SEMAPHORE_H
+
+#include <stdint.h>
+
+namespace yans {
+
+class SystemSemaphorePrivate;
+
+class SystemSemaphore {
+public:
+	SystemSemaphore (uint32_t init);
+	~SystemSemaphore ();
+	void post (void);
+	void post (uint32_t n);
+	void wait (void);
+	void wait (uint32_t n);
+private:
+	SystemSemaphorePrivate *m_priv;
+};
+
+}; // namespace yans
+
+#endif /* SYSTEM_SEMAPHORE_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/system-thread.h	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,41 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2006 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#ifndef SYSTEM_THREAD_H
+#define SYSTEM_THREAD_H
+
+namespace yans {
+
+class SystemThreadPrivate;
+
+class SystemThread {
+public:
+	SystemThread ();
+	virtual ~SystemThread ();
+private:
+	friend class SystemThreadPrivate;
+	SystemThreadPrivate *m_priv;
+	virtual void real_run (void) = 0;
+};
+
+}; // namespace yans
+
+
+#endif /* SYSTEM_THREAD_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/test.cc	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,107 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2005 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#include "test.h"
+
+#ifdef RUN_SELF_TESTS
+#include <iostream>
+
+namespace yans {
+
+TestManager *
+TestManager::get (void)
+{
+	static TestManager manager;
+	return &manager;
+}
+
+TestManager::TestManager ()
+	: m_verbose (false)
+{}
+
+TestManager::~TestManager ()
+{
+	TestsI i = m_tests.begin ();
+	while (i != m_tests.end ()) {
+		delete (*i).second;
+		i = m_tests.erase (i);
+	}
+}
+void
+TestManager::add (Test *test, char const *name)
+{
+	get ()->m_tests.push_back (std::make_pair (test, new std::string (name)));
+}
+void
+TestManager::enable_verbose (void)
+{
+	get ()->m_verbose = true;
+}
+std::ostream &
+TestManager::failure (void)
+{
+	return std::cerr;
+}
+bool 
+TestManager::run_tests (void)
+{
+	return get ()->real_run_tests ();
+}
+bool 
+TestManager::real_run_tests (void)
+{
+	bool is_success = true;
+	for (TestsCI i = m_tests.begin (); i != m_tests.end (); i++) {
+		std::string *test_name = (*i).second;
+		if (!(*i).first->run_tests ()) {
+			is_success = false;
+			if (m_verbose) {
+				std::cerr << "FAIL " << *test_name << std::endl;
+			}
+		} else {
+			if (m_verbose) {
+				std::cerr << "PASS "<<*test_name << std::endl;
+			}
+		}
+	}
+	if (!is_success) {
+		std::cerr << "FAIL" << std::endl;
+	}
+	return is_success;
+}
+
+Test::Test (char const *name)
+{
+	TestManager::add (this, name);
+}
+
+Test::~Test ()
+{}
+
+std::ostream &
+Test::failure (void)
+{
+	return TestManager::failure ();
+}
+
+}; // namespace yans
+
+#endif /* RUN_SELF_TESTS */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/test.h	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,75 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2005 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#ifndef TEST_H
+#define TEST_H
+
+#include <list>
+#include <string>
+#include <utility>
+#include <ostream>
+
+#ifdef RUN_SELF_TESTS
+
+namespace yans {
+
+class TestManager;
+
+class Test {
+public:
+	Test (char const *name);
+	virtual ~Test ();
+
+	virtual bool run_tests (void) = 0;
+
+protected:
+	std::ostream &failure (void);
+};
+
+class TestManager {
+public:
+	// main methods the test runner is supposed to
+	// invoke.
+	static void enable_verbose (void);
+	static bool run_tests (void);
+
+	// helper methods
+	static void add (Test *test, char const *name);
+	static std::ostream &failure (void);
+private:
+	static TestManager *get (void);
+	bool real_run_tests (void);
+
+	TestManager ();
+	~TestManager ();
+
+	typedef std::list<std::pair<Test *,std::string *> > Tests;
+	typedef std::list<std::pair<Test *,std::string *> >::iterator TestsI;
+	typedef std::list<std::pair<Test *,std::string *> >::const_iterator TestsCI;
+
+	Tests m_tests;
+	bool m_verbose;
+};
+}; // namespace yans 
+
+#endif /* RUN_SELF_TESTS */
+
+#endif /* TEST_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/unix-exec-commands.cc	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,516 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2006 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#include "exec-commands.h"
+#include "system-thread.h"
+#include "system-semaphore.h"
+#include "system-mutex.h"
+#include "callback.h"
+#include <cassert>
+#include <vector>
+
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <iostream>
+#include <sys/select.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+
+#define noTRACE_COMMAND 1
+
+#ifdef TRACE_COMMAND
+#include <iostream>
+# define TRACE(x) \
+std::cout << "COMMAND TRACE " << x << std::endl;
+#else /* TRACE_COMMAND */
+# define TRACE(format,...)
+#endif /* TRACE_COMMAND */
+
+
+namespace yans {
+
+class LogThread : public SystemThread {
+public:
+	LogThread (int main_log);
+	virtual ~LogThread ();
+	void add (int in, int out);
+private:
+	virtual void real_run (void);
+	void write_to (int fd, char *buffer, int size);
+	typedef std::vector<int> Fds;
+	typedef std::vector<int>::iterator FdsI;
+
+	int m_main_log;
+	Fds m_input_fds;
+	Fds m_output_fds;
+	SystemMutex m_fds_mutex;
+};
+
+LogThread::LogThread (int main_log)
+	: m_main_log (main_log)
+{}
+
+LogThread::~LogThread ()
+{}
+
+void
+LogThread::add (int in, int out)
+{
+	m_fds_mutex.lock ();
+	m_input_fds.push_back (in);
+	m_output_fds.push_back (out);
+	m_fds_mutex.unlock ();
+}
+void
+LogThread::write_to (int fd, char *buffer, int to_write)
+{
+	while (to_write > 0) {
+		int written = write (fd, buffer, to_write);
+		to_write -= written;
+		buffer += written;
+		assert (written >= 0);
+	}
+}
+
+void
+LogThread::real_run (void)
+{
+	char buffer[1024];
+	while (true) {
+		fd_set in;
+		struct timeval tv;
+		int retval;
+
+		TRACE ("prepare fd set");
+		m_fds_mutex.lock ();
+		assert (m_input_fds.size () == m_output_fds.size ());
+		FD_ZERO (&in);
+		int max_fd = 0;
+		for (uint32_t i = 0; i < m_input_fds.size (); i++) {
+			if (m_input_fds[i] > max_fd) {
+				max_fd = m_input_fds[i];
+			}
+			FD_SET (m_input_fds[i], &in);
+		}
+		m_fds_mutex.unlock ();
+		TRACE ("fd set prepared");
+
+		tv.tv_sec = 1;
+		tv.tv_usec = 0;
+
+		retval = select (max_fd+1, &in, NULL, NULL, &tv);
+		TRACE ("selected");
+		for (uint32_t i = 0; i < m_input_fds.size (); i++) {
+			if (FD_ISSET (m_input_fds[i], &in)) {
+				retval = read (m_input_fds[i], buffer, 1024);
+				if (retval == 0) {
+					close (m_output_fds[i]);
+					TRACE ("closed input");
+					m_fds_mutex.lock ();
+					FdsI cur = m_input_fds.begin ();
+					cur += i;
+					m_input_fds.erase (cur);
+					cur = m_output_fds.begin ();
+					cur += i;
+					m_output_fds.erase (cur);
+					m_fds_mutex.unlock ();
+					continue;
+				}
+				assert (retval > 0);
+				write_to (m_output_fds[i], buffer, retval);
+				write_to (m_main_log, buffer, retval);
+			}
+		}
+		TRACE ("written");
+	}
+}
+
+
+class CommandSystemThread : public SystemThread {
+public:
+	typedef Callback<void, CommandSystemThread *, int, std::string> DoneLogCallback;
+	typedef Callback<void, CommandSystemThread *> DoneNoLogCallback;
+	CommandSystemThread ();
+	void start_log (Command command, std::string id, DoneLogCallback callback);
+	void start_no_log (Command command, DoneNoLogCallback callback);
+	void stop (void);
+private:
+	virtual void real_run (void);
+	void run_exec (void);
+	SystemSemaphore m_sem;
+	bool m_stop;
+	Command m_command;
+	std::string m_id;
+	DoneLogCallback m_done_log;
+	DoneNoLogCallback m_done_no_log;
+	bool m_no_log;
+};
+
+CommandSystemThread::CommandSystemThread ()
+	: m_sem (0),
+	  m_stop (false)
+{}
+
+void
+CommandSystemThread::start_no_log (Command command, DoneNoLogCallback done)
+{
+	m_no_log = true;
+	m_command = command;
+	m_done_no_log = done;
+	m_sem.post ();
+}
+
+void
+CommandSystemThread::start_log (Command command, std::string id, DoneLogCallback done)
+{
+	m_no_log = false;
+	m_command = command;
+	m_id = id;
+	m_done_log = done;
+	m_sem.post ();
+}
+
+void
+CommandSystemThread::stop (void)
+{
+	m_stop = true;
+	m_sem.post ();
+}
+
+void
+CommandSystemThread::run_exec (void)
+{
+	char ** args = (char **)malloc (sizeof (char *) * (m_command.get_n ()+1));
+	char const *file = m_command.get (0);
+	args[0] = strdup (m_command.get (0));
+	for (uint32_t i = 1; i < m_command.get_n (); i++) {
+		args[i] = strdup (m_command.get (i));
+		//std::cout << "arg " << args[i-1] << std::endl;
+	}
+	args[m_command.get_n ()] = (char *)NULL;
+	int retval = execvp (file, args);
+	if (retval != 0) {
+		std::cout << strerror (errno) << std::endl;
+		exit (1);
+	}
+	// NOTREACHED
+	assert (false);
+}
+
+void
+CommandSystemThread::real_run (void)
+{
+	while (true) {
+		m_sem.wait ();
+		if (m_stop) {
+			break;
+		}
+		int retval;
+		int filedes[2];
+		if (m_no_log) {
+			pid_t pid = fork ();
+			if (pid == -1) {
+				assert (false);
+				// error in parent fork.
+			} else if (pid == 0) {
+				retval = open ("/dev/null", O_WRONLY);
+				dup2 (retval, 1);
+				close (retval);
+				// success, child.
+				run_exec ();
+			} else {
+				// success, parent.
+				m_done_no_log (this);
+			}
+		} else {
+			retval = pipe (filedes);
+			assert (retval == 0);
+			pid_t pid = fork ();
+			if (pid == -1) {
+				assert (false);
+				// error in parent fork.
+			} else if (pid == 0) {
+				// success, child.
+				TRACE ("child");
+				close (1);
+				close (filedes[0]);
+				dup2 (filedes[1], 1);
+				run_exec ();
+			} else {
+				TRACE ("parent");
+				// success, parent.
+				close (filedes[1]);
+				m_done_log (this, filedes[0], m_id);
+			}
+		}
+	}
+}
+
+class ExecCommandsPrivate {
+public:
+	ExecCommandsPrivate (uint32_t pool_size);
+	~ExecCommandsPrivate ();
+	void enable_log (char const *main_log);
+	void add (Command command, std::string id);
+	void start (void);
+	uint32_t get_size (void);
+private:
+	struct CommandRequest {
+		Command m_command;
+		std::string m_id;
+	};
+	typedef std::vector<CommandSystemThread *> Threads;
+	typedef std::vector<CommandSystemThread *>::iterator ThreadsI;
+	typedef std::vector<CommandRequest> Requests;
+	typedef std::vector<CommandRequest>::iterator RequestsI;
+	void command_done_log (CommandSystemThread *thread, int fd, std::string id);
+	void command_done_no_log (CommandSystemThread *thread);
+
+	Requests m_requests;
+	SystemSemaphore m_n_threads;
+	uint32_t m_pool_size;
+	Threads m_threads;
+	SystemMutex m_threads_mutex;
+	int m_main_log;
+	LogThread *m_log;
+};
+
+
+ExecCommandsPrivate::ExecCommandsPrivate (uint32_t pool_size)
+	: m_n_threads (0),
+	  m_pool_size (pool_size),
+	  m_main_log (0),
+	  m_log (0)
+{
+	m_threads_mutex.lock ();
+	for (uint32_t i = 0; i < pool_size; i++) {
+		m_threads.push_back (new CommandSystemThread ());
+	}
+	m_threads_mutex.unlock ();
+	m_n_threads.post (m_pool_size);
+}
+
+ExecCommandsPrivate::~ExecCommandsPrivate ()
+{
+	m_threads_mutex.lock ();
+	for (ThreadsI i = m_threads.begin (); i != m_threads.end (); i++) {
+		(*i)->stop ();
+		delete *i;
+	}
+	m_threads.erase (m_threads.begin (), m_threads.end ());
+	m_threads_mutex.unlock ();
+	delete m_log;
+}
+
+void 
+ExecCommandsPrivate::enable_log (char const *main_log)
+{
+	m_main_log = open (main_log, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
+	m_log = new LogThread (m_main_log);
+	assert (m_main_log != -1);
+}
+
+
+void
+ExecCommandsPrivate::add (Command command, std::string id)
+{
+	struct CommandRequest request;
+	request.m_command = command;
+	request.m_id = id;
+	m_requests.push_back (request);
+}
+void 
+ExecCommandsPrivate::start (void)
+{
+	for (RequestsI i = m_requests.begin (); i != m_requests.end (); i++) {
+		TRACE ("wait for thread");
+		m_n_threads.wait ();
+		m_threads_mutex.lock ();
+		CommandSystemThread *thread = m_threads.back ();
+		m_threads.pop_back ();
+		m_threads_mutex.unlock ();
+		TRACE ("start command");
+		if (m_main_log != 0) {
+			thread->start_log (i->m_command, i->m_id, 
+					   make_callback (&ExecCommandsPrivate::command_done_log, this));
+		} else {
+			thread->start_no_log (i->m_command, 
+					      make_callback (&ExecCommandsPrivate::command_done_no_log, this));
+		}
+	}
+}
+void
+ExecCommandsPrivate::command_done_log (CommandSystemThread *thread, int in, std::string id)
+{
+	TRACE ("command done");
+	m_threads_mutex.lock ();
+	m_threads.push_back (thread);
+	m_threads_mutex.unlock ();
+	m_n_threads.post ();
+
+	std::string out_filename = id;
+	out_filename.append (".log");
+	int out_fd = open (out_filename.c_str (), O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
+	assert (out_fd != -1);
+	m_log->add (in, out_fd);
+	TRACE ("notify command done");
+}
+
+void
+ExecCommandsPrivate::command_done_no_log (CommandSystemThread *thread)
+{
+	TRACE ("command done");
+	m_threads_mutex.lock ();
+	m_threads.push_back (thread);
+	m_threads_mutex.unlock ();
+	m_n_threads.post ();
+	TRACE ("notify command done");
+}
+
+uint32_t
+ExecCommandsPrivate::get_size (void)
+{
+	return m_requests.size ();
+}
+				   
+void 
+Command::reset (void)
+{
+	m_args.erase (m_args.begin (), m_args.end ());
+}
+
+void 
+Command::append (std::string arg)
+{
+	m_args.push_back (arg);
+}
+
+
+uint32_t
+Command::get_n (void)
+{
+	return m_args.size ();
+}
+char const*
+Command::get (uint32_t i)
+{
+	return m_args[i].c_str ();
+}
+
+
+
+ExecCommands::ExecCommands (uint32_t pool_size)
+	: m_priv (new ExecCommandsPrivate (pool_size))
+{
+	assert (pool_size != 0);
+}
+void 
+ExecCommands::enable_log (char const *main_log)
+{
+	m_priv->enable_log (main_log);
+}
+void 
+ExecCommands::add (Command command, char const *id)
+{
+	m_priv->add (command, id);
+}
+void 
+ExecCommands::start (void)
+{
+	m_priv->start ();
+}
+
+uint32_t 
+ExecCommands::get_size (void)
+{
+	return m_priv->get_size ();
+}
+
+}; // namespace yans
+
+#ifdef RUN_SELF_TESTS
+
+#include "test.h"
+#include <iomanip>
+#include <iostream>
+
+namespace yans {
+
+class ExecCommandsTest: public Test {
+public:
+	ExecCommandsTest ();
+	virtual ~ExecCommandsTest ();
+	virtual bool run_tests (void);
+private:
+	void command_output (char const *data, uint32_t size);
+};
+
+ExecCommandsTest::ExecCommandsTest ()
+	: Test ("ExecCommands")
+{}
+ExecCommandsTest::~ExecCommandsTest ()
+{}
+void 
+ExecCommandsTest::command_output (char const *data, uint32_t size)
+{
+	for (uint32_t i = 0; i < size; i++) {
+		std::cout << data[i];
+	};
+}
+bool 
+ExecCommandsTest::run_tests (void)
+{
+	bool ok = true;
+#if 0
+	ExecCommands commands = ExecCommands (2);
+	Command command;
+	command.append ("ls");
+	command.append ("-l");
+	commands.add (command, "ls");
+
+	command.reset ();
+	command.append ("ls");
+	command.append ("-l");
+	command.append ("src");
+	commands.add (command, "ls-src");
+
+	command.reset ();
+	command.append ("ls");
+	command.append ("-l");
+	command.append ("/usr/bin");
+	commands.add (command, "ls-usr-bin");
+
+	commands.enable_log ("main.log");
+	commands.start ();
+	sleep (5);
+#endif
+	return ok;
+}
+
+static ExecCommandsTest g_exec_commands_test;
+
+}; // namespace yans
+
+#endif /* RUN_SELF_TESTS */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/unix-system-file.cc	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,119 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2005 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#include "system-file.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/poll.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <cassert>
+#include <string.h>
+#include <list>
+
+#define noTRACE_SYS_FILE 1
+
+#ifdef TRACE_SYS_FILE
+#include <iostream>
+# define TRACE(x) \
+std::cout << "SYS FILE TRACE " << this << " " << x << std::endl;
+#else /* TRACE_SYS_FILE */
+# define TRACE(format,...)
+#endif /* TRACE_SYS_FILE */
+
+#define BUFFER_SIZE (4096)
+
+
+namespace yans {
+
+class SystemFilePrivate {
+public:
+	SystemFilePrivate ();
+	~SystemFilePrivate ();
+
+	void open (char const *filename);
+	void write (uint8_t *buffer, uint32_t size);
+private:
+	uint8_t m_data[BUFFER_SIZE];
+	uint32_t m_current;
+	int m_fd;
+};
+
+SystemFilePrivate::SystemFilePrivate ()
+	: m_current (0)
+{}
+SystemFilePrivate::~SystemFilePrivate ()
+{
+	::write (m_fd, m_data, m_current);
+	::close (m_fd);
+}
+
+
+void
+SystemFilePrivate::open (char const *filename)
+{
+	m_fd = ::open (filename, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
+	assert (m_fd != -1);
+}
+
+#ifndef min
+#define min(a,b) ((a)<(b)?(a):(b))
+#endif /* min */
+
+void
+SystemFilePrivate::write (uint8_t *buffer, uint32_t size)
+{
+	while (size > 0) {
+		uint32_t to_copy = min (BUFFER_SIZE - m_current, size);
+		memcpy (m_data + m_current, buffer, to_copy);
+		size -= to_copy;
+		m_current += to_copy;
+		buffer += to_copy;
+		if (m_current == BUFFER_SIZE) {
+			ssize_t written = 0;
+			written = ::write (m_fd, m_data, BUFFER_SIZE);
+			assert (written == BUFFER_SIZE);
+			m_current = 0;
+		}
+	}
+}
+
+SystemFile::SystemFile ()
+	: m_priv (new SystemFilePrivate ())
+{}
+SystemFile::~SystemFile ()
+{
+	delete m_priv;
+	m_priv = 0;
+}
+
+void 
+SystemFile::open (char const *filename)
+{
+	m_priv->open (filename);
+}
+void 
+SystemFile::write (uint8_t *buffer, uint32_t size)
+{
+	m_priv->write (buffer, size);
+}
+
+}; // namespace
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/unix-system-mutex.cc	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,82 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2006 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#include "system-mutex.h"
+
+#include <pthread.h>
+#include <cassert>
+
+namespace yans {
+
+class SystemMutexPrivate {
+public:
+	SystemMutexPrivate ();
+	~SystemMutexPrivate ();
+	void lock (void);
+	void unlock (void);
+private:
+	pthread_mutex_t m_mutex;
+};
+
+SystemMutexPrivate::SystemMutexPrivate ()
+{
+	int retval;
+	retval = pthread_mutex_init (&m_mutex, NULL);
+	assert (retval == 0);
+}
+SystemMutexPrivate::~SystemMutexPrivate ()
+{
+	int retval;
+	retval = pthread_mutex_destroy (&m_mutex);
+	assert (retval == 0);
+}
+void 
+SystemMutexPrivate::lock (void)
+{
+	pthread_mutex_lock (&m_mutex);
+}
+void 
+SystemMutexPrivate::unlock (void)
+{
+	pthread_mutex_unlock (&m_mutex);
+}
+
+SystemMutex::SystemMutex ()
+	: m_priv (new SystemMutexPrivate ())
+{}
+SystemMutex::~SystemMutex ()
+{
+	delete m_priv;
+}
+void 
+SystemMutex::lock (void)
+{
+	m_priv->lock ();
+}
+void 
+SystemMutex::unlock (void)
+{
+	m_priv->unlock ();
+}
+
+
+
+}; // namespace yans
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/unix-system-semaphore.cc	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,114 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2006 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#include "system-semaphore.h"
+
+#include <semaphore.h>
+#include <cassert>
+#include <iostream>
+#include "errno.h"
+#include "string.h"
+
+namespace yans {
+
+class SystemSemaphorePrivate {
+public:
+	SystemSemaphorePrivate (uint32_t init);
+	void post (void);
+	void post (uint32_t n);
+	void wait (void);
+	void wait (uint32_t n);
+private:
+	sem_t m_sem;
+};
+
+SystemSemaphorePrivate::SystemSemaphorePrivate (uint32_t init)
+{
+	int retval = sem_init (&m_sem, 0, init);
+	if (retval == -1) {
+		std::cout << "sem init " << this << " " << strerror (errno) << std::endl;
+	}
+}
+void 
+SystemSemaphorePrivate::post (void)
+{
+	int retval = sem_post (&m_sem);
+	if (retval == -1) {
+		std::cout << "sem post " << this << " " << strerror (errno) << std::endl;
+	}
+}
+void 
+SystemSemaphorePrivate::wait (void)
+{
+	int retval;
+	do {
+		retval = sem_wait (&m_sem);
+	} while (retval == -1 && errno == EINTR);
+	if (retval == -1) {
+		std::cout << "sem wait " << this << " " << strerror (errno) << std::endl;
+	}
+}
+void 
+SystemSemaphorePrivate::post (uint32_t n)
+{
+	for (uint32_t i = 0; i < n; i++) {
+		post ();
+	}
+}
+void 
+SystemSemaphorePrivate::wait (uint32_t n)
+{
+	for (uint32_t i = 0; i < n; i++) {
+		wait ();
+	}
+}
+
+SystemSemaphore::SystemSemaphore (uint32_t init)
+	: m_priv (new SystemSemaphorePrivate (init))
+{}
+SystemSemaphore::~SystemSemaphore ()
+{
+	delete m_priv;
+}
+void 
+SystemSemaphore::post (void)
+{
+	m_priv->post ();
+}
+void 
+SystemSemaphore::post (uint32_t n)
+{
+	m_priv->post (n);
+}
+void 
+SystemSemaphore::wait (void)
+{
+	m_priv->wait ();
+}
+void 
+SystemSemaphore::wait (uint32_t n)
+{
+	m_priv->wait (n);
+}
+
+
+
+}; // namespace yans
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/unix-system-thread.cc	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,69 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2006 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#include "system-thread.h"
+
+#include <pthread.h>
+#include <cassert>
+
+namespace yans {
+
+class SystemThreadPrivate {
+public:
+	SystemThreadPrivate (SystemThread *thread);
+	~SystemThreadPrivate ();
+private:
+	static void *pthread_run (void *thread);
+	pthread_t m_system_thread;
+	SystemThread *m_thread;
+};
+
+SystemThreadPrivate::SystemThreadPrivate (SystemThread *thread)
+	: m_thread (thread)
+{
+	int retval;
+	retval = pthread_create (&m_system_thread,
+				 NULL,
+				 SystemThreadPrivate::pthread_run,
+				 this);
+	assert (retval == 0);
+}
+SystemThreadPrivate::~SystemThreadPrivate ()
+{}
+void *
+SystemThreadPrivate::pthread_run (void *thread)
+{
+	SystemThreadPrivate *self = reinterpret_cast<SystemThreadPrivate *> (thread);
+	self->m_thread->real_run ();
+	return thread;
+}
+
+SystemThread::SystemThread ()
+	: m_priv (new SystemThreadPrivate (this))
+{}
+
+SystemThread::~SystemThread ()
+{
+	delete m_priv;
+}
+
+}; // namespace yans
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/unix-wall-clock-ms.cc	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,74 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2005 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage.inria.fr>
+ */
+
+#include "wall-clock-ms.h"
+#include <sys/time.h>
+
+namespace yans {
+
+class WallClockMsPrivate {
+public:
+	void start (void);
+	unsigned long long end (void);
+private:
+	struct timeval m_start_tv;
+	struct timeval m_end_tv;
+};
+
+void 
+WallClockMsPrivate::start (void)
+{
+	struct timezone tz;
+	gettimeofday (&m_start_tv, &tz);
+}
+
+unsigned long long 
+WallClockMsPrivate::end (void)
+{
+	struct timezone tz;
+	gettimeofday (&m_end_tv, &tz);
+	unsigned long long end = m_end_tv.tv_sec *1000 + m_end_tv.tv_usec / 1000;
+	unsigned long long start = m_start_tv.tv_sec *1000 + m_start_tv.tv_usec / 1000;
+	return end - start;
+}
+
+WallClockMs::WallClockMs ()
+	: m_priv (new WallClockMsPrivate ())
+{}
+
+WallClockMs::~WallClockMs ()
+{
+	delete m_priv;
+	m_priv = 0;
+}
+
+void
+WallClockMs::start (void)
+{
+	m_priv->start ();
+}
+unsigned long long
+WallClockMs::end (void)
+{
+	return m_priv->end ();
+}
+
+}; // namespace yans
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/wall-clock-ms.h	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,40 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2005 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage.inria.fr>
+ */
+
+#ifndef WALL_CLOCK_MS_H
+#define WALL_CLOCK_MS_H
+
+namespace yans {
+
+class WallClockMs {
+public:
+	WallClockMs ();
+	~WallClockMs ();
+
+	void start (void);
+	unsigned long long end (void);
+private:
+	class WallClockMsPrivate *m_priv;
+};
+
+}; // namespace yans
+
+#endif /* WALL_CLOCK_MS_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/win32-system-file.cc	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,86 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2005 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#include "system-file.h"
+
+
+#define noTRACE_SYS_FILE 1
+
+#ifdef TRACE_SYS_FILE
+#include <iostream>
+# define TRACE(x) \
+std::cout << "SYS FILE TRACE " << this << " " << x << std::endl;
+#else /* TRACE_SYS_FILE */
+# define TRACE(format,...)
+#endif /* TRACE_SYS_FILE */
+
+#define BUFFER_SIZE (4096)
+
+
+namespace yans {
+
+class SystemFilePrivate {
+public:
+	SystemFilePrivate ();
+	~SystemFilePrivate ();
+
+	void open (char const *filename);
+	void write (uint8_t *buffer, uint32_t size);
+private:
+};
+
+SystemFilePrivate::SystemFilePrivate ()
+{}
+SystemFilePrivate::~SystemFilePrivate ()
+{
+}
+
+
+void
+SystemFilePrivate::open (char const *filename)
+{
+}
+
+void
+SystemFilePrivate::write (uint8_t *buffer, uint32_t size)
+{
+}
+
+SystemFile::SystemFile ()
+	: m_priv (new SystemFilePrivate ())
+{}
+SystemFile::~SystemFile ()
+{
+	delete m_priv;
+	m_priv = 0;
+}
+
+void 
+SystemFile::open (char const *filename)
+{
+	m_priv->open (filename);
+}
+void 
+SystemFile::write (uint8_t *buffer, uint32_t size)
+{
+	m_priv->write (buffer, size);
+}
+
+}; // namespace
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/win32-system-mutex.cc	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,78 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2006 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#include "system-mutex.h"
+
+#include <windows.h>
+#include <cassert>
+
+namespace yans {
+
+class SystemMutexPrivate {
+public:
+	SystemMutexPrivate ();
+	~SystemMutexPrivate ();
+	void lock (void);
+	void unlock (void);
+private:
+	HANDLE m_mutex;
+};
+
+SystemMutexPrivate::SystemMutexPrivate ()
+{
+	m_mutex = CreateMutex(NULL, FALSE, "mutex");
+}
+SystemMutexPrivate::~SystemMutexPrivate ()
+{
+	CloseHandle (m_mutex);
+}
+void 
+SystemMutexPrivate::lock (void)
+{
+	WaitForSingleObject (m_mutex,INFINITE);
+}
+void 
+SystemMutexPrivate::unlock (void)
+{
+	ReleaseMutex (m_mutex);
+}
+
+SystemMutex::SystemMutex ()
+	: m_priv (new SystemMutexPrivate ())
+{}
+SystemMutex::~SystemMutex ()
+{
+	delete m_priv;
+}
+void 
+SystemMutex::lock (void)
+{
+	m_priv->lock ();
+}
+void 
+SystemMutex::unlock (void)
+{
+	m_priv->unlock ();
+}
+
+
+
+}; // namespace yans
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/win32-system-semaphore.cc	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,103 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2006 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#include "system-semaphore.h"
+
+#include <windows.h>
+#include <cassert>
+#include <iostream>
+
+namespace yans {
+
+class SystemSemaphorePrivate {
+public:
+	SystemSemaphorePrivate (uint32_t init);
+	~SystemSemaphorePrivate ();
+	void post (void);
+	void post (uint32_t n);
+	void wait (void);
+	void wait (uint32_t n);
+private:
+        HANDLE m_sem;
+};
+
+SystemSemaphorePrivate::SystemSemaphorePrivate (uint32_t init)
+{
+	m_sem = CreateSemaphore(NULL, init, 0, "semaphore");
+}
+SystemSemaphorePrivate::~SystemSemaphorePrivate ()
+{
+	CloseHandle (m_sem);
+}
+void 
+SystemSemaphorePrivate::post (void)
+{
+	ReleaseSemaphore(m_sem,1,NULL);
+}
+void 
+SystemSemaphorePrivate::wait (void)
+{
+	WaitForSingleObject (m_sem, INFINITE);
+}
+void 
+SystemSemaphorePrivate::post (uint32_t n)
+{
+	ReleaseSemaphore(m_sem,n,NULL);
+}
+void 
+SystemSemaphorePrivate::wait (uint32_t n)
+{
+	for (uint32_t i = 0; i < n; i++) {
+		wait ();
+	}
+}
+
+SystemSemaphore::SystemSemaphore (uint32_t init)
+	: m_priv (new SystemSemaphorePrivate (init))
+{}
+SystemSemaphore::~SystemSemaphore ()
+{
+	delete m_priv;
+}
+void 
+SystemSemaphore::post (void)
+{
+	m_priv->post ();
+}
+void 
+SystemSemaphore::post (uint32_t n)
+{
+	m_priv->post (n);
+}
+void 
+SystemSemaphore::wait (void)
+{
+	m_priv->wait ();
+}
+void 
+SystemSemaphore::wait (uint32_t n)
+{
+	m_priv->wait (n);
+}
+
+
+
+}; // namespace yans
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/win32-system-thread.cc	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,66 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2006 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#include "system-thread.h"
+#include <windows.h>
+#include <cassert>
+
+namespace yans {
+
+class SystemThreadPrivate {
+public:
+	SystemThreadPrivate (SystemThread *thread);
+	~SystemThreadPrivate ();
+private:
+	static void *thread_run (void *thread);
+	SystemThread *m_thread;
+	HANDLE m_system_thread;
+};
+
+SystemThreadPrivate::SystemThreadPrivate (SystemThread *thread)
+	: m_thread (thread)
+{
+	m_system_thread = CreateThread(NULL, 0, 
+				       (LPTHREAD_START_ROUTINE)SystemThreadPrivate::thread_run, 
+				       this, 0, 0);
+	assert (m_system_thread != NULL);
+}
+SystemThreadPrivate::~SystemThreadPrivate ()
+{}
+void *
+SystemThreadPrivate::thread_run (void *thread)
+{
+	SystemThreadPrivate *self = reinterpret_cast<SystemThreadPrivate *> (thread);
+	self->m_thread->real_run ();
+	return thread;
+}
+
+SystemThread::SystemThread ()
+	: m_priv (new SystemThreadPrivate (this))
+{}
+
+SystemThread::~SystemThread ()
+{
+	delete m_priv;
+}
+
+}; // namespace yans
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/win32-wall-clock-ms.cc	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,65 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2005 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage.inria.fr>
+ */
+
+#include "wall-clock-ms.h"
+
+namespace yans {
+
+class WallClockMsPrivate {
+public:
+	void start (void);
+	unsigned long long end (void);
+private:
+};
+
+void 
+WallClockMsPrivate::start (void)
+{
+}
+
+unsigned long long 
+WallClockMsPrivate::end (void)
+{
+	return 0;
+}
+
+WallClockMs::WallClockMs ()
+	: m_priv (new WallClockMsPrivate ())
+{}
+
+WallClockMs::~WallClockMs ()
+{
+	delete m_priv;
+	m_priv = 0;
+}
+
+void
+WallClockMs::start (void)
+{
+	m_priv->start ();
+}
+unsigned long long
+WallClockMs::end (void)
+{
+	return m_priv->end ();
+}
+
+}; // namespace yans
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/simulator/event-impl.cc	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,67 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2005 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#include "event-impl.h"
+
+
+namespace yans {
+
+
+EventImpl::~EventImpl ()
+{}
+
+EventImpl::EventImpl ()
+	: m_id (0),
+	  m_count (1),
+	  m_cancel (0),
+	  m_running (1)
+{}
+void 
+EventImpl::invoke (void)
+{
+	if (m_cancel == 0) {
+		notify ();
+	}
+	m_running = 0;
+}
+void 
+EventImpl::set_tag (void *tag)
+{
+	m_id = tag;
+}
+void *
+EventImpl::get_tag (void) const
+{
+	return m_id;
+}
+void 
+EventImpl::cancel (void)
+{
+	m_cancel = 1;
+	m_running = 0;
+}
+bool 
+EventImpl::is_running (void)
+{
+	return (m_running == 1);
+}
+
+}; // namespace yans
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/simulator/event-impl.h	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,49 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2005,2006 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#ifndef EVENT_IMPL_H
+#define EVENT_IMPL_H
+
+#include <stdint.h>
+
+namespace yans {
+
+class EventImpl {
+public:
+	EventImpl ();
+	virtual ~EventImpl () = 0;
+	void invoke (void);
+	void set_tag (void *tag);
+	void *get_tag (void) const;
+	void cancel (void);
+	bool is_running (void);
+protected:
+	virtual void notify (void) = 0;
+private:
+	friend class Event;
+	void *m_id;
+	uint32_t m_count;
+	uint32_t m_cancel : 1;
+	uint32_t m_running : 1;
+};
+
+}; // namespace yans
+
+#endif /* EVENT_IMPL_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/simulator/event-tcc-test.cc	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,110 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2006 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#include "event.tcc"
+#include "yans/test.h"
+
+#ifdef RUN_SELF_TESTS
+
+#define ENSURE(got,expected) \
+if (got != expected) { \
+	g_error = true; \
+}
+
+namespace {
+bool g_error = false;
+
+void null_cb (void)
+{}
+void one_cb (int a)
+{
+	ENSURE (a, 1);
+}
+void two_cb (int a,int b)
+{
+	ENSURE (a, 1);
+	ENSURE (b, 2);
+}
+void three_cb (int a,int b,int c)
+{
+	ENSURE (a, 1);
+	ENSURE (b, 2);
+	ENSURE (c, 3);
+}
+void four_cb (int a,int b,int c,int d)
+{
+	ENSURE (a, 1);
+	ENSURE (b, 2);
+	ENSURE (c, 3);
+	ENSURE (d, 4);
+}
+void five_cb (int a,int b,int c,int d,int e)
+{
+	ENSURE (a, 1);
+	ENSURE (b, 2);
+	ENSURE (c, 3);
+	ENSURE (d, 4);
+	ENSURE (e, 5);
+}
+
+};
+
+namespace yans {
+class EventTest : public Test {
+public:
+	EventTest ();
+	virtual bool run_tests (void);
+};
+
+EventTest::EventTest ()
+	: Test ("Event")
+{}
+
+bool 
+EventTest::run_tests (void)
+{
+	Event ev;
+
+	ev = yans::make_event (&null_cb);
+	ev ();
+	ev = yans::make_event (&one_cb, 1);
+	ev ();
+	ev = yans::make_event (&two_cb, 1, 2);
+	ev ();
+	ev = yans::make_event (&three_cb, 1, 2, 3);
+	ev ();
+	ev = yans::make_event (&four_cb, 1, 2, 3, 4);
+	ev ();
+	ev = yans::make_event (&five_cb, 1, 2, 3, 4, 5);
+	ev ();
+
+	if (g_error) {
+		return false;
+	}
+	return true;
+}
+
+static EventTest g_test;
+
+};
+
+
+
+#endif /* RUN_SELF_TESTS */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/simulator/event-tcc.cc	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,47 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2005 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#include "event-impl.h"
+#include "event.h"
+
+namespace yans {
+
+class EventFunctionImpl0 : public EventImpl {
+public:
+	typedef void (*F)(void);
+
+	EventFunctionImpl0 (F function) 
+		: m_function (function)
+	{}
+	virtual ~EventFunctionImpl0 () {}
+private:
+	virtual void notify (void) { 
+		(*m_function) (); 
+	}
+private:
+	F m_function;
+};
+
+Event make_event(void (*f) (void)) 
+{
+	return Event (new EventFunctionImpl0 (f));
+}
+
+}; // namespace yans
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/simulator/event.h	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,140 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2005 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#ifndef EVENT_H
+#define EVENT_H
+
+#include <algorithm>
+#include "event-impl.h"
+
+namespace yans {
+
+
+class EventImpl;
+/**
+ * \brief Simulation events.
+ *
+ * The Event class has POD semantics: it can and should
+ * be passed around by value. The Event class is a mere
+ * wrapper around the EventImpl class and performs
+ * memory management of EventImpl object instances.
+ *
+ * While users could create Events by instanciating 
+ * subclasses of the EventImpl class and storing them
+ * in an Event instance, they are advised to use the 
+ * template functions \ref make_event instead.
+ */
+class Event {
+public:
+	Event ()
+		: m_impl (0)
+	{}
+	Event (EventImpl *impl)
+		: m_impl (impl)
+	{}
+	Event (Event const &o)
+		: m_impl (o.m_impl)
+	{
+		if (m_impl != 0) {
+			m_impl->m_count++;
+		}
+	}
+	~Event ()
+	{
+		if (m_impl != 0) {
+			m_impl->m_count--;
+			if (m_impl->m_count == 0) {
+				delete m_impl;
+			}
+		}
+		m_impl = 0;
+	}
+	Event &operator = (Event const&o)
+	{
+		if (m_impl != 0) {
+			m_impl->m_count--;
+			if (m_impl->m_count == 0) {
+				delete m_impl;
+			}
+		}
+		m_impl = o.m_impl;
+		if (m_impl != 0) {
+			m_impl->m_count++;
+		}
+		return *this;
+	}
+	void operator () (void)
+	{
+		m_impl->invoke ();
+	}
+	/**
+	 * Cancel an event. This operation has O(1) 
+	 * complexity since it merely sets a "cancel" bit
+	 * to on and does not remove the Event from the 
+	 * scheduler's event list. When the event expires, 
+	 * the scheduler checks this cancel bit and, if set,
+	 * does not execute the event.
+	 */
+	void cancel (void)
+	{
+		if (m_impl != 0) {
+			m_impl->cancel ();
+		}
+	}
+	/**
+	 * Return true if the event is in RUNNING state.
+	 * Return false otherwise.
+	 *
+	 * An Event is created in RUNNING state and switches
+	 * to NON_RUNNING state upon one of:
+	 *    - cancel bit is set to on
+	 *    - Event execution is completed.
+	 * It is important to note that an event is in RUNNING
+	 * state while being executed.
+	 */
+	bool is_running (void)
+	{
+		if (m_impl != 0 && m_impl->is_running ()) {
+			return true;
+		} else {
+			return false;
+		}
+	}
+
+private:
+	friend class SchedulerHeap;
+	friend class SchedulerList;
+	friend class SchedulerMap;
+	void set_tag (void *tag)
+	{
+		return m_impl->set_tag (tag);
+	}
+	void *get_tag (void) const
+	{
+		return m_impl->get_tag ();
+	}
+
+	EventImpl *m_impl;
+};
+
+}; // namespace yans
+
+#endif /* EVENT_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/simulator/event.tcc	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,454 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2005 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#ifndef EVENT_TCC
+#define EVENT_TCC
+
+#include "event.h"
+#include "event-impl.h"
+
+/**
+ * yans namespace
+ */
+namespace yans {
+
+/**
+ * \defgroup make_event make_event
+ *
+ * Every make_event template function returns a newly-created Event
+ * which holds a pointer to a special subclass of the EventImpl 
+ * base class. Each of these subclasses holds information about which
+ * function or method to call and which parameters must be forwarded
+ * to this function or method.
+ *
+ * Sample code is shown below:
+ * \include samples/main-event.cc
+ */
+
+template<typename T>
+class EventMemberImpl0 : public EventImpl {
+public:
+	typedef void (T::*F)(void);
+
+	EventMemberImpl0 (T *obj, F function) 
+		: m_obj (obj), 
+		  m_function (function)
+	{}
+	virtual ~EventMemberImpl0 () {}
+private:
+	virtual void notify (void) { 
+		(m_obj->*m_function) (); 
+	}
+	T* m_obj;
+	F m_function;
+};
+
+template<typename T, typename T1>
+class EventMemberImpl1 : public EventImpl {
+public:
+	typedef void (T::*F)(T1);
+
+	EventMemberImpl1 (T *obj, F function, T1 a1) 
+		: m_obj (obj), 
+		  m_function (function),
+		  m_a1 (a1)
+	{ }
+	virtual ~EventMemberImpl1 () {}
+private:
+	virtual void notify (void) { 
+		(m_obj->*m_function) (m_a1);
+	}
+	T* m_obj;
+	F m_function;
+	T1 m_a1;
+};
+
+template<typename T, typename T1, typename T2>
+class EventMemberImpl2 : public EventImpl {
+public:
+	typedef void (T::*F)(T1, T2);
+
+	EventMemberImpl2 (T *obj, F function, T1 a1, T2 a2) 
+		: m_obj (obj), 
+		  m_function (function),
+		  m_a1 (a1),
+		  m_a2 (a2)
+	{ }
+	virtual ~EventMemberImpl2 () {}
+private:
+	virtual void notify (void) { 
+		(m_obj->*m_function) (m_a1, m_a2);
+	}
+	T* m_obj;
+	F m_function;
+	T1 m_a1;
+	T2 m_a2;
+};
+
+template<typename T, typename T1, typename T2, typename T3>
+class EventMemberImpl3 : public EventImpl {
+public:
+	typedef void (T::*F)(T1, T2, T3);
+
+	EventMemberImpl3 (T *obj, F function, T1 a1, T2 a2, T3 a3) 
+		: m_obj (obj), 
+		  m_function (function),
+		  m_a1 (a1),
+		  m_a2 (a2),
+		  m_a3 (a3)
+	{ }
+	virtual ~EventMemberImpl3 () {}
+private:
+	virtual void notify (void) { 
+		(m_obj->*m_function) (m_a1, m_a2, m_a3);
+	}
+	T* m_obj;
+	F m_function;
+	T1 m_a1;
+	T2 m_a2;
+	T3 m_a3;
+};
+
+template<typename T, typename T1, typename T2, typename T3, typename T4>
+class EventMemberImpl4 : public EventImpl {
+public:
+	typedef void (T::*F)(T1, T2, T3, T4);
+
+	EventMemberImpl4 (T *obj, F function, T1 a1, T2 a2, T3 a3, T4 a4) 
+		: m_obj (obj), 
+		  m_function (function),
+		  m_a1 (a1),
+		  m_a2 (a2),
+		  m_a3 (a3),
+		  m_a4 (a4)
+	{ }
+	virtual ~EventMemberImpl4 () {}
+private:
+	virtual void notify (void) { 
+		(m_obj->*m_function) (m_a1, m_a2, m_a3, m_a4);
+	}
+	T* m_obj;
+	F m_function;
+	T1 m_a1;
+	T2 m_a2;
+	T3 m_a3;
+	T4 m_a4;
+};
+
+template<typename T, typename T1, typename T2, typename T3, typename T4, typename T5>
+class EventMemberImpl5 : public EventImpl {
+public:
+	typedef void (T::*F)(T1, T2, T3, T4, T5);
+
+	EventMemberImpl5 (T *obj, F function, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) 
+		: m_obj (obj), 
+		  m_function (function),
+		  m_a1 (a1),
+		  m_a2 (a2),
+		  m_a3 (a3),
+		  m_a4 (a4),
+		  m_a5 (a5)
+	{ }
+	virtual ~EventMemberImpl5 () {}
+private:
+	virtual void notify (void) { 
+		(m_obj->*m_function) (m_a1, m_a2, m_a3, m_a4, m_a5);
+	}
+	T* m_obj;
+	F m_function;
+	T1 m_a1;
+	T2 m_a2;
+	T3 m_a3;
+	T4 m_a4;
+	T5 m_a5;
+};
+
+/**
+ * \ingroup make_event
+ * \param f class method member pointer
+ * \param t class instance
+ * \return a wrapper Event
+ * Build Events for class method members which take no arguments.
+ */
+template<typename T>
+Event make_event(void (T::*f) (void), T* t) {
+	return Event (new EventMemberImpl0<T>(t, f));
+}
+/**
+ * \ingroup make_event
+ * \param f class method member pointer
+ * \param t class instance
+ * \param a1 first argument to pass to the target method when the event expires
+ * \return a wrapper Event
+ * Build Events for class method members which take only one argument
+ */
+template<typename T, typename T1>
+Event make_event(void (T::*f) (T1), T* t, T1 a1) {
+	return Event (new EventMemberImpl1<T, T1>(t, f, a1));
+}
+/**
+ * \ingroup make_event
+ * \param f class method member pointer
+ * \param t class instance
+ * \param a1 first argument to pass to the target method when the event expires
+ * \param a2 second argument to pass to the target method when the event expires
+ * \return a wrapper Event
+ * Build Events for class method members which take two arguments
+ */
+template<typename T, typename T1, typename T2>
+Event make_event(void (T::*f) (T1, T2), T* t, T1 a1, T2 a2) {
+	return Event (new EventMemberImpl2<T, T1, T2>(t, f, a1, a2));
+}
+/**
+ * \ingroup make_event
+ * \param f class method member pointer
+ * \param t class instance
+ * \param a1 first argument to pass to the target method when the event expires
+ * \param a2 second argument to pass to the target method when the event expires
+ * \param a3 third argument to pass to the target method when the event expires
+ * \return a wrapper Event
+ * Build Events for class method members which take three arguments
+ */
+template<typename T, typename T1, typename T2, typename T3>
+Event make_event(void (T::*f) (T1, T2, T3), T* t, T1 a1, T2 a2, T3 a3) {
+	return Event (new EventMemberImpl3<T, T1, T2, T3>(t, f, a1, a2, a3));
+}
+/**
+ * \ingroup make_event
+ * \param f class method member pointer
+ * \param t class instance
+ * \param a1 first argument to pass to the target method when the event expires
+ * \param a2 second argument to pass to the target method when the event expires
+ * \param a3 third argument to pass to the target method when the event expires
+ * \param a4 fourth argument to pass to the target method when the event expires
+ * \return a wrapper Event
+ * Build Events for class method members which take four arguments
+ */
+template<typename T, typename T1, typename T2, typename T3, typename T4>
+Event make_event(void (T::*f) (T1, T2, T3, T4), T* t, T1 a1, T2 a2, T3 a3, T4 a4) {
+	return Event (new EventMemberImpl4<T, T1, T2, T3, T4>(t, f, a1, a2, a3, a4));
+}
+/**
+ * \ingroup make_event
+ * \param f class method member pointer
+ * \param t class instance
+ * \param a1 first argument to pass to the target method when the event expires
+ * \param a2 second argument to pass to the target method when the event expires
+ * \param a3 third argument to pass to the target method when the event expires
+ * \param a4 fourth argument to pass to the target method when the event expires
+ * \param a5 fifth argument to pass to the target method when the event expires
+ * \return a wrapper Event
+ * Build Events for class method members which take five arguments.
+ */
+template<typename T, typename T1, typename T2, typename T3, typename T4, typename T5>
+Event make_event(void (T::*f) (T1, T2, T3, T4, T5), T* t, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) {
+	return Event (new EventMemberImpl5<T, T1, T2, T3, T4, T5>(t, f, a1, a2, a3, a4, a5));
+}
+
+template<typename T1>
+class EventFunctionImpl1 : public EventImpl {
+public:
+	typedef void (*F)(T1);
+
+	EventFunctionImpl1 (F function, T1 a1) 
+		: m_function (function),
+		  m_a1 (a1)
+	{ }
+	virtual ~EventFunctionImpl1 () {}
+private:
+	virtual void notify (void) { 
+		(*m_function) (m_a1);
+	}
+	F m_function;
+	T1 m_a1;
+};
+
+template<typename T1, typename T2>
+class EventFunctionImpl2 : public EventImpl {
+public:
+	typedef void (*F)(T1, T2);
+
+	EventFunctionImpl2 (F function, T1 a1, T2 a2) 
+		: m_function (function),
+		  m_a1 (a1),
+		  m_a2 (a2)
+	{ }
+	virtual ~EventFunctionImpl2 () {}
+private:
+	virtual void notify (void) { 
+		(*m_function) (m_a1, m_a2);
+	}
+	F m_function;
+	T1 m_a1;
+	T2 m_a2;
+};
+
+template<typename T1, typename T2, typename T3>
+class EventFunctionImpl3 : public EventImpl {
+public:
+	typedef void (*F)(T1, T2, T3);
+
+	EventFunctionImpl3 (F function, T1 a1, T2 a2, T3 a3) 
+		: m_function (function),
+		  m_a1 (a1),
+		  m_a2 (a2),
+		  m_a3 (a3)
+	{ }
+	virtual ~EventFunctionImpl3 () {}
+private:
+	virtual void notify (void) { 
+		(*m_function) (m_a1, m_a2, m_a3);
+	}
+	F m_function;
+	T1 m_a1;
+	T2 m_a2;
+	T3 m_a3;
+};
+
+template<typename T1, typename T2, typename T3, typename T4>
+class EventFunctionImpl4 : public EventImpl {
+public:
+	typedef void (*F)(T1, T2, T3, T4);
+
+	EventFunctionImpl4 (F function, T1 a1, T2 a2, T3 a3, T4 a4) 
+		: m_function (function),
+		  m_a1 (a1),
+		  m_a2 (a2),
+		  m_a3 (a3),
+		  m_a4 (a4)
+	{ }
+	virtual ~EventFunctionImpl4 () {}
+private:
+	virtual void notify (void) { 
+		(*m_function) (m_a1, m_a2, m_a3, m_a4);
+	}
+	F m_function;
+	T1 m_a1;
+	T2 m_a2;
+	T3 m_a3;
+	T4 m_a4;
+};
+
+template<typename T1, typename T2, typename T3, typename T4, typename T5>
+class EventFunctionImpl5 : public EventImpl {
+public:
+	typedef void (*F)(T1, T2, T3, T4, T5);
+
+	EventFunctionImpl5 (F function, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) 
+		: m_function (function),
+		  m_a1 (a1),
+		  m_a2 (a2),
+		  m_a3 (a3),
+		  m_a4 (a4),
+		  m_a5 (a5)
+	{ }
+	virtual ~EventFunctionImpl5 () {}
+private:
+	virtual void notify (void) { 
+		(*m_function) (m_a1, m_a2, m_a3, m_a4, m_a5);
+	}
+	F m_function;
+	T1 m_a1;
+	T2 m_a2;
+	T3 m_a3;
+	T4 m_a4;
+	T5 m_a5;
+};
+
+
+/**
+ * \ingroup make_event
+ * \param f function pointer
+ * \return a wrapper Event
+ * Build Events for function pointers which take no arguments
+ */
+Event make_event(void (*f) (void));
+
+/**
+ * \ingroup make_event
+ * \param f function pointer
+ * \param a1 first argument to pass to the target function when the event expires
+ * \return a wrapper Event
+ * Build Events for function pointers which take one argument
+ */
+template<typename T1>
+Event make_event(void (*f) (T1), T1 a1) {
+	return Event (new EventFunctionImpl1<T1>(f, a1));
+}
+/**
+ * \ingroup make_event
+ * \param f function pointer
+ * \param a1 first argument to pass to the target function when the event expires
+ * \param a2 second argument to pass to the target function when the event expires
+ * \return a wrapper Event
+ * Build Events for function pointers which take two argument
+ */
+template<typename T1, typename T2>
+Event make_event(void (*f) (T1, T2), T1 a1, T2 a2) {
+	return Event (new EventFunctionImpl2<T1, T2>(f, a1, a2));
+}
+/**
+ * \ingroup make_event
+ * \param f function pointer
+ * \param a1 first argument to pass to the target function when the event expires
+ * \param a2 second argument to pass to the target function when the event expires
+ * \param a3 third argument to pass to the target function when the event expires
+ * \return a wrapper Event
+ * Build Events for function pointers which take three argument
+ */
+template<typename T1, typename T2, typename T3>
+Event make_event(void (*f) (T1, T2, T3), T1 a1, T2 a2, T3 a3) {
+	return Event (new EventFunctionImpl3<T1, T2, T3>(f, a1, a2, a3));
+}
+/**
+ * \ingroup make_event
+ * \param f function pointer
+ * \param a1 first argument to pass to the target function when the event expires
+ * \param a2 second argument to pass to the target function when the event expires
+ * \param a3 third argument to pass to the target function when the event expires
+ * \param a4 fourth argument to pass to the target function when the event expires
+ * \return a wrapper Event
+ * Build Events for function pointers which take four argument
+ */
+template<typename T1, typename T2, typename T3, typename T4>
+Event make_event(void (*f) (T1, T2, T3, T4), T1 a1, T2 a2, T3 a3, T4 a4) {
+	return Event (new EventFunctionImpl4<T1, T2, T3, T4>(f, a1, a2, a3, a4));
+}
+/**
+ * \ingroup make_event
+ * \param f function pointer
+ * \param a1 first argument to pass to the target function when the event expires
+ * \param a2 second argument to pass to the target function when the event expires
+ * \param a3 third argument to pass to the target function when the event expires
+ * \param a4 fourth argument to pass to the target function when the event expires
+ * \param a5 fifth argument to pass to the target function when the event expires
+ * \return a wrapper Event
+ * Build Events for function pointers which take five argument
+ */
+template<typename T1, typename T2, typename T3, typename T4, typename T5>
+Event make_event(void (*f) (T1, T2, T3, T4, T5), T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) {
+	return Event (new EventFunctionImpl5<T1, T2, T3, T4, T5>(f, a1, a2, a3, a4, a5));
+}
+
+
+}; // namespace yans
+
+#endif /* EVENT_TCC */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/simulator/scheduler-heap.cc	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,243 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2006 INRIA
+ * Copyright (c) 2005 Mathieu Lacage
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ *
+ * This code started as a c++ translation of a java-based code written in 2005
+ * to implement a heap sort. Which explains the Copyright Mathieu Lacage at the
+ * top of this file.
+ *
+ * What is smart about this code ?
+ *  - it does not use the index 0 in the array to avoid having to convert
+ *    C-style array indexes (which start at zero) and heap-style indexes
+ *    (which start at 1). This is why _all_ indexes start at 1, and that
+ *    the index of the root is 1.
+ *  - It uses a slightly non-standard while loop for top-down heapify
+ *    to move one if statement out of the loop.
+ */
+
+#include "scheduler-heap.h"
+#include "event.h"
+#include <cassert>
+
+#define noTRACE_HEAP 1
+
+#ifdef TRACE_HEAP
+#include <iostream>
+# define TRACE(x) \
+std::cout << "HEAP TRACE " << x << std::endl;
+#else /* TRACE_HEAP */
+# define TRACE(format,...)
+#endif /* TRACE_HEAP */
+
+
+
+
+namespace yans {
+
+SchedulerHeap::SchedulerHeap ()
+{
+	// we purposedly waste an item at the start of
+	// the array to make sure the indexes in the
+	// array start at one.
+	Scheduler::EventKey empty_key = {0,0};
+	m_heap.push_back (std::make_pair ((Event )0, empty_key));
+}
+
+SchedulerHeap::~SchedulerHeap ()
+{}
+
+ 
+void 
+SchedulerHeap::store_in_event (Event ev, uint32_t index) const
+{
+	ev.set_tag ((void *)index);
+}
+uint32_t 
+SchedulerHeap::get_from_event (Event const ev) const
+{
+ 	return (uint32_t)ev.get_tag ();
+}
+
+
+uint32_t 
+SchedulerHeap::parent (uint32_t id) const
+{
+	return id / 2;
+}
+uint32_t 
+SchedulerHeap::sibling (uint32_t id) const
+{
+	return id + 1;
+}
+uint32_t 
+SchedulerHeap::left_child (uint32_t id) const
+{
+	return id * 2;
+}
+uint32_t 
+SchedulerHeap::right_child (uint32_t id) const
+{
+	return id * 2 + 1;
+}
+
+uint32_t
+SchedulerHeap::root (void) const
+{
+	return 1;
+}
+
+bool
+SchedulerHeap::is_root (uint32_t id) const
+{
+	return (id == root ())?true:false;
+}
+
+uint32_t
+SchedulerHeap::last (void) const
+{
+	return m_heap.size () - 1;
+}
+
+
+bool
+SchedulerHeap::is_bottom (uint32_t id) const
+{
+	return (id >= m_heap.size ())?true:false;
+}
+
+void
+SchedulerHeap::exch (uint32_t a, uint32_t b) 
+{
+	assert (b < m_heap.size () && a < m_heap.size ());
+	TRACE ("exch " << a << ", " << b);
+#if 1
+	std::swap (m_heap[a].second, m_heap[b].second);
+	std::swap (m_heap[a].first.m_impl, m_heap[b].first.m_impl);
+#else
+	std::pair<Event , Scheduler::EventKey> tmp (m_heap[a]);
+	m_heap[a] = m_heap[b];
+	m_heap[b] = tmp;
+#endif
+	store_in_event (m_heap[a].first, a);
+	store_in_event (m_heap[b].first, b);
+}
+
+bool
+SchedulerHeap::is_less (uint32_t a, uint32_t b)
+{
+	Scheduler::EventKeyCompare compare;
+	return compare (m_heap[a].second, m_heap[b].second);
+}
+
+uint32_t 
+SchedulerHeap::smallest (uint32_t a, uint32_t b)
+{
+	return is_less (a,b)?a:b;
+}
+
+bool
+SchedulerHeap::is_empty (void) const
+{
+	return (m_heap.size () == 1)?true:false;
+}
+
+void
+SchedulerHeap::bottom_up (void)
+{
+	uint32_t index = last ();
+	while (!is_root (index) && 
+	       is_less (index, parent (index))) { 
+		exch(index, parent (index)); 
+		index = parent (index); 
+	}
+}
+
+void
+SchedulerHeap::top_down (void)
+{
+	uint32_t index = root ();
+	uint32_t right = right_child (index);
+	while (!is_bottom (right)) {
+		uint32_t left = left_child (index);
+		uint32_t tmp = smallest (left, right);
+		if (is_less (index, tmp)) {
+			return;
+		}
+		exch (index, tmp);
+		index = tmp;
+		right = right_child (index);
+	}
+	if (is_bottom (index)) {
+		return;
+	}
+	assert (!is_bottom (index));
+	uint32_t left = left_child (index);
+	if (is_bottom (left)) {
+		return;
+	}
+	if (is_less (index, left)) {
+		return;
+	}
+	exch (index, left);
+}
+
+
+Event  
+SchedulerHeap::insert (Event event, Scheduler::EventKey key)
+{
+	m_heap.push_back (std::make_pair (event, key));
+	store_in_event (event, last ());
+	bottom_up ();
+	return event;
+}
+
+Event
+SchedulerHeap::peek_next (void) const
+{
+	assert (!is_empty ());
+	return m_heap[root ()].first;
+}
+Scheduler::EventKey
+SchedulerHeap::peek_next_key (void) const
+{
+	assert (!is_empty ());
+	return m_heap[root ()].second;
+}
+void     
+SchedulerHeap::remove_next (void)
+{
+	assert (!is_empty ());
+	exch (root (), last ());
+	m_heap.pop_back ();
+	top_down ();
+}
+
+Scheduler::EventKey
+SchedulerHeap::remove (Event const ev)
+{
+	uint32_t i = get_from_event (ev);
+	EventKey key = m_heap[i].second;
+	exch (i, last ());
+	m_heap.pop_back ();
+	top_down ();
+	return key;
+}
+
+}; // namespace yans
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/simulator/scheduler-heap.h	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,71 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2005 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#ifndef SCHEDULER_HEAP_H
+#define SCHEDULER_HEAP_H
+
+#include "scheduler.h"
+#include <stdint.h>
+#include <vector>
+
+namespace yans {
+
+class Event;
+class EventHolder;
+
+class SchedulerHeap : public Scheduler {
+public:
+	SchedulerHeap ();
+	virtual ~SchedulerHeap ();
+
+	virtual Event insert (Event event, Scheduler::EventKey key);
+	virtual bool is_empty (void) const;
+	virtual Event peek_next (void) const;
+	virtual Scheduler::EventKey peek_next_key (void) const;
+	virtual void remove_next (void);
+	virtual Scheduler::EventKey remove (Event const ev);
+private:
+	typedef std::vector<std::pair<Event, Scheduler::EventKey> > BinaryHeap;
+	inline void store_in_event (Event ev, uint32_t index) const;
+	uint32_t get_from_event (Event const ev) const;
+
+	inline uint32_t parent (uint32_t id) const;
+	uint32_t sibling (uint32_t id) const;
+	inline uint32_t left_child (uint32_t id) const;
+	inline uint32_t right_child (uint32_t id) const;
+	inline uint32_t root (void) const;
+	uint32_t last (void) const;
+	inline bool is_root (uint32_t id) const;
+	inline bool is_bottom (uint32_t id) const;
+	inline bool is_less (uint32_t a, uint32_t b);
+	inline uint32_t smallest (uint32_t a, uint32_t b);
+
+	inline void exch (uint32_t a, uint32_t b);
+	void bottom_up (void);
+	void top_down (void);
+
+	BinaryHeap m_heap;
+};
+
+}; // namespace yans
+
+
+#endif /* SCHEDULER_HEAP_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/simulator/scheduler-list.cc	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,107 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2005 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#include "scheduler-list.h"
+#include "event.h"
+#include <utility>
+#include <cassert>
+
+namespace yans {
+
+SchedulerList::SchedulerList ()
+{}
+SchedulerList::~SchedulerList ()
+{}
+
+/*  !! WARNING !! 
+ * This is a very nasty piece of code but it really should work
+ * with pretty much any implementation of a std::list.
+ * it relies on the fact that a std::list<>::iterator has a single
+ * member variable, a pointer.
+ */
+void 
+SchedulerList::store_in_event (Event ev, EventsI i)
+{
+	assert (sizeof (i) <= sizeof (Event));
+	void *tag;
+	strncpy ((char *)&(tag), (char *)&i, sizeof (void *));
+	ev.set_tag (tag);
+}
+SchedulerList::EventsI 
+SchedulerList::get_from_event (Event const ev)
+{
+	SchedulerList::EventsI i;
+	assert (sizeof (i) <= sizeof (Event));
+	void *tag = ev.get_tag ();
+	strncpy ((char *)&i, (char *)&(tag), sizeof (void *));
+	return i;
+}
+
+
+Event  
+SchedulerList::insert (Event event, Scheduler::EventKey key)
+{
+	Scheduler::EventKeyCompare compare;
+	for (EventsI i = m_events.begin (); i != m_events.end (); i++) {
+		if (compare (key, i->second)) {
+			m_events.insert (i, std::make_pair (event, key));
+			store_in_event (event, i);
+			return event;
+		}
+	}
+	m_events.push_back (std::make_pair (event, key));
+	store_in_event (event, --(m_events.end ()));
+	return event;
+}
+bool 
+SchedulerList::is_empty (void) const
+{
+	return m_events.empty ();
+}
+Event 
+SchedulerList::peek_next (void) const
+{
+	assert (!is_empty ());
+	return m_events.front ().first;
+}
+Scheduler::EventKey
+SchedulerList::peek_next_key (void) const
+{
+	assert (!is_empty ());
+	return m_events.front ().second;
+}
+
+void
+SchedulerList::remove_next (void)
+{
+	m_events.pop_front ();
+}
+
+Scheduler::EventKey
+SchedulerList::remove (Event const ev)
+{
+	EventsI i = get_from_event (ev);
+	EventKey key = (*i).second;
+	m_events.erase (get_from_event (ev));
+	return key;
+}
+
+}; // namespace yans
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/simulator/scheduler-list.h	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,57 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2005 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#ifndef SCHEDULER_LIST_H
+#define SCHEDULER_LIST_H
+
+#include "scheduler.h"
+#include <list>
+#include <utility>
+#include <stdint.h>
+
+namespace yans {
+
+class Event;
+
+class SchedulerList : public Scheduler {
+ public:
+	SchedulerList ();
+	virtual ~SchedulerList ();
+
+	virtual Event insert (Event event, EventKey key);
+	virtual bool is_empty (void) const;
+	virtual Event peek_next (void) const;
+	virtual Scheduler::EventKey peek_next_key (void) const;
+	virtual void remove_next (void);
+	virtual Scheduler::EventKey remove (Event const ev);
+
+ private:
+	typedef std::list<std::pair<Event, EventKey> > Events;
+	typedef std::list<std::pair<Event, EventKey> >::iterator EventsI;
+	void store_in_event (Event ev, EventsI i);
+	EventsI get_from_event (Event const ev);
+	Events m_events;
+};
+
+}; // namespace yans
+
+
+#endif /* SCHEDULER_LIST_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/simulator/scheduler-map.cc	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,112 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2006 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ * The idea to use a std c++ map came from GTNetS
+ */
+
+#include "scheduler-map.h"
+#include "event.h"
+#include <cassert>
+
+#define noTRACE_MAP 1
+
+#ifdef TRACE_MAP
+#include <iostream>
+# define TRACE(x) \
+std::cout << "MAP TRACE " << x << std::endl;
+#else /* TRACE_MAP */
+# define TRACE(format,...)
+#endif /* TRACE_MAP */
+
+
+namespace yans {
+
+
+SchedulerMap::SchedulerMap ()
+{}
+SchedulerMap::~SchedulerMap ()
+{}
+
+
+void 
+SchedulerMap::store_in_event (Event ev, EventMapI i) const
+{
+	void *tag;
+	memcpy (&(tag), &i, sizeof (tag));
+	ev.set_tag (tag);
+}
+SchedulerMap::EventMapI
+SchedulerMap::get_from_event (Event const ev) const
+{
+	EventMapI i;
+	void *tag = ev.get_tag ();
+	memcpy (&i, &(tag), sizeof (i));
+ 	return i;
+}
+
+Event  
+SchedulerMap::insert (Event event, Scheduler::EventKey key)
+{
+	std::pair<EventMapI,bool> result = m_list.insert (std::make_pair (key, event));
+	assert (result.second);
+	store_in_event (event, result.first);
+	return event;
+}
+
+bool
+SchedulerMap::is_empty (void) const
+{
+	return m_list.empty ();
+}
+
+Event 
+SchedulerMap::peek_next (void) const
+{
+	assert (!is_empty ());
+	EventMapCI i = m_list.begin ();
+	assert (i != m_list.end ());
+	return (*i).second;
+}
+Scheduler::EventKey
+SchedulerMap::peek_next_key (void) const
+{
+	assert (!is_empty ());
+	EventMapCI i = m_list.begin ();
+	assert (i != m_list.end ());
+	return (*i).first;
+}
+void
+SchedulerMap::remove_next (void)
+{
+	assert (!is_empty ());
+	m_list.erase (m_list.begin ());
+}
+
+Scheduler::EventKey
+SchedulerMap::remove (Event const ev)
+{
+	assert (!is_empty ());
+	EventMapI i = get_from_event (ev);
+	EventKey key = (*i).first;
+	m_list.erase (i);
+	return key;
+}
+
+
+}; // namespace yans
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/simulator/scheduler-map.h	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,59 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2006 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#ifndef SCHEDULER_MAP_H
+#define SCHEDULER_MAP_H
+
+#include "scheduler.h"
+#include <stdint.h>
+#include <map>
+#include <utility>
+
+namespace yans {
+
+class SchedulerMap : public Scheduler {
+public:
+	SchedulerMap ();
+	virtual ~SchedulerMap ();
+
+	virtual Event insert (Event event, Scheduler::EventKey key);
+	virtual bool is_empty (void) const;
+	virtual Event peek_next (void) const;
+	virtual Scheduler::EventKey peek_next_key (void) const;
+	virtual void remove_next (void);
+	virtual Scheduler::EventKey remove (Event const ev);
+private:
+	typedef std::map<Scheduler::EventKey, Event, Scheduler::EventKeyCompare> EventMap;
+	typedef std::map<Scheduler::EventKey, Event, Scheduler::EventKeyCompare>::iterator EventMapI;
+	typedef std::map<Scheduler::EventKey, Event, Scheduler::EventKeyCompare>::const_iterator EventMapCI;
+
+	void store_in_event (Event ev, EventMapI i) const;
+	EventMapI get_from_event (Event const ev) const;
+
+
+	EventMap m_list;
+	uint32_t m_uid;
+};
+
+}; // namespace yans
+
+
+#endif /* SCHEDULER_MAP_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/simulator/scheduler.cc	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,46 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2006 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#include "scheduler.h"
+#include <cassert>
+
+
+yans::Scheduler::~Scheduler () 
+{}
+
+/* Note the invariants which this function must provide:
+ * - irreflexibility: f (x,x) is false)
+ * - antisymmetry: f(x,y) = !f(y,x)
+ * - transitivity: f(x,y) and f(y,z) => f(x,z)
+ */
+bool
+yans::Scheduler::EventKeyCompare::operator () (struct EventKey a, struct EventKey b)
+{
+	assert (a.m_uid != b.m_uid);
+	if (a.m_time < b.m_time) {
+		return true;
+	} else if (a.m_time == b.m_time && a.m_uid < b.m_uid) {
+		return true;
+	} else {
+		return false;
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/simulator/scheduler.h	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,54 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2005 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#ifndef SCHEDULER_H
+#define SCHEDULER_H
+
+#include <stdint.h>
+#include "event.h"
+
+namespace yans {
+
+class Scheduler {
+ public:
+	struct EventKey {
+		uint64_t m_time;
+		uint32_t m_uid;
+	};
+	class EventKeyCompare {
+	public:
+		bool operator () (struct EventKey a, struct EventKey b);
+	};
+
+	virtual ~Scheduler () = 0;
+	virtual Event insert (Event event, EventKey key) = 0;
+	virtual bool is_empty (void) const = 0;
+	virtual Event peek_next (void) const = 0;
+	virtual EventKey peek_next_key (void) const = 0;
+	virtual void remove_next (void) = 0;
+	virtual EventKey remove (Event const ev) = 0;
+
+};
+
+}; // namespace yans
+
+
+#endif /* SCHEDULER_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/simulator/simulator.cc	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,544 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2005,2006 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#include "simulator.h"
+#include "scheduler.h"
+#include "event.h"
+#include "event.tcc"
+#include "yans/system-semaphore.h"
+
+#include <math.h>
+#include <cassert>
+#include <fstream>
+#include <list>
+#include <vector>
+#include <iostream>
+
+#define noTRACE_SIMU 1
+
+#ifdef TRACE_SIMU
+#include <iostream>
+# define TRACE(x) \
+std::cout << "SIMU TRACE " << Simulator::now_s () << " " << x << std::endl;
+# define TRACE_S(x) \
+std::cout << "SIMU TRACE " << x << std::endl;
+#else /* TRACE_SIMU */
+# define TRACE(format,...)
+# define TRACE_S(format,...)
+#endif /* TRACE_SIMU */
+
+
+namespace yans {
+
+class ParallelSimulatorQueuePrivate {
+public:
+	ParallelSimulatorQueuePrivate (SimulatorPrivate *priv);
+	~ParallelSimulatorQueuePrivate ();
+	void set_queue (ParallelSimulatorQueue *queue);
+	void schedule_abs_us (Event ev, uint64_t at);
+	void send_null_message (void);
+private:
+	void remove_event (Event ev);
+	uint32_t m_n;
+	SimulatorPrivate *m_simulator;
+	ParallelSimulatorQueue *m_queue;
+};
+
+class SimulatorPrivate {
+public:
+	SimulatorPrivate (Scheduler *events);
+	~SimulatorPrivate ();
+
+	void enable_log_to (char const *filename);
+
+	void add_queue (ParallelSimulatorQueuePrivate *queue);
+	void notify_queue_not_empty (void);
+	void notify_queue_empty (void);
+	void wait_until_no_queue_empty (void);
+	bool is_parallel (void);
+
+	bool is_finished (void) const;
+	uint64_t next_us (void) const;
+	void run_serial (void);
+	void run_parallel (void);
+	void stop (void);
+	void stop_at_us (uint64_t at);
+	Event schedule_rel_us (Event event, uint64_t delta);
+	Event schedule_rel_s (Event event, double delta);
+	Event schedule_abs_us (Event event, uint64_t time);
+	Event schedule_abs_s (Event event, double time);
+	Event remove (Event const ev);
+	uint64_t now_us (void);
+	double now_s (void);
+	void schedule_now (Event event);
+	void schedule_destroy (Event event);
+
+private:
+	void process_one_event (void);
+
+	typedef std::list<std::pair<Event,uint32_t> > Events;
+	typedef std::vector<ParallelSimulatorQueuePrivate *> Queues;
+	typedef std::vector<ParallelSimulatorQueuePrivate *>::iterator QueuesI;
+	Events m_destroy;
+	uint64_t m_stop_at;
+	bool m_stop;
+	Scheduler *m_events;
+	uint32_t m_uid;
+	uint32_t m_current_uid;
+	uint64_t m_current_us;
+	std::ofstream m_log;
+	std::ifstream m_input_log;
+	bool m_log_enable;
+	uint32_t m_n_full_queues;
+	uint32_t m_n_queues;
+	SystemSemaphore *m_all_queues;
+	Queues m_queues;
+};
+
+
+ParallelSimulatorQueuePrivate::ParallelSimulatorQueuePrivate (SimulatorPrivate *simulator)
+	: m_simulator (simulator)
+{}
+ParallelSimulatorQueuePrivate::~ParallelSimulatorQueuePrivate ()
+{}
+void 
+ParallelSimulatorQueuePrivate::schedule_abs_us (Event ev, uint64_t at)
+{
+	m_n++;
+	if (m_n == 1) {
+		m_simulator->notify_queue_not_empty ();
+	}
+	m_simulator->schedule_abs_us (make_event (&ParallelSimulatorQueuePrivate::remove_event, this, ev), at);
+}
+void
+ParallelSimulatorQueuePrivate::remove_event (Event ev)
+{
+	m_n--;
+	if (m_n == 0) {
+		m_simulator->notify_queue_empty ();
+	}
+	ev ();
+}
+
+void
+ParallelSimulatorQueuePrivate::set_queue (ParallelSimulatorQueue *queue)
+{
+	m_queue = queue;
+}
+
+void 
+ParallelSimulatorQueuePrivate::send_null_message (void)
+{
+	m_queue->send_null_message ();
+}
+
+
+
+
+SimulatorPrivate::SimulatorPrivate (Scheduler *events)
+{
+	m_stop = false;
+	m_stop_at = 0;
+	m_events = events;
+	m_uid = 0;	
+	m_log_enable = false;
+	m_current_us = 0;
+	m_all_queues = new SystemSemaphore (0);
+	m_n_queues = 0;
+	m_n_full_queues = 0;
+}
+
+SimulatorPrivate::~SimulatorPrivate ()
+{
+	while (!m_destroy.empty ()) {
+		Event ev = m_destroy.front ().first;
+		m_destroy.pop_front ();
+		TRACE ("handle destroy " << ev);
+		ev ();
+	}
+	delete m_events;
+	m_events = (Scheduler *)0xdeadbeaf;
+	delete m_all_queues;
+	m_queues.erase (m_queues.begin (), m_queues.end ());
+}
+
+bool 
+SimulatorPrivate::is_parallel (void)
+{
+	return (m_n_queues > 0);
+}
+
+void
+SimulatorPrivate::enable_log_to (char const *filename)
+{
+	m_log.open (filename);
+	m_log_enable = true;
+}
+
+void 
+SimulatorPrivate::notify_queue_not_empty (void)
+{
+	m_n_full_queues++;
+	if (m_n_full_queues == m_n_queues) {
+		m_all_queues->post ();
+	}
+}
+void 
+SimulatorPrivate::notify_queue_empty (void)
+{
+	m_n_full_queues--;
+}
+void
+SimulatorPrivate::wait_until_no_queue_empty (void)
+{
+	while (m_n_full_queues < m_n_queues) {
+		m_all_queues->wait ();
+	}
+}
+
+void
+SimulatorPrivate::add_queue (ParallelSimulatorQueuePrivate *queue)
+{
+	m_n_queues++;
+	m_queues.push_back (queue);
+}
+
+void
+SimulatorPrivate::process_one_event (void)
+{
+	Event next_ev = m_events->peek_next ();
+	Scheduler::EventKey next_key = m_events->peek_next_key ();
+	m_events->remove_next ();
+	TRACE ("handle " << next_ev);
+	m_current_us = next_key.m_time;
+	m_current_uid = next_key.m_uid;
+	if (m_log_enable) {
+		m_log << "e "<<next_key.m_uid << " " << next_key.m_time << std::endl;
+	}
+	next_ev ();
+}
+
+bool 
+SimulatorPrivate::is_finished (void) const
+{
+	return m_events->is_empty ();
+}
+uint64_t 
+SimulatorPrivate::next_us (void) const
+{
+	assert (!m_events->is_empty ());
+	Scheduler::EventKey next_key = m_events->peek_next_key ();
+	return next_key.m_time;
+}
+
+
+void
+SimulatorPrivate::run_serial (void)
+{
+	while (!m_events->is_empty () && !m_stop && 
+	       (m_stop_at == 0 || m_stop_at > next_us ())) {
+		process_one_event ();
+	}
+	m_log.close ();
+}
+
+void
+SimulatorPrivate::run_parallel (void)
+{
+	TRACE ("run parallel");
+	while (!m_stop && 
+	       (m_stop_at == 0 || m_stop_at >= next_us ())) {
+		TRACE ("send null messages");
+		for (QueuesI i = m_queues.begin (); i != m_queues.end (); i++) {
+			(*i)->send_null_message ();
+		}
+		TRACE ("sent null messages");
+		wait_until_no_queue_empty ();
+		TRACE ("no queue empty");
+		process_one_event();
+		TRACE ("processed event");
+	}
+	m_log.close ();
+	TRACE ("done run parallel");
+}
+
+void 
+SimulatorPrivate::stop (void)
+{
+	m_stop = true;
+}
+void 
+SimulatorPrivate::stop_at_us (uint64_t at)
+{
+	m_stop_at = at;
+}
+Event   
+SimulatorPrivate::schedule_rel_us (Event event, uint64_t delta)
+{
+	uint64_t current = now_us ();
+	return schedule_abs_us (event, current+delta);
+}
+Event  
+SimulatorPrivate::schedule_abs_us (Event event, uint64_t time)
+{
+	assert (time >= now_us ());
+	Scheduler::EventKey key = {time, m_uid};
+	if (m_log_enable) {
+		m_log << "i "<<m_current_uid<<" "<<now_us ()<<" "
+		      <<m_uid<<" "<<time << std::endl;
+	}
+	m_uid++;
+	return m_events->insert (event, key);
+}
+uint64_t 
+SimulatorPrivate::now_us (void)
+{
+	return m_current_us;
+}
+Event  
+SimulatorPrivate::schedule_rel_s (Event event, double delta)
+{
+	int64_t delta_us = (int64_t)(delta * 1000000.0);
+	uint64_t us = now_us () + delta_us;
+	return schedule_abs_us (event, us);
+}
+Event  
+SimulatorPrivate::schedule_abs_s (Event event, double time)
+{
+	int64_t us = (int64_t)(time * 1000000.0);
+	assert (us >= 0);
+	return schedule_abs_us (event, (uint64_t)us);
+}
+double 
+SimulatorPrivate::now_s (void)
+{
+	double us = m_current_us;
+	us /= 1000000;
+	return us;
+}
+void
+SimulatorPrivate::schedule_now (Event event)
+{
+	schedule_abs_us (event, now_us ());
+}
+void
+SimulatorPrivate::schedule_destroy (Event event)
+{
+	m_destroy.push_back (std::make_pair (event, m_uid));
+	if (m_log_enable) {
+		m_log << "id " << m_current_uid << " " << now_us () << " "
+		      << m_uid << std::endl;
+	}
+	m_uid++;
+}
+
+Event 
+SimulatorPrivate::remove (Event const ev)
+{
+	Scheduler::EventKey key = m_events->remove (ev);
+	if (m_log_enable) {
+		m_log << "r " << m_current_uid << " " << now_us () << " "
+		      << key.m_uid << " " << key.m_time << std::endl;
+	}
+	return Event (ev);
+}
+
+
+}; // namespace yans
+
+
+#include "scheduler-list.h"
+#include "scheduler-heap.h"
+#include "scheduler-map.h"
+
+
+namespace yans {
+
+SimulatorPrivate *Simulator::m_priv = 0;
+Simulator::ListType Simulator::m_list_type = LINKED_LIST;
+
+void Simulator::set_linked_list (void)
+{
+	m_list_type = LINKED_LIST;
+}
+void Simulator::set_binary_heap (void)
+{
+	m_list_type = BINARY_HEAP;
+}
+void Simulator::set_std_map (void)
+{
+	m_list_type = STD_MAP;
+}
+void Simulator::enable_log_to (char const *filename)
+{
+	get_priv ()->enable_log_to (filename);
+}
+
+
+SimulatorPrivate *
+Simulator::get_priv (void)
+{
+	if (m_priv == 0) {
+		Scheduler *events;
+		switch (m_list_type) {
+		case LINKED_LIST:
+			events = new SchedulerList ();
+			break;
+		case BINARY_HEAP:
+			events = new SchedulerHeap ();
+			break;
+		case STD_MAP:
+			events = new SchedulerMap ();
+			break;
+		default: // not reached
+			events = 0;
+			assert (false); 
+			break;
+		}
+		m_priv = new SimulatorPrivate (events);
+	}
+	TRACE_S ("priv " << m_priv);
+	return m_priv;
+}
+
+void
+Simulator::destroy (void)
+{
+	delete m_priv;
+	m_priv = 0;
+}
+
+void
+Simulator::add_parallel_queue (ParallelSimulatorQueue *queue)
+{
+	ParallelSimulatorQueuePrivate *priv = new ParallelSimulatorQueuePrivate (get_priv ());
+	priv->set_queue (queue);
+	queue->set_priv (priv);
+	return get_priv ()->add_queue (priv);
+}
+
+bool 
+Simulator::is_finished (void)
+{
+	return get_priv ()->is_finished ();
+}
+uint64_t 
+Simulator::next_us (void)
+{
+	return get_priv ()->next_us ();
+}
+
+
+void 
+Simulator::run (void)
+{
+	if (get_priv ()->is_parallel ()) {
+		get_priv ()->run_parallel ();
+	} else {
+		get_priv ()->run_serial ();
+	}
+}
+void 
+Simulator::stop (void)
+{
+	TRACE ("stop");
+	get_priv ()->stop ();
+}
+void 
+Simulator::stop_at_us (uint64_t at)
+{
+	get_priv ()->stop_at_us (at);
+}
+Event 
+Simulator::schedule_rel_us (uint64_t delta, Event event)
+{
+	TRACE ("insert " << event << " in " << delta << "us");
+	return get_priv ()->schedule_rel_us (event, delta);
+}
+Event 
+Simulator::schedule_abs_us (uint64_t time, Event event)
+{
+	TRACE ("insert " << event << " at " << time << "us");
+	return get_priv ()->schedule_abs_us (event, time);
+}
+uint64_t 
+Simulator::now_us (void)
+{
+	return get_priv ()->now_us ();
+}
+Event  
+Simulator::schedule_rel_s (double delta, Event event)
+{
+	TRACE ("insert " << event << " in " << delta << "s");
+	return get_priv ()->schedule_rel_s (event, delta);
+}
+Event  
+Simulator::schedule_abs_s (double time, Event event)
+{
+	TRACE ("insert " << event << " at " << time << "s");
+	return get_priv ()->schedule_abs_s (event, time);
+}
+double 
+Simulator::now_s (void)
+{
+	return get_priv ()->now_s ();
+}
+void
+Simulator::schedule_now (Event event)
+{
+	TRACE ("insert later " << event);
+	return get_priv ()->schedule_now (event);
+}
+void 
+Simulator::schedule_destroy (Event event)
+{
+	TRACE ("insert at destroy " << event);
+	return get_priv ()->schedule_destroy (event);
+}
+
+Event 
+Simulator::remove (Event const ev)
+{
+	return get_priv ()->remove (ev);
+}
+
+}; // namespace yans
+
+
+namespace yans {
+
+ParallelSimulatorQueue::ParallelSimulatorQueue ()
+{}
+ParallelSimulatorQueue::~ParallelSimulatorQueue ()
+{
+	delete m_priv;
+}
+void 
+ParallelSimulatorQueue::schedule_abs_us (uint64_t at, Event ev)
+{
+	m_priv->schedule_abs_us (ev, at);
+}
+void
+ParallelSimulatorQueue::set_priv (ParallelSimulatorQueuePrivate *priv)
+{
+	m_priv = priv;
+}
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/simulator/simulator.h	Tue Aug 29 17:42:13 2006 +0200
@@ -0,0 +1,231 @@
+/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
+/*
+ * Copyright (c) 2005 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#ifndef SIMULATOR_H
+#define SIMULATOR_H
+
+#include <stdint.h>
+#include "event.h"
+
+namespace yans {
+
+class SimulatorPrivate;
+class ParallelSimulatorQueuePrivate;
+
+class ParallelSimulatorQueue {
+public:
+	virtual ~ParallelSimulatorQueue () = 0;
+	void schedule_abs_us (uint64_t at, Event ev);
+private:
+	friend class Simulator;
+	friend class ParallelSimulatorQueuePrivate;
+
+	void set_priv (ParallelSimulatorQueuePrivate *priv);
+	virtual void send_null_message (void) = 0;
+	ParallelSimulatorQueuePrivate *m_priv;
+protected:
+	ParallelSimulatorQueue ();
+};
+
+/**
+ * \brief Control the scheduling of simulation events. 
+ *
+ * The internal simulation clock is maintained
+ * as a 64-bit integer in microsecond units. This means that it is
+ * not possible to specify event expiration times with anything better
+ * than microsecond accuracy. Events which whose expiration time is
+ * the same are scheduled in FIFO order: the first event inserted in the
+ * Scheduling queue is scheduled to expire first.
+ */
+class Simulator {
+public:
+	/**
+	 * Force the use of an event scheduler based on a linked-list.
+	 * This method must be invoked before any other method exported
+	 * by the Simulator class.
+	 *   - insert: O(n)
+	 *   - remove: O(1)
+	 */
+	static void set_linked_list (void);
+	/**
+	 * Force the use of an event scheduler based on a binary heap.
+	 * This method must be invoked before any other method exported
+	 * by the Simulator class.
+	 *   - insert: O(log(n))
+	 *   - remove: O(log(n))
+	 */
+	static void set_binary_heap (void);
+	/**
+	 * Force the use of an event scheduler based on a std::map.
+	 * This method must be invoked before any other method exported
+	 * by the Simulator class.
+	 *   - insert: O(log(n))
+	 *   - remove: O(log(n))
+	 */
+	static void set_std_map (void);
+
+	/**
+	 * Enable logging to the file identified by filename. If the file
+	 * does not exist, it is created. If it exists, it is destroyed and
+	 * re-created. Every scheduling event is logged to this file in a
+	 * simple text format which can be read back by the event replay
+	 * utility. This allows you to record the scheduling behavior of
+	 * a simulation, and measure the exact overhead related to
+	 * event scheduling with the event replay utility. It is also possible
+	 * to compare the performance of every scheduling algorithms on this
+	 * specific scheduling load.
+	 * This method must be invoked before any call to Simulator::run
+	 * @param filename the name of the file to log to 
+	 */
+	static void enable_log_to (char const *filename);
+
+	/**
+	 * Every event scheduled by the Simulator::insert_at_destroy method is
+	 * invoked. Then, we ensure that any memory allocated by the 
+	 * Simulator is freed.
+	 * This method is typically invoked at the end of a simulation
+	 * to avoid false-positive reports by a leak checker.
+	 * After this method has been invoked, it is actually possible
+	 * to restart a new simulation with a set of calls to Simulator::run
+	 * and Simulator::insert_*.
+	 */
+	static void destroy (void);
+
+	/**
+	 * Register a new source of events from a remote simulation engine.
+	 * This new source of events is used by the parallel scheduler
+	 * to synchronize with the remote simulation engine by sending and
+	 * receiving null messages. The synchronization algorithm used
+	 * here is the classic Chandy/Misra/Bryant null-message algorithm.
+	 * This method must be invoked bfore any call to Simulator::run.
+	 * @param queue the queue to add to the list of event sources.
+	 */
+	static void add_parallel_queue (ParallelSimulatorQueue *queue);
+
+	/**
+	 * If there any any events lefts to be scheduled, return
+	 * true. Return false otherwise.
+	 */
+	static bool is_finished (void);
+	/**
+	 * If Simulator::is_finished returns true, the behavior of this
+	 * method is undefined. Otherwise, it returns the microsecond-based
+	 * time of the next event expected to be scheduled.
+	 */
+	static uint64_t next_us (void);
+
+	/**
+	 * Run the simulation until one of:
+	 *   - no events are present anymore
+	 *   - the user called Simulator::stop
+	 *   - the user called Simulator::stop_at_us and the
+	 *     expiration time of the next event to be processed
+	 *     is greater than or equal to the stop time.
+	 */
+	static void run (void);
+	/**
+	 * If an event invokes this method, it will be the last
+	 * event scheduled by the Simulator::run method before
+	 * returning to the caller.
+	 */
+	static void stop (void);
+	/**
+	 * Force the Simulator::run method to return to the caller
+	 * when the expiration time of the next event to be processed 
+	 * is greater than or equal to the stop time.
+	 * @param at the stop time.
+	 */
+	static void stop_at_us (uint64_t at);
+
+	/**
+	 * Schedule an event to expire at delta, relative to the
+	 * current time.
+	 * @param delta the expiration time relative to the current
+	 *        time. Expressed in microsecond units.
+	 * @param event the event to schedule.
+	 */
+	static Event schedule_rel_us (uint64_t delta, Event event);
+	/**
+	 * Schedule an event to expire at delta, relative to the
+	 * current time.
+	 * @param delta the expiration time, relative to the current
+	 *        time. Expressed in second units.
+	 * @param event the event to schedule.
+	 */
+	static Event schedule_rel_s (double delta, Event event);
+	/**
+	 * Schedule an event to expire at an absolute time.
+	 * @param time the expiration time. Expressed in 
+	 *             microsecond units.
+	 * @param event the event to schedule.
+	 */
+	static Event schedule_abs_us (uint64_t time, Event event);
+	/**
+	 * Schedule an event to expire at an absolute time.
+	 * @param time the expiration time. Expressed in 
+	 *             second units.
+	 * @param event the event to schedule.
+	 */
+	static Event schedule_abs_s (double time, Event event);
+	/**
+	 * Unschedule the event. i.e.: the removed event never expires.
+	 * @param id the event to remove from the list of scheduled events.
+	 */
+	static Event remove (Event const id);
+	/**
+	 * Return the "current time" in microsecond units.
+	 */
+	static uint64_t now_us (void);
+	/**
+	 * Return the "current time" in second units.
+	 */
+	static double now_s (void);
+	/**
+	 * Schedule an event to expire right now. i.e., it will
+	 * expire after the currently-executing event is executed.
+	 * If multiple events are scheduled with this method, 
+	 * they are executed in FIFO order: the events scheduled first
+	 * are executed first.
+	 * @param event the event to schedule now.
+	 */
+	static void schedule_now (Event event);
+	/**
+	 * Schedule an event to expire when the Simulator::destroy method
+	 * is invoked. Events are executed in FIFO order: the events
+	 * scheduled first are executed first.
+	 * @param event the event to schedule.
+	 */
+	static void schedule_destroy (Event event);
+private:
+	Simulator ();
+	~Simulator ();
+	static SimulatorPrivate *get_priv (void);
+	static SimulatorPrivate *m_priv;
+	static enum ListType {
+		LINKED_LIST,
+		BINARY_HEAP,
+		STD_MAP
+	} m_list_type;
+};
+
+}; // namespace yans
+
+#endif /* SIMULATOR_H */