--- /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 = ©->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 */